From 17c9805259f3605dea80022aa7a6f71424548abd Mon Sep 17 00:00:00 2001 From: Naufal Malik Rabbani Date: Tue, 18 Aug 2026 14:19:34 +0700 Subject: [PATCH] fix(commandcode): strip thinking suffix from params.model Upstream reads params.model and rejects unknown ids. The client thinking suffix "model(level)" was copied verbatim into params.model (chatCore strips only the top-level model field), so requests like gpt-5.6-luna(max) failed with 403 "Model/provider not recognized: anthropic:gpt-5.6-luna(max)". Strip the suffix in the commandcode translator; applyThinking still consumes the suffix for the thinking override before the body is sent. --- .../request/openai-to-commandcode.js | 6 ++++- tests/unit/openai-to-commandcode.test.js | 26 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/open-sse/translator/request/openai-to-commandcode.js b/open-sse/translator/request/openai-to-commandcode.js index 9825048bd4..b0f79d0bb2 100644 --- a/open-sse/translator/request/openai-to-commandcode.js +++ b/open-sse/translator/request/openai-to-commandcode.js @@ -13,6 +13,7 @@ import { register } from "../index.js"; import { FORMATS } from "../formats.js"; import { randomUUID } from "crypto"; import { ROLE, OPENAI_BLOCK } from "../schema/index.js"; +import { stripThinkingSuffix } from "../concerns/thinkingUnified.js"; import { DEFAULT_MAX_TOKENS } from "../../config/runtimeConfig.js"; function flattenText(content) { @@ -136,7 +137,10 @@ function convertTools(tools) { export function openaiToCommandCodeRequest(model, body, stream /* , credentials */) { const { messages, system } = convertMessages(body.messages); const params = { - model, + // Upstream reads params.model and rejects unknown ids — never leak the + // client thinking suffix "model(level)" (chatCore strips only the top-level + // model field; the suffix is consumed by applyThinking, not the wire). + model: stripThinkingSuffix(model), messages, stream: stream !== false, max_tokens: body.max_tokens ?? body.max_output_tokens ?? DEFAULT_MAX_TOKENS, diff --git a/tests/unit/openai-to-commandcode.test.js b/tests/unit/openai-to-commandcode.test.js index 7f12dc85f1..27732c4427 100644 --- a/tests/unit/openai-to-commandcode.test.js +++ b/tests/unit/openai-to-commandcode.test.js @@ -28,6 +28,32 @@ describe("openaiToCommandCodeRequest — basic envelope", () => { }); }); +describe("openaiToCommandCodeRequest — thinking suffix stripping", () => { + it("strips a client thinking suffix from params.model (upstream rejects it)", () => { + const out = openaiToCommandCodeRequest("gpt-5.6-luna(max)", { + messages: [{ role: "user", content: "hi" }], + }, true); + + expect(out.params.model).toBe("gpt-5.6-luna"); + }); + + it("strips the suffix from family-prefixed ids too", () => { + const out = openaiToCommandCodeRequest("deepseek/deepseek-v4-pro(max)", { + messages: [{ role: "user", content: "hi" }], + }, true); + + expect(out.params.model).toBe("deepseek/deepseek-v4-pro"); + }); + + it("leaves plain model ids untouched", () => { + const out = openaiToCommandCodeRequest("deepseek/deepseek-v4-pro", { + messages: [{ role: "user", content: "hi" }], + }, true); + + expect(out.params.model).toBe("deepseek/deepseek-v4-pro"); + }); +}); + describe("openaiToCommandCodeRequest — system handling", () => { it("hoists system messages to params.system (string), not messages[]", () => { const out = openaiToCommandCodeRequest(MODEL, {