Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/types/src/__tests__/lite-llm.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
72 changes: 72 additions & 0 deletions packages/types/src/__tests__/moonshot.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
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 modelEntries) {
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 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 modelInfos) {
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 modelInfos) {
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)
})
})
})
18 changes: 18 additions & 0 deletions packages/types/src/__tests__/opencode-go.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ describe("opencode-go registry", () => {
"glm-5",
"glm-5.1",
"glm-5.2",
"kimi-k3",
"kimi-k2.5",
Comment thread
zoomote[bot] marked this conversation as resolved.
"kimi-k2.6",
"mimo-v2.5",
Expand Down Expand Up @@ -60,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", () => {
Expand Down
3 changes: 3 additions & 0 deletions packages/types/src/providers/lite-llm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
15 changes: 15 additions & 0 deletions packages/types/src/providers/moonshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,21 @@ export type MoonshotModelId = keyof typeof moonshotModels
export const moonshotDefaultModelId: MoonshotModelId = "kimi-k2-0905-preview"

export const moonshotModels = {
"kimi-k3": {
Comment thread
zoomote[bot] marked this conversation as resolved.
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,
Expand Down
17 changes: 17 additions & 0 deletions packages/types/src/providers/opencode-go.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,23 @@ export const opencodeGoModels: Record<string, ModelInfo> = {
},

// --- 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,
Expand Down
Loading