mirror of https://github.com/openclaw/openclaw.git
xAI: normalize deprecated Grok 4.20 ids
This commit is contained in:
parent
a168cde6ee
commit
73079d1cb1
|
|
@ -1,3 +1,4 @@
|
|||
import { normalizeXaiModelId } from "openclaw/plugin-sdk/provider-models";
|
||||
import { postTrustedWebToolsJson, wrapWebContent } from "openclaw/plugin-sdk/provider-web-search";
|
||||
|
||||
export const XAI_WEB_SEARCH_ENDPOINT = "https://api.x.ai/v1/responses";
|
||||
|
|
@ -79,7 +80,7 @@ export function resolveXaiSearchConfig(searchConfig?: Record<string, unknown>):
|
|||
export function resolveXaiWebSearchModel(searchConfig?: Record<string, unknown>): string {
|
||||
const config = resolveXaiSearchConfig(searchConfig);
|
||||
return typeof config.model === "string" && config.model.trim()
|
||||
? config.model.trim()
|
||||
? normalizeXaiModelId(config.model.trim())
|
||||
: XAI_DEFAULT_WEB_SEARCH_MODEL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,19 @@ describe("xai web search config resolution", () => {
|
|||
);
|
||||
});
|
||||
|
||||
it("normalizes deprecated grok 4.20 beta model ids to GA ids", () => {
|
||||
expect(
|
||||
resolveXaiWebSearchModel({
|
||||
grok: { model: "grok-4.20-experimental-beta-0304-reasoning" },
|
||||
}),
|
||||
).toBe("grok-4.20-reasoning");
|
||||
expect(
|
||||
resolveXaiWebSearchModel({
|
||||
grok: { model: "grok-4.20-experimental-beta-0304-non-reasoning" },
|
||||
}),
|
||||
).toBe("grok-4.20-non-reasoning");
|
||||
});
|
||||
|
||||
it("defaults inlineCitations to false", () => {
|
||||
expect(resolveXaiInlineCitations({})).toBe(false);
|
||||
expect(resolveXaiInlineCitations(undefined)).toBe(false);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import { normalizeXaiModelId } from "./model-id-normalization.js";
|
||||
|
||||
describe("normalizeXaiModelId", () => {
|
||||
it("maps deprecated grok 4.20 beta ids to GA ids", () => {
|
||||
expect(normalizeXaiModelId("grok-4.20-experimental-beta-0304-reasoning")).toBe(
|
||||
"grok-4.20-reasoning",
|
||||
);
|
||||
expect(normalizeXaiModelId("grok-4.20-experimental-beta-0304-non-reasoning")).toBe(
|
||||
"grok-4.20-non-reasoning",
|
||||
);
|
||||
});
|
||||
|
||||
it("leaves current xai model ids unchanged", () => {
|
||||
expect(normalizeXaiModelId("grok-4.20-reasoning")).toBe("grok-4.20-reasoning");
|
||||
expect(normalizeXaiModelId("grok-4")).toBe("grok-4");
|
||||
});
|
||||
});
|
||||
|
|
@ -21,3 +21,13 @@ export function normalizeGoogleModelId(id: string): string {
|
|||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
export function normalizeXaiModelId(id: string): string {
|
||||
if (id === "grok-4.20-experimental-beta-0304-reasoning") {
|
||||
return "grok-4.20-reasoning";
|
||||
}
|
||||
if (id === "grok-4.20-experimental-beta-0304-non-reasoning") {
|
||||
return "grok-4.20-non-reasoning";
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -194,6 +194,15 @@ describe("model-selection", () => {
|
|||
defaultProvider: "google",
|
||||
expected: { provider: "google", model: "gemini-3.1-flash-lite-preview" },
|
||||
},
|
||||
{
|
||||
name: "normalizes deprecated xai grok 4.20 beta ids",
|
||||
variants: [
|
||||
"xai/grok-4.20-experimental-beta-0304-reasoning",
|
||||
"grok-4.20-experimental-beta-0304-reasoning",
|
||||
],
|
||||
defaultProvider: "xai",
|
||||
expected: { provider: "xai", model: "grok-4.20-reasoning" },
|
||||
},
|
||||
{
|
||||
name: "keeps OpenAI codex refs on the openai provider",
|
||||
variants: ["openai/gpt-5.3-codex", "gpt-5.3-codex"],
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import {
|
|||
} from "./agent-scope.js";
|
||||
import { DEFAULT_MODEL, DEFAULT_PROVIDER } from "./defaults.js";
|
||||
import type { ModelCatalogEntry } from "./model-catalog.js";
|
||||
import { normalizeGoogleModelId } from "./model-id-normalization.js";
|
||||
import { normalizeGoogleModelId, normalizeXaiModelId } from "./model-id-normalization.js";
|
||||
import { splitTrailingAuthProfile } from "./model-ref-profile.js";
|
||||
import {
|
||||
findNormalizedProviderKey,
|
||||
|
|
@ -121,6 +121,9 @@ function normalizeProviderModelId(provider: string, model: string): string {
|
|||
if (provider === "google" || provider === "google-vertex") {
|
||||
return normalizeGoogleModelId(model);
|
||||
}
|
||||
if (provider === "xai") {
|
||||
return normalizeXaiModelId(model);
|
||||
}
|
||||
// OpenRouter-native models (e.g. "openrouter/aurora-alpha") need the full
|
||||
// "openrouter/<name>" as the model ID sent to the API. Models from external
|
||||
// providers already contain a slash (e.g. "anthropic/claude-sonnet-4-5") and
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import { isRecord } from "../utils.js";
|
|||
import { normalizeOptionalSecretInput } from "../utils/normalize-secret-input.js";
|
||||
import { ensureAuthProfileStore, listProfilesForProvider } from "./auth-profiles.js";
|
||||
import { discoverBedrockModels } from "./bedrock-discovery.js";
|
||||
import { normalizeGoogleModelId } from "./model-id-normalization.js";
|
||||
import { normalizeGoogleModelId, normalizeXaiModelId } from "./model-id-normalization.js";
|
||||
import { resolveOllamaApiBase } from "./models-config.providers.discovery.js";
|
||||
export { buildKimiCodingProvider } from "../../extensions/kimi-coding/provider-catalog.js";
|
||||
export { buildKilocodeProvider } from "../../extensions/kilocode/provider-catalog.js";
|
||||
|
|
@ -42,7 +42,7 @@ import {
|
|||
} from "./model-auth-markers.js";
|
||||
import { resolveAwsSdkEnvVarName, resolveEnvApiKey } from "./model-auth.js";
|
||||
export { resolveOllamaApiBase } from "./models-config.providers.discovery.js";
|
||||
export { normalizeGoogleModelId };
|
||||
export { normalizeGoogleModelId, normalizeXaiModelId };
|
||||
|
||||
type ModelsConfig = NonNullable<OpenClawConfig["models"]>;
|
||||
export type ProviderConfig = NonNullable<ModelsConfig["providers"]>[string];
|
||||
|
|
|
|||
|
|
@ -341,6 +341,15 @@ describe("web_search grok config resolution", () => {
|
|||
expect(resolveGrokModel({ model: "grok-4-fast" })).toBe("grok-4-fast");
|
||||
});
|
||||
|
||||
it("normalizes deprecated grok 4.20 beta ids to GA ids", () => {
|
||||
expect(resolveGrokModel({ model: "grok-4.20-experimental-beta-0304-reasoning" })).toBe(
|
||||
"grok-4.20-reasoning",
|
||||
);
|
||||
expect(resolveGrokModel({ model: "grok-4.20-experimental-beta-0304-non-reasoning" })).toBe(
|
||||
"grok-4.20-non-reasoning",
|
||||
);
|
||||
});
|
||||
|
||||
it("falls back to default model", () => {
|
||||
expect(resolveGrokModel({})).toBe("grok-4-1-fast");
|
||||
});
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ describe("model-pricing-cache", () => {
|
|||
],
|
||||
},
|
||||
hooks: {
|
||||
mappings: [{ model: "xai/grok-4" }],
|
||||
mappings: [{ model: "xai/grok-4.20-experimental-beta-0304-reasoning" }],
|
||||
},
|
||||
tools: {
|
||||
subagents: { model: { primary: "zai/glm-5" } },
|
||||
|
|
@ -130,7 +130,7 @@ describe("model-pricing-cache", () => {
|
|||
},
|
||||
},
|
||||
{
|
||||
id: "x-ai/grok-4",
|
||||
id: "x-ai/grok-4.20-experimental-beta-0304-reasoning",
|
||||
pricing: {
|
||||
prompt: "0.000002",
|
||||
completion: "0.00001",
|
||||
|
|
@ -172,12 +172,25 @@ describe("model-pricing-cache", () => {
|
|||
cacheRead: 0.3,
|
||||
cacheWrite: 0,
|
||||
});
|
||||
expect(getCachedGatewayModelPricing({ provider: "xai", model: "grok-4" })).toEqual({
|
||||
expect(
|
||||
getCachedGatewayModelPricing({
|
||||
provider: "xai",
|
||||
model: "grok-4.20-experimental-beta-0304-reasoning",
|
||||
}),
|
||||
).toEqual({
|
||||
input: 2,
|
||||
output: 10,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
});
|
||||
expect(getCachedGatewayModelPricing({ provider: "xai", model: "grok-4.20-reasoning" })).toEqual(
|
||||
{
|
||||
input: 2,
|
||||
output: 10,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
);
|
||||
expect(getCachedGatewayModelPricing({ provider: "zai", model: "glm-5" })).toEqual({
|
||||
input: 1,
|
||||
output: 4,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import {
|
|||
resolveModelRefFromString,
|
||||
type ModelRef,
|
||||
} from "../agents/model-selection.js";
|
||||
import { normalizeGoogleModelId } from "../agents/models-config.providers.js";
|
||||
import { normalizeGoogleModelId, normalizeXaiModelId } from "../agents/models-config.providers.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { createSubsystemLogger } from "../logging/subsystem.js";
|
||||
|
||||
|
|
@ -155,6 +155,9 @@ function canonicalizeOpenRouterLookupId(id: string): string {
|
|||
if (provider === "google") {
|
||||
model = normalizeGoogleModelId(model);
|
||||
}
|
||||
if (provider === "x-ai") {
|
||||
model = normalizeXaiModelId(model);
|
||||
}
|
||||
return `${provider}/${model}`;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ export {
|
|||
XAI_TOOL_SCHEMA_PROFILE,
|
||||
} from "../agents/model-compat.js";
|
||||
export { normalizeProviderId } from "../agents/provider-id.js";
|
||||
export { normalizeXaiModelId } from "../agents/model-id-normalization.js";
|
||||
export { cloneFirstTemplateModel } from "../plugins/provider-model-helpers.js";
|
||||
|
||||
export {
|
||||
|
|
|
|||
Loading…
Reference in New Issue