fix: aggressively prune retired model catalogs

This commit is contained in:
Peter Steinberger
2026-05-23 17:29:44 +01:00
parent 7fffbf60b0
commit f4b5e58231
26 changed files with 231 additions and 750 deletions

View File

@@ -54,7 +54,7 @@ Docs: https://docs.openclaw.ai
### Fixes
- Models: prune retired GitHub Copilot model rows and old Claude catalog entries below 4.6, with doctor migration to upgrade existing configs to current Claude/Copilot refs.
- Models: prune retired Groq, GitHub Copilot, OpenAI, xAI, and old Claude catalog entries, with doctor migration to upgrade existing configs to current provider refs.
- Doctor/update: recognize junction-backed source checkouts as git installs by comparing canonical paths before showing package-manager update guidance. Fixes #82215. Thanks @igormf.
- CLI/skills: show an all-ready note with next-step commands when skill setup has no missing dependencies to install. (#85032) Thanks @aniruddhaadak80.
- Microsoft Foundry: route DeepSeek V4 Pro and Flash models through the Foundry Responses API while keeping older DeepSeek models on their existing path. (#85549) Thanks @roslinmahmud.

View File

@@ -163,7 +163,7 @@ openclaw infer model run --local --model google/gemini-2.5-flash --prompt "Reply
openclaw infer model run --local --model groq/llama-3.1-8b-instant --prompt "Reply with exactly: pong" --json
openclaw infer model run --local --model mistral/mistral-medium-3-5 --prompt "Reply with exactly: pong" --json
openclaw infer model run --local --model mistral/mistral-small-latest --prompt "Reply with exactly: pong" --json
openclaw infer model run --local --model openai/gpt-4.1 --prompt "Reply with exactly: pong" --json
openclaw infer model run --local --model openai/gpt-5.5 --prompt "Reply with exactly: pong" --json
openclaw infer model run --local --model ollama/qwen2.5vl:7b --prompt "Describe this image." --file ./photo.jpg --json
```
@@ -196,7 +196,7 @@ openclaw infer image describe --file ./photo.jpg --json
openclaw infer image describe --file https://example.com/photo.png --json
openclaw infer image describe --file ./receipt.jpg --prompt "Extract the merchant, date, and total" --json
openclaw infer image describe-many --file ./before.png --file ./after.png --prompt "Compare the screenshots and list visible UI changes" --json
openclaw infer image describe --file ./ui-screenshot.png --model openai/gpt-4.1-mini --json
openclaw infer image describe --file ./ui-screenshot.png --model openai/gpt-5.4-mini --json
openclaw infer image describe --file ./photo.jpg --model ollama/qwen2.5vl:7b --prompt "Describe the image in one sentence" --timeout-ms 300000 --json
```
@@ -272,7 +272,7 @@ Use `video` for generation and description.
openclaw infer video generate --prompt "cinematic sunset over the ocean" --json
openclaw infer video generate --prompt "slow drone shot over a forest lake" --resolution 768P --duration 6 --json
openclaw infer video describe --file ./clip.mp4 --json
openclaw infer video describe --file ./clip.mp4 --model openai/gpt-4.1-mini --json
openclaw infer video describe --file ./clip.mp4 --model openai/gpt-5.4-mini --json
```
Notes:

View File

@@ -1397,7 +1397,7 @@ Batches rapid text-only messages from the same sender into a single agent turn.
auto: "always", // off | always | inbound | tagged
mode: "final", // final | all
provider: "elevenlabs",
summaryModel: "openai/gpt-4.1-mini",
summaryModel: "openai/gpt-5.4-mini",
modelOverrides: { enabled: true },
maxTextLength: 4000,
timeoutMs: 30000,

View File

@@ -53,10 +53,10 @@ Use `channels.modelByChannel` to pin specific channel IDs to a model. Values acc
"123456789012345678": "anthropic/claude-opus-4-6",
},
slack: {
C1234567890: "openai/gpt-4.1",
C1234567890: "openai/gpt-5.5",
},
telegram: {
"-1001234567890": "openai/gpt-4.1-mini",
"-1001234567890": "openai/gpt-5.4-mini",
"-1001234567890:topic:99": "anthropic/claude-sonnet-4-6",
},
},

View File

@@ -99,7 +99,7 @@ back to `COPILOT_GITHUB_TOKEN`, `GH_TOKEN`, then `GITHUB_TOKEN`. Use
<Accordion title="Model availability depends on your plan">
Copilot model availability depends on your GitHub plan. If a model is
rejected, try another ID (for example `github-copilot/gpt-4.1`). See
rejected, try another ID (for example `github-copilot/gpt-5.5`). See
GitHub's [supported models per Copilot plan](https://docs.github.com/en/copilot/reference/ai-models/supported-models#supported-ai-models-per-copilot-plan)
for the current model list.
</Accordion>

View File

@@ -75,26 +75,17 @@ export GROQ_API_KEY=gsk_...
OpenClaw ships a manifest-backed Groq catalog with both reasoning and non-reasoning entries. Run `openclaw models list --provider groq` to see the bundled rows for your installed version, or check [console.groq.com/docs/models](https://console.groq.com/docs/models) for Groq's authoritative list.
| Model ref | Name | Reasoning | Input | Context |
| ---------------------------------------------------- | ----------------------------- | --------- | ------------ | ------- |
| `groq/llama-3.3-70b-versatile` | Llama 3.3 70B Versatile | no | text | 131,072 |
| `groq/llama-3.1-8b-instant` | Llama 3.1 8B Instant | no | text | 131,072 |
| `groq/meta-llama/llama-4-maverick-17b-128e-instruct` | Llama 4 Maverick 17B | no | text + image | 131,072 |
| `groq/meta-llama/llama-4-scout-17b-16e-instruct` | Llama 4 Scout 17B | no | text + image | 131,072 |
| `groq/llama3-70b-8192` | Llama 3 70B | no | text | 8,192 |
| `groq/llama3-8b-8192` | Llama 3 8B | no | text | 8,192 |
| `groq/gemma2-9b-it` | Gemma 2 9B | no | text | 8,192 |
| `groq/mistral-saba-24b` | Mistral Saba 24B | no | text | 32,768 |
| `groq/moonshotai/kimi-k2-instruct` | Kimi K2 Instruct | no | text | 131,072 |
| `groq/moonshotai/kimi-k2-instruct-0905` | Kimi K2 Instruct 0905 | no | text | 262,144 |
| `groq/openai/gpt-oss-120b` | GPT OSS 120B | yes | text | 131,072 |
| `groq/openai/gpt-oss-20b` | GPT OSS 20B | yes | text | 131,072 |
| `groq/openai/gpt-oss-safeguard-20b` | Safety GPT OSS 20B | yes | text | 131,072 |
| `groq/qwen-qwq-32b` | Qwen QwQ 32B | yes | text | 131,072 |
| `groq/qwen/qwen3-32b` | Qwen3 32B | yes | text | 131,072 |
| `groq/deepseek-r1-distill-llama-70b` | DeepSeek R1 Distill Llama 70B | yes | text | 131,072 |
| `groq/groq/compound` | Compound | yes | text | 131,072 |
| `groq/groq/compound-mini` | Compound Mini | yes | text | 131,072 |
| Model ref | Name | Reasoning | Input | Context |
| ------------------------------------------------ | ----------------------- | --------- | ------------ | ------- |
| `groq/llama-3.3-70b-versatile` | Llama 3.3 70B Versatile | no | text | 131,072 |
| `groq/llama-3.1-8b-instant` | Llama 3.1 8B Instant | no | text | 131,072 |
| `groq/meta-llama/llama-4-scout-17b-16e-instruct` | Llama 4 Scout 17B | no | text + image | 131,072 |
| `groq/openai/gpt-oss-120b` | GPT OSS 120B | yes | text | 131,072 |
| `groq/openai/gpt-oss-20b` | GPT OSS 20B | yes | text | 131,072 |
| `groq/openai/gpt-oss-safeguard-20b` | Safety GPT OSS 20B | yes | text | 131,072 |
| `groq/qwen/qwen3-32b` | Qwen3 32B | yes | text | 131,072 |
| `groq/groq/compound` | Compound | yes | text | 131,072 |
| `groq/groq/compound-mini` | Compound Mini | yes | text | 131,072 |
<Tip>
The catalog evolves with each OpenClaw release. `openclaw models list --provider groq` shows the rows known to your installed version; cross-check with [console.groq.com/docs/models](https://console.groq.com/docs/models) for newly-added or deprecated models.

View File

@@ -29,13 +29,6 @@ export const FALLBACK_CODEX_MODELS = [
inputModalities: ["text", "image"],
supportedReasoningEfforts: ["low", "medium", "high", "xhigh"],
},
{
id: "gpt-5.2",
model: "gpt-5.2",
displayName: "gpt-5.2",
inputModalities: ["text", "image"],
supportedReasoningEfforts: ["low", "medium", "high", "xhigh"],
},
] satisfies CodexAppServerModel[];
export function buildCodexModelDefinition(model: {

View File

@@ -16,11 +16,7 @@ afterEach(() => {
function expectStaticFallbackCatalog(
result: Awaited<ReturnType<typeof buildCodexProviderCatalog>>,
) {
expect(result.provider.models.map((model) => model.id)).toEqual([
"gpt-5.5",
"gpt-5.4-mini",
"gpt-5.2",
]);
expect(result.provider.models.map((model) => model.id)).toEqual(["gpt-5.5", "gpt-5.4-mini"]);
}
function createFakeCodexClient(): CodexAppServerClient {
@@ -170,8 +166,8 @@ describe("codex provider", () => {
.mockResolvedValueOnce({
models: [
{
id: "gpt-5.2",
model: "gpt-5.2",
id: "gpt-5.5",
model: "gpt-5.5",
hidden: false,
inputModalities: ["text"],
supportedReasoningEfforts: [],
@@ -194,7 +190,7 @@ describe("codex provider", () => {
limit: 100,
sharedClient: false,
});
expect(result.provider.models.map((model) => model.id)).toEqual(["gpt-5.4", "gpt-5.2"]);
expect(result.provider.models.map((model) => model.id)).toEqual(["gpt-5.4", "gpt-5.5"]);
});
it("reports discovery failures before using the fallback catalog", async () => {
@@ -353,7 +349,7 @@ describe("codex provider", () => {
expect(
result && "provider" in result ? result.provider.models.map((model) => model.id) : [],
).toEqual(["gpt-5.5", "gpt-5.4-mini", "gpt-5.2"]);
).toEqual(["gpt-5.5", "gpt-5.4-mini"]);
});
it("adds the GPT-5 prompt overlay to Codex provider runs", () => {

View File

@@ -237,7 +237,5 @@ function isKnownXHighCodexModel(modelId: string): boolean {
// CLI default. (#71946)
export function isModernCodexModel(modelId: string): boolean {
const lower = modelId.trim().toLowerCase();
return (
lower === "gpt-5.5" || lower === "gpt-5.4" || lower === "gpt-5.4-mini" || lower === "gpt-5.2"
);
return lower === "gpt-5.5" || lower === "gpt-5.4" || lower === "gpt-5.4-mini";
}

View File

@@ -172,13 +172,13 @@ describe("listCodexAppServerModels", () => {
result: {
data: [
{
id: "gpt-5.2",
model: "gpt-5.2",
id: "gpt-5.5",
model: "gpt-5.5",
upgrade: null,
upgradeInfo: null,
availabilityNux: null,
displayName: "gpt-5.2",
description: "GPT-5.2",
displayName: "gpt-5.5",
description: "GPT-5.5",
hidden: false,
inputModalities: ["text", "image"],
supportedReasoningEfforts: [],
@@ -193,7 +193,7 @@ describe("listCodexAppServerModels", () => {
});
const list = await listPromise;
expect(list.models.map((model) => model.id)).toEqual(["gpt-5.4", "gpt-5.2"]);
expect(list.models.map((model) => model.id)).toEqual(["gpt-5.4", "gpt-5.5"]);
harness.client.close();
startSpy.mockRestore();
});

View File

@@ -421,14 +421,14 @@ describe("Codex app-server model provider selection", () => {
describe("resolveReasoningEffort (#71946)", () => {
describe("modern Codex models (none/low/medium/high/xhigh enum)", () => {
it.each(["gpt-5.5", "gpt-5.4", "gpt-5.4-mini", "gpt-5.2"] as const)(
it.each(["gpt-5.5", "gpt-5.4", "gpt-5.4-mini"] as const)(
"translates 'minimal' -> 'low' for %s so the first request is accepted",
(modelId) => {
expect(resolveReasoningEffort("minimal", modelId)).toBe("low");
},
);
it.each(["gpt-5.5", "gpt-5.4", "gpt-5.4-mini", "gpt-5.2"] as const)(
it.each(["gpt-5.5", "gpt-5.4", "gpt-5.4-mini"] as const)(
"passes 'low' / 'medium' / 'high' / 'xhigh' through unchanged for %s",
(modelId) => {
expect(resolveReasoningEffort("low", modelId)).toBe("low");

View File

@@ -979,7 +979,7 @@ export function resolveCodexAppServerModelProvider(params: {
return normalizedLower === "openai-codex" ? "openai" : normalized;
}
// Modern Codex models (gpt-5.5, gpt-5.4, gpt-5.4-mini, gpt-5.2) use the
// Modern Codex models (gpt-5.5, gpt-5.4, gpt-5.4-mini) use the
// none/low/medium/high/xhigh effort enum and reject "minimal". The CLI
// defaults thinkLevel to "minimal", so without translation EVERY agent turn
// on those models pays a wasted first request + retry-with-low fallback in

View File

@@ -34,7 +34,7 @@ import { wrapCopilotProviderStream } from "./stream.js";
const COPILOT_ENV_VARS = ["COPILOT_GITHUB_TOKEN", "GH_TOKEN", "GITHUB_TOKEN"];
const DEFAULT_COPILOT_MODEL = "github-copilot/claude-opus-4.7";
const DEFAULT_COPILOT_PROFILE_ID = "github-copilot:github";
const COPILOT_XHIGH_MODEL_IDS = ["gpt-5.4", "gpt-5.3-codex", "gpt-5.2", "gpt-5.2-codex"] as const;
const COPILOT_XHIGH_MODEL_IDS = ["gpt-5.4", "gpt-5.3-codex"] as const;
type GithubCopilotPluginConfig = {
discovery?: {

View File

@@ -18,10 +18,6 @@ const DEFAULT_MODEL_IDS = [
"gemini-2.5-pro",
"gemini-3-flash",
"gemini-3.1-pro",
"gpt-4.1",
"gpt-5-mini",
"gpt-5.2",
"gpt-5.2-codex",
"gpt-5.3-codex",
"gpt-5.4",
"gpt-5.4-mini",

View File

@@ -148,17 +148,17 @@ describe("resolveCopilotForwardCompatModel", () => {
expect(resolveCopilotForwardCompatModel(ctx)).toBeUndefined();
});
it("clones gpt-5.2-codex template for gpt-5.4", () => {
it("clones gpt-5.3-codex template for gpt-5.4", () => {
const template = {
id: "gpt-5.2-codex",
name: "gpt-5.2-codex",
id: "gpt-5.3-codex",
name: "gpt-5.3-codex",
provider: "github-copilot",
api: "openai-responses",
reasoning: true,
contextWindow: 200_000,
};
const ctx = createMockCtx("gpt-5.4", {
"github-copilot/gpt-5.2-codex": template,
"github-copilot/gpt-5.3-codex": template,
});
const result = requireResolvedModel(ctx);
expect(result.id).toBe("gpt-5.4");
@@ -166,25 +166,15 @@ describe("resolveCopilotForwardCompatModel", () => {
expect((result as unknown as Record<string, unknown>).reasoning).toBe(true);
});
it("clones gpt-5.3-codex template for gpt-5.3-codex when not in registry", () => {
const template = {
id: "gpt-5.2-codex",
name: "gpt-5.2-codex",
provider: "github-copilot",
api: "openai-responses",
reasoning: true,
contextWindow: 200_000,
};
const ctx = createMockCtx("gpt-5.3-codex", {
"github-copilot/gpt-5.2-codex": template,
});
it("uses static metadata for gpt-5.3-codex when not in registry", () => {
const ctx = createMockCtx("gpt-5.3-codex");
const result = requireResolvedModel(ctx);
expect(result.id).toBe("gpt-5.3-codex");
expect(result.name).toBe("gpt-5.3-codex");
expect((result as unknown as Record<string, unknown>).reasoning).toBe(true);
});
it("prefers gpt-5.3-codex as template source over gpt-5.2-codex for gpt-5.4", () => {
it("uses gpt-5.3-codex as the template source for gpt-5.4", () => {
const template53 = {
id: "gpt-5.3-codex",
name: "gpt-5.3-codex",
@@ -193,17 +183,8 @@ describe("resolveCopilotForwardCompatModel", () => {
reasoning: true,
contextWindow: 300_000,
};
const template52 = {
id: "gpt-5.2-codex",
name: "gpt-5.2-codex",
provider: "github-copilot",
api: "openai-responses",
reasoning: true,
contextWindow: 200_000,
};
const ctx = createMockCtx("gpt-5.4", {
"github-copilot/gpt-5.3-codex": template53,
"github-copilot/gpt-5.2-codex": template52,
});
const result = requireResolvedModel(ctx);
expect(result.id).toBe("gpt-5.4");

View File

@@ -17,7 +17,7 @@ export const PROVIDER_ID = "github-copilot";
const CODEX_FORWARD_COMPAT_TARGET_IDS = new Set(["gpt-5.4", "gpt-5.3-codex"]);
// gpt-5.3-codex is only a useful template when gpt-5.4 is the target; it is
// always a registry miss (and therefore skipped) when it is the target itself.
const CODEX_TEMPLATE_MODEL_IDS = ["gpt-5.3-codex", "gpt-5.2-codex"] as const;
const CODEX_TEMPLATE_MODEL_IDS = ["gpt-5.3-codex"] as const;
const DEFAULT_CONTEXT_WINDOW = 128_000;
const DEFAULT_MAX_TOKENS = 8192;

View File

@@ -75,41 +75,6 @@
"maxTokens": 8192,
"cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 }
},
{
"id": "gpt-4.1",
"name": "GPT-4.1",
"input": ["text", "image"],
"contextWindow": 128000,
"maxTokens": 8192,
"cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 }
},
{
"id": "gpt-5-mini",
"name": "GPT-5 mini",
"reasoning": true,
"input": ["text", "image"],
"contextWindow": 128000,
"maxTokens": 8192,
"cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 }
},
{
"id": "gpt-5.2",
"name": "GPT-5.2",
"reasoning": true,
"input": ["text", "image"],
"contextWindow": 128000,
"maxTokens": 8192,
"cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 }
},
{
"id": "gpt-5.2-codex",
"name": "GPT-5.2-Codex",
"reasoning": true,
"input": ["text"],
"contextWindow": 128000,
"maxTokens": 8192,
"cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 }
},
{
"id": "gpt-5.3-codex",
"name": "GPT-5.3-Codex",

View File

@@ -33,34 +33,6 @@
"baseUrl": "https://api.groq.com/openai/v1",
"api": "openai-completions",
"models": [
{
"id": "deepseek-r1-distill-llama-70b",
"name": "DeepSeek R1 Distill Llama 70B",
"reasoning": true,
"input": ["text"],
"contextWindow": 131072,
"maxTokens": 8192,
"cost": {
"input": 0.75,
"output": 0.99,
"cacheRead": 0,
"cacheWrite": 0
}
},
{
"id": "gemma2-9b-it",
"name": "Gemma 2 9B",
"reasoning": false,
"input": ["text"],
"contextWindow": 8192,
"maxTokens": 8192,
"cost": {
"input": 0.2,
"output": 0.2,
"cacheRead": 0,
"cacheWrite": 0
}
},
{
"id": "groq/compound",
"name": "Compound",
@@ -117,48 +89,6 @@
"cacheWrite": 0
}
},
{
"id": "llama3-70b-8192",
"name": "Llama 3 70B",
"reasoning": false,
"input": ["text"],
"contextWindow": 8192,
"maxTokens": 8192,
"cost": {
"input": 0.59,
"output": 0.79,
"cacheRead": 0,
"cacheWrite": 0
}
},
{
"id": "llama3-8b-8192",
"name": "Llama 3 8B",
"reasoning": false,
"input": ["text"],
"contextWindow": 8192,
"maxTokens": 8192,
"cost": {
"input": 0.05,
"output": 0.08,
"cacheRead": 0,
"cacheWrite": 0
}
},
{
"id": "meta-llama/llama-4-maverick-17b-128e-instruct",
"name": "Llama 4 Maverick 17B",
"reasoning": false,
"input": ["text", "image"],
"contextWindow": 131072,
"maxTokens": 8192,
"cost": {
"input": 0.2,
"output": 0.6,
"cacheRead": 0,
"cacheWrite": 0
}
},
{
"id": "meta-llama/llama-4-scout-17b-16e-instruct",
"name": "Llama 4 Scout 17B",
@@ -173,48 +103,6 @@
"cacheWrite": 0
}
},
{
"id": "mistral-saba-24b",
"name": "Mistral Saba 24B",
"reasoning": false,
"input": ["text"],
"contextWindow": 32768,
"maxTokens": 32768,
"cost": {
"input": 0.79,
"output": 0.79,
"cacheRead": 0,
"cacheWrite": 0
}
},
{
"id": "moonshotai/kimi-k2-instruct",
"name": "Kimi K2 Instruct",
"reasoning": false,
"input": ["text"],
"contextWindow": 131072,
"maxTokens": 16384,
"cost": {
"input": 1,
"output": 3,
"cacheRead": 0,
"cacheWrite": 0
}
},
{
"id": "moonshotai/kimi-k2-instruct-0905",
"name": "Kimi K2 Instruct 0905",
"reasoning": false,
"input": ["text"],
"contextWindow": 262144,
"maxTokens": 16384,
"cost": {
"input": 1,
"output": 3,
"cacheRead": 0,
"cacheWrite": 0
}
},
{
"id": "openai/gpt-oss-120b",
"name": "GPT OSS 120B",
@@ -257,20 +145,6 @@
"cacheWrite": 0
}
},
{
"id": "qwen-qwq-32b",
"name": "Qwen QwQ 32B",
"reasoning": true,
"input": ["text"],
"contextWindow": 131072,
"maxTokens": 16384,
"cost": {
"input": 0.29,
"output": 0.39,
"cacheRead": 0,
"cacheWrite": 0
}
},
{
"id": "qwen/qwen3-32b",
"name": "Qwen3 32B",

View File

@@ -95,7 +95,7 @@ const OPENAI_CODEX_GPT_54_MINI_COST = {
cacheRead: 0.075,
cacheWrite: 0,
} as const;
const OPENAI_CODEX_GPT_54_TEMPLATE_MODEL_IDS = ["gpt-5.3-codex", "gpt-5.2-codex"] as const;
const OPENAI_CODEX_GPT_54_TEMPLATE_MODEL_IDS = ["gpt-5.3-codex"] as const;
/** Legacy codex rows first; fall back to catalog `gpt-5.4` when the API omits 5.3/5.2. */
const OPENAI_CODEX_GPT_54_CATALOG_SYNTH_TEMPLATE_MODEL_IDS = [
...OPENAI_CODEX_GPT_54_TEMPLATE_MODEL_IDS,

View File

@@ -435,7 +435,7 @@ describe("buildOpenAIProvider", () => {
expectNoCatalogEntry(entries, "chat-latest");
});
it("keeps modern live selection on OpenAI 5.2+ and current Codex models", () => {
it("keeps modern live selection on current OpenAI and Codex models", () => {
const provider = buildOpenAIProvider();
const codexProvider = buildOpenAICodexProviderPlugin();
@@ -450,7 +450,7 @@ describe("buildOpenAIProvider", () => {
provider: "openai",
modelId: "gpt-5.2",
} as never),
).toBe(true);
).toBe(false);
expect(
provider.isModernModelRef?.({
provider: "openai",

View File

@@ -55,17 +55,14 @@ const OPENAI_GPT_54_NANO_COST = {
const OPENAI_GPT_55_PRO_TEMPLATE_MODEL_IDS = [
OPENAI_GPT_54_PRO_MODEL_ID,
OPENAI_GPT_54_MODEL_ID,
"gpt-5.2-pro",
"gpt-5.2",
] as const;
const OPENAI_GPT_54_TEMPLATE_MODEL_IDS = ["gpt-5.2"] as const;
const OPENAI_GPT_54_PRO_TEMPLATE_MODEL_IDS = ["gpt-5.2-pro", "gpt-5.2"] as const;
const OPENAI_GPT_54_TEMPLATE_MODEL_IDS = [OPENAI_GPT_55_MODEL_ID] as const;
const OPENAI_GPT_54_PRO_TEMPLATE_MODEL_IDS = [OPENAI_GPT_55_PRO_MODEL_ID] as const;
const OPENAI_GPT_54_MINI_TEMPLATE_MODEL_IDS = ["gpt-5-mini"] as const;
const OPENAI_GPT_54_NANO_TEMPLATE_MODEL_IDS = ["gpt-5-nano", "gpt-5-mini"] as const;
const OPENAI_CHAT_LATEST_TEMPLATE_MODEL_IDS = [
OPENAI_GPT_55_MODEL_ID,
OPENAI_GPT_54_MODEL_ID,
"gpt-5.2",
] as const;
const OPENAI_MODERN_MODEL_IDS = [
OPENAI_CHAT_LATEST_MODEL_ID,
@@ -75,7 +72,6 @@ const OPENAI_MODERN_MODEL_IDS = [
OPENAI_GPT_54_PRO_MODEL_ID,
OPENAI_GPT_54_MINI_MODEL_ID,
OPENAI_GPT_54_NANO_MODEL_ID,
"gpt-5.2",
] as const;
function shouldUseOpenAIResponsesTransport(params: {

View File

@@ -50,356 +50,6 @@
"baseUrl": "https://api.openai.com/v1",
"api": "openai-responses",
"models": [
{
"id": "gpt-4",
"name": "GPT-4",
"reasoning": false,
"input": ["text"],
"contextWindow": 8192,
"maxTokens": 8192,
"cost": {
"input": 30,
"output": 60,
"cacheRead": 0,
"cacheWrite": 0
}
},
{
"id": "gpt-4-turbo",
"name": "GPT-4 Turbo",
"reasoning": false,
"input": ["text", "image"],
"contextWindow": 128000,
"maxTokens": 4096,
"cost": {
"input": 10,
"output": 30,
"cacheRead": 0,
"cacheWrite": 0
}
},
{
"id": "gpt-4.1",
"name": "GPT-4.1",
"reasoning": false,
"input": ["text", "image"],
"contextWindow": 1047576,
"maxTokens": 32768,
"cost": {
"input": 2,
"output": 8,
"cacheRead": 0.5,
"cacheWrite": 0
}
},
{
"id": "gpt-4.1-mini",
"name": "GPT-4.1 mini",
"reasoning": false,
"input": ["text", "image"],
"contextWindow": 1047576,
"maxTokens": 32768,
"cost": {
"input": 0.4,
"output": 1.6,
"cacheRead": 0.1,
"cacheWrite": 0
}
},
{
"id": "gpt-4.1-nano",
"name": "GPT-4.1 nano",
"reasoning": false,
"input": ["text", "image"],
"contextWindow": 1047576,
"maxTokens": 32768,
"cost": {
"input": 0.1,
"output": 0.4,
"cacheRead": 0.03,
"cacheWrite": 0
}
},
{
"id": "gpt-4o",
"name": "GPT-4o",
"reasoning": false,
"input": ["text", "image"],
"contextWindow": 128000,
"maxTokens": 16384,
"cost": {
"input": 2.5,
"output": 10,
"cacheRead": 1.25,
"cacheWrite": 0
}
},
{
"id": "gpt-4o-2024-05-13",
"name": "GPT-4o (2024-05-13)",
"reasoning": false,
"input": ["text", "image"],
"contextWindow": 128000,
"maxTokens": 4096,
"cost": {
"input": 5,
"output": 15,
"cacheRead": 0,
"cacheWrite": 0
}
},
{
"id": "gpt-4o-2024-08-06",
"name": "GPT-4o (2024-08-06)",
"reasoning": false,
"input": ["text", "image"],
"contextWindow": 128000,
"maxTokens": 16384,
"cost": {
"input": 2.5,
"output": 10,
"cacheRead": 1.25,
"cacheWrite": 0
}
},
{
"id": "gpt-4o-2024-11-20",
"name": "GPT-4o (2024-11-20)",
"reasoning": false,
"input": ["text", "image"],
"contextWindow": 128000,
"maxTokens": 16384,
"cost": {
"input": 2.5,
"output": 10,
"cacheRead": 1.25,
"cacheWrite": 0
}
},
{
"id": "gpt-4o-mini",
"name": "GPT-4o mini",
"reasoning": false,
"input": ["text", "image"],
"contextWindow": 128000,
"maxTokens": 16384,
"cost": {
"input": 0.15,
"output": 0.6,
"cacheRead": 0.08,
"cacheWrite": 0
}
},
{
"id": "gpt-5",
"name": "GPT-5",
"reasoning": true,
"input": ["text", "image"],
"contextWindow": 400000,
"maxTokens": 128000,
"cost": {
"input": 1.25,
"output": 10,
"cacheRead": 0.125,
"cacheWrite": 0
}
},
{
"id": "gpt-5-chat-latest",
"name": "GPT-5 Chat Latest",
"reasoning": false,
"input": ["text", "image"],
"contextWindow": 128000,
"maxTokens": 16384,
"cost": {
"input": 1.25,
"output": 10,
"cacheRead": 0.125,
"cacheWrite": 0
}
},
{
"id": "gpt-5-codex",
"name": "GPT-5-Codex",
"reasoning": true,
"input": ["text", "image"],
"contextWindow": 400000,
"maxTokens": 128000,
"cost": {
"input": 1.25,
"output": 10,
"cacheRead": 0.125,
"cacheWrite": 0
}
},
{
"id": "gpt-5-mini",
"name": "GPT-5 Mini",
"reasoning": true,
"input": ["text", "image"],
"contextWindow": 400000,
"maxTokens": 128000,
"cost": {
"input": 0.25,
"output": 2,
"cacheRead": 0.025,
"cacheWrite": 0
}
},
{
"id": "gpt-5-nano",
"name": "GPT-5 Nano",
"reasoning": true,
"input": ["text", "image"],
"contextWindow": 400000,
"maxTokens": 128000,
"cost": {
"input": 0.05,
"output": 0.4,
"cacheRead": 0.005,
"cacheWrite": 0
}
},
{
"id": "gpt-5-pro",
"name": "GPT-5 Pro",
"reasoning": true,
"input": ["text", "image"],
"contextWindow": 400000,
"maxTokens": 272000,
"cost": {
"input": 15,
"output": 120,
"cacheRead": 0,
"cacheWrite": 0
}
},
{
"id": "gpt-5.1",
"name": "GPT-5.1",
"reasoning": true,
"input": ["text", "image"],
"contextWindow": 400000,
"maxTokens": 128000,
"cost": {
"input": 1.25,
"output": 10,
"cacheRead": 0.13,
"cacheWrite": 0
}
},
{
"id": "gpt-5.1-chat-latest",
"name": "GPT-5.1 Chat",
"reasoning": true,
"input": ["text", "image"],
"contextWindow": 128000,
"maxTokens": 16384,
"cost": {
"input": 1.25,
"output": 10,
"cacheRead": 0.125,
"cacheWrite": 0
}
},
{
"id": "gpt-5.1-codex",
"name": "GPT-5.1 Codex",
"reasoning": true,
"input": ["text", "image"],
"contextWindow": 400000,
"maxTokens": 128000,
"cost": {
"input": 1.25,
"output": 10,
"cacheRead": 0.125,
"cacheWrite": 0
}
},
{
"id": "gpt-5.1-codex-max",
"name": "GPT-5.1 Codex Max",
"reasoning": true,
"input": ["text", "image"],
"contextWindow": 400000,
"maxTokens": 128000,
"cost": {
"input": 1.25,
"output": 10,
"cacheRead": 0.125,
"cacheWrite": 0
}
},
{
"id": "gpt-5.1-codex-mini",
"name": "GPT-5.1 Codex mini",
"reasoning": true,
"input": ["text", "image"],
"contextWindow": 400000,
"maxTokens": 128000,
"cost": {
"input": 0.25,
"output": 2,
"cacheRead": 0.025,
"cacheWrite": 0
}
},
{
"id": "gpt-5.2",
"name": "GPT-5.2",
"reasoning": true,
"input": ["text", "image"],
"contextWindow": 400000,
"maxTokens": 128000,
"cost": {
"input": 1.75,
"output": 14,
"cacheRead": 0.175,
"cacheWrite": 0
}
},
{
"id": "gpt-5.2-chat-latest",
"name": "GPT-5.2 Chat",
"reasoning": true,
"input": ["text", "image"],
"contextWindow": 128000,
"maxTokens": 16384,
"cost": {
"input": 1.75,
"output": 14,
"cacheRead": 0.175,
"cacheWrite": 0
}
},
{
"id": "gpt-5.2-codex",
"name": "GPT-5.2 Codex",
"reasoning": true,
"input": ["text", "image"],
"contextWindow": 400000,
"maxTokens": 128000,
"cost": {
"input": 1.75,
"output": 14,
"cacheRead": 0.175,
"cacheWrite": 0
}
},
{
"id": "gpt-5.2-pro",
"name": "GPT-5.2 Pro",
"reasoning": true,
"input": ["text", "image"],
"contextWindow": 400000,
"maxTokens": 128000,
"cost": {
"input": 21,
"output": 168,
"cacheRead": 0,
"cacheWrite": 0
}
},
{
"id": "gpt-5.3-chat-latest",
"name": "GPT-5.3 Chat (latest)",
@@ -407,12 +57,7 @@
"input": ["text", "image"],
"contextWindow": 128000,
"maxTokens": 16384,
"cost": {
"input": 1.75,
"output": 14,
"cacheRead": 0.175,
"cacheWrite": 0
}
"cost": { "input": 1.75, "output": 14, "cacheRead": 0.175, "cacheWrite": 0 }
},
{
"id": "gpt-5.3-codex",
@@ -421,12 +66,7 @@
"input": ["text", "image"],
"contextWindow": 400000,
"maxTokens": 128000,
"cost": {
"input": 1.75,
"output": 14,
"cacheRead": 0.175,
"cacheWrite": 0
}
"cost": { "input": 1.75, "output": 14, "cacheRead": 0.175, "cacheWrite": 0 }
},
{
"id": "gpt-5.4",
@@ -435,12 +75,7 @@
"input": ["text", "image"],
"contextWindow": 272000,
"maxTokens": 128000,
"cost": {
"input": 2.5,
"output": 15,
"cacheRead": 0.25,
"cacheWrite": 0
}
"cost": { "input": 2.5, "output": 15, "cacheRead": 0.25, "cacheWrite": 0 }
},
{
"id": "gpt-5.4-mini",
@@ -449,12 +84,7 @@
"input": ["text", "image"],
"contextWindow": 400000,
"maxTokens": 128000,
"cost": {
"input": 0.75,
"output": 4.5,
"cacheRead": 0.075,
"cacheWrite": 0
}
"cost": { "input": 0.75, "output": 4.5, "cacheRead": 0.075, "cacheWrite": 0 }
},
{
"id": "gpt-5.4-nano",
@@ -463,12 +93,7 @@
"input": ["text", "image"],
"contextWindow": 400000,
"maxTokens": 128000,
"cost": {
"input": 0.2,
"output": 1.25,
"cacheRead": 0.02,
"cacheWrite": 0
}
"cost": { "input": 0.2, "output": 1.25, "cacheRead": 0.02, "cacheWrite": 0 }
},
{
"id": "gpt-5.4-pro",
@@ -477,12 +102,7 @@
"input": ["text", "image"],
"contextWindow": 1050000,
"maxTokens": 128000,
"cost": {
"input": 30,
"output": 180,
"cacheRead": 0,
"cacheWrite": 0
}
"cost": { "input": 30, "output": 180, "cacheRead": 0, "cacheWrite": 0 }
},
{
"id": "gpt-5.5",
@@ -491,12 +111,7 @@
"input": ["text", "image"],
"contextWindow": 272000,
"maxTokens": 128000,
"cost": {
"input": 5,
"output": 30,
"cacheRead": 0.5,
"cacheWrite": 0
}
"cost": { "input": 5, "output": 30, "cacheRead": 0.5, "cacheWrite": 0 }
},
{
"id": "o1",
@@ -505,12 +120,7 @@
"input": ["text", "image"],
"contextWindow": 200000,
"maxTokens": 100000,
"cost": {
"input": 15,
"output": 60,
"cacheRead": 7.5,
"cacheWrite": 0
}
"cost": { "input": 15, "output": 60, "cacheRead": 7.5, "cacheWrite": 0 }
},
{
"id": "o1-pro",
@@ -519,12 +129,7 @@
"input": ["text", "image"],
"contextWindow": 200000,
"maxTokens": 100000,
"cost": {
"input": 150,
"output": 600,
"cacheRead": 0,
"cacheWrite": 0
}
"cost": { "input": 150, "output": 600, "cacheRead": 0, "cacheWrite": 0 }
},
{
"id": "o3",
@@ -533,12 +138,7 @@
"input": ["text", "image"],
"contextWindow": 200000,
"maxTokens": 100000,
"cost": {
"input": 2,
"output": 8,
"cacheRead": 0.5,
"cacheWrite": 0
}
"cost": { "input": 2, "output": 8, "cacheRead": 0.5, "cacheWrite": 0 }
},
{
"id": "o3-deep-research",
@@ -547,12 +147,7 @@
"input": ["text", "image"],
"contextWindow": 200000,
"maxTokens": 100000,
"cost": {
"input": 10,
"output": 40,
"cacheRead": 2.5,
"cacheWrite": 0
}
"cost": { "input": 10, "output": 40, "cacheRead": 2.5, "cacheWrite": 0 }
},
{
"id": "o3-mini",
@@ -561,12 +156,7 @@
"input": ["text"],
"contextWindow": 200000,
"maxTokens": 100000,
"cost": {
"input": 1.1,
"output": 4.4,
"cacheRead": 0.55,
"cacheWrite": 0
}
"cost": { "input": 1.1, "output": 4.4, "cacheRead": 0.55, "cacheWrite": 0 }
},
{
"id": "o3-pro",
@@ -575,12 +165,7 @@
"input": ["text", "image"],
"contextWindow": 200000,
"maxTokens": 100000,
"cost": {
"input": 20,
"output": 80,
"cacheRead": 0,
"cacheWrite": 0
}
"cost": { "input": 20, "output": 80, "cacheRead": 0, "cacheWrite": 0 }
},
{
"id": "o4-mini",
@@ -589,12 +174,7 @@
"input": ["text", "image"],
"contextWindow": 200000,
"maxTokens": 100000,
"cost": {
"input": 1.1,
"output": 4.4,
"cacheRead": 0.28,
"cacheWrite": 0
}
"cost": { "input": 1.1, "output": 4.4, "cacheRead": 0.28, "cacheWrite": 0 }
},
{
"id": "o4-mini-deep-research",
@@ -603,12 +183,7 @@
"input": ["text", "image"],
"contextWindow": 200000,
"maxTokens": 100000,
"cost": {
"input": 2,
"output": 8,
"cacheRead": 0.5,
"cacheWrite": 0
}
"cost": { "input": 2, "output": 8, "cacheRead": 0.5, "cacheWrite": 0 }
},
{
"id": "gpt-5.5-pro",
@@ -617,12 +192,7 @@
"input": ["text", "image"],
"contextWindow": 1000000,
"maxTokens": 128000,
"cost": {
"input": 30,
"output": 180,
"cacheRead": 0,
"cacheWrite": 0
}
"cost": { "input": 30, "output": 180, "cacheRead": 0, "cacheWrite": 0 }
}
]
},
@@ -638,12 +208,7 @@
"contextWindow": 400000,
"contextTokens": 272000,
"maxTokens": 128000,
"cost": {
"input": 5,
"output": 30,
"cacheRead": 0.5,
"cacheWrite": 0
}
"cost": { "input": 5, "output": 30, "cacheRead": 0.5, "cacheWrite": 0 }
},
{
"id": "gpt-5.4",
@@ -653,12 +218,7 @@
"contextWindow": 1050000,
"contextTokens": 272000,
"maxTokens": 128000,
"cost": {
"input": 2.5,
"output": 15,
"cacheRead": 0.25,
"cacheWrite": 0
}
"cost": { "input": 2.5, "output": 15, "cacheRead": 0.25, "cacheWrite": 0 }
},
{
"id": "gpt-5.4-pro",
@@ -668,12 +228,7 @@
"contextWindow": 1050000,
"contextTokens": 272000,
"maxTokens": 128000,
"cost": {
"input": 30,
"output": 180,
"cacheRead": 0,
"cacheWrite": 0
}
"cost": { "input": 30, "output": 180, "cacheRead": 0, "cacheWrite": 0 }
},
{
"id": "gpt-5.4-mini",
@@ -683,12 +238,7 @@
"contextWindow": 400000,
"contextTokens": 272000,
"maxTokens": 128000,
"cost": {
"input": 0.75,
"output": 4.5,
"cacheRead": 0.075,
"cacheWrite": 0
}
"cost": { "input": 0.75, "output": 4.5, "cacheRead": 0.075, "cacheWrite": 0 }
},
{
"id": "gpt-5.5-pro",
@@ -698,12 +248,7 @@
"contextWindow": 1000000,
"contextTokens": 272000,
"maxTokens": 128000,
"cost": {
"input": 30,
"output": 180,
"cacheRead": 0,
"cacheWrite": 0
}
"cost": { "input": 30, "output": 180, "cacheRead": 0, "cacheWrite": 0 }
}
]
}

View File

@@ -15,7 +15,6 @@ const OPENAI_XHIGH_MODEL_IDS = [
"gpt-5.4-pro",
"gpt-5.4-mini",
"gpt-5.4-nano",
"gpt-5.2",
] as const;
const OPENAI_CODEX_XHIGH_MODEL_IDS = ["gpt-5.5", "gpt-5.5-pro", "gpt-5.4", "gpt-5.4-pro"] as const;

View File

@@ -10,11 +10,6 @@
"providers": {
"xai": {
"aliases": {
"grok-code-fast-1": "grok-build-0.1",
"grok-code-fast": "grok-build-0.1",
"grok-code-fast-1-0825": "grok-build-0.1",
"grok-4-fast-reasoning": "grok-4-fast",
"grok-4-1-fast-reasoning": "grok-4-1-fast",
"grok-4.20-experimental-beta-0304-reasoning": "grok-4.20-beta-latest-reasoning",
"grok-4.20-experimental-beta-0304-non-reasoning": "grok-4.20-beta-latest-non-reasoning",
"grok-4.20-reasoning": "grok-4.20-beta-latest-reasoning",

View File

@@ -1142,7 +1142,7 @@ describe("legacy migrate controlUi.allowedOrigins seed (issue #29385)", () => {
});
describe("legacy model compat migrate", () => {
it("upgrades retired Claude and Copilot model refs", () => {
it("upgrades retired model refs", () => {
const res = migrateLegacyConfigForTest({
agents: {
defaults: {
@@ -1169,13 +1169,30 @@ describe("legacy model compat migrate", () => {
"kilocode/anthropic/claude-sonnet-4",
"amazon-bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0",
"openai/gpt-5.5",
"openai/gpt-4o",
"openai/gpt-4.1-mini",
"openai/gpt-5.1-codex-mini",
"openai/gpt-5.2-codex",
"openai-codex/gpt-5.2",
"openai-codex/gpt-5.1-codex-mini",
"github-copilot/gpt-4.1",
"github-copilot/gpt-5.2",
"github-copilot/gpt-5.2-codex",
"groq/llama3-70b-8192",
"groq/gemma2-9b-it",
"groq/moonshotai/kimi-k2-instruct-0905",
"xai/grok-code-fast-1",
"xai/grok-4-fast-reasoning",
"openai/gpt-4o-transcribe",
"openai/gpt-4o-mini-tts",
],
},
models: {
"anthropic/claude-haiku-4-5": { alias: "haiku" },
"anthropic/claude-sonnet-4-6": { alias: "current-sonnet" },
"github-copilot/claude-opus-4.5": { alias: "copilot-opus" },
"github-copilot/gpt-5-mini": { alias: "mini" },
"openai/gpt-5.2-pro": { alias: "old-pro" },
"github-copilot/gpt-5-mini": { alias: "old-mini" },
},
},
},
@@ -1204,7 +1221,7 @@ describe("legacy model compat migrate", () => {
expect(res.config?.agents?.defaults?.imageModel).toBe("anthropic/claude-sonnet-4-6");
expect(res.config?.agents?.defaults?.imageGenerationModel).toEqual({
primary: "github-copilot/claude-sonnet-4.6",
fallbacks: ["github-copilot/gpt-5-mini"],
fallbacks: ["github-copilot/gpt-5.4-mini"],
});
expect(res.config?.agents?.defaults?.musicGenerationModel).toBe(
"vercel-ai-gateway/anthropic/claude-opus-4-6",
@@ -1216,7 +1233,7 @@ describe("legacy model compat migrate", () => {
fallbacks: [
"anthropic/claude-sonnet-4-6",
"github-copilot/claude-sonnet-4.6",
"github-copilot/gpt-5-mini@github:work",
"github-copilot/gpt-5.4-mini@github:work",
"venice/claude-opus-4-6",
"vercel-ai-gateway/anthropic/claude-opus-4-6",
"anthropic/claude-opus-5-0",
@@ -1225,13 +1242,30 @@ describe("legacy model compat migrate", () => {
"kilocode/anthropic/claude-sonnet-4",
"amazon-bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0",
"openai/gpt-5.5",
"openai/gpt-5.5",
"openai/gpt-5.4-mini",
"openai/gpt-5.4-mini",
"openai/gpt-5.3-codex",
"openai-codex/gpt-5.5",
"openai-codex/gpt-5.4-mini",
"github-copilot/gpt-5.5",
"github-copilot/gpt-5.5",
"github-copilot/gpt-5.3-codex",
"groq/llama-3.3-70b-versatile",
"groq/llama-3.1-8b-instant",
"groq/openai/gpt-oss-120b",
"xai/grok-build-0.1",
"xai/grok-4.3",
"openai/gpt-4o-transcribe",
"openai/gpt-4o-mini-tts",
],
});
expect(res.config?.agents?.defaults?.workspace).toBe("/tmp/claude-3-sonnet");
expect(res.config?.agents?.defaults?.models).toEqual({
"anthropic/claude-sonnet-4-6": { alias: "current-sonnet" },
"github-copilot/claude-opus-4.7": { alias: "copilot-opus" },
"github-copilot/gpt-5-mini": { alias: "mini" },
"openai/gpt-5.5-pro": { alias: "old-pro" },
"github-copilot/gpt-5.4-mini": { alias: "old-mini" },
});
expect(
(res.config?.plugins?.entries?.["lossless-claw"] as { config?: { summaryModel?: string } })
@@ -1252,14 +1286,30 @@ describe("legacy model compat migrate", () => {
expectMigrationChangesToIncludeFragments(res.changes, [
'config.agents.defaults.imageModel from "anthropic/claude-haiku-4-5" to "anthropic/claude-sonnet-4-6"',
'config.agents.defaults.imageGenerationModel.primary from "github-copilot/claude-sonnet-4" to "github-copilot/claude-sonnet-4.6"',
'config.agents.defaults.imageGenerationModel.fallbacks.0 from "github-copilot/grok-code-fast-1" to "github-copilot/gpt-5-mini"',
'config.agents.defaults.imageGenerationModel.fallbacks.0 from "github-copilot/grok-code-fast-1" to "github-copilot/gpt-5.4-mini"',
'config.agents.defaults.musicGenerationModel from "vercel-ai-gateway/anthropic/claude-opus-4-5" to "vercel-ai-gateway/anthropic/claude-opus-4-6"',
'config.agents.defaults.pdfModel from "anthropic/claude-3-5-sonnet" to "anthropic/claude-sonnet-4-6"',
'config.agents.defaults.model.primary from "anthropic/claude-opus-4-5@anthropic:work" to "anthropic/claude-opus-4-7@anthropic:work"',
'config.agents.defaults.model.fallbacks.2 from "github-copilot/grok-code-fast-1@github:work" to "github-copilot/gpt-5-mini@github:work"',
'config.agents.defaults.model.fallbacks.2 from "github-copilot/grok-code-fast-1@github:work" to "github-copilot/gpt-5.4-mini@github:work"',
'config.agents.defaults.model.fallbacks.3 from "venice/claude-opus-4-5" to "venice/claude-opus-4-6"',
'config.agents.defaults.model.fallbacks.4 from "vercel-ai-gateway/anthropic/claude-opus-4-5" to "vercel-ai-gateway/anthropic/claude-opus-4-6"',
'config.agents.defaults.model.fallbacks.11 from "openai/gpt-4o" to "openai/gpt-5.5"',
'config.agents.defaults.model.fallbacks.12 from "openai/gpt-4.1-mini" to "openai/gpt-5.4-mini"',
'config.agents.defaults.model.fallbacks.13 from "openai/gpt-5.1-codex-mini" to "openai/gpt-5.4-mini"',
'config.agents.defaults.model.fallbacks.14 from "openai/gpt-5.2-codex" to "openai/gpt-5.3-codex"',
'config.agents.defaults.model.fallbacks.15 from "openai-codex/gpt-5.2" to "openai-codex/gpt-5.5"',
'config.agents.defaults.model.fallbacks.16 from "openai-codex/gpt-5.1-codex-mini" to "openai-codex/gpt-5.4-mini"',
'config.agents.defaults.model.fallbacks.17 from "github-copilot/gpt-4.1" to "github-copilot/gpt-5.5"',
'config.agents.defaults.model.fallbacks.18 from "github-copilot/gpt-5.2" to "github-copilot/gpt-5.5"',
'config.agents.defaults.model.fallbacks.19 from "github-copilot/gpt-5.2-codex" to "github-copilot/gpt-5.3-codex"',
'config.agents.defaults.model.fallbacks.20 from "groq/llama3-70b-8192" to "groq/llama-3.3-70b-versatile"',
'config.agents.defaults.model.fallbacks.21 from "groq/gemma2-9b-it" to "groq/llama-3.1-8b-instant"',
'config.agents.defaults.model.fallbacks.22 from "groq/moonshotai/kimi-k2-instruct-0905" to "groq/openai/gpt-oss-120b"',
'config.agents.defaults.model.fallbacks.23 from "xai/grok-code-fast-1" to "xai/grok-build-0.1"',
'config.agents.defaults.model.fallbacks.24 from "xai/grok-4-fast-reasoning" to "xai/grok-4.3"',
'config.agents.defaults.models key from "github-copilot/claude-opus-4.5" to "github-copilot/claude-opus-4.7"',
'config.agents.defaults.models key from "openai/gpt-5.2-pro" to "openai/gpt-5.5-pro"',
'config.agents.defaults.models key from "github-copilot/gpt-5-mini" to "github-copilot/gpt-5.4-mini"',
'config.plugins.entries.lossless-claw.config.summaryModel from "anthropic/claude-3-5-sonnet" to "anthropic/claude-sonnet-4-6"',
'config.plugins.entries.lossless-claw.subagent.allowedModels.0 from "anthropic/claude-haiku-4-5" to "anthropic/claude-sonnet-4-6"',
'config.channels.modelByChannel.telegram.* from "anthropic/claude-opus-4-5" to "anthropic/claude-opus-4-7"',

View File

@@ -67,6 +67,94 @@ function shouldUpgradeClaudeProvider(provider: string | undefined): boolean {
);
}
function upgradeRetiredGroqModelId(model: string): string | null {
const normalized = normalizeString(model);
switch (normalized) {
case "deepseek-r1-distill-llama-70b":
return "llama-3.3-70b-versatile";
case "gemma2-9b-it":
case "llama3-8b-8192":
return "llama-3.1-8b-instant";
case "llama3-70b-8192":
return "llama-3.3-70b-versatile";
case "meta-llama/llama-4-maverick-17b-128e-instruct":
case "moonshotai/kimi-k2-instruct":
case "moonshotai/kimi-k2-instruct-0905":
return "openai/gpt-oss-120b";
case "mistral-saba-24b":
case "qwen-qwq-32b":
return "qwen/qwen3-32b";
default:
return null;
}
}
function upgradeRetiredXaiModelId(model: string): string | null {
const normalized = normalizeString(model);
switch (normalized) {
case "grok-code-fast":
case "grok-code-fast-1":
case "grok-code-fast-1-0825":
return "grok-build-0.1";
case "grok-4-fast-reasoning":
case "grok-4-1-fast-reasoning":
return "grok-4.3";
default:
return null;
}
}
function upgradeRetiredOpenAiModelId(model: string, provider?: string): string | null {
const normalized = normalizeString(model);
const codexProvider = provider === "openai-codex";
if (codexProvider && normalized === "gpt-5.2") {
return "gpt-5.5";
}
if (
normalized === "gpt-5.2-codex" ||
normalized === "gpt-5.1-codex" ||
normalized === "gpt-5-codex"
) {
return codexProvider ? "gpt-5.5" : "gpt-5.3-codex";
}
if (normalized === "gpt-5-pro" || normalized === "gpt-5.2-pro") {
return "gpt-5.5-pro";
}
if (normalized === "gpt-4.1-nano" || normalized === "gpt-5-nano") {
if (codexProvider) {
return "gpt-5.4-mini";
}
return "gpt-5.4-nano";
}
if (
normalized === "gpt-4.1-mini" ||
normalized === "gpt-4o-mini" ||
normalized === "gpt-5.1-codex-mini" ||
normalized === "gpt-5-mini"
) {
return "gpt-5.4-mini";
}
if (
normalized === "gpt-4" ||
normalized === "gpt-4-turbo" ||
normalized === "gpt-4.1" ||
normalized === "gpt-4o" ||
normalized === "gpt-4o-2024-05-13" ||
normalized === "gpt-4o-2024-08-06" ||
normalized === "gpt-4o-2024-11-20" ||
normalized === "gpt-5" ||
normalized === "gpt-5-chat-latest" ||
normalized === "gpt-5.1" ||
normalized === "gpt-5.1-chat-latest" ||
normalized === "gpt-5.1-codex-max" ||
normalized === "gpt-5.2" ||
normalized === "gpt-5.2-chat-latest"
) {
return "gpt-5.5";
}
return null;
}
function hasRetiredVersionPrefix(normalized: string, prefix: string): boolean {
if (normalized === prefix) {
return true;
@@ -217,11 +305,25 @@ function upgradeRetiredModelRef(value: string): string | null {
const normalizedProvider = normalizeString(provider);
const normalizedModel = normalizeString(model);
const retiredOwnerModel =
normalizedProvider === "groq"
? upgradeRetiredGroqModelId(model)
: normalizedProvider === "xai"
? upgradeRetiredXaiModelId(model)
: normalizedProvider === "openai" ||
normalizedProvider === "openai-codex" ||
normalizedProvider === "github-copilot"
? upgradeRetiredOpenAiModelId(model, normalizedProvider)
: undefined;
if (retiredOwnerModel) {
return `${provider}/${retiredOwnerModel}${split.profile ? `@${split.profile}` : ""}`;
}
if (
(normalizedProvider === "github-copilot" || normalizedProvider === "copilot-proxy") &&
normalizedModel === "grok-code-fast-1"
) {
return `${provider}/gpt-5-mini${split.profile ? `@${split.profile}` : ""}`;
return `${provider}/gpt-5.4-mini${split.profile ? `@${split.profile}` : ""}`;
}
if (!shouldUpgradeClaudeProvider(normalizedProvider || undefined)) {
return null;
@@ -372,7 +474,7 @@ function rewriteKnownModelRefs(
}
const RETIRED_MODEL_REF_MESSAGE =
'Configured Claude models older than 4.6 or retired Copilot model refs are no longer in the bundled catalogs; run "openclaw doctor --fix" to upgrade them.';
'Configured retired model refs are no longer in the bundled catalogs; run "openclaw doctor --fix" to upgrade them.';
const RETIRED_MODEL_REF_RULES: LegacyConfigRule[] = [
"agents",
"plugins",
@@ -389,8 +491,8 @@ const RETIRED_MODEL_REF_RULES: LegacyConfigRule[] = [
export const LEGACY_CONFIG_MIGRATIONS_RUNTIME_MODELS: LegacyConfigMigrationSpec[] = [
defineLegacyConfigMigration({
id: "models.retired-claude-and-copilot-refs",
describe: "Upgrade retired Claude/Copilot model refs to current catalog entries",
id: "models.retired-model-refs",
describe: "Upgrade retired model refs to current catalog entries",
legacyRules: RETIRED_MODEL_REF_RULES,
apply: (raw, changes) => {
const rewritten = rewriteKnownModelRefs(raw, "config", changes);