Skip to content

feat(desktop): provider/model manager - #74297

Open
wildminder wants to merge 1 commit into
NousResearch:mainfrom
wildminder:feat/provider-model-manager
Open

feat(desktop): provider/model manager#74297
wildminder wants to merge 1 commit into
NousResearch:mainfrom
wildminder:feat/provider-model-manager

Conversation

@wildminder

Copy link
Copy Markdown

What does this PR do?

Adds a Provider / Model Manager settings view to the desktop app. Users can browse all configured providers (built-in + custom), toggle per-model visibility, add/edit/delete custom OpenAI-compatible providers, activate/deactivate providers, and discover or refresh model catalogs - all from a two-pane Settings UI. The backend gains model-discovery and provider-filtering endpoints to support it.

Related Issue

N/A (new feature)

Type of Change

  • ✨ New feature (non-breaking change that adds functionality)
  • ✅ Tests (adding or improving test coverage)

Changes Made

Desktop — new Settings view (apps/desktop/src/app/settings/)

  • provider-model-manager.tsx — two-pane container (provider nav + model list), search, deep-link via ?pmprovider=<slug>
  • provider-manager-nav.tsx — left pane: ARIA listbox, arrow-key nav, per-provider active-model count pill, enable/disable switch
  • provider-model-list.tsx — right pane: per-model Switch toggles, capability badges, letter grouping (opt-in), sort A–Z/Z–A, active-model bold emphasis
  • provider-form-dialog.tsx — add/edit custom provider modal (name, base_url, api_key, api_mode, models); auto-generates provider ID from name
  • provider-configure-panel.tsx — edit-credentials dialog for built-in providers
  • model-add-dialog.tsx — manual model addition for custom providers
  • provider-grouping.ts, model-list-utils.ts — pure helpers (letter grouping, capability color meta, discover-button label)
  • use-provider-catalog.ts, use-provider-config.ts, use-provider-visibility.ts — TanStack Query + nanostore hooks

Desktop — lib / store / types / i18n

  • lib/custom-provider-config.ts — pure-TS config helpers (upsert/remove/enable, name normalization, models list↔dict)
  • store/model-visibility.ts — extended with provider-scoped helpers
  • types/hermes.tsenabled? on ModelOptionProvider
  • i18n/{en,ja,zh,zh-hant,types}.tsproviderManager namespace (~30 keys × 4 locales)
  • hermes.tsgetGlobalModelOptions({ includePricing, includeUnconfigured, explicitOnly, refresh }), discoverProviderModels()

Backend

  • hermes_cli/inventory.pybuild_model_options_payload(include_pricing=…), provider enabled flag, model display names, discover_provider_models()
  • hermes_cli/web_server.pyGET /api/model/options (include_pricing param), POST /api/model/discover
  • tui_gateway/server.pymodel.options respects model.disabled_providers + custom enabled: false

Tests

  • 5 new Python test files (test_inventory_discover.py, test_inventory_model_display_names.py, test_inventory_options_flags.py, test_inventory_provider_enabled.py, test_web_server_model_discover.py)
  • 13 new/extended TS test files covering all components, hooks, and pure helpers

Toolchain

  • apps/desktop/package.json — vitest pinned to ^3.2.7 (4.1.x crashes on Node 26)
  • apps/desktop/vitest.setup.ts — localStorage polyfill for jsdom

How to Test

  1. Launch the desktop app (_run_desktop.bat or hermes dashboard), open Settings → Provider Manager.
  2. Verify the provider list renders with model-count pills; select a provider and toggle models on/off — confirm toggles persist across remount.
  3. Click Add provider, fill in a custom OpenAI-compatible endpoint (e.g. http://localhost:11434/v1), save — confirm it appears in the nav with all models disabled by default.
  4. Click Discover models on the custom provider — confirm models populate. Toggle the provider off/on — confirm models hide/show.
  5. Run cd apps/desktop && npx tsc -p . --noEmit && npx tsc -p tsconfig.electron.json --noEmit — both exit 0.
  6. Run scripts/run_tests.sh tests/hermes_cli/test_inventory_discover.py tests/hermes_cli/test_inventory_options_flags.py tests/hermes_cli/test_inventory_provider_enabled.py tests/hermes_cli/test_inventory_model_display_names.py tests/hermes_cli/test_web_server_model_discover.py -q — all pass.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (feat(desktop): …)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (13 TS test files + 5 Python test files)
  • I've tested on my platform: Windows 10

Documentation & Housekeeping

  • N/A — no user-facing docs changes (feature is self-documenting via i18n UI)
  • N/A — no new config.yaml keys (uses existing custom_providers / model.disabled_providers)
  • N/A — no architecture/workflow changes to AGENTS.md
  • I've considered cross-platform impact — the feature is pure Electron/React + Python backend; no OS-specific primitives
  • N/A — no tool schema changes

Screenshots / Logs

image

@wildminder
wildminder requested a review from a team July 29, 2026 18:53
@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/desktop Electron desktop app (apps/desktop/*) comp/dashboard Web dashboard / control panel UI (dashboard/, landing) comp/cli CLI entry point, hermes_cli/, setup wizard comp/tui Terminal UI (ui-tui/ + tui_gateway/) area/config Config system, migrations, profiles sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades needs-decision Awaiting maintainer decision before any implementation labels Jul 29, 2026
@wildminder
wildminder force-pushed the feat/provider-model-manager branch from 09abf0c to 0c101e1 Compare July 29, 2026 21:09

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the substantial Desktop UI and test work. Current main has moved custom-endpoint management onto a keyed providers: schema, so this needs a focused rework before it can safely land.

Problems

  • apps/desktop/src/lib/custom-provider-config.ts:204 writes a custom provider API key into the config record. Current main deliberately keeps these keys in .env and stores key_env instead (hermes_cli/web_server.py:7189-7210).
  • apps/desktop/src/lib/custom-provider-config.ts:164-214 only manages legacy custom_providers, while current v12 custom endpoints use providers: (hermes_cli/config.py:1508-1571; hermes_cli/web_server.py:7133-7223). This can omit current entries or create duplicate representations.
  • apps/desktop/src/app/settings/use-provider-catalog.ts:26 uses REST catalog data, but the PR adds enabled annotation only in the TUI JSON-RPC path. The proposed model.disabled_providers state at custom-provider-config.ts:252-268 also differs from main's runtime-supported providers.<name>.enabled configuration (hermes_cli/config.py:2850-2872).

Suggested changes

  • Rebuild persistence and enablement on the current providers:/key_env lifecycle, and expose one authoritative enablement state through the REST catalog.
  • Add end-to-end coverage for v12 provider edit, credential storage, disable, and re-enable.

Automated hermes-sweeper review.

Comment thread apps/desktop/src/lib/custom-provider-config.ts Outdated
Comment thread apps/desktop/src/lib/custom-provider-config.ts Outdated
Comment thread apps/desktop/src/lib/custom-provider-config.ts Outdated
@teknium1 teknium1 added sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 30, 2026
@wildminder
wildminder force-pushed the feat/provider-model-manager branch from 0c101e1 to 281fbe2 Compare July 30, 2026 22:22
…very, activation toggle, i18n, backend inventory

- Provider Manager settings view with two-pane layout (provider list + model list)
- Custom provider CRUD via REST endpoints (canonical providers:/key_env lifecycle)
- Model discovery (auto-probe /v1/models) + manual add-model dialog
- Per-model visibility toggles with $visibleModels store
- Provider grouping (Local / Configured / Unconfigured), active-on-top, letter grouping
- Capability filters (vision / multimodal / reasoning / fast)
- Connection test for custom providers
- i18n support (en, ja, zh, zh-hant)
- Backend: inventory enabled-flag attach, custom-endpoint lifecycle, legacy compat
- vitest.setup.ts localStorage polyfill for Node 26 compatibility
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/config Config system, migrations, profiles comp/cli CLI entry point, hermes_cli/, setup wizard comp/dashboard Web dashboard / control panel UI (dashboard/, landing) comp/desktop Electron desktop app (apps/desktop/*) comp/tui Terminal UI (ui-tui/ + tui_gateway/) needs-decision Awaiting maintainer decision before any implementation P3 Low — cosmetic, nice to have sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants