mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-18 16:34:45 +00:00
fix(kimi): use stable coding model id
This commit is contained in:
@@ -65,6 +65,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Agents/Anthropic: report 1M session context for Claude Opus/Sonnet 4 models even when local model config still advertises 200k, matching model discovery and preventing premature status/UI overflow. Fixes #66766.
|
||||
- Models/OpenRouter: hide missing-auth direct provider rows in `/model status` when they are only duplicated by a nested OpenRouter model id such as `openrouter/google/...`, while preserving explicitly configured direct providers. Fixes #62317.
|
||||
- Models: preserve an explicitly selected provider/model such as `opencode-go/deepseek-v4-pro` when another provider owns the same bare model alias. Fixes #79325.
|
||||
- Kimi Code: use Kimi's stable `kimi-for-coding` API model id in bundled catalog, onboarding, and docs while normalizing legacy `kimi-code` and `k2p5` refs. Fixes #79965.
|
||||
- Volcengine/Kimi: strip provider-unsupported tool schema length and item constraint keywords for direct and coding-plan models so hosted Kimi runs do not reject message tools with `minLength`. Fixes #38817.
|
||||
- DeepSeek: backfill V4 `reasoning_content` replay fields for unowned OpenAI-compatible proxy providers, preventing follow-up request failures outside the bundled DeepSeek and OpenRouter routes. Fixes #79608.
|
||||
|
||||
|
||||
@@ -301,7 +301,7 @@ See [/providers/kilocode](/providers/kilocode) for setup details.
|
||||
| Groq | `groq` | `GROQ_API_KEY` | - |
|
||||
| Hugging Face Inference | `huggingface` | `HUGGINGFACE_HUB_TOKEN` or `HF_TOKEN` | `huggingface/deepseek-ai/DeepSeek-R1` |
|
||||
| Kilo Gateway | `kilocode` | `KILOCODE_API_KEY` | `kilocode/kilo/auto` |
|
||||
| Kimi Coding | `kimi` | `KIMI_API_KEY` or `KIMICODE_API_KEY` | `kimi/kimi-code` |
|
||||
| Kimi Coding | `kimi` | `KIMI_API_KEY` or `KIMICODE_API_KEY` | `kimi/kimi-for-coding` |
|
||||
| MiniMax | `minimax` / `minimax-portal` | `MINIMAX_API_KEY` / `MINIMAX_OAUTH_TOKEN` | `minimax/MiniMax-M2.7` |
|
||||
| Mistral | `mistral` | `MISTRAL_API_KEY` | `mistral/mistral-large-latest` |
|
||||
| Moonshot | `moonshot` | `MOONSHOT_API_KEY` | `moonshot/kimi-k2.6` |
|
||||
@@ -394,18 +394,18 @@ Kimi Coding uses Moonshot AI's Anthropic-compatible endpoint:
|
||||
|
||||
- Provider: `kimi`
|
||||
- Auth: `KIMI_API_KEY`
|
||||
- Example model: `kimi/kimi-code`
|
||||
- Example model: `kimi/kimi-for-coding`
|
||||
|
||||
```json5
|
||||
{
|
||||
env: { KIMI_API_KEY: "sk-..." },
|
||||
agents: {
|
||||
defaults: { model: { primary: "kimi/kimi-code" } },
|
||||
defaults: { model: { primary: "kimi/kimi-for-coding" } },
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Legacy `kimi/k2p5` remains accepted as a compatibility model id.
|
||||
Legacy `kimi/kimi-code` and `kimi/k2p5` remain accepted as compatibility model ids and normalize to Kimi's stable API model id.
|
||||
|
||||
### Volcano Engine (Doubao)
|
||||
|
||||
|
||||
@@ -538,8 +538,8 @@ Interactive custom-provider onboarding infers image input for common vision mode
|
||||
env: { KIMI_API_KEY: "sk-..." },
|
||||
agents: {
|
||||
defaults: {
|
||||
model: { primary: "kimi/kimi-code" },
|
||||
models: { "kimi/kimi-code": { alias: "Kimi Code" } },
|
||||
model: { primary: "kimi/kimi-for-coding" },
|
||||
models: { "kimi/kimi-for-coding": { alias: "Kimi Code" } },
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ title: "Moonshot AI"
|
||||
|
||||
Moonshot provides the Kimi API with OpenAI-compatible endpoints. Configure the
|
||||
provider and set the default model to `moonshot/kimi-k2.6`, or use
|
||||
Kimi Coding with `kimi/kimi-code`.
|
||||
Kimi Coding with `kimi/kimi-for-coding`.
|
||||
|
||||
<Warning>
|
||||
Moonshot and Kimi Coding are **separate providers**. Keys are not interchangeable, endpoints differ, and model refs differ (`moonshot/...` vs `kimi/...`).
|
||||
@@ -185,7 +185,7 @@ Choose your provider and follow the setup steps.
|
||||
**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/...`). Legacy model ref `kimi/k2p5` remains accepted as a compatibility id.
|
||||
Kimi Coding uses a different API key and provider prefix (`kimi/...`) than Moonshot (`moonshot/...`). The stable API model ref is `kimi/kimi-for-coding`; legacy refs `kimi/kimi-code` and `kimi/k2p5` remain accepted and normalize to that API model id.
|
||||
</Note>
|
||||
|
||||
<Steps>
|
||||
@@ -199,7 +199,7 @@ Choose your provider and follow the setup steps.
|
||||
{
|
||||
agents: {
|
||||
defaults: {
|
||||
model: { primary: "kimi/kimi-code" },
|
||||
model: { primary: "kimi/kimi-for-coding" },
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -219,9 +219,9 @@ Choose your provider and follow the setup steps.
|
||||
env: { KIMI_API_KEY: "sk-..." },
|
||||
agents: {
|
||||
defaults: {
|
||||
model: { primary: "kimi/kimi-code" },
|
||||
model: { primary: "kimi/kimi-for-coding" },
|
||||
models: {
|
||||
"kimi/kimi-code": { alias: "Kimi" },
|
||||
"kimi/kimi-for-coding": { alias: "Kimi" },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -2,5 +2,7 @@ export {
|
||||
buildKimiCodingProvider,
|
||||
KIMI_CODING_BASE_URL,
|
||||
KIMI_CODING_DEFAULT_MODEL_ID,
|
||||
KIMI_CODING_LEGACY_MODEL_IDS,
|
||||
normalizeKimiCodingModelId,
|
||||
} from "./provider-catalog.js";
|
||||
export { KIMI_CODING_MODEL_REF, KIMI_MODEL_REF } from "./onboard.js";
|
||||
|
||||
@@ -3,6 +3,23 @@ import { describe, expect, it } from "vitest";
|
||||
import plugin from "./index.js";
|
||||
|
||||
describe("kimi provider plugin", () => {
|
||||
it("normalizes legacy Kimi Code ids to the stable API model id", async () => {
|
||||
const provider = await registerSingleProviderPlugin(plugin);
|
||||
|
||||
expect(
|
||||
provider.normalizeResolvedModel?.({
|
||||
provider: "kimi",
|
||||
modelId: "kimi-code",
|
||||
model: {
|
||||
id: "kimi-code",
|
||||
name: "Kimi Code",
|
||||
provider: "kimi",
|
||||
api: "anthropic-messages",
|
||||
},
|
||||
} as never),
|
||||
).toMatchObject({ id: "kimi-for-coding" });
|
||||
});
|
||||
|
||||
it("uses binary thinking with thinking off by default", async () => {
|
||||
const provider = await registerSingleProviderPlugin(plugin);
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { normalizeProviderId } from "openclaw/plugin-sdk/provider-model-shared";
|
||||
import type { SecretInput } from "openclaw/plugin-sdk/secret-input";
|
||||
import { isRecord, normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { applyKimiCodeConfig, KIMI_CODING_MODEL_REF } from "./onboard.js";
|
||||
import { buildKimiCodingProvider } from "./provider-catalog.js";
|
||||
import { buildKimiCodingProvider, normalizeKimiCodingModelId } from "./provider-catalog.js";
|
||||
import { KIMI_REPLAY_POLICY } from "./replay-policy.js";
|
||||
import { wrapKimiProviderStream } from "./stream.js";
|
||||
|
||||
@@ -96,6 +96,10 @@ export default definePluginEntry({
|
||||
},
|
||||
},
|
||||
buildReplayPolicy: () => KIMI_REPLAY_POLICY,
|
||||
normalizeResolvedModel: ({ model }) => {
|
||||
const normalizedId = normalizeKimiCodingModelId(model.id);
|
||||
return normalizedId === model.id ? undefined : { ...model, id: normalizedId };
|
||||
},
|
||||
resolveThinkingProfile: () => ({
|
||||
levels: [
|
||||
{ id: "off", label: "off" },
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
|
||||
describe("kimi coding onboard", () => {
|
||||
it("keeps the historical Kimi model ref alias pointed at the coding default", () => {
|
||||
expect(KIMI_MODEL_REF).toBe("kimi/kimi-code");
|
||||
expect(KIMI_MODEL_REF).toBe("kimi/kimi-for-coding");
|
||||
expect(KIMI_CODING_MODEL_REF).toBe(KIMI_MODEL_REF);
|
||||
});
|
||||
|
||||
@@ -21,7 +21,7 @@ describe("kimi coding onboard", () => {
|
||||
api: "anthropic-messages",
|
||||
baseUrl: "https://api.kimi.com/coding/",
|
||||
});
|
||||
expect(provider?.models?.map((model) => model.id)).toEqual(["kimi-code"]);
|
||||
expect(provider?.models?.map((model) => model.id)).toEqual(["kimi-for-coding"]);
|
||||
expect(cfg.agents?.defaults?.models?.[KIMI_MODEL_REF]?.alias).toBe("Kimi");
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { buildKimiCodingProvider } from "./provider-catalog.js";
|
||||
import { buildKimiCodingProvider, normalizeKimiCodingModelId } from "./provider-catalog.js";
|
||||
|
||||
describe("kimi provider catalog", () => {
|
||||
it("builds the bundled Kimi coding defaults", () => {
|
||||
@@ -8,6 +8,16 @@ describe("kimi provider catalog", () => {
|
||||
expect(provider.api).toBe("anthropic-messages");
|
||||
expect(provider.baseUrl).toBe("https://api.kimi.com/coding/");
|
||||
expect(provider.headers).toEqual({ "User-Agent": "claude-code/0.1.0" });
|
||||
expect(provider.models.map((model) => model.id)).toEqual(["kimi-code", "k2p5"]);
|
||||
expect(provider.models.map((model) => model.id)).toEqual([
|
||||
"kimi-for-coding",
|
||||
"kimi-code",
|
||||
"k2p5",
|
||||
]);
|
||||
});
|
||||
|
||||
it("normalizes legacy Kimi coding model ids to the stable API model id", () => {
|
||||
expect(normalizeKimiCodingModelId("kimi-code")).toBe("kimi-for-coding");
|
||||
expect(normalizeKimiCodingModelId("k2p5")).toBe("kimi-for-coding");
|
||||
expect(normalizeKimiCodingModelId("kimi-for-coding")).toBe("kimi-for-coding");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import type { ModelProviderConfig } from "openclaw/plugin-sdk/provider-model-shared";
|
||||
import type {
|
||||
ModelDefinitionConfig,
|
||||
ModelProviderConfig,
|
||||
} from "openclaw/plugin-sdk/provider-model-shared";
|
||||
|
||||
const KIMI_BASE_URL = "https://api.kimi.com/coding/";
|
||||
const KIMI_CODING_USER_AGENT = "claude-code/0.1.0";
|
||||
const KIMI_DEFAULT_MODEL_ID = "kimi-code";
|
||||
const KIMI_LEGACY_MODEL_ID = "k2p5";
|
||||
const KIMI_DEFAULT_MODEL_ID = "kimi-for-coding";
|
||||
const KIMI_LEGACY_MODEL_IDS = ["kimi-code", "k2p5"] as const;
|
||||
const KIMI_CODING_DEFAULT_CONTEXT_WINDOW = 262144;
|
||||
const KIMI_CODING_DEFAULT_MAX_TOKENS = 32768;
|
||||
const KIMI_CODING_DEFAULT_COST = {
|
||||
@@ -12,6 +15,7 @@ const KIMI_CODING_DEFAULT_COST = {
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
};
|
||||
const KIMI_CODING_INPUT = ["text", "image"] satisfies NonNullable<ModelDefinitionConfig["input"]>;
|
||||
|
||||
export function buildKimiCodingProvider(): ModelProviderConfig {
|
||||
return {
|
||||
@@ -25,23 +29,30 @@ export function buildKimiCodingProvider(): ModelProviderConfig {
|
||||
id: KIMI_DEFAULT_MODEL_ID,
|
||||
name: "Kimi Code",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
input: [...KIMI_CODING_INPUT],
|
||||
cost: KIMI_CODING_DEFAULT_COST,
|
||||
contextWindow: KIMI_CODING_DEFAULT_CONTEXT_WINDOW,
|
||||
maxTokens: KIMI_CODING_DEFAULT_MAX_TOKENS,
|
||||
},
|
||||
{
|
||||
id: KIMI_LEGACY_MODEL_ID,
|
||||
name: "Kimi Code (legacy model id)",
|
||||
...KIMI_LEGACY_MODEL_IDS.map((id) => ({
|
||||
id,
|
||||
name: `Kimi Code (legacy ${id})`,
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
input: [...KIMI_CODING_INPUT],
|
||||
cost: KIMI_CODING_DEFAULT_COST,
|
||||
contextWindow: KIMI_CODING_DEFAULT_CONTEXT_WINDOW,
|
||||
maxTokens: KIMI_CODING_DEFAULT_MAX_TOKENS,
|
||||
},
|
||||
})),
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
export function normalizeKimiCodingModelId(modelId: string): string {
|
||||
return KIMI_LEGACY_MODEL_IDS.includes(modelId as (typeof KIMI_LEGACY_MODEL_IDS)[number])
|
||||
? KIMI_DEFAULT_MODEL_ID
|
||||
: modelId;
|
||||
}
|
||||
|
||||
export const KIMI_CODING_BASE_URL = KIMI_BASE_URL;
|
||||
export const KIMI_CODING_DEFAULT_MODEL_ID = KIMI_DEFAULT_MODEL_ID;
|
||||
export const KIMI_CODING_LEGACY_MODEL_IDS = KIMI_LEGACY_MODEL_IDS;
|
||||
|
||||
Reference in New Issue
Block a user