Skip to content

Commit d6dad9d

Browse files
SunnyShu0925claudevincentkoc
authored
fix(agents): detect bundled and legacy providers in model-not-found hint (#100120)
* [AI] fix(agents): detect legacy openai-codex provider in model-not-found hint In buildMissingProviderModelRegistrationHint, add an early-return check for the legacy openai-codex alias (via normalizeProviderId). Instead of suggesting a models.providers[] config entry that the config validator rejects without baseUrl, the hint now points operators to run openclaw doctor --fix for migration or check provider auth. Fixes #100066 Co-Authored-By: Claude <[email protected]> * fix(agents): cover legacy Codex provider config hint --------- Co-authored-by: Claude <[email protected]> Co-authored-by: Vincent Koc <[email protected]>
1 parent 133ca4b commit d6dad9d

2 files changed

Lines changed: 69 additions & 0 deletions

File tree

src/agents/embedded-agent-runner/model.test.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2832,6 +2832,69 @@ describe("resolveModel", () => {
28322832
);
28332833
});
28342834

2835+
it.each([
2836+
{
2837+
name: "agent model entry",
2838+
cfg: {
2839+
agents: {
2840+
defaults: {
2841+
models: {
2842+
"openai-codex/gpt-5.4": {},
2843+
},
2844+
},
2845+
},
2846+
},
2847+
},
2848+
{
2849+
name: "legacy provider config",
2850+
cfg: {
2851+
models: {
2852+
providers: {
2853+
"openai-codex": {
2854+
models: [{ id: "gpt-5.3-codex", name: "GPT-5.3 Codex" }],
2855+
},
2856+
},
2857+
},
2858+
},
2859+
},
2860+
])("suggests running doctor for openai-codex from $name", async ({ cfg }) => {
2861+
const result = await resolveModelAsync(
2862+
"openai-codex",
2863+
"gpt-5.4",
2864+
"/tmp/agent",
2865+
cfg as unknown as OpenClawConfig,
2866+
{
2867+
runtimeHooks: createRuntimeHooks(),
2868+
skipAgentDiscovery: true,
2869+
},
2870+
);
2871+
2872+
expect(result.error).toBe(
2873+
'Unknown model: openai-codex/gpt-5.4. "openai-codex" is a legacy provider ID. Run `openclaw doctor --fix` to migrate legacy model and provider config to the current OpenAI format. If the provider has no authenticated profile, run `openclaw models status` to check provider auth and re-authenticate if needed. See https://docs.openclaw.ai/concepts/model-providers.',
2874+
);
2875+
});
2876+
2877+
it("suggests adding config entry when a non-bundled provider model is missing", async () => {
2878+
const cfg = {
2879+
agents: {
2880+
defaults: {
2881+
models: {
2882+
"custom-provider/some-model": {},
2883+
},
2884+
},
2885+
},
2886+
} as unknown as OpenClawConfig;
2887+
2888+
const result = await resolveModelAsync("custom-provider", "some-model", "/tmp/agent", cfg, {
2889+
runtimeHooks: createRuntimeHooks(),
2890+
skipAgentDiscovery: true,
2891+
});
2892+
2893+
expect(result.error).toBe(
2894+
'Unknown model: custom-provider/some-model. Found agents.defaults.models["custom-provider/some-model"], but no matching models.providers["custom-provider"].models[] entry. Add { "id": "some-model", "name": "some-model" } to models.providers["custom-provider"].models[] to register this provider model. For custom or proxy providers, also set api and baseUrl so requests route to the intended endpoint. See https://docs.openclaw.ai/concepts/model-providers.',
2895+
);
2896+
});
2897+
28352898
it("points runtime-bound model entries at the runtime catalog instead of provider registration", async () => {
28362899
const cfg = {
28372900
agents: {

src/agents/embedded-agent-runner/model.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1908,6 +1908,12 @@ function buildMissingProviderModelRegistrationHint(params: {
19081908
modelId: string;
19091909
cfg?: OpenClawConfig;
19101910
}): string | undefined {
1911+
// Legacy openai-codex refs can come from model selections, provider config,
1912+
// or persisted routes. All of them should be repaired by doctor rather than
1913+
// turned into a new models.providers[] registration.
1914+
if (normalizeProviderId(params.provider) === "openai-codex") {
1915+
return `"openai-codex" is a legacy provider ID. Run \`openclaw doctor --fix\` to migrate legacy model and provider config to the current OpenAI format. If the provider has no authenticated profile, run \`openclaw models status\` to check provider auth and re-authenticate if needed. See https://docs.openclaw.ai/concepts/model-providers.`;
1916+
}
19111917
const configuredModels = params.cfg?.agents?.defaults?.models;
19121918
if (!configuredModels) {
19131919
return undefined;

0 commit comments

Comments
 (0)