diff --git a/tests/unit/cc-compatible-provider.test.ts b/tests/unit/cc-compatible-provider.test.ts index 3447126827..34fd6db62a 100644 --- a/tests/unit/cc-compatible-provider.test.ts +++ b/tests/unit/cc-compatible-provider.test.ts @@ -782,6 +782,7 @@ test("handleChatCore preserves client cache markers for Claude Code requests to }); assert.deepEqual(calls[0].body.messages[0].content[0].cache_control, { type: "ephemeral", + ttl: "1h", }); assert.deepEqual(calls[0].body.messages[1].content[0].cache_control, { type: "ephemeral", diff --git a/tests/unit/chatcore-translation-paths.test.ts b/tests/unit/chatcore-translation-paths.test.ts index 8c60e1a789..0ea88229b4 100644 --- a/tests/unit/chatcore-translation-paths.test.ts +++ b/tests/unit/chatcore-translation-paths.test.ts @@ -861,7 +861,10 @@ test("chatCore preserves Opus 5 mid-conversation system cache breakpoints", asyn call.body.messages.map((message: { role: string }) => message.role), ["user", "assistant", "system", "user"] ); - assert.deepEqual(call.body.messages[2].content[0].cache_control, { type: "ephemeral" }); + assert.deepEqual(call.body.messages[2].content[0].cache_control, { + type: "ephemeral", + ttl: "1h", + }); assert.equal( call.body.system.some((block: { text?: string }) => block.text === "compact continuation"), false @@ -1037,7 +1040,10 @@ test("chatCore preserves cache_control automatically for Claude Code single-mode assert.equal(hasCacheControl(call.body), true); // system[0] and system[1] are now the billing line and sentinel injected by base.ts for Claude Code assert.deepEqual(call.body.system[2].cache_control, { type: "ephemeral", ttl: "5m" }); - assert.deepEqual(call.body.messages[0].content[0].cache_control, { type: "ephemeral" }); + assert.deepEqual(call.body.messages[0].content[0].cache_control, { + type: "ephemeral", + ttl: "1h", + }); // base.ts executor explicitly strips cache_control from tools for Claude Code clients assert.equal(call.body.tools[0].cache_control, undefined); }); @@ -1083,7 +1089,10 @@ test("chatCore supplements a missing message cache breakpoint for native Claude responseFormat: "claude", }); - assert.deepEqual(call.body.messages[2].content[0].cache_control, { type: "ephemeral" }); + assert.deepEqual(call.body.messages[2].content[0].cache_control, { + type: "ephemeral", + ttl: "1h", + }); assert.equal(call.body.tools[0].cache_control, undefined); }); test("chatCore auto cache policy becomes false for nondeterministic combos", async () => { @@ -1171,7 +1180,10 @@ test("chatCore disables raw Claude passthrough when cache preservation is off an true ); // Cache preservation is on for native Claude, so cache markers are intact - assert.deepEqual(call.body.messages[0].content[0].cache_control, { type: "ephemeral" }); + assert.deepEqual(call.body.messages[0].content[0].cache_control, { + type: "ephemeral", + ttl: "1h", + }); // Tools disable flag is applied assert.equal("_disableToolPrefix" in call.body, false); }); @@ -1314,7 +1326,7 @@ test("chatCore strips unsupported reasoning params and caps provider token field assert.equal(call.body.max_tokens, undefined); assert.equal(call.body.max_completion_tokens, 16384); }); -test("chatCore preserves reasoning_effort for assistant-prefill OpenAI-compatible requests", async () => { +test("chatCore downgrades unsupported xhigh effort for assistant-prefill OpenAI-compatible requests", async () => { const { call, result } = await invokeChatCore({ provider: "openai-compatible-aio", model: "glm-5.1", @@ -1333,7 +1345,7 @@ test("chatCore preserves reasoning_effort for assistant-prefill OpenAI-compatibl assert.equal(result.success, true); assert.equal(call.body.model, "glm-5.1"); - assert.equal(call.body.reasoning_effort, "xhigh"); + assert.equal(call.body.reasoning_effort, "high"); }); test("chatCore logs chat completions endpoint as OpenAI protocol", async () => { const { call, result } = await invokeChatCore({ diff --git a/tests/unit/executor-xai.test.ts b/tests/unit/executor-xai.test.ts index fdfeea3d1e..5d4d05fa74 100644 --- a/tests/unit/executor-xai.test.ts +++ b/tests/unit/executor-xai.test.ts @@ -23,11 +23,9 @@ test("XaiExecutor is registered under the 'xai' key and set as the registry exec test("XaiExecutor can target the separate xAI OAuth provider config", () => { const executor = new XaiExecutor("xai-oauth"); assert.equal(executor.getProvider(), "xai-oauth"); - // a367bf62f5 (#9994) scoped model-level targetFormat to the DECLARING provider's - // catalog: xai-oauth's own catalog lists grok-4.5 without a targetFormat tag, so - // it stays on /v1/chat/completions instead of importing a global entry's - // openai-responses tag (the transient #9612 global-fallback behavior). - assert.equal(executor.buildUrl("grok-4.5", false), "https://api.x.ai/v1/chat/completions"); + // #10170 declares grok-4.5 as a native Responses model in xai-oauth's own + // catalog, so provider-scoped target-format resolution must select that URL. + assert.equal(executor.buildUrl("grok-4.5", false), "https://api.x.ai/v1/responses"); }); test("strips a -{level} suffix from an allow-listed model and sets reasoning_effort", () => { @@ -88,7 +86,7 @@ test("strips reasoning_effort for the explicit -non-reasoning variant (already e assert.equal(out.reasoning_effort, undefined); }); -test("leaves a plain, unlisted model id and body unchanged (no suffix, not allow/deny listed)", () => { +test("converts a Responses-tagged model while leaving its unclassified reasoning state alone", () => { const executor = new XaiExecutor(); const body = { model: "grok-4.20-multi-agent-0309", messages: [{ role: "user", content: "hi" }] }; const out = executor.transformRequest( @@ -100,7 +98,13 @@ test("leaves a plain, unlisted model id and body unchanged (no suffix, not allow assert.equal(out.model, "grok-4.20-multi-agent-0309"); assert.equal(out.reasoning_effort, undefined); - assert.deepEqual(out.messages, body.messages); + assert.equal(out.messages, undefined); + assert.deepEqual(out.input, [ + { + role: "user", + content: [{ type: "input_text", text: "hi" }], + }, + ]); }); // Port of decolua/9router#2439 (author: @ryanngit): xAI ships a native