fix(qoder): report usage to all clients and stop inlining large attachments

- Coalesce Qoder's empty finish-in-delta frame with the later choices:[] usage
  frame so OpenAI and Claude clients receive prompt_tokens, completion_tokens
  and cache-hit tokens (the dashboard already saw them)
- Upload inlined images through /api/v2/image/upload like qodercli, and stub
  oversized non-image files instead of stuffing 30MB+ data URIs into
  agent_chat_generation
- Emit response.completed -> response.usage for chat-native upstreams so
  /v1/responses clients (Codex CLI, sub2api) no longer log 0/0/0
- Keep Claude message_delta.usage working when usage arrives without choices[0]
- Escalate to the smallest advertised Qoder context tier (200K/400K/1M) when
  the estimated prompt no longer fits max_input_tokens
- Pass apiKey for PAT connections and list hidden enable:false catalog keys
  from /v1/models
This commit is contained in:
LLL authored and decolua committed 2026-09-10 22:08:19 +07:00
1 parent 832a34659e
commit 1f10f9e5c4
19 files changed
+1615 -121

No files matched your search

+27
View File
@@ -203,4 +203,31 @@ describe("openaiToClaudeResponse", () => {
limit: 120
});
});
it("records usage from a choices:[] frame so the finish chunk can emit it", () => {
const state = { toolCalls: new Map() };
expect(openaiToClaudeResponse({
usage: {
prompt_tokens: 90,
completion_tokens: 7,
prompt_tokens_details: { cached_tokens: 30 },
},
choices: [],
}, state)).toBeNull();
expect(state.usage).toEqual({
input_tokens: 60,
output_tokens: 7,
cache_read_input_tokens: 30,
});
const events = openaiToClaudeResponse({
id: "chatcmpl-qoder-finish",
model: "qoder/auto",
choices: [{ index: 0, delta: {}, finish_reason: "stop" }],
}, state);
const delta = events.find((e) => e.type === "message_delta");
expect(delta.usage.input_tokens).toBe(60);
expect(delta.usage.output_tokens).toBe(7);
expect(delta.usage.cache_read_input_tokens).toBe(30);
});
});