fix(models): use catalog for models list --all#39678
fix(models): use catalog for models list --all#39678sd1114820 wants to merge 4 commits intoopenclaw:mainfrom
Conversation
Greptile SummaryThis PR fixes Issues found:
Confidence Score: 3/5
|
| model: (discoveredModel ?? { | ||
| ...entry, | ||
| baseUrl: "", | ||
| }) as Model<Api>, |
There was a problem hiding this comment.
Runtime crash when catalog entry has no input field
ModelCatalogEntry.input is typed as ModelInputType[] | undefined (optional). When discoveredModel is undefined (i.e. the entry only exists in the catalog, not in the runtime registry), the fallback object { ...entry, baseUrl: "" } may carry input: undefined. This value is then cast to Model<Api> and passed to toModelRow, which unconditionally calls model.input.join("+") on line 162 of list.registry.ts — with no null-guard. This will throw TypeError: Cannot read properties of undefined (reading 'join') for any catalog-only entry that has no input in its catalog record (e.g. synthetic fallbacks derived from a template that lacked an input field, or opt-in provider models without an input value).
The existing test doesn't catch this because the mock always provides input: ["text"].
| model: (discoveredModel ?? { | |
| ...entry, | |
| baseUrl: "", | |
| }) as Model<Api>, | |
| model: (discoveredModel ?? { | |
| ...entry, | |
| baseUrl: "", | |
| input: entry.input ?? [], | |
| }) as Model<Api>, |
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/commands/models/list.list-command.ts
Line: 96-99
Comment:
**Runtime crash when catalog entry has no `input` field**
`ModelCatalogEntry.input` is typed as `ModelInputType[] | undefined` (optional). When `discoveredModel` is `undefined` (i.e. the entry only exists in the catalog, not in the runtime registry), the fallback object `{ ...entry, baseUrl: "" }` may carry `input: undefined`. This value is then cast to `Model<Api>` and passed to `toModelRow`, which unconditionally calls `model.input.join("+")` on line 162 of `list.registry.ts` — with no null-guard. This will throw `TypeError: Cannot read properties of undefined (reading 'join')` for any catalog-only entry that has no `input` in its catalog record (e.g. synthetic fallbacks derived from a template that lacked an `input` field, or opt-in provider models without an `input` value).
The existing test doesn't catch this because the mock always provides `input: ["text"]`.
```suggestion
model: (discoveredModel ?? {
...entry,
baseUrl: "",
input: entry.input ?? [],
}) as Model<Api>,
```
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6eabe656f4
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
|
||
| if (opts.all) { | ||
| const sorted = [...models].toSorted((a, b) => { | ||
| const catalog = await loadModelCatalog({ config: cfg }); |
There was a problem hiding this comment.
Fallback to discovered models when catalog is empty
Using loadModelCatalog as the sole source in --all can incorrectly hide all models when the catalog loader transiently fails and returns [] (it intentionally swallows errors in src/agents/model-catalog.ts and may return an empty list). In that case loadModelRegistry has already succeeded and provided discovered models, but this path still prints No models found, which is a user-visible regression from the previous behavior where --all listed runtime-discovered models.
Useful? React with 👍 / 👎.
|
Closing as superseded by #40160. That PR lands the same |
Summary
openclaw models list --allwas reading the raw runtime registry (discoverModels(...).getAll()) instead of the OpenClaw model catalog.That meant synthetic catalog fallback entries from
src/agents/model-catalog.ts(for exampleopenai-codex/gpt-5.4,openai/gpt-5.4, andopenai/gpt-5.4-pro) could exist in the official catalog but still not appear in CLI output.This change makes
models list --alluseloadModelCatalog({ config: cfg })for the list source, while still reusing runtime registry discovery for availability/auth hints and local filtering.What changed
--allcode path insrc/commands/models/list.list-command.tsfrom raw registrygetAll()toloadModelCatalog()availableKeys+ provider fallback heuristics--localbehavior by filtering against discovered runtime models when neededopenai-codex/gpt-5.4visibility in--alloutputWhy
Official upstream already defines GPT-5.4 synthetic fallbacks in
src/agents/model-catalog.ts, butmodels list --allbypassed that layer entirely. This caused a mismatch between the official catalog and CLI output.Validation
Validated in a container (no host dependency pollution) with:
src/commands/models/list.list-command.forward-compat.test.tssrc/commands/models.list.auth-sync.test.tssrc/commands/models/list.status.test.tsResult: 15/15 tests passed.