mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
fix(kimi): refresh K3 catalog and add 256K variant (#113918)
* fix(kimi): retire k3[1m], add k3-256k, k3 now 1M * fix(kimi): integrate K3 256K catalog split * docs(kimi): correct K3 thinking-level ladder in thinking.md
This commit is contained in:
committed by
GitHub
parent
bb12c4b78c
commit
48addb3d57
@@ -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)
|
||||
|
||||
|
||||
@@ -184,7 +184,7 @@ onboarding.
|
||||
**Best for:** code-focused tasks via the Kimi Coding endpoint.
|
||||
|
||||
<Note>
|
||||
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`.
|
||||
</Note>
|
||||
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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",
|
||||
});
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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<AssistantMessage> {
|
||||
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" });
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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,
|
||||
})),
|
||||
],
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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 = [
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user