feat(tui): overhaul /model picker to match hermes model with inline auth#18117
Merged
Conversation
Collaborator
|
Likely duplicate of #18085 — same root cause: TUI passes user_providers as wrong type to switch_model(). |
1 similar comment
Collaborator
|
Likely duplicate of #18085 — same root cause: TUI passes user_providers as wrong type to switch_model(). |
Contributor
There was a problem hiding this comment.
Pull request overview
Overhauls the TUI /model picker to align with hermes model by showing all canonical providers (not just authenticated ones), surfacing auth status, and enabling inline API-key setup from within the TUI.
Changes:
- Updated gateway model-option typing to include auth metadata (
auth_type,authenticated,key_env). - Rewrote the TUI
ModelPickerinto a 3-stage flow (provider → key → model) with auth indicators and absolute row numbering. - Extended
tui_gatewaymodel RPCs to return unauthenticated canonical providers and added amodel.save_keymethod; fixeduser_providersshape handling.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 7 comments.
| File | Description |
|---|---|
| ui-tui/src/gatewayTypes.ts | Extends model provider option types with auth-related fields. |
| ui-tui/src/components/modelPicker.tsx | Implements the new staged picker UI, auth indicators, inline key entry, and absolute numbering. |
| tui_gateway/server.py | Fixes user_providers passing, expands model.options to include unauthenticated canonicals, and adds model.save_key. |
| hermes_cli/model_switch.py | Adjusts model validation override logic to handle providers: dict model lists (dict or list). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The TUI's _apply_model_switch() was converting the config.yaml
`providers:` dict into a list of dicts before passing it to
switch_model(). This caused resolve_provider_full() →
resolve_user_provider() to fail, since that function expects a dict
and does `user_config.get(name)` to look up provider entries.
The result: user-defined providers (e.g. ollama) appeared in CLI's
/model picker but were invisible in the TUI.
Fix:
- tui_gateway/server.py: pass cfg.get('providers') directly (dict),
matching what cli.py already does at line 5598.
- hermes_cli/model_switch.py: fix the validation-override block
(line ~893) which iterated user_providers as a list — now correctly
handles the dict format with support for both dict-keyed and
list-format models arrays.
The model picker displayed row numbers 1-12 regardless of scroll position, making it impossible to tell where you were in the list. Now shows the actual item index (e.g. 5, 6, 7... when scrolled down). Also removed '1-9,0 quick' from the hint text since digit shortcuts still work relative to the visible window, which would be confusing with absolute numbering.
- model.options now returns all canonical providers (not just authenticated), each with authenticated/auth_type/key_env fields - New model.save_key RPC method: saves API key to .env, sets in process, returns refreshed provider with models - Picker shows ● (authed) / ○ (no key) markers with dimmed styling - Selecting an unauthenticated api_key provider opens inline masked key input — after save, transitions directly to model selection - Non-api_key auth providers show guidance to run hermes model - Row numbers now show absolute position in list
…icker - New model.disconnect RPC method: clears API key env vars from .env and OAuth/credential pool state via clear_provider_auth() - Press 'd' on an authenticated provider opens confirmation prompt - y/Enter confirms disconnect, n/Esc cancels - Provider flips to unauthenticated state in-place (re-selectable to re-auth by pressing Enter again)
7851038 to
f4c761c
Compare
- Reset keySaving on back() to prevent blocked key entry after Esc - Show '(needs setup)' for non-API-key auth providers instead of generic '(no key)' - Set is_current correctly for unauthenticated providers that happen to be the active session provider - Guard model.save_key with is_managed() check — return error on managed installs where .env is read-only
…tcuts - Emit providers in CANONICAL_PROVIDERS order (matching hermes model) with user-defined/custom providers appended after - Remove digit quick-select (1-9,0) handler — inconsistent with absolute row numbering and already removed from hint text - Remove unused windowOffset import
1 task
jsboige
pushed a commit
to jsboige/hermes-agent
that referenced
this pull request
May 14, 2026
…del-selector feat(tui): overhaul /model picker to match hermes model with inline auth
dannyJ848
pushed a commit
to dannyJ848/hermes-agent
that referenced
this pull request
May 17, 2026
…del-selector feat(tui): overhaul /model picker to match hermes model with inline auth
gweeteve
pushed a commit
to gweeteve/hermes-agent
that referenced
this pull request
Jun 2, 2026
…del-selector feat(tui): overhaul /model picker to match hermes model with inline auth
Egavasyug
pushed a commit
to Egavasyug/hermes-agent
that referenced
this pull request
Jun 10, 2026
…del-selector feat(tui): overhaul /model picker to match hermes model with inline auth
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.
What does this PR do?
Overhauls the TUI
/modelpicker to reach parity withhermes model. Previously the TUI only showed authenticated providers (5-ish), whilehermes modelshowed all 35+ canonical providers. Users couldn't tell what was available or set up new providers without leaving the TUI.Now:
●ready /○needs key).env, and transitions directly to model selectionhermes modeluser_providersbeing passed as a list instead of dictRelated Issue
Fixes TUI/CLI
/modelparity gap — user-reported: "why does the /model picker behave differently between the cli and TUI? I see my ollama model in /model in the cli but don't see them when I use TUI"Type of Change
Changes Made
tui_gateway/server.py: Fix_apply_model_switch()to passcfg.get("providers")as dict (not list).model.optionsnow returns all canonical providers withauthenticated,auth_type,key_envfields. Newmodel.save_keyRPC method for inline credential setup.hermes_cli/model_switch.py: Fix validation-override block (~line 893) to handleuser_providersas dict with both dict-keyed and list-format models.ui-tui/src/components/modelPicker.tsx: Full rewrite — 3 stages (provider → key → model), inline masked API key input, absolute row numbering, auth status indicators, dimmed unauthenticated rows.ui-tui/src/gatewayTypes.ts: Addedauth_type?,authenticated?,key_env?toModelOptionProvider.How to Test
hermes --tuiand type/model○and(no key)— selecting one opens key input.env→ transitions to model list●with model counts — selecting proceeds to model pickerconfig.yamlunderproviders:(e.g. ollama), verify it appearsChecklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests passDocumentation & Housekeeping
docs/, docstrings) — or N/Acli-config.yaml.exampleif I added/changed config keys — or N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — or N/AScreenshots