fix(desktop): structured Fallback Models editor + out-of-catalog model visibility - #47522
Closed
MarkVLK wants to merge 3 commits into
Closed
fix(desktop): structured Fallback Models editor + out-of-catalog model visibility#47522MarkVLK wants to merge 3 commits into
MarkVLK wants to merge 3 commits into
Conversation
Settings → Model rendered `fallback_providers` (a list of `{provider,
model}` objects) through the generic `list` config field, which does
`value.join(', ')` and stringified each entry to `[object Object],
[object Object]`.
Add a dedicated provider+model row editor (add/remove), sourced from the
same `getGlobalModelOptions()` the composer picker uses, that reads and
writes the `{provider, model}` chain. Half-filled rows are kept in local
state so the config autosave never persists a partial entry, and an
out-of-catalog model stays selectable so existing custom entries render.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The model `<Select>` only listed the provider's advertised catalog, so a configured model that isn't in it (e.g. a Nous-proxied `openai/*` id, or any overridden model) rendered as a blank box — hiding what's actually set. Include the current value as a selectable item, and show a warning when it isn't in the provider's catalog so the user knows calls may fall back. Apply the same out-of-catalog guard to the auxiliary model select. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Asserts each {provider, model} entry renders as its own row (the bug
produced "[object Object]"), that removing a row emits the remaining
entries, that adding a blank row never persists a partial pair, and the
empty-state hint.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
MarkVLK
marked this pull request as ready for review
June 17, 2026 05:20
Contributor
|
Salvaged the remaining structured fallback-editor scope into a current-main PR. The out-of-catalog visibility half was already implemented independently, so the salvage keeps only the object-list editor, tests, and profile/config reload hardening while preserving your authorship. |
alonre
added a commit
to alonre/hermes-agent
that referenced
this pull request
Jul 13, 2026
Sync PR #37 pulled PR NousResearch#59778 (desktop: dismiss stale prompt overlays) by frizikk and PR NousResearch#63080 (desktop: structured Fallback Models editor, salvaging MarkVLK's work from NousResearch#47522), whose commit emails weren't yet mapped. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
In Settings → Model, two things were confusing or broken:
[object Object], [object Object].fallback_providersis a list of{provider, model}objects, but it was shown through the genericlistconfig field, which doesvalue.join(', ')and stringifies each object.openai/*id, an LM Studio / custom‑endpoint model, or any overridden id. Radix<Select>renders nothing for a value with no matching item, so the page hid what was actually configured.Both surfaced from a real case where a primary model was misconfigured (a provider/model mismatch that 404'd and silently fell back) and the UI gave no usable signal about what was set or why.
Changes
FallbackModelsField— a structured provider + model row editor (add / remove) forfallback_providers, sourced from the samegetGlobalModelOptions()the composer model picker uses.ConfigFieldrenders it for that key instead of the genericlistinput. Half‑filled rows are kept in local state so the config autosave never persists a partial{provider, model: ''}, and an out‑of‑catalog model stays selectable so existing custom entries still render.<Select>now includes the current value as a selectable item even when it isn't in the provider's catalog, and shows a ⚠ note when the configured model isn't in the catalog, so the user knows calls may fall back.settings.model.{fallbackAdd, fallbackEmpty, notInCatalog}(en + zh; ja / zh‑hant fall back to English viadefineLocale).fallback-models-field.test.tsx: each entry renders as its own row (never[object Object]), removing a row emits the remaining entries, adding a blank row never persists a partial pair, and the empty‑state hint.Old

New

Verification
npm run typecheckandeslintclean on the changed files (the two remainingreact-hooks/exhaustive-depswarnings inconfig-settings.tsxare pre‑existing in untoucheduseEffects).vitest— the 4 newfallback-models-fieldtests pass.model-settings.test.tsxis unchanged by this PR; its one failing case fails identically onmain(pre‑existing, unrelated).Follow-up (not in this PR)
A "running on a fallback" banner: when the default model is failing and the agent is silently serving from the
fallback_providerschain, surface it (e.g. "Defaultnous/…unavailable — runningcopilot/…"). Doing this correctly needs a backendfallback_activatedsignal onsession.info— a pure effective‑vs‑configured comparison would false‑positive on intentional per‑session model switches — plus making the agent's self‑report name the effective model. Tracked separately.🤖 Generated with Claude Code