app-server model/list caches model_catalog_json until restart
Summary
app-server snapshots a configured model_catalog_json when it starts. Replacing
the referenced catalog file while the server is running does not affect latermodel/list responses, even after a config/batchWrite request withreloadUserConfig: true.
This prevents a long-running CLI or Desktop app from advertising a managed live
catalog whose models may be added or removed over time.
Reproduction
- Configure a local catalog:
``toml``
model_catalog_json = "/absolute/path/to/models.json"
- Start
app-server. - Call
model/list; observe a visible model namedcustom-before. - Rewrite the same catalog path so it contains only
custom-after. - Call
model/listagain in the same app-server process.
Current result: the second response still contains custom-before.
Expected result: the second response contains custom-after, so reopening a model
picker reflects additions and removals without restarting the host application.
I reproduced this against the Codex Desktop bundled app-server0.146.0-alpha.3. The process loaded a 30-model custom catalog successfully at
startup, but neither rewriting the file nor requesting a user-config reload changed
membership in a later model/list response.
Root cause
model_catalog_json is parsed into Config.model_catalog, then theThreadManager's model manager retains that startup snapshot.CatalogRequestProcessor::model_list delegates tothread_manager.list_models(...) without loading the latest effective config, so
the custom catalog file is not revisited.
Proposed behavior
For each model/list request:
- load the latest effective config for the current cwd;
- when
model_catalog_jsonis configured, construct a temporary
StaticModelsManager from the newly loaded catalog;
- otherwise preserve the existing
ThreadManageronline/remote catalog behavior.
This keeps the change limited to explicitly configured custom catalogs and avoids
altering ChatGPT remote-catalog refresh semantics.
Tested implementation
A focused implementation and regression test are available here:
https://github.com/Ajnunezg/codex/tree/agent/reload-custom-model-catalog
The regression test starts one app-server, calls model/list, rewrites the catalog
from custom-before to custom-after, and verifies the next model/list response
uses the new model.
Validation on current openai/codex:main:
cargo fmt --all --check
cargo test -p codex-app-server --test all suite::v2::model_list -- --nocapture
6 passed; 0 failed
Related but distinct issues
- #19694 tracks Desktop renderer filtering of models already returned by
model/list.
- #34837 proposes network-fetched provider manifests.
This report is only about refreshing an already supported localmodel_catalog_json in a running app-server.
Would the maintainers accept this behavior and invite a PR for the tested branch?