OpenAI-compatible profile models absent in /model with model_picker_providers set
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 19.9k
- Forks
- 2.3k
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 30
Description
Summary
When using a custom named provider profile in config.toml (e.g., [providers.ninerouter]) with:
[provider]
default_provider = "ninerouter"
default_model = "gcli/grok-4.5"
model_picker_providers = ["ninerouter"]
The /model endpoint does not display the full static model list from [[providers.ninerouter.models]]. It only shows the currently selected model, expanded into reasoning-effort rows, all labeled:
- PROVIDER: auto
- METHOD: openrouter
Example (only current model visible):
PROVIDER MODEL METHOD
auto gcli/grok-4.5 (high) openrouter
auto gcli/grok-4.5 (low) openrouter
auto gcli/grok-4.5 (med) openrouter
...
Expected:
All configured static models under ninerouter, e.g.:
- cx/gpt-5.6-sol
- cx/gpt-5.6-terra
- cx/gpt-5.6-luna
- gcli/grok-4.5
Environment
- macOS (aarch64)
- jcode remote/shared-server client (remote=true in picker logs)
- Named profile type openai-compatible with model ids that contain /
- Shell also has OPENROUTER_API_KEY set (common; makes the OpenRouter slot look “configured”)
Reproduction Steps
- Configure a named profile with static models that include / in the id:
[provider]
default_provider = "ninerouter"
default_model = "gcli/grok-4.5"
model_picker_providers = ["ninerouter"]
[providers.ninerouter]
type = "openai-compatible"
base_url = "https://example.gateway/v1"
auth = "bearer"
api_key_env = "NINE_ROUTER_API_KEY"
default_model = "gcli/grok-4.5"
model_catalog = false
[[providers.ninerouter.models]]
id = "cx/gpt-5.6-sol"
[[providers.ninerouter.models]]
id = "cx/gpt-5.6-terra"
[[providers.ninerouter.models]]
id = "cx/gpt-5.6-luna"
[[providers.ninerouter.models]]
id = "gcli/grok-4.5"
- Ensure credentials for the named profile resolve (env var or env_file under the app config dir).
- Optionally leave OPENROUTER_API_KEY set in the environment.
- Start jcode (remote/shared-server path).
- Open /model.
Actual Behavior
- Picker allowlist keeps only the current model (or only routes that don’t match ninerouter).
- Slash model ids are labeled provider=auto, api_method=openrouter.
- Logs look like:
EVENT event=model_picker_open by_provider=auto:6 current_model=gcli/grok-4.5 current_provider=ninerouter routes_in=1 - Related earlier failure mode when the profile key was missing:
Preferred provider ‘ninerouter’ is not configured, using auto-detected default
Failed to apply default_model ‘…’: NINE_ROUTER_API_KEY not found in environment
(credential path is separate; the picker labeling bug remains even after the profile works.)
Expected Behavior
- All
[[providers.ninerouter.models]]entries appear in /model. - Routes are labeled with the profile, e.g.:
- provider = "ninerouter"
- api_method = "openai-compatible:ninerouter"
model_picker_providers = ["ninerouter"]filters to those routes, not to a single current-model OpenRouter auto row.
Context / Root Cause (from investigation)
There appear to be two related gaps:
-
Active named profile static list skipped
When the named profile is active, catalog building can skip re-emitting[[providers.<name>.models]]under the assumption that the shared OpenRouter-slot runtime already contributes them. With a real OPENROUTER_API_KEY, that slot often contributes a large OpenRouter catalog (auto / openrouter) instead of the profile’s static list. -
Remote names-only History fallback misclassifies slash model ids
Initial History often ships model names only (available_model_routes empty for speed). The client rebuilds routes viaremote_model_routes_fallback. Any model id containing / is treated as OpenRouter and labeled auto + openrouter.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing the model_picker_open path, catalog building for active named profiles, and remote_model_routes_fallback when History contains names only. Reproduce with the ninerouter configuration and inspect how slash-containing model IDs and model_picker_providers are labeled and filtered. Done means all configured static models appear under ninerouter with the expected provider and API method.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100