diff --git a/packages/types/src/__tests__/lite-llm.test.ts b/packages/types/src/__tests__/lite-llm.test.ts index d276333aa5..87fdfdd0ad 100644 --- a/packages/types/src/__tests__/lite-llm.test.ts +++ b/packages/types/src/__tests__/lite-llm.test.ts @@ -21,6 +21,7 @@ describe("LiteLLM preserveReasoning model detection", () => { it("matches case-insensitively", () => { expect(isLiteLLMPreserveReasoningModel("MiniMax-M2.7-Highspeed")).toBe(true) expect(isLiteLLMPreserveReasoningModel("GLM-5.3")).toBe(true) + expect(isLiteLLMPreserveReasoningModel("QWEN3.8-MAX")).toBe(true) }) it("does not match model ids that merely contain a known family as a substring", () => { diff --git a/packages/types/src/__tests__/opencode-go.test.ts b/packages/types/src/__tests__/opencode-go.test.ts index 99376e3c35..adacbe274c 100644 --- a/packages/types/src/__tests__/opencode-go.test.ts +++ b/packages/types/src/__tests__/opencode-go.test.ts @@ -10,6 +10,7 @@ import { describe("opencode-go registry", () => { const anthropicFormatModels = [ + "qwen3.8-max", "qwen3.7-max", "qwen3.7-plus", "qwen3.6-plus", @@ -80,6 +81,22 @@ describe("opencode-go registry", () => { expect(info?.cacheReadsPrice).toBe(0.3) }) + it("exposes current Qwen3.8 Max capabilities and Go pricing", () => { + const info = getOpencodeGoModelInfo("qwen3.8-max") + expect(info).toMatchObject({ + maxTokens: 131_072, + contextWindow: 1_000_000, + supportsImages: true, + supportsPromptCache: true, + supportsMaxTokens: true, + inputPrice: 2.0, + outputPrice: 6.0, + cacheReadsPrice: 0.25, + cacheWritesPrice: 2.5, + }) + expect(info?.preserveReasoning).toBeUndefined() + }) + it("glm-5.3 exposes its native context, pricing, and always-on reasoning levels", () => { const info = getOpencodeGoModelInfo("glm-5.3") expect(info).toBeDefined() diff --git a/packages/types/src/__tests__/provider-settings.test.ts b/packages/types/src/__tests__/provider-settings.test.ts index ddf1ff4f5d..b29a93ca3e 100644 --- a/packages/types/src/__tests__/provider-settings.test.ts +++ b/packages/types/src/__tests__/provider-settings.test.ts @@ -130,6 +130,7 @@ describe("getApiProtocol", () => { describe("Opencode Go provider", () => { it("should return 'anthropic' for opencode-go Anthropic-format models (Qwen/MiniMax)", () => { + expect(getApiProtocol(providerIdentifiers.opencodeGo, "qwen3.8-max")).toBe(ANTHROPIC_API_PROTOCOL) expect(getApiProtocol(providerIdentifiers.opencodeGo, "qwen3.7-max")).toBe(ANTHROPIC_API_PROTOCOL) expect(getApiProtocol(providerIdentifiers.opencodeGo, "qwen3.7-plus")).toBe(ANTHROPIC_API_PROTOCOL) expect(getApiProtocol(providerIdentifiers.opencodeGo, "qwen3.6-plus")).toBe(ANTHROPIC_API_PROTOCOL) diff --git a/packages/types/src/providers/lite-llm.ts b/packages/types/src/providers/lite-llm.ts index 36277774d7..2e19b5b8b7 100644 --- a/packages/types/src/providers/lite-llm.ts +++ b/packages/types/src/providers/lite-llm.ts @@ -24,14 +24,12 @@ export const litellmDefaultModelInfo: ModelInfo = { * * Rather than matching model-family substrings with a regex (which can * over-match unrelated aliases, e.g. a family fragment appearing inside a - * longer unrelated model id), this is an explicit list of the exact model - * ids that set `preserveReasoning: true` in their native provider config - * (see deepseek.ts, mimo.ts, moonshot.ts, bedrock.ts, fireworks.ts, zai.ts, - * minimax.ts, opencode-go.ts). The same behavior is inferred for a - * LiteLLM-routed alias of the same underlying model. Keep this list in sync - * with those registries. This is still best-effort: unrecognized aliases or - * renamed deployments will not match, and callers should treat it as a - * heuristic, not a source of truth. + * longer unrelated model id), this is an explicit list of models whose + * OpenAI-compatible routes use interleaved `reasoning_content`. Native + * provider metadata informs this list where applicable, but gateway routes + * can have different preservation semantics. This is still best-effort: + * unrecognized aliases or renamed deployments will not match, and callers + * should treat it as a heuristic, not a source of truth. */ export const LITELLM_PRESERVE_REASONING_MODEL_IDS = [ // deepseek.ts @@ -75,6 +73,7 @@ export const LITELLM_PRESERVE_REASONING_MODEL_IDS = [ "qwen3.6-plus", "qwen3.7-plus", "qwen3.7-max", + "qwen3.8-max", ] as const const LITELLM_PRESERVE_REASONING_MODEL_ID_SET = new Set(LITELLM_PRESERVE_REASONING_MODEL_IDS) diff --git a/packages/types/src/providers/opencode-go.ts b/packages/types/src/providers/opencode-go.ts index 77e89fb80f..0d218a3274 100644 --- a/packages/types/src/providers/opencode-go.ts +++ b/packages/types/src/providers/opencode-go.ts @@ -307,6 +307,19 @@ export const opencodeGoModels: Record = { description: "Qwen3.7 Max - Alibaba's flagship text-only reasoning agent model with a 1M context window, designed for long-horizon agent workflows. Available via the Opencode Go plan.", }, + "qwen3.8-max": { + maxTokens: 131_072, + contextWindow: 1_000_000, + supportsImages: true, + supportsPromptCache: true, + supportsMaxTokens: true, + inputPrice: 2.0, + outputPrice: 6.0, + cacheReadsPrice: 0.25, + cacheWritesPrice: 2.5, + description: + "Qwen3.8 Max - Alibaba's flagship multimodal reasoning model with a 1M context window, 128k max output, and long-horizon coding and agentic capabilities. Available via the Opencode Go plan.", + }, // --- DeepSeek --- "deepseek-v4-pro": { @@ -364,6 +377,7 @@ export const opencodeGoModels: Record = { */ export const OPENCODE_GO_ANTHROPIC_FORMAT_MODELS = new Set([ // --- Alibaba Qwen --- + "qwen3.8-max", "qwen3.7-max", "qwen3.7-plus", "qwen3.6-plus", diff --git a/src/api/providers/opencode-go.ts b/src/api/providers/opencode-go.ts index be53dc1c02..6b3f633829 100644 --- a/src/api/providers/opencode-go.ts +++ b/src/api/providers/opencode-go.ts @@ -54,9 +54,9 @@ import { * * - OpenAI-compatible chat completions (`/v1/chat/completions`, "oa-compat") * — used by GLM, Kimi, DeepSeek, and MiMo models. - * - Anthropic Messages (`/v1/messages`) — used by Qwen (qwen3.7-max, - * qwen3.7-plus, qwen3.6-plus) and MiniMax (minimax-m3, minimax-m2.7, - * minimax-m2.5) models. + * - Anthropic Messages (`/v1/messages`) — used by Qwen (qwen3.8-max, + * qwen3.7-max, qwen3.7-plus, qwen3.6-plus) and MiniMax (minimax-m3, + * minimax-m2.7, minimax-m2.5) models. * * Sending an Anthropic-format model to the chat completions endpoint is * rejected with `401 Model is not supported for format oa-compat`, so this