fix(doctor): merge disjoint openai-codex model entries into canonical openai provider#90056
Conversation
|
Codex review: needs maintainer review before merge. Reviewed June 7, 2026, 4:27 AM ET / 08:27 UTC. Summary PR surface: Source +260, Tests +405. Total +665 across 4 files. Reproducibility: unclear. The review failed before ClawSweeper could establish a reproduction path. Review metrics: none identified. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Risk before merge
Maintainer options:
Next step before merge
Review detailsBest possible solution: Retry the Codex review after fixing the execution failure. Do we have a high-confidence way to reproduce the issue? Unclear. The review failed before ClawSweeper could establish a reproduction path. Is this the best way to solve the issue? Unclear. Retry the review first so ClawSweeper can evaluate the actual issue and fix direction. AGENTS.md: unclear because the file could not be read completely. Codex review notes: model gpt-5.5, reasoning high; reviewed against a58a6f63cac3. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +260, Tests +405. Total +665 across 4 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
91cdb40 to
1b1fa93
Compare
815da58 to
e5e6a11
Compare
|
Land-ready maintainer pass complete. What changed after review:
Local proof:
Autoreview:
GitHub CI on e5e6a11 is green, including check-test-types, check-lint, check-prod-types, build-artifacts, doctor-shared shard, and security/quality gates. |
… openai provider When both an openai-codex and an openai provider existed (e.g. codex for chat via OAuth, openai for embeddings via API key), the 2026.6.1 doctor migration silently dropped the entire openai-codex provider without carrying its model definitions over to the canonical openai provider, causing every agent turn to fail after a routine update. In migrateLegacyOpenAICodexProvider, replace the silent drop with a merge: collect model entries from the normalized legacy provider, skip those whose id or name already exists in the canonical provider (using separate id/name Sets to avoid cross-type false positives), and append the remaining disjoint entries. For each merged model that lacks its own baseUrl or api, stamp the legacy provider's values so the model continues to route to the correct endpoint (e.g. chatgpt.com/backend-api instead of api.openai.com/v1). An entry with neither id nor name is excluded to avoid duplicating malformed records. Only when no entries survive the filter is the old removal message emitted. Fixes openclaw#90047
e5e6a11 to
b9495fb
Compare
|
Final rebase/proof update:
|
Summary
openaiprovider exists for embeddings — agents go silent #90047 reports that the 2026.6.1 doctor migration silently drops the entireopenai-codexprovider when any canonicalopenaiprovider already exists — including cases where both serve disjoint purposes (e.g.openaifor embeddings via API key,openai-codexfor chat via OAuth/ChatGPT backend). After a routine update,gpt-5.5was gone and every agent turn failed.migrateLegacyOpenAICodexProvider(legacy-config-migrations.runtime.models.ts:997), theelsebranch for the shadowed-provider case recorded "Removed" and calleddelete providers[providerId]. The already-normalizednormalized.value— containing the API-renamed model entries — was discarded without checking for model rows absent from the canonical provider. The branch assumed a canonicalopenaiprovider is a superset ofopenai-codex, which is false when the two served disjoint models.idalready appears in the canonical provider's model id Set or whosenameappears in its name Set (separate Sets to avoid cross-type false positives); (2) stamp the legacy provider'sbaseUrlandapionto merged models that lack their own, so they continue routing to the correct endpoint (e.g.chatgpt.com/backend-apinotapi.openai.com/v1); (3) skip entries with neitheridnornameto avoid duplicating malformed records. Only when the filtered set is empty is the old "Removed … already exists" message emitted.src/commands/doctor/shared/legacy-config-migrations.runtime.models.ts— replace theelsedrop with a merge-or-remove branch; separatecanonicalModelIds/canonicalModelNamesSets; stamp legacy providerbaseUrl/apionto merged models that lack them.src/commands/doctor/shared/legacy-config-migrate.test.ts— 3 new tests: disjoint merge withbaseUrlpreserved (the exact reporter scenario); partial-conflict merge (one duplicate skipped, one new entry with endpoint stamped); all-duplicate scenario still triggers the "Removed" message.hasCanonicalOpenAIProvidercheck andnormalizeLegacyOpenAIResponsesApiare unchanged.!hasCanonicalOpenAIProvider) is unchanged.Reproduction
models.providers.openai(embeddings, API key,baseUrl: https://api.openai.com/v1) andmodels.providers.openai-codex(chat, OAuth,baseUrl: https://chatgpt.com/backend-api,models: [{ id: "gpt-5.5" }]).openclaw doctor --fixoropenclaw updateon OpenClaw 2026.6.1.openai-codexentirely;gpt-5.5is gone; agents fail.gpt-5.5(api →openai-chatgpt-responses,baseUrl: https://chatgpt.com/backend-apistamped) intoopenai.models[]; both endpoints preserved; agents continue working.Real behavior proof
Behavior addressed (#90047):
migrateLegacyOpenAICodexProvidernow merges disjoint model entries with correct endpoint metadata instead of dropping them.Real environment tested (Ubuntu Server Node 24, source-level — Vitest against
migrateLegacyConfigForTestwith the reporter's exact multi-provider config): new tests reproduce the exact upgrade scenario and assert that the merged model array contains the correctbaseUrland renamedapi.Exact steps or command run after this patch:
node scripts/run-vitest.mjs src/commands/doctor/shared/legacy-config-migrate.test.ts src/commands/doctor/shared/legacy-config-migrations.runtime.models.test.ts— 116 tests pass (113 pre-existing + 3 new).pnpm exec oxlintclean.pnpm format:checkclean.Evidence after fix:
New tests:
merges disjoint model entries from legacy codex into canonical openai and preserves legacy baseUrl (#90047)— assertsopenai.models=[{ id: "text-embedding-3-small" }, { id: "gpt-5.5", api: "openai-chatgpt-responses", baseUrl: "https://chatgpt.com/backend-api" }];skips already-present model ids when merging legacy codex into canonical openai— one duplicate skipped, one new entry stamped with legacybaseUrl;removes openai-codex when all its models already exist in canonical openai— canonical unchanged, "Removed" message emitted.What was not tested: live
openclaw doctor --fixrun against a real multi-provider config file.Repro confirmation: the disjoint-merge test fails on the pre-patch tree (
openai.modelsonly contains the embeddings entry,gpt-5.5absent) and passes with the fix.Risk / Mitigation
baseUrl/apiare stamped onto merged models that lack their own, tested by the newbaseUrlassertion.Change Type (select all)
Scope (select all touched areas)
Linked Issue/PR
Fixes #90047