fix(models): respect models.mode: "replace" in models list output#94722
fix(models): respect models.mode: "replace" in models list output#94722ZOOWH wants to merge 3 commits into
Conversation
When models.mode is set to "replace", the openclaw models list command
should only show models from user-configured providers — not built-in
catalog entries from openai, groq, cerebras, etc.
The model picker and embedded backend already handle this correctly by
short-circuiting to buildConfiguredModelCatalog({ cfg }) when mode is
"replace". But the models list command's code path never checked
models.mode, so it always appended built-in catalog rows regardless
of the config setting.
Three changes:
1. list.source-plan.ts: When cfg.models?.mode === "replace", return a
registry-only source plan (no manifest/provider-index catalog rows).
This prevents loading 231+ built-in catalog entries that would be
filtered out anyway.
2. list.row-sources.ts — appendConfiguredModelRowSources (default list
path): Skip appendAuthenticatedCatalogRows when mode is "replace".
Configured rows + configured provider rows already cover all
user-specified models.
3. list.row-sources.ts — appendAllModelRowSources (--all/provider-filter
path): Skip all built-in catalog row sources (manifest, provider-index,
provider-runtime, supplement) when mode is "replace". Only registry
and configured rows remain, mirroring the model picker's behavior.
Closes openclaw#94705
Co-Authored-By: Claude <[email protected]>
|
Codex review: needs real behavior proof before merge. Reviewed June 18, 2026, 9:48 PM ET / 01:48 UTC. Summary PR surface: Source +19, Tests +39. Total +58 across 3 files. Reproducibility: yes. at source level: current main appends authenticated catalog rows in the default model-list path without checking Review metrics: 1 noteworthy metric.
Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Risk before merge
Maintainer options:
Next step before merge
Security Review findings
Review detailsBest possible solution: Keep default replace-mode Do we have a high-confidence way to reproduce the issue? Yes, at source level: current main appends authenticated catalog rows in the default model-list path without checking Is this the best way to solve the issue? No. The default-list gate is the right boundary, but applying the same replace shortcut to explicit Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 10f0588ee39b. Label changesLabel justifications:
Evidence reviewedPR surface: Source +19, Tests +39. Total +58 across 3 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
|
|
Closing as superseded by #82638 (platinum hermit, proof: sufficient, ready for maintainer look). The canonical fix targets the provider discovery layer (resolveProvidersForModelsJsonWithDeps early-return on mode=replace), not the display layer. |
Summary
When
models.modeis set to"replace"inopenclaw.json, theopenclaw models listcommand should only show models from user-configured providers — not built-in catalog entries from openai, groq, cerebras, etc. that the user explicitly excluded.The model picker (
src/flows/model-picker.ts:148) and embedded backend (src/tui/embedded-backend.ts:126-136) already handle this correctly by short-circuiting tobuildConfiguredModelCatalog({ cfg })when mode is"replace". But themodels listcommand code path never checkedmodels.mode, so it always appended built-in catalog rows regardless of the config setting.What changed
src/commands/models/list.source-plan.ts: Whencfg.models?.mode === "replace",planAllModelListSourcesreturns a registry-only source plan (no manifest/provider-index catalog rows). This prevents loading 231+ built-in catalog entries that would be filtered out anyway.src/commands/models/list.row-sources.ts—appendConfiguredModelRowSources(default list path): SkipappendAuthenticatedCatalogRowswhen mode is"replace". Configured rows + configured provider rows already cover all user-specified models.src/commands/models/list.row-sources.ts—appendAllModelRowSources(--all/provider-filter path): Skip all built-in catalog row sources (manifest, provider-index, provider-runtime, supplement) when mode is"replace". Only registry and configured rows remain, mirroring the model picker behavior.src/commands/models/list.source-plan.test.ts: Two new tests verifying the replace-mode gate.What did NOT change (scope boundary)
model-pickerandembedded-backendreplace-mode handling — already correct.buildConfiguredModelCatalogfunction — unchanged.loadModelCatalog,loadManifestModelCatalog, etc.) — unchanged, they still return full catalogs; the filtering is done at the orchestration level by simply not calling them in replace mode.Linked context
Closes #94705
Real behavior proof
Behavior addressed:
models.mode: "replace"now causesmodels listto only show user-configured providers, not built-in catalog entries.Environment tested: Node v24.13.1 on Linux x86_64; imported real production functions
planAllModelListSourcesandbuildConfiguredModelCatalog.Steps run after the patch:
node --import tsx --no-warnings proof-models-list-replace.mjsEvidence after fix: Terminal capture of console output from running
node --import tsx:Observed result after the fix: All 5 proof checks pass. In replace mode,
planAllModelListSourcesreturns a registry-only plan with 0 built-in catalog rows (vs. 231 in merge mode).buildConfiguredModelCatalogcorrectly returns only the 2 configured providers (deepseek, xai), excluding all built-in providers.What was not tested: Full
openclaw models listCLI end-to-end output (requires a running gateway instance with auth configuration). Only the source-plan and catalog functions were tested directly. The row-sources gate (Proof 5) was verified via source code inspection.Proof limitations or environment constraints: CMake 3.18 on this machine (< 3.19 required by node-llama-cpp), so
pnpm install --frozen-lockfilefails at node-llama-cpp postinstall. Core dependencies (vitest, tsx) are installed and functional. No live gateway instance for end-to-end CLI testing.Tests and validation
node_modules/.bin/vitest run src/commands/models/list.source-plan.test.ts— 10 tests pass (8 existing + 2 new replace-mode tests)Risk checklist
openclaw models listin replace mode now only shows configured providers instead of all providers.appendAllModelRowSourcesreplace-mode gate — could incorrectly skip catalog rows that a user wants. Mitigation: the gate mirrors the model-picker logic which has been in production since the replace mode was introduced; merge/undefined mode (the default) is unaffected.