From f685cc25c07ecbd6c5efc27c8541f689f4fd659e Mon Sep 17 00:00:00 2001 From: Roomote Date: Fri, 24 Jul 2026 05:58:23 +0000 Subject: [PATCH 1/3] feat(types): add Kimi K3 to moonshot and opencode-go providers --- packages/types/src/__tests__/lite-llm.test.ts | 1 + .../types/src/__tests__/opencode-go.test.ts | 1 + packages/types/src/providers/lite-llm.ts | 3 +++ packages/types/src/providers/moonshot.ts | 15 +++++++++++++++ packages/types/src/providers/opencode-go.ts | 17 +++++++++++++++++ 5 files changed, 37 insertions(+) diff --git a/packages/types/src/__tests__/lite-llm.test.ts b/packages/types/src/__tests__/lite-llm.test.ts index 03424b2e57..74436c1848 100644 --- a/packages/types/src/__tests__/lite-llm.test.ts +++ b/packages/types/src/__tests__/lite-llm.test.ts @@ -12,6 +12,7 @@ describe("LiteLLM preserveReasoning model detection", () => { }) it("matches provider-prefixed routed model names by their final segment", () => { + expect(isLiteLLMPreserveReasoningModel("kimi-k3")).toBe(true) expect(isLiteLLMPreserveReasoningModel("deepseek/deepseek-reasoner")).toBe(true) expect(isLiteLLMPreserveReasoningModel("bedrock/moonshot.kimi-k2-thinking")).toBe(true) expect(isLiteLLMPreserveReasoningModel("fireworks_ai/accounts/fireworks/models/kimi-k2p7-code")).toBe(true) diff --git a/packages/types/src/__tests__/opencode-go.test.ts b/packages/types/src/__tests__/opencode-go.test.ts index 617c88675c..67f8e50b39 100644 --- a/packages/types/src/__tests__/opencode-go.test.ts +++ b/packages/types/src/__tests__/opencode-go.test.ts @@ -21,6 +21,7 @@ describe("opencode-go registry", () => { "glm-5", "glm-5.1", "glm-5.2", + "kimi-k3", "kimi-k2.5", "kimi-k2.6", "mimo-v2.5", diff --git a/packages/types/src/providers/lite-llm.ts b/packages/types/src/providers/lite-llm.ts index a63f3971f5..2b72de9d51 100644 --- a/packages/types/src/providers/lite-llm.ts +++ b/packages/types/src/providers/lite-llm.ts @@ -48,6 +48,9 @@ export const LITELLM_PRESERVE_REASONING_MODEL_IDS = [ "moonshot.kimi-k2-thinking", "kimi-k2p7-code", + // moonshot.ts, opencode-go.ts + "kimi-k3", + // zai.ts "glm-4.7", "glm-5", diff --git a/packages/types/src/providers/moonshot.ts b/packages/types/src/providers/moonshot.ts index ad729bc2a7..8e041d160a 100644 --- a/packages/types/src/providers/moonshot.ts +++ b/packages/types/src/providers/moonshot.ts @@ -6,6 +6,21 @@ export type MoonshotModelId = keyof typeof moonshotModels export const moonshotDefaultModelId: MoonshotModelId = "kimi-k2-0905-preview" export const moonshotModels = { + "kimi-k3": { + maxTokens: 131_072, // Default max_completion_tokens (configurable up to 1,048,576) + contextWindow: 1_048_576, // 1M tokens + supportsImages: true, // Native visual understanding (text, image, video) + supportsPromptCache: true, // Automatic context caching + supportsReasoningEffort: ["low", "high", "max"], // Always reasons; default "max" + reasoningEffort: "max", + preserveReasoning: true, + inputPrice: 3.0, // $3.00 per million tokens (cache miss) + outputPrice: 15.0, // $15.00 per million tokens + cacheWritesPrice: 0, // $0 per million tokens (cache miss) + cacheReadsPrice: 0.3, // $0.30 per million tokens (cache hit) + defaultTemperature: 1.0, // temperature is fixed at 1.0 + description: `Kimi K3 is Kimi's most capable flagship model with 2.8 trillion parameters, native visual understanding, and a 1M-token context window, designed for long-horizon coding, knowledge work, and deep reasoning. Thinking is always enabled with configurable reasoning effort (low/high/max, default max).`, + }, "kimi-k2-0711-preview": { maxTokens: 32_000, contextWindow: 131_072, diff --git a/packages/types/src/providers/opencode-go.ts b/packages/types/src/providers/opencode-go.ts index 5b1e0ada8e..bd60c4d349 100644 --- a/packages/types/src/providers/opencode-go.ts +++ b/packages/types/src/providers/opencode-go.ts @@ -104,6 +104,23 @@ export const opencodeGoModels: Record = { }, // --- Moonshot Kimi --- + "kimi-k3": { + maxTokens: 131_072, // Default max_completion_tokens (configurable up to 1,048,576) + contextWindow: 1_048_576, + supportsImages: false, + supportsPromptCache: true, + supportsMaxTokens: true, + supportsReasoningEffort: ["low", "high", "max"], // Always reasons; default "max" + reasoningEffort: "max", + preserveReasoning: true, + defaultTemperature: 1.0, + // Go pricing matches Moonshot direct ($3 in / $0.30 cache / $15 out per 1M tokens). + inputPrice: 3.0, + outputPrice: 15.0, + cacheReadsPrice: 0.3, + description: + "Kimi K3 is Moonshot AI's flagship model with 2.8 trillion parameters, a 1M context window, and always-on reasoning with configurable effort (low/high/max). Available via the Opencode Go plan.", + }, "kimi-k2.5": { maxTokens: 16_384, contextWindow: 262_144, From 2517179dee5a8256e2f247278bd8493286fb59f1 Mon Sep 17 00:00:00 2001 From: Roomote Date: Fri, 24 Jul 2026 13:17:20 +0000 Subject: [PATCH 2/3] test(types): add moonshot registry suite and explicit kimi-k3 reasoning assertions --- packages/types/src/__tests__/moonshot.test.ts | 68 +++++++++++++++++++ .../types/src/__tests__/opencode-go.test.ts | 17 +++++ 2 files changed, 85 insertions(+) create mode 100644 packages/types/src/__tests__/moonshot.test.ts diff --git a/packages/types/src/__tests__/moonshot.test.ts b/packages/types/src/__tests__/moonshot.test.ts new file mode 100644 index 0000000000..274e0664fb --- /dev/null +++ b/packages/types/src/__tests__/moonshot.test.ts @@ -0,0 +1,68 @@ +import { MOONSHOT_DEFAULT_TEMPERATURE, moonshotDefaultModelId, moonshotModels } from "../providers/moonshot.js" + +describe("moonshot registry", () => { + describe("moonshotModels registry invariants", () => { + it("every entry has a positive maxTokens and contextWindow", () => { + for (const [id, info] of Object.entries(moonshotModels)) { + expect(info.maxTokens).toBeGreaterThan(0) + expect(info.contextWindow).toBeGreaterThan(0) + // Sanity: max output must not exceed the context window. + expect(info.maxTokens).toBeLessThanOrEqual(info.contextWindow) + void id + } + }) + + it("every entry declares supportsImages and supportsPromptCache", () => { + for (const info of Object.values(moonshotModels)) { + expect(typeof info.supportsImages).toBe("boolean") + expect(typeof info.supportsPromptCache).toBe("boolean") + } + }) + + it("models with an array supportsReasoningEffort expose a non-empty allow-list", () => { + for (const info of Object.values(moonshotModels)) { + if (Array.isArray(info.supportsReasoningEffort)) { + expect(info.supportsReasoningEffort.length).toBeGreaterThan(0) + } + } + }) + + it("every entry declares a reasoningEffort that is covered by its allow-list", () => { + for (const info of Object.values(moonshotModels)) { + if (Array.isArray(info.supportsReasoningEffort) && info.reasoningEffort !== undefined) { + expect(info.supportsReasoningEffort).toContain(info.reasoningEffort) + } + } + }) + }) + + describe("kimi-k3", () => { + it("exposes always-on reasoning with effort allow-list and reasoning preservation", () => { + const info = moonshotModels["kimi-k3"] + expect(info).toBeDefined() + expect(info.maxTokens).toBe(131_072) + expect(info.contextWindow).toBe(1_048_576) + expect(info.supportsImages).toBe(true) + expect(info.supportsPromptCache).toBe(true) + expect(info.supportsReasoningEffort).toEqual(["low", "high", "max"]) + expect(info.reasoningEffort).toBe("max") + expect(info.preserveReasoning).toBe(true) + expect(info.defaultTemperature).toBe(1.0) + expect(info.inputPrice).toBe(3.0) + expect(info.outputPrice).toBe(15.0) + expect(info.cacheWritesPrice).toBe(0) + expect(info.cacheReadsPrice).toBe(0.3) + }) + }) + + describe("defaults", () => { + it("the default model id is a curated registry entry", () => { + expect(moonshotDefaultModelId).toBe("kimi-k2-0905-preview") + expect(moonshotModels[moonshotDefaultModelId]).toBeDefined() + }) + + it("exposes a deterministic default temperature", () => { + expect(MOONSHOT_DEFAULT_TEMPERATURE).toBe(0.6) + }) + }) +}) diff --git a/packages/types/src/__tests__/opencode-go.test.ts b/packages/types/src/__tests__/opencode-go.test.ts index 67f8e50b39..8079fe1bcb 100644 --- a/packages/types/src/__tests__/opencode-go.test.ts +++ b/packages/types/src/__tests__/opencode-go.test.ts @@ -61,6 +61,23 @@ describe("opencode-go registry", () => { it("returns undefined for an unknown model ID", () => { expect(getOpencodeGoModelInfo("not-a-real-go-model")).toBeUndefined() }) + + it("kimi-k3 exposes always-on reasoning with effort allow-list and reasoning preservation", () => { + const info = getOpencodeGoModelInfo("kimi-k3") + expect(info).toBeDefined() + expect(info?.maxTokens).toBe(131_072) + expect(info?.contextWindow).toBe(1_048_576) + expect(info?.supportsReasoningEffort).toEqual(["low", "high", "max"]) + expect(info?.reasoningEffort).toBe("max") + expect(info?.preserveReasoning).toBe(true) + expect(info?.defaultTemperature).toBe(1.0) + expect(info?.supportsPromptCache).toBe(true) + expect(info?.supportsMaxTokens).toBe(true) + expect(info?.supportsImages).toBe(false) + expect(info?.inputPrice).toBe(3.0) + expect(info?.outputPrice).toBe(15.0) + expect(info?.cacheReadsPrice).toBe(0.3) + }) }) describe("OPENCODE_GO_ANTHROPIC_FORMAT_MODELS", () => { From e782967cc84d7d3388f51039455b9911bd2ef70a Mon Sep 17 00:00:00 2001 From: Roomote Date: Fri, 24 Jul 2026 13:22:42 +0000 Subject: [PATCH 3/3] test(types): widen moonshot registry entries to ModelInfo in tests --- packages/types/src/__tests__/moonshot.test.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/types/src/__tests__/moonshot.test.ts b/packages/types/src/__tests__/moonshot.test.ts index 274e0664fb..61cafd3167 100644 --- a/packages/types/src/__tests__/moonshot.test.ts +++ b/packages/types/src/__tests__/moonshot.test.ts @@ -1,9 +1,13 @@ +import type { ModelInfo } from "../model.js" import { MOONSHOT_DEFAULT_TEMPERATURE, moonshotDefaultModelId, moonshotModels } from "../providers/moonshot.js" +const modelEntries: [string, ModelInfo][] = Object.entries(moonshotModels) +const modelInfos: ModelInfo[] = Object.values(moonshotModels) + describe("moonshot registry", () => { describe("moonshotModels registry invariants", () => { it("every entry has a positive maxTokens and contextWindow", () => { - for (const [id, info] of Object.entries(moonshotModels)) { + for (const [id, info] of modelEntries) { expect(info.maxTokens).toBeGreaterThan(0) expect(info.contextWindow).toBeGreaterThan(0) // Sanity: max output must not exceed the context window. @@ -13,14 +17,14 @@ describe("moonshot registry", () => { }) it("every entry declares supportsImages and supportsPromptCache", () => { - for (const info of Object.values(moonshotModels)) { + for (const info of modelInfos) { expect(typeof info.supportsImages).toBe("boolean") expect(typeof info.supportsPromptCache).toBe("boolean") } }) it("models with an array supportsReasoningEffort expose a non-empty allow-list", () => { - for (const info of Object.values(moonshotModels)) { + for (const info of modelInfos) { if (Array.isArray(info.supportsReasoningEffort)) { expect(info.supportsReasoningEffort.length).toBeGreaterThan(0) } @@ -28,7 +32,7 @@ describe("moonshot registry", () => { }) it("every entry declares a reasoningEffort that is covered by its allow-list", () => { - for (const info of Object.values(moonshotModels)) { + for (const info of modelInfos) { if (Array.isArray(info.supportsReasoningEffort) && info.reasoningEffort !== undefined) { expect(info.supportsReasoningEffort).toContain(info.reasoningEffort) }