diff --git a/docs/concepts/model-providers.md b/docs/concepts/model-providers.md index 3640c9dda625..0f2ae0229dc2 100644 --- a/docs/concepts/model-providers.md +++ b/docs/concepts/model-providers.md @@ -411,7 +411,7 @@ Kimi Coding uses Moonshot AI's Anthropic-compatible endpoint: - Provider: `kimi` - Auth: `KIMI_API_KEY` -- Kimi K3: `kimi/k3` (1,048,576-token context, 131,072-token max output) +- Kimi K3: `kimi/k3` (up to 1M, tier-gated) or `kimi/k3-256k` (256K, lower quota use) - Kimi Code: `kimi/kimi-for-coding` - Kimi Code HighSpeed: `kimi/kimi-for-coding-highspeed` @@ -429,8 +429,8 @@ Kimi K3 uses adaptive thinking. `--thinking minimal|low` selects low effort, selects max effort. Catalog pricing is $3/MTok input, $15/MTok output, and $0.30/MTok cache reads. Legacy `kimi/kimi-code` and `kimi/k2p5` remain accepted as compatibility model ids and normalize to Kimi's stable API model -id; the previously published `kimi/k3[1m]` ref remains available for existing -configs. +id; the previously published `kimi/k3[1m]` ref normalizes to `kimi/k3` for +existing configs. ### Volcano Engine (Doubao) diff --git a/docs/providers/moonshot.md b/docs/providers/moonshot.md index 79633a39d118..3e979b5800bf 100644 --- a/docs/providers/moonshot.md +++ b/docs/providers/moonshot.md @@ -184,7 +184,7 @@ onboarding. **Best for:** code-focused tasks via the Kimi Coding endpoint. - Kimi Coding uses a different API key and provider prefix (`kimi/...`) than Moonshot (`moonshot/...`). Current refs are `kimi/k3`, `kimi/kimi-for-coding`, and `kimi/kimi-for-coding-highspeed`. Legacy refs `kimi/kimi-code` and `kimi/k2p5` remain accepted and normalize to `kimi/kimi-for-coding`; the previously published `kimi/k3[1m]` ref remains available for existing configs. + Kimi Coding uses a different API key and provider prefix (`kimi/...`) than Moonshot (`moonshot/...`). Current refs are `kimi/k3` for up to 1M context (tier-gated), `kimi/k3-256k` for 256K context with lower quota use, `kimi/kimi-for-coding`, and `kimi/kimi-for-coding-highspeed`. Legacy refs `kimi/kimi-code` and `kimi/k2p5` normalize to `kimi/kimi-for-coding`; legacy `kimi/k3[1m]` normalizes to `kimi/k3`. The coding service accepts both OpenAI-compatible @@ -197,6 +197,7 @@ onboarding. | Model ref | Name | Reasoning | Input | Context | Max output | | --- | --- | --- | --- | --- | --- | | `kimi/k3` | Kimi K3 | adaptive; low / high / max effort | text, image | 1,048,576 | 131,072 | + | `kimi/k3-256k` | Kimi K3 (256k) | adaptive; low / high / max effort | text, image | 262,144 | 131,072 | The K3 catalog estimates $3/MTok input, $15/MTok output, $0.30/MTok cache reads, and $0/MTok cache writes. The catalog reports K3's maximum @@ -322,7 +323,8 @@ Config lives under `plugins.entries.moonshot.config.webSearch`: Its Anthropic-compatible endpoint receives `thinking.type: "disabled"` for off. Every enabled level uses adaptive thinking; minimal/low maps to low effort, medium/high/adaptive maps to high effort, and xhigh/max maps to max - effort. This also applies to the compatibility ref `kimi/k3[1m]`. + effort. This applies to both `kimi/k3` and `kimi/k3-256k`. Legacy + `kimi/k3[1m]` normalizes to `kimi/k3`. Moonshot API K3 supports `auto`, `none`, `required`, and pinned tool choices, so OpenClaw preserves the requested `tool_choice`. For multi-turn tool use, OpenClaw preserves the assistant reasoning content required by Moonshot's diff --git a/docs/tools/thinking.md b/docs/tools/thinking.md index da416313afa8..2751047a1387 100644 --- a/docs/tools/thinking.md +++ b/docs/tools/thinking.md @@ -38,7 +38,7 @@ title: "Thinking levels" - Google Gemini maps `/think adaptive` to Gemini's provider-owned dynamic thinking. Gemini 3 requests omit a fixed `thinkingLevel`, while Gemini 2.5 requests send `thinkingBudget: -1`; fixed levels still map to the closest Gemini `thinkingLevel` or budget for that model family. - MiniMax M2.x (`minimax/MiniMax-M2*`) on the Anthropic-compatible streaming path defaults to `thinking: { type: "disabled" }` unless you explicitly set thinking in model params or request params. This avoids leaked `reasoning_content` deltas from M2.x's non-native Anthropic stream format. MiniMax-M3 (and M3.x) is exempt: M3 emits proper Anthropic thinking blocks and returns empty content when thinking is disabled, so OpenClaw keeps M3 on the provider's omitted/adaptive thinking path. - Z.AI (`zai/*`) is binary (`on`/`off`) for most GLM models. GLM-5.2 is the exception: it exposes `/think off|low|high|max`, maps `low` and `high` to Z.AI `reasoning_effort: "high"`, and maps `max` to `reasoning_effort: "max"`. - - Moonshot API Kimi K3 (`moonshot/kimi-k3`) always thinks at `max`, sends `reasoning_effort: "max"`, omits the K2 `thinking` field and fixed sampling overrides, and preserves K3-supported tool choices. Kimi Code K3 (`kimi/k3` and `kimi/k3[1m]`) exposes `/think off|max`: off sends `thinking.type: "disabled"`, while max sends adaptive thinking with max effort. Current Kimi Code refs also include `kimi/kimi-for-coding` and `kimi/kimi-for-coding-highspeed`. Kimi K2.7 Code (`moonshot/kimi-k2.7-code` and `moonshot/kimi-k2.7-code-highspeed`) always thinks, exposes only `on`, and omits both outbound `thinking` and `reasoning_effort`. Other `moonshot/*` models map `/think off` to `thinking: { type: "disabled" }` and any non-`off` level to `thinking: { type: "enabled" }`. When K2 thinking is enabled, Moonshot only accepts `tool_choice` `auto|none`; OpenClaw normalizes incompatible values to `auto`. + - Moonshot API Kimi K3 (`moonshot/kimi-k3`) always thinks at `max`, sends `reasoning_effort: "max"`, omits the K2 `thinking` field and fixed sampling overrides, and preserves K3-supported tool choices. Kimi Code K3 (`kimi/k3` and `kimi/k3-256k`) exposes the full `/think` ladder with a `high` default: `off` sends `thinking.type: "disabled"`, `minimal`/`low` map to low effort, `medium`/`high`/`adaptive` to high effort, and `xhigh`/`max` to max effort. Current Kimi Code refs also include `kimi/kimi-for-coding` and `kimi/kimi-for-coding-highspeed`. Kimi K2.7 Code (`moonshot/kimi-k2.7-code` and `moonshot/kimi-k2.7-code-highspeed`) always thinks, exposes only `on`, and omits both outbound `thinking` and `reasoning_effort`. Other `moonshot/*` models map `/think off` to `thinking: { type: "disabled" }` and any non-`off` level to `thinking: { type: "enabled" }`. When K2 thinking is enabled, Moonshot only accepts `tool_choice` `auto|none`; OpenClaw normalizes incompatible values to `auto`. ## Resolution order diff --git a/extensions/kimi-coding/implicit-provider.test.ts b/extensions/kimi-coding/implicit-provider.test.ts index 00c1f0cc15e9..b36cb7a600a3 100644 --- a/extensions/kimi-coding/implicit-provider.test.ts +++ b/extensions/kimi-coding/implicit-provider.test.ts @@ -91,6 +91,24 @@ describe("Kimi implicit provider (#22409)", () => { contextWindow: 1048576, maxTokens: 131072, }, + { + id: "k3-256k", + name: "Kimi K3 (256k)", + reasoning: true, + thinkingLevelMap: { + off: null, + minimal: "low", + low: "low", + medium: "high", + high: "high", + xhigh: "max", + max: "max", + }, + input: ["text", "image"], + cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 0 }, + contextWindow: 262144, + maxTokens: 131072, + }, ], apiKey: "test-key", }); diff --git a/extensions/kimi-coding/index.test.ts b/extensions/kimi-coding/index.test.ts index d1e1df39e18a..214592b30fee 100644 --- a/extensions/kimi-coding/index.test.ts +++ b/extensions/kimi-coding/index.test.ts @@ -48,7 +48,7 @@ describe("kimi provider plugin", () => { }); }); - it.each(["k3", "k3[1m]"])("exposes %s adaptive thinking levels", async (modelId) => { + it.each(["k3", "k3-256k"])("exposes %s adaptive thinking levels", async (modelId) => { const provider = await registerSingleProviderPlugin(plugin); expect( diff --git a/extensions/kimi-coding/kimi-coding.live.test.ts b/extensions/kimi-coding/kimi-coding.live.test.ts index 876a7e1126d6..a8626c679ef4 100644 --- a/extensions/kimi-coding/kimi-coding.live.test.ts +++ b/extensions/kimi-coding/kimi-coding.live.test.ts @@ -33,7 +33,7 @@ async function collectDoneMessage( return doneMessage; } -function resolveModel(modelId: "k3" | "k3[1m]"): Model<"anthropic-messages"> { +function resolveModel(modelId: "k3" | "k3-256k"): Model<"anthropic-messages"> { const provider = buildKimiCodingProvider(); const normalizedModelId = normalizeKimiCodingModelId(modelId); const definition = provider.models.find((model) => model.id === normalizedModelId); @@ -62,7 +62,7 @@ function countContentChars(message: AssistantMessage, type: "text" | "thinking") } async function runReasoningScenario(params: { - modelId: "k3" | "k3[1m]"; + modelId: "k3" | "k3-256k"; thinkingLevel: "off" | "low" | "adaptive" | "max"; }): Promise { const registered = await registerSingleProviderPlugin(plugin); @@ -99,7 +99,7 @@ async function runReasoningScenario(params: { } describeLive("Kimi Code K3 reasoning live", () => { - it.each(["k3", "k3[1m]"] as const)( + it.each(["k3", "k3-256k"] as const)( "%s honors off and max reasoning", async (modelId) => { const off = await runReasoningScenario({ modelId, thinkingLevel: "off" }); diff --git a/extensions/kimi-coding/provider-catalog.test.ts b/extensions/kimi-coding/provider-catalog.test.ts index 61fca4118ebe..2a6fd27f8662 100644 --- a/extensions/kimi-coding/provider-catalog.test.ts +++ b/extensions/kimi-coding/provider-catalog.test.ts @@ -14,6 +14,7 @@ describe("kimi provider catalog", () => { "kimi-for-coding", "kimi-for-coding-highspeed", "k3", + "k3-256k", ]); expect(provider.models.find((model) => model.id === "k3")).toMatchObject({ name: "Kimi K3", @@ -31,6 +32,22 @@ describe("kimi provider catalog", () => { contextWindow: 1_048_576, maxTokens: 131_072, }); + expect(provider.models.find((model) => model.id === "k3-256k")).toMatchObject({ + name: "Kimi K3 (256k)", + reasoning: true, + thinkingLevelMap: { + off: null, + minimal: "low", + low: "low", + medium: "high", + high: "high", + xhigh: "max", + max: "max", + }, + cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 0 }, + contextWindow: 262_144, + maxTokens: 131_072, + }); expect(provider.models.find((model) => model.id === "kimi-for-coding-highspeed")).toMatchObject( { name: "Kimi K2.7 Code HighSpeed", @@ -51,7 +68,7 @@ describe("kimi provider catalog", () => { "kimi-for-coding-highspeed", ); expect(isKimiK3ModelId("k3")).toBe(true); - expect(isKimiK3ModelId("k3[1m]")).toBe(true); + expect(isKimiK3ModelId("K3-256K")).toBe(true); expect(isKimiK3ModelId("kimi-for-coding")).toBe(false); }); }); diff --git a/extensions/kimi-coding/provider-catalog.ts b/extensions/kimi-coding/provider-catalog.ts index b68b7b474319..8e32549ebeda 100644 --- a/extensions/kimi-coding/provider-catalog.ts +++ b/extensions/kimi-coding/provider-catalog.ts @@ -24,7 +24,8 @@ const KIMI_K3_COST = { cacheRead: 0.3, cacheWrite: 0, }; -// Catalog the model maximum; Kimi membership entitlements may enforce a lower live limit. +// k3 serves up to 1M context, tier-gated server-side; k3-256k is the cheaper 256K variant. +// Legacy k3[1m] was retired upstream and normalizes to k3 for shipped configurations. const KIMI_K3_CONTEXT_WINDOW = 1_048_576; const KIMI_K3_MAX_TOKENS = 131_072; const KIMI_K3_THINKING_LEVEL_MAP = { @@ -66,12 +67,12 @@ export function buildKimiCodingProvider(): ModelProviderConfig { }, ...KIMI_K3_MODEL_IDS.map((id) => ({ id, - name: "Kimi K3", + name: id === "k3" ? "Kimi K3" : "Kimi K3 (256k)", reasoning: true, thinkingLevelMap: { ...KIMI_K3_THINKING_LEVEL_MAP }, input: [...KIMI_CODING_INPUT], cost: KIMI_K3_COST, - contextWindow: KIMI_K3_CONTEXT_WINDOW, + contextWindow: id === "k3" ? KIMI_K3_CONTEXT_WINDOW : KIMI_CODING_DEFAULT_CONTEXT_WINDOW, maxTokens: KIMI_K3_MAX_TOKENS, })), ], diff --git a/extensions/kimi-coding/provider-policy-api.test.ts b/extensions/kimi-coding/provider-policy-api.test.ts index 9090e4916e89..f860933e9ce9 100644 --- a/extensions/kimi-coding/provider-policy-api.test.ts +++ b/extensions/kimi-coding/provider-policy-api.test.ts @@ -2,7 +2,7 @@ import { describe, expect, it } from "vitest"; import { isKimiK3ModelId, resolveThinkingProfile } from "./provider-policy-api.js"; describe("Kimi Code provider policy", () => { - it.each(["k3", "k3[1m]"])("exposes adaptive K3 thinking levels for %s", (modelId) => { + it.each(["k3", "k3-256k"])("exposes adaptive K3 thinking levels for %s", (modelId) => { expect(resolveThinkingProfile({ provider: "kimi", modelId })).toEqual({ levels: [ { id: "off" }, @@ -31,7 +31,7 @@ describe("Kimi Code provider policy", () => { it("recognizes K3 wire ids case-insensitively", () => { expect(isKimiK3ModelId("K3")).toBe(true); - expect(isKimiK3ModelId("k3[1M]")).toBe(true); + expect(isKimiK3ModelId("K3-256K")).toBe(true); expect(isKimiK3ModelId("kimi-for-coding")).toBe(false); }); }); diff --git a/extensions/kimi-coding/provider-policy-api.ts b/extensions/kimi-coding/provider-policy-api.ts index ee4e697218a9..f5eb47da1868 100644 --- a/extensions/kimi-coding/provider-policy-api.ts +++ b/extensions/kimi-coding/provider-policy-api.ts @@ -4,7 +4,7 @@ import type { ProviderThinkingProfile, } from "openclaw/plugin-sdk/plugin-entry"; -export const KIMI_K3_MODEL_IDS = ["k3"] as const; +export const KIMI_K3_MODEL_IDS = ["k3", "k3-256k"] as const; const KIMI_K3_LEGACY_MODEL_IDS = ["k3[1m]"] as const; const KIMI_K3_THINKING_LEVELS = [ diff --git a/extensions/kimi-coding/stream.test.ts b/extensions/kimi-coding/stream.test.ts index a56132a5507b..ee38fd297c4b 100644 --- a/extensions/kimi-coding/stream.test.ts +++ b/extensions/kimi-coding/stream.test.ts @@ -274,7 +274,7 @@ describe("kimi tool-call markup wrapper", () => { }); }); - it.each(["k3", "k3[1m]"])("defaults %s to adaptive high thinking", (modelId) => { + it.each(["k3", "k3-256k"])("defaults %s to adaptive high thinking", (modelId) => { const { streamFn: baseStreamFn, getCapturedModel, @@ -346,8 +346,8 @@ describe("kimi tool-call markup wrapper", () => { it.each([ { modelId: "k3", extraParams: undefined, thinkingLevel: "off" }, { modelId: "k3", extraParams: { thinking: "off" }, thinkingLevel: "max" }, - { modelId: "k3[1m]", extraParams: undefined, thinkingLevel: "off" }, - { modelId: "k3[1m]", extraParams: { thinking: "off" }, thinkingLevel: "max" }, + { modelId: "k3-256k", extraParams: undefined, thinkingLevel: "off" }, + { modelId: "k3-256k", extraParams: { thinking: "off" }, thinkingLevel: "max" }, ] as const)("honors $modelId thinking off", ({ modelId, extraParams, thinkingLevel }) => { const { streamFn: baseStreamFn, getCapturedPayload } = createPayloadCapturingStream({ thinking: { type: "adaptive" }, @@ -381,7 +381,7 @@ describe("kimi tool-call markup wrapper", () => { }); }); - it.each(["k3", "k3[1m]"])( + it.each(["k3", "k3-256k"])( "lets explicit %s thinking enablement override session off", (modelId) => { const { streamFn: baseStreamFn, getCapturedPayload } = createPayloadCapturingStream();