fix(providers): refresh stale onboarding defaults (#113870)

* fix(providers): refresh onboarding defaults

* fix(moonshot): import manifest default from catalog
This commit is contained in:
Peter Steinberger
2026-07-25 14:44:47 -07:00
committed by GitHub
parent ce5ab8adb8
commit d5dcc3fb19
29 changed files with 183 additions and 108 deletions

View File

@@ -17,7 +17,7 @@ read_when:
| Direct CLI flag | `--cerebras-api-key <key>` |
| API | OpenAI-compatible (`openai-completions`) |
| Base URL | `https://api.cerebras.ai/v1` |
| Default model | `cerebras/zai-glm-4.7` |
| Default model | `cerebras/gpt-oss-120b` |
## Install plugin
@@ -75,11 +75,11 @@ openclaw onboard --non-interactive \
All three models have a 131,072-token context window and a 40,960-token max output.
| Model ref | Name | Reasoning | Notes |
| ----------------------- | ------------ | --------- | ---------------------------------------- |
| `cerebras/zai-glm-4.7` | Z.ai GLM 4.7 | yes | Default model; scheduled for deprecation |
| `cerebras/gpt-oss-120b` | GPT OSS 120B | yes | Production reasoning model |
| `cerebras/gemma-4-31b` | Gemma 4 31B | yes | Text-and-image input; text output |
| Model ref | Name | Reasoning | Notes |
| ----------------------- | ------------ | --------- | ----------------------------------------- |
| `cerebras/zai-glm-4.7` | Z.ai GLM 4.7 | yes | Scheduled for deprecation August 17, 2026 |
| `cerebras/gpt-oss-120b` | GPT OSS 120B | yes | Default production reasoning model |
| `cerebras/gemma-4-31b` | Gemma 4 31B | yes | Preview; text-and-image input |
## Manual config
@@ -90,7 +90,7 @@ Most setups only need the API key. Use explicit `models.providers.cerebras` conf
env: { CEREBRAS_API_KEY: "csk-..." },
agents: {
defaults: {
model: { primary: "cerebras/zai-glm-4.7" },
model: { primary: "cerebras/gpt-oss-120b" },
},
},
models: {

View File

@@ -7,19 +7,19 @@ read_when:
- You are debugging Kimi thinking-off behavior on Fireworks
---
[Fireworks](https://fireworks.ai) exposes open-weight and routed models through an OpenAI-compatible API. Install the official Fireworks provider plugin to use two pre-cataloged Kimi models and any Fireworks model or router id at runtime.
[Fireworks](https://fireworks.ai) exposes open-weight and routed models through an OpenAI-compatible API. Install the official Fireworks provider plugin to use the current Fire Pass GLM router, two pre-cataloged Kimi models, and any Fireworks model or router id at runtime.
| Property | Value |
| --------------- | ------------------------------------------------------ |
| Provider id | `fireworks` (alias: `fireworks-ai`) |
| Package | `@openclaw/fireworks-provider` |
| Auth env var | `FIREWORKS_API_KEY` |
| Onboarding flag | `--auth-choice fireworks-api-key` |
| Direct CLI flag | `--fireworks-api-key <key>` |
| API | OpenAI-compatible (`openai-completions`) |
| Base URL | `https://api.fireworks.ai/inference/v1` |
| Default model | `fireworks/accounts/fireworks/routers/kimi-k2p6-turbo` |
| Default alias | `Kimi K2.6 Turbo` |
| Property | Value |
| --------------- | --------------------------------------------------- |
| Provider id | `fireworks` (alias: `fireworks-ai`) |
| Package | `@openclaw/fireworks-provider` |
| Auth env var | `FIREWORKS_API_KEY` |
| Onboarding flag | `--auth-choice fireworks-api-key` |
| Direct CLI flag | `--fireworks-api-key <key>` |
| API | OpenAI-compatible (`openai-completions`) |
| Base URL | `https://api.fireworks.ai/inference/v1` |
| Default model | `fireworks/accounts/fireworks/routers/glm-5p2-fast` |
| Default alias | `GLM 5.2 Fast` |
## Getting started
@@ -48,7 +48,7 @@ export FIREWORKS_API_KEY=fw-...
</CodeGroup>
Onboarding stores the key against the `fireworks` provider in your auth profiles and sets the **Fire Pass** Kimi K2.6 Turbo router as the default model.
Onboarding stores the key against the `fireworks` provider in your auth profiles and sets Fireworks' current [Fire Pass](https://docs.fireworks.ai/firepass) GLM 5.2 Fast router as the default model.
</Step>
<Step title="Verify the model is available">
@@ -56,7 +56,7 @@ export FIREWORKS_API_KEY=fw-...
openclaw models list --provider fireworks
```
The list should include `Kimi K2.6` and `Kimi K2.6 Turbo (Fire Pass)`. If `FIREWORKS_API_KEY` is unresolved, `openclaw models status --json` reports the missing credential under `auth.unusableProfiles`.
The list should include `GLM 5.2 Fast`, `Kimi K2.6`, and `Kimi K2.6 Fast`. If `FIREWORKS_API_KEY` is unresolved, `openclaw models status --json` reports the missing credential under `auth.unusableProfiles`.
</Step>
</Steps>
@@ -76,10 +76,11 @@ openclaw onboard --non-interactive \
## Built-in catalog
| Model ref | Name | Input | Context | Max output | Thinking |
| ------------------------------------------------------ | -------------- | ------------ | ------- | ---------- | -------------------- |
| `fireworks/accounts/fireworks/models/kimi-k2p6` | Kimi K2.6 | text + image | 262,144 | 262,144 | Forced off |
| `fireworks/accounts/fireworks/routers/kimi-k2p6-turbo` | Kimi K2.6 Fast | text + image | 262,144 | 256,000 | Forced off (default) |
| Model ref | Name | Input | Context | Max output | Thinking |
| ------------------------------------------------------ | -------------- | ------------ | ------- | ---------- | ------------ |
| `fireworks/accounts/fireworks/routers/glm-5p2-fast` | GLM 5.2 Fast | text + image | 256,000 | 256,000 | On (default) |
| `fireworks/accounts/fireworks/models/kimi-k2p6` | Kimi K2.6 | text + image | 262,144 | 262,144 | Forced off |
| `fireworks/accounts/fireworks/routers/kimi-k2p6-turbo` | Kimi K2.6 Fast | text + image | 262,144 | 256,000 | Forced off |
<Note>
OpenClaw pins all Fireworks Kimi models to `thinking: off` because Kimi on Fireworks can leak chain-of-thought into the visible reply unless the request explicitly disables thinking. Routing the same model through [Moonshot](/providers/moonshot) directly preserves Kimi reasoning output. See [thinking modes](/tools/thinking) for switching between providers.
@@ -87,7 +88,7 @@ openclaw onboard --non-interactive \
## Custom Fireworks model ids
OpenClaw accepts any Fireworks model or router id at runtime. Use the exact id shown by Fireworks and prefix it with `fireworks/`. Dynamic resolution clones the Fire Pass template (text + image input, OpenAI-compatible API, default cost zero) and disables thinking automatically when the id matches the Kimi pattern. GLM dynamic ids are marked text-only unless you configure a custom model entry with image input.
OpenClaw accepts any Fireworks model or router id at runtime. Use the exact id shown by Fireworks and prefix it with `fireworks/`. Dynamic resolution clones the Fire Pass template (text + image input and the OpenAI-compatible API) and disables thinking automatically when the id matches the Kimi pattern. GLM dynamic ids are marked text-only unless you configure a custom model entry with image input.
```json5
{

View File

@@ -7,9 +7,9 @@ read_when:
title: "Moonshot AI"
---
Moonshot provides the Kimi API with OpenAI-compatible endpoints. Select
`moonshot/kimi-k3` for Kimi K3, keep the onboarding default
`moonshot/kimi-k2.6`, or use `kimi/kimi-for-coding` for Kimi Coding.
Moonshot provides the Kimi API with OpenAI-compatible endpoints. Fresh Moonshot
onboarding selects `moonshot/kimi-k3`; use `kimi/kimi-for-coding` for the
separate Kimi Coding provider.
<Warning>
Moonshot and Kimi Coding are **separate providers**, each shipped as a separate external plugin. Keys are not interchangeable, endpoints differ, and model refs differ (`moonshot/...` vs `kimi/...`).
@@ -39,7 +39,7 @@ overrides (`temperature`, `top_p`, `n`, `presence_penalty`, and
`frequency_penalty`) that K3 fixes to provider defaults. Kimi K2.7 Code also
always uses native thinking but requires both `thinking` and
`reasoning_effort` to be omitted; the HighSpeed variant uses the same contract.
Kimi K2.6 remains the onboarding default.
Kimi K3 is the onboarding default.
See Moonshot's [Kimi K3 quickstart](https://platform.kimi.ai/docs/guide/kimi-k3-quickstart).
## Getting started
@@ -75,9 +75,8 @@ onboarding.
openclaw onboard --auth-choice moonshot-api-key-cn
```
</Step>
<Step title="Set Kimi K3 as the default model">
Onboarding keeps Kimi K2.6 as the initial default. Switch explicitly
when you want Kimi K3:
<Step title="Confirm the Kimi K3 default">
Fresh onboarding selects Kimi K3. Existing installations can switch explicitly:
```bash
openclaw models set moonshot/kimi-k3
@@ -398,7 +397,7 @@ Config lives under `plugins.entries.moonshot.config.webSearch`:
provider id pointed at the same native Moonshot host inherits the same
streaming-usage behavior.
With the catalog K2.6 pricing, streamed usage that includes input, output,
With the catalog K3 pricing, streamed usage that includes input, output,
and cache-read tokens is also converted into local estimated USD cost for
`/status`, `/usage full`, `/usage cost`, and transcript-backed session
accounting.

View File

@@ -95,7 +95,7 @@ You can also run `openclaw configure` and pick **Model/auth provider > Venice AI
| Model ID | Name | Context | Notes |
| -------------------------------------- | --------------------------- | ------- | --------------------------- |
| `zai-org-glm-5-2` | GLM 5.2 | 1M | Recommended, coding |
| `zai-org-glm-4.7` | GLM 4.7 | 198k | Venice default |
| `zai-org-glm-4.7` | GLM 4.7 | 198k | Private reasoning |
| `venice-uncensored-1-2` | Venice Uncensored 1.2 | 128k | Most uncensored, vision |
| `google-gemma-4-31b-it` | Google Gemma 4 31B Instruct | 256k | Recommended, vision |
| `kimi-k2-6` | Kimi K2.6 | 256k | Recommended, coding, vision |

View File

@@ -82,8 +82,8 @@ openclaw plugins install @openclaw/zai-provider
| Onboarding choice | Base URL | Default model |
| ------------------- | --------------------------------------------- | ------------- |
| `zai-global` | `https://api.z.ai/api/paas/v4` | `glm-5.1` |
| `zai-cn` | `https://open.bigmodel.cn/api/paas/v4` | `glm-5.1` |
| `zai-global` | `https://api.z.ai/api/paas/v4` | `glm-5.2` |
| `zai-cn` | `https://open.bigmodel.cn/api/paas/v4` | `glm-5.2` |
| `zai-coding-global` | `https://api.z.ai/api/coding/paas/v4` | `glm-5.2` |
| `zai-coding-cn` | `https://open.bigmodel.cn/api/coding/paas/v4` | `glm-5.2` |
@@ -167,7 +167,7 @@ The manifest-backed catalog currently includes:
| Model ref | Notes |
| ------------------ | ------------------------------------------------- |
| `zai/glm-5.2` | Coding Plan default; 1M context |
| `zai/glm-5.2` | Default; 1M context |
| `zai/glm-5-turbo` | OpenClaw-optimized text model; 200K context |
| `zai/glm-5v-turbo` | Multimodal coding model; 200K context |
| `zai/glm-5.1` | Deprecated; hidden unless configured; use GLM-5.2 |
@@ -182,8 +182,8 @@ GLM models are available as `zai/<model>` (example: `zai/glm-5.2`).
</Tip>
<Note>
Coding Plan setup defaults to `zai/glm-5.2`; general API setup keeps
`zai/glm-5.1`. On the Coding Plan endpoints, auto-detection falls back to
All fresh Z.AI setup paths default to `zai/glm-5.2`. On the Coding Plan endpoints,
auto-detection falls back to
`glm-5.1` and then `glm-4.7` when the key/plan does not expose GLM-5.2. GLM
versions and availability can change; run `openclaw models list --all --provider zai`
to see the catalog known to your installed version.

View File

@@ -14,7 +14,7 @@ describe("Cerebras onboarding", () => {
CEREBRAS_DEFAULT_MODEL_REF,
);
expect(config.agents?.defaults?.models).toEqual({
[CEREBRAS_DEFAULT_MODEL_REF]: { alias: "Cerebras GLM 4.7" },
[CEREBRAS_DEFAULT_MODEL_REF]: { alias: "Cerebras GPT OSS 120B" },
});
});
});

View File

@@ -22,7 +22,7 @@ const cerebrasPresetAppliers = createModelCatalogPresetAppliers({
api: "openai-completions",
baseUrl: CEREBRAS_BASE_URL,
catalogModels: CEREBRAS_MODEL_CATALOG.map(buildCerebrasModelDefinition),
aliases: [{ modelRef: CEREBRAS_DEFAULT_MODEL_REF, alias: "Cerebras GLM 4.7" }],
aliases: [{ modelRef: CEREBRAS_DEFAULT_MODEL_REF, alias: "Cerebras GPT OSS 120B" }],
}),
});

View File

@@ -23,7 +23,7 @@
"cerebras": {
"baseUrl": "https://api.cerebras.ai/v1",
"api": "openai-completions",
"defaultModel": "zai-glm-4.7",
"defaultModel": "gpt-oss-120b",
"models": [
{
"id": "zai-glm-4.7",

View File

@@ -19,6 +19,7 @@ import {
import { resolveThinkingProfile } from "./provider-policy-api.js";
const FIREWORKS_KIMI_K2_6_MODEL_ID = "accounts/fireworks/models/kimi-k2p6";
const FIREWORKS_KIMI_K2_6_TURBO_MODEL_ID = "accounts/fireworks/routers/kimi-k2p6-turbo";
function createFireworksDefaultRuntimeModel(params: { reasoning: boolean }): ProviderRuntimeModel {
return {
@@ -66,29 +67,44 @@ describe("fireworks provider plugin", () => {
throw new Error("expected Fireworks catalog models");
}
expect(models.map((model) => model.id)).toEqual([
FIREWORKS_KIMI_K2_6_MODEL_ID,
FIREWORKS_DEFAULT_MODEL_ID,
FIREWORKS_KIMI_K2_6_MODEL_ID,
FIREWORKS_KIMI_K2_6_TURBO_MODEL_ID,
]);
expect(models[0]?.reasoning).toBe(false);
expect(models[0]?.name).toBe("GLM 5.2 Fast");
expect(models[0]?.reasoning).toBe(true);
expect(models[0]?.input).toEqual(["text", "image"]);
expect(models[0]?.contextWindow).toBe(262144);
expect(models[0]?.maxTokens).toBe(262144);
expect(models[0]?.contextWindow).toBe(FIREWORKS_DEFAULT_CONTEXT_WINDOW);
expect(models[0]?.maxTokens).toBe(FIREWORKS_DEFAULT_MAX_TOKENS);
expect(models[0]?.cost).toEqual({
input: 2.1,
output: 6.6,
cacheRead: 0.21,
cacheWrite: 0,
});
expect(models[1]?.name).toBe("Kimi K2.6");
expect(models[1]?.reasoning).toBe(false);
expect(models[1]?.input).toEqual(["text", "image"]);
expect(models[1]?.contextWindow).toBe(262144);
expect(models[1]?.maxTokens).toBe(262144);
expect(models[1]?.cost).toEqual({
input: 0.95,
output: 4,
cacheRead: 0.16,
cacheWrite: 0,
});
expect(models[1]?.name).toBe("Kimi K2.6 Fast");
expect(models[1]?.reasoning).toBe(false);
expect(models[1]?.input).toEqual(["text", "image"]);
expect(models[1]?.contextWindow).toBe(262144);
expect(models[1]?.maxTokens).toBe(FIREWORKS_DEFAULT_MAX_TOKENS);
expect(models[1]?.cost).toEqual({
input: 2,
output: 8,
cacheRead: 0.3,
cacheWrite: 0,
expect(models[2]).toMatchObject({
name: "Kimi K2.6 Fast",
reasoning: false,
input: ["text", "image"],
contextWindow: 262144,
maxTokens: 256000,
cost: {
input: 2,
output: 8,
cacheRead: 0.3,
cacheWrite: 0,
},
});
});
@@ -158,7 +174,11 @@ describe("fireworks provider plugin", () => {
it("defers manifest catalog models to core static-catalog resolution", async () => {
const provider = await registerSingleProviderPlugin(fireworksPlugin);
for (const modelId of [FIREWORKS_KIMI_K2_6_MODEL_ID, FIREWORKS_DEFAULT_MODEL_ID]) {
for (const modelId of [
FIREWORKS_DEFAULT_MODEL_ID,
FIREWORKS_KIMI_K2_6_MODEL_ID,
FIREWORKS_KIMI_K2_6_TURBO_MODEL_ID,
]) {
const resolved = provider.resolveDynamicModel?.(
createProviderDynamicModelContext({
provider: "fireworks",
@@ -177,7 +197,7 @@ describe("fireworks provider plugin", () => {
expect(
provider.resolveThinkingProfile?.({
provider: "fireworks",
modelId: FIREWORKS_DEFAULT_MODEL_ID,
modelId: FIREWORKS_KIMI_K2_6_TURBO_MODEL_ID,
}),
).toEqual({
levels: [{ id: "off" }],
@@ -195,7 +215,7 @@ describe("fireworks provider plugin", () => {
expect(
provider.resolveThinkingProfile?.({
provider: "fireworks",
modelId: "accounts/fireworks/models/qwen3.6-plus",
modelId: FIREWORKS_DEFAULT_MODEL_ID,
}),
).toBeUndefined();
expect(resolveThinkingProfile({ modelId: FIREWORKS_KIMI_K2_6_MODEL_ID })).toEqual({

View File

@@ -12,7 +12,7 @@ describe("Fireworks onboarding", () => {
FIREWORKS_DEFAULT_MODEL_REF,
);
expect(config.agents?.defaults?.models).toEqual({
[FIREWORKS_DEFAULT_MODEL_REF]: { alias: "Kimi K2.6 Turbo" },
[FIREWORKS_DEFAULT_MODEL_REF]: { alias: "GLM 5.2 Fast" },
});
});
});

View File

@@ -19,7 +19,7 @@ const fireworksPresetAppliers = createDefaultModelsPresetAppliers({
baseUrl: defaultProvider.baseUrl,
defaultModels: buildFireworksCatalogModels(),
defaultModelId: FIREWORKS_DEFAULT_MODEL_ID,
aliases: [{ modelRef: FIREWORKS_DEFAULT_MODEL_REF, alias: "Kimi K2.6 Turbo" }],
aliases: [{ modelRef: FIREWORKS_DEFAULT_MODEL_REF, alias: "GLM 5.2 Fast" }],
};
},
});

View File

@@ -34,8 +34,22 @@
"fireworks": {
"baseUrl": "https://api.fireworks.ai/inference/v1",
"api": "openai-completions",
"defaultModel": "accounts/fireworks/routers/kimi-k2p6-turbo",
"defaultModel": "accounts/fireworks/routers/glm-5p2-fast",
"models": [
{
"id": "accounts/fireworks/routers/glm-5p2-fast",
"name": "GLM 5.2 Fast",
"reasoning": true,
"input": ["text", "image"],
"contextWindow": 256000,
"maxTokens": 256000,
"cost": {
"input": 2.1,
"output": 6.6,
"cacheRead": 0.21,
"cacheWrite": 0
}
},
{
"id": "accounts/fireworks/models/kimi-k2p6",
"name": "Kimi K2.6",

View File

@@ -6,5 +6,5 @@ export {
MOONSHOT_BASE_URL,
MOONSHOT_CN_BASE_URL,
MOONSHOT_DEFAULT_MODEL_ID,
MOONSHOT_DEFAULT_MODEL_REF,
} from "./provider-catalog.js";
export { MOONSHOT_DEFAULT_MODEL_REF } from "./onboard.js";

View File

@@ -4,12 +4,8 @@ import { buildOpenAICompatibleReplayPolicy } from "openclaw/plugin-sdk/provider-
import { buildProviderStreamFamilyHooks } from "openclaw/plugin-sdk/provider-stream-family";
import { applyMoonshotNativeStreamingUsageCompat } from "./api.js";
import { moonshotMediaUnderstandingProvider } from "./media-understanding-provider.js";
import {
applyMoonshotConfig,
applyMoonshotConfigCn,
MOONSHOT_DEFAULT_MODEL_REF,
} from "./onboard.js";
import { buildMoonshotProvider } from "./provider-catalog.js";
import { applyMoonshotConfig, applyMoonshotConfigCn } from "./onboard.js";
import { buildMoonshotProvider, MOONSHOT_DEFAULT_MODEL_REF } from "./provider-catalog.js";
import { isMoonshotAlwaysThinkingModelId, resolveThinkingProfile } from "./provider-policy-api.js";
import { createKimiWebSearchProvider } from "./src/kimi-web-search-provider.js";

View File

@@ -16,10 +16,14 @@ import {
readProviderJsonResponse,
resolveProviderHttpRequestConfig,
} from "openclaw/plugin-sdk/provider-http";
import { MOONSHOT_DEFAULT_MODEL_ID } from "./provider-catalog.js";
import manifest from "./openclaw.plugin.json" with { type: "json" };
const DEFAULT_MOONSHOT_VIDEO_BASE_URL = "https://api.moonshot.ai/v1";
const DEFAULT_MOONSHOT_VIDEO_MODEL = MOONSHOT_DEFAULT_MODEL_ID;
// Media defaults are capability-specific and intentionally independent from chat onboarding.
const DEFAULT_MOONSHOT_IMAGE_MODEL =
manifest.mediaUnderstandingProviderMetadata.moonshot.defaultModels.image;
const DEFAULT_MOONSHOT_VIDEO_MODEL =
manifest.mediaUnderstandingProviderMetadata.moonshot.defaultModels.video;
const DEFAULT_MOONSHOT_VIDEO_PROMPT = "Describe the video.";
async function describeMoonshotVideo(
@@ -83,7 +87,10 @@ async function describeMoonshotVideo(
export const moonshotMediaUnderstandingProvider: MediaUnderstandingProvider = {
id: "moonshot",
capabilities: ["image", "video"],
defaultModels: { image: MOONSHOT_DEFAULT_MODEL_ID, video: DEFAULT_MOONSHOT_VIDEO_MODEL },
defaultModels: {
image: DEFAULT_MOONSHOT_IMAGE_MODEL,
video: DEFAULT_MOONSHOT_VIDEO_MODEL,
},
autoPriority: { video: 20 },
describeImage: describeImageWithModel,
describeImages: describeImagesWithModel,

View File

@@ -0,0 +1,30 @@
import { resolveAgentModelPrimaryValue } from "openclaw/plugin-sdk/provider-onboard";
import { describe, expect, it } from "vitest";
import { applyMoonshotConfig, applyMoonshotConfigCn } from "./onboard.js";
import manifest from "./openclaw.plugin.json" with { type: "json" };
import {
MOONSHOT_BASE_URL,
MOONSHOT_CN_BASE_URL,
MOONSHOT_DEFAULT_MODEL_ID,
MOONSHOT_DEFAULT_MODEL_REF,
} from "./provider-catalog.js";
describe("Moonshot onboarding", () => {
it.each([
["international", applyMoonshotConfig, MOONSHOT_BASE_URL],
["China", applyMoonshotConfigCn, MOONSHOT_CN_BASE_URL],
])("applies the manifest default on the %s endpoint", (_name, applyConfig, baseUrl) => {
const config = applyConfig({});
const provider = config.models?.providers?.moonshot;
expect(MOONSHOT_DEFAULT_MODEL_ID).toBe(manifest.modelCatalog.providers.moonshot.defaultModel);
expect(provider?.baseUrl).toBe(baseUrl);
expect(provider?.models.map((model) => model.id)).toEqual([MOONSHOT_DEFAULT_MODEL_ID]);
expect(resolveAgentModelPrimaryValue(config.agents?.defaults?.model)).toBe(
MOONSHOT_DEFAULT_MODEL_REF,
);
expect(config.agents?.defaults?.models).toEqual({
[MOONSHOT_DEFAULT_MODEL_REF]: { alias: "Kimi" },
});
});
});

View File

@@ -8,13 +8,15 @@ import {
MOONSHOT_BASE_URL,
MOONSHOT_CN_BASE_URL,
MOONSHOT_DEFAULT_MODEL_ID,
MOONSHOT_DEFAULT_MODEL_REF,
} from "./provider-catalog.js";
export const MOONSHOT_DEFAULT_MODEL_REF = `moonshot/${MOONSHOT_DEFAULT_MODEL_ID}`;
const moonshotPresetAppliers = createDefaultModelPresetAppliers<[string]>({
primaryModelRef: MOONSHOT_DEFAULT_MODEL_REF,
resolveParams: (_cfg: OpenClawConfig, baseUrl: string) => {
const defaultModel = buildMoonshotProvider().models[0];
const defaultModel = buildMoonshotProvider().models.find(
(model) => model.id === MOONSHOT_DEFAULT_MODEL_ID,
);
if (!defaultModel) {
return null;
}

View File

@@ -54,6 +54,7 @@
"moonshot": {
"baseUrl": "https://api.moonshot.ai/v1",
"api": "openai-completions",
"defaultModel": "kimi-k3",
"models": [
{
"id": "kimi-k3",

View File

@@ -55,7 +55,7 @@ describe("moonshot provider catalog", () => {
xhigh: "max",
max: "max",
},
input: ["text", "image", "video"],
input: ["text", "image"],
contextWindow: 1_048_576,
maxTokens: 1_048_576,
cost: {
@@ -71,7 +71,7 @@ describe("moonshot provider catalog", () => {
});
expect(requireMoonshotModel(provider, "kimi-k2.7-code")).toMatchObject({
reasoning: true,
input: ["text", "image", "video"],
input: ["text", "image"],
contextWindow: 262144,
maxTokens: 262144,
cost: {
@@ -83,7 +83,7 @@ describe("moonshot provider catalog", () => {
});
expect(requireMoonshotModel(provider, "kimi-k2.7-code-highspeed")).toMatchObject({
reasoning: true,
input: ["text", "image", "video"],
input: ["text", "image"],
contextWindow: 262144,
maxTokens: 262144,
cost: {

View File

@@ -1,7 +1,8 @@
// Moonshot provider module implements model/runtime integration.
import {
buildManifestModelProviderConfig,
applyProviderNativeStreamingUsageCompat,
buildManifestModelProviderConfig,
readManifestProviderDefaultModelRef,
supportsNativeStreamingUsageCompat,
} from "openclaw/plugin-sdk/provider-catalog-shared";
import type { ModelProviderConfig } from "openclaw/plugin-sdk/provider-model-shared";
@@ -9,7 +10,11 @@ import manifest from "./openclaw.plugin.json" with { type: "json" };
export const MOONSHOT_BASE_URL = "https://api.moonshot.ai/v1";
export const MOONSHOT_CN_BASE_URL = "https://api.moonshot.cn/v1";
export const MOONSHOT_DEFAULT_MODEL_ID = "kimi-k2.6";
export const MOONSHOT_DEFAULT_MODEL_REF = readManifestProviderDefaultModelRef(
manifest,
"moonshot",
)!;
export const MOONSHOT_DEFAULT_MODEL_ID = MOONSHOT_DEFAULT_MODEL_REF.slice("moonshot/".length);
export function isNativeMoonshotBaseUrl(baseUrl: string | undefined): boolean {
return supportsNativeStreamingUsageCompat({

View File

@@ -35,11 +35,11 @@ import {
isNativeMoonshotBaseUrl,
MOONSHOT_BASE_URL,
MOONSHOT_CN_BASE_URL,
MOONSHOT_DEFAULT_MODEL_ID,
} from "../provider-catalog.js";
const DEFAULT_KIMI_BASE_URL = MOONSHOT_BASE_URL;
const DEFAULT_KIMI_SEARCH_MODEL = MOONSHOT_DEFAULT_MODEL_ID;
// Search owns a separate model default so chat onboarding changes do not silently reroute searches.
const DEFAULT_KIMI_SEARCH_MODEL = "kimi-k2.6";
/** Models that require explicit thinking disablement for web search. */
const KIMI_THINKING_MODELS = new Set(["kimi-k2.6", "kimi-k2.5"]);
const KIMI_WEB_SEARCH_TOOL = {

View File

@@ -15,7 +15,7 @@ describe("Venice onboarding", () => {
VENICE_DEFAULT_MODEL_REF,
);
expect(config.agents?.defaults?.models).toEqual({
[VENICE_DEFAULT_MODEL_REF]: { alias: "Kimi K2.5" },
[VENICE_DEFAULT_MODEL_REF]: { alias: "Kimi K2.6" },
});
});
});

View File

@@ -17,7 +17,7 @@ const venicePresetAppliers = createModelCatalogPresetAppliers({
api: "openai-completions",
baseUrl: VENICE_BASE_URL,
catalogModels: VENICE_MODEL_CATALOG.map(buildVeniceModelDefinition),
aliases: [{ modelRef: VENICE_DEFAULT_MODEL_REF, alias: "Kimi K2.5" }],
aliases: [{ modelRef: VENICE_DEFAULT_MODEL_REF, alias: "Kimi K2.6" }],
}),
});

View File

@@ -43,7 +43,7 @@
"venice": {
"baseUrl": "https://api.venice.ai/api/v1",
"api": "openai-completions",
"defaultModel": "kimi-k2-5",
"defaultModel": "kimi-k2-6",
"models": [
{
"id": "zai-org-glm-5-2",

View File

@@ -100,21 +100,21 @@ describe("detectZaiEndpoint", () => {
}> = [
{
responses: {
"https://api.z.ai/api/paas/v4/chat/completions::glm-5.1": { status: 200 },
"https://api.z.ai/api/paas/v4/chat/completions::glm-5.2": { status: 200 },
},
expected: { endpoint: "global", modelId: "glm-5.1" },
expected: { endpoint: "global", modelId: "glm-5.2" },
},
{
responses: {
"https://api.z.ai/api/paas/v4/chat/completions::glm-5.1": { status: 404 },
"https://open.bigmodel.cn/api/paas/v4/chat/completions::glm-5.1": { status: 200 },
"https://api.z.ai/api/paas/v4/chat/completions::glm-5.2": { status: 404 },
"https://open.bigmodel.cn/api/paas/v4/chat/completions::glm-5.2": { status: 200 },
},
expected: { endpoint: "cn", modelId: "glm-5.1" },
expected: { endpoint: "cn", modelId: "glm-5.2" },
},
{
responses: {
"https://api.z.ai/api/paas/v4/chat/completions::glm-5.1": { status: 404 },
"https://open.bigmodel.cn/api/paas/v4/chat/completions::glm-5.1": { status: 404 },
"https://api.z.ai/api/paas/v4/chat/completions::glm-5.2": { status: 404 },
"https://open.bigmodel.cn/api/paas/v4/chat/completions::glm-5.2": { status: 404 },
"https://api.z.ai/api/coding/paas/v4/chat/completions::glm-5.2": { status: 200 },
},
expected: { endpoint: "coding-global", modelId: "glm-5.2" },
@@ -199,8 +199,8 @@ describe("detectZaiEndpoint", () => {
},
{
responses: {
"https://api.z.ai/api/paas/v4/chat/completions::glm-5.1": { status: 401 },
"https://open.bigmodel.cn/api/paas/v4/chat/completions::glm-5.1": { status: 401 },
"https://api.z.ai/api/paas/v4/chat/completions::glm-5.2": { status: 401 },
"https://open.bigmodel.cn/api/paas/v4/chat/completions::glm-5.2": { status: 401 },
"https://api.z.ai/api/coding/paas/v4/chat/completions::glm-5.2": { status: 401 },
"https://api.z.ai/api/coding/paas/v4/chat/completions::glm-5.1": { status: 401 },
"https://api.z.ai/api/coding/paas/v4/chat/completions::glm-4.7": { status: 401 },
@@ -240,7 +240,7 @@ describe("detectZaiEndpoint", () => {
.mockReturnValue(1 as unknown as ReturnType<typeof setTimeout>);
vi.spyOn(globalThis, "clearTimeout").mockImplementation(() => undefined);
const fetchFn = makeFetch({
"https://api.z.ai/api/paas/v4/chat/completions::glm-5.1": { status: 200 },
"https://api.z.ai/api/paas/v4/chat/completions::glm-5.2": { status: 200 },
});
await detectZaiEndpoint({

View File

@@ -165,13 +165,13 @@ export async function detectZaiEndpoint(params: {
endpoint: "global" as const,
baseUrl: ZAI_GLOBAL_BASE_URL,
modelId: ZAI_DEFAULT_MODEL_ID,
note: "Verified GLM-5.1 on global endpoint.",
note: "Verified GLM-5.2 on global endpoint.",
},
{
endpoint: "cn" as const,
baseUrl: ZAI_CN_BASE_URL,
modelId: ZAI_DEFAULT_MODEL_ID,
note: "Verified GLM-5.1 on cn endpoint.",
note: "Verified GLM-5.2 on cn endpoint.",
},
];
const codingModels: ProbeCandidate[] = [

View File

@@ -194,13 +194,13 @@ describe("zai provider plugin", () => {
const resolved = provider.resolveDynamicModel?.({
provider: "zai",
modelId: "glm-5-turbo",
modelId: "glm-5.3",
modelRegistry: {
find: () => null,
},
} as never) as Record<string, unknown> | undefined;
expectModelFields(resolved, {
id: "glm-5-turbo",
id: "glm-5.3",
provider: "zai",
api: "openai-completions",
baseUrl: "https://api.z.ai/api/paas/v4",
@@ -215,14 +215,13 @@ describe("zai provider plugin", () => {
const resolved = provider.resolveDynamicModel?.({
provider: "zai",
modelId: "glm-5-turbo",
modelId: "glm-5.3",
modelRegistry: {
find: (_provider: string, modelId: string) => (modelId === "glm-4.7" ? template : null),
},
} as never) as Record<string, unknown> | undefined;
expectModelFields(resolved, {
id: "glm-5-turbo",
name: "GLM-5 Turbo",
id: "glm-5.3",
provider: "zai",
api: "openai-completions",
baseUrl: "https://api.z.ai/api/paas/v4",

View File

@@ -12,6 +12,7 @@ import {
ZAI_GLOBAL_BASE_URL,
} from "./model-definitions.js";
import { applyZaiConfig, applyZaiProviderConfig } from "./onboard.js";
import manifest from "./openclaw.plugin.json" with { type: "json" };
describe("zai onboard", () => {
let defaultCfg: ReturnType<typeof applyZaiConfig>;
@@ -28,7 +29,7 @@ describe("zai onboard", () => {
expect(defaultCfg.models?.providers?.zai?.baseUrl).toBe(ZAI_GLOBAL_BASE_URL);
expect(defaultCfg.models?.providers?.zai?.api).toBe("openai-completions");
const ids = defaultCfg.models?.providers?.zai?.models?.map((m) => m.id);
expect(ids).toEqual(["glm-5.2", "glm-5.1"]);
expect(ids).toEqual(manifest.modelCatalog.providers.zai.models.map((model) => model.id));
expect(
defaultCfg.models?.providers?.zai?.models?.find((model) => model.id === "glm-5.2"),
).toMatchObject({
@@ -41,9 +42,9 @@ describe("zai onboard", () => {
});
it("uses the manifest default and alias for a fresh general endpoint setup", () => {
expect(resolveAgentModelPrimaryValue(defaultCfg.agents?.defaults?.model)).toBe("zai/glm-5.1");
expect(resolveAgentModelPrimaryValue(defaultCfg.agents?.defaults?.model)).toBe("zai/glm-5.2");
expect(defaultCfg.agents?.defaults?.models).toEqual({
"zai/glm-5.1": { alias: "GLM" },
"zai/glm-5.2": { alias: "GLM" },
});
});
@@ -98,7 +99,7 @@ describe("zai onboard", () => {
}
});
it("defaults Coding Plan endpoints to GLM-5.2 without changing the general API default", () => {
it("defaults general and Coding Plan endpoints to GLM-5.2", () => {
const codingCfg = applyZaiConfig({}, { endpoint: "coding-global" });
const existingCodingCfg = applyZaiConfig({
models: {
@@ -112,7 +113,7 @@ describe("zai onboard", () => {
},
});
expect(resolveAgentModelPrimaryValue(defaultCfg.agents?.defaults?.model)).toBe("zai/glm-5.1");
expect(resolveAgentModelPrimaryValue(defaultCfg.agents?.defaults?.model)).toBe("zai/glm-5.2");
expect(codingCfg.models?.providers?.zai?.baseUrl).toBe(ZAI_CODING_GLOBAL_BASE_URL);
expect(resolveAgentModelPrimaryValue(codingCfg.agents?.defaults?.model)).toBe("zai/glm-5.2");
expect(resolveAgentModelPrimaryValue(existingCodingCfg.agents?.defaults?.model)).toBe(

View File

@@ -32,7 +32,7 @@
"zai": {
"baseUrl": "https://api.z.ai/api/paas/v4",
"api": "openai-completions",
"defaultModel": "glm-5.1",
"defaultModel": "glm-5.2",
"models": [
{
"id": "glm-5.2",