Skip to content

Orbit: models discovered from an OpenAI-compatible endpoint vanish from the picker after saving (only return if you retype the API key) #432

Description

@dannon

Steps to reproduce

  1. Click the model button in the bottom toolbar, go to model configuration.
  2. Select OpenAI API compatible endpoint.
  3. Fill in a base URL (reported against https://openrouter.ai/api/v1/) and an API key.
  4. The endpoint's models are discovered and populate the dropdown.
  5. Pick one, save the config, close Preferences.
  6. Send a prompt. (In the reporter's case it failed with a provider-side 404 about
    guardrail/data-policy restrictions -- expected for their key, and not the bug.)
  7. Reopen the model picker.

Observed: only the previously selected model is in the dropdown. Every other
discovered model is gone.

Recovery the tester found: delete the model and API key from config.json
by hand, reopen the config, paste the API key again -- the dropdown repopulates.

Expected: the list persists, or is re-fetched when the dropdown is opened.
The tester also suggested an explicit "fetch available models" button.

Cause

Discovery only ever runs from wireApiKeyValidation in
app/src/renderer/app.ts. That helper is wired to input on the API-key and
base-URL fields and change on the provider dropdown, and its validateNow()
returns early when the key field is empty:

const key = keyEl.value.trim();
if (!key) { setStatus("", ""); return; }

When Preferences reopens, loadProviderFields() deliberately does not
refill the key -- the stored credential lives in the main process, and the
renderer only knows hadKey:

prefsApiKey.value = state.typedKey;          // "" for a saved-but-not-retyped key
prefsApiKey.placeholder = state.hadKey ? "leave blank to keep existing key" : "";

So no input event fires, validateNow() early-returns, no /models call
happens, and the dropdown falls back to populateModels(). For
openai-compatible the static catalog is empty:

"openai-compatible": [],

which leaves exactly one entry -- the saved model, appended by the
(custom) fallback branch at the bottom of populateModels(). That is precisely
the reported symptom, and it also explains the workaround: retyping the key fires
input, which re-runs discovery.

Discovered models are never persisted either, so nothing survives a restart.

Notes on a fix

The renderer can't just re-run the existing call on open -- it doesn't have the
key. Either:

  • add a main-process path that re-probes /models using the stored credential
    (main already reads it via secure-config), triggered on Preferences open
    and/or by an explicit refresh button; or
  • persist the discovered id list alongside the provider config and seed
    MODELS_BY_PROVIDER["openai-compatible"] from it, re-probing in the background.

The second is cheaper; the first is more correct when the endpoint's catalog
changes. A refresh button (the tester's suggestion) is worth having either way,
since a failed probe currently leaves no way to retry without editing the key.

Related: #236 proposes deriving the picker from live /models for all
providers, which subsumes this. This issue is the narrow bug that's biting the
openai-compatible path today.

Suggested test

With a saved openai-compatible provider (stored key, no retyping), open
Preferences and assert the model dropdown contains more than just the saved
model.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions