Skip to content

feat(desktop): warn when main-model switch leaves auxiliary tasks pinned to another provider#40286

Merged
teknium1 merged 1 commit into
mainfrom
hermes/hermes-0f554cf7
Jun 6, 2026
Merged

feat(desktop): warn when main-model switch leaves auxiliary tasks pinned to another provider#40286
teknium1 merged 1 commit into
mainfrom
hermes/hermes-0f554cf7

Conversation

@teknium1

@teknium1 teknium1 commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Switching the main model in the desktop app now warns when auxiliary tasks are still pinned to a different provider, so users don't silently burn credits on a provider they thought they left.

Root cause: a main-model switch (/api/model/set scope:main) writes config.yaml model.default/model.provider, which the auxiliary client reads as its fallback. But per-task aux pins (auxiliary.<task>.provider) are independent and win over the main model — and the switch never touches them. A user who switches main away from a now-unpaid provider keeps paying 402s on every background aux call (compression, curator, skill-review, title gen) with zero UI signal. This is the credit-burn path from the Discord report (gemini main + aux still pinned to nous/claude on a $0 balance).

Changes

  • hermes_cli/web_server.py: /api/model/set scope:main now returns stale_aux — aux slots pinned to a provider different from the new main (additive field; existing callers ignore it). Never auto-clears pins.
  • apps/desktop/src/app/settings/model-settings.tsx: switch-time notice after Apply and a persistent banner when any loaded aux slot mismatches the main provider; both wired to the existing "Reset all to main" action.
  • Type defs added in apps/desktop/src/types/hermes.ts + web/src/lib/api.ts (shared /api/model/set endpoint).
  • Fixed a stale pre-existing assertion in the panel test (main model now renders via selectors, not a standalone label).

Desktop == CLI engine confirmed: both write the same config.yaml, so the main-model switch already propagates to aux routing. The gap was purely the silent sticky aux pins — surfaced here, not auto-nuked (a dedicated cheaper aux model is a legitimate config).

Validation

Result
Backend tests/hermes_cli/test_web_server.py -k "stale_aux or set_model_main" 7 passed (2 new)
Desktop tsc -b clean
Desktop model-settings.test.tsx (jsdom) 5/5 passed (2 new + stale fix)

Infographic

aux-model-drift-guard

…ned to another provider

Switching the main model never touches auxiliary slot pins (they're
independent, sticky per-task overrides). A user who switches main away
from a now-unpaid provider keeps paying 402s on every background aux call
until they manually reset those pins — silently, with no UI signal.

- /api/model/set scope:'main' now returns stale_aux: slots still pinned
  to a provider different from the new main (additive field).
- Desktop Model Settings shows a switch-time notice after Apply AND a
  persistent banner when any loaded aux slot mismatches the main provider,
  both wired to the existing 'Reset all to main' action.
- Never auto-clears pins — a dedicated cheaper aux model is a legitimate
  config; surface-and-offer instead of nuking.
- Fixes a stale pre-existing assertion in the panel test (main model now
  renders via selectors, not a standalone label).
@github-actions

github-actions Bot commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

🔎 Lint report: hermes/hermes-0f554cf7 vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 9871 on HEAD, 9871 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 5120 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

@alpindiay alpindiay left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

LGTM. Excellent UX improvement that prevents the silent credit-burn path — when a user switches their main model provider but auxiliary tasks remain pinned to the old provider. Two detection layers:

Backend (web_server.py)

set_model_assignment with scope: "main" now returns stale_aux listing any auxiliary slots pinned to a provider different from the new main. Auto slots are correctly excluded.

Frontend (model-settings.tsx)

  • Switch-time warning (switchStaleAux): shown immediately after applying a new main model
  • Persistent warning (persistentStaleAux): computed on load from current config, catches "forgot months ago" cases
  • Shared StaleAuxWarning component with task names, provider info, and one-click "Reset all to main" button
  • Banner uses amber styling — noticeable but not alarming

New StaleAuxAssignment type defined in both hermes.ts (desktop) and api.ts (web). Tests cover both the backend stale_aux response and the React component rendering. No security concerns.

Minor suggestion (non-blocking): the StaleAuxWarning prop applying could be named disabled or resetting for clarity, but it's clear from context.

@alt-glitch alt-glitch added type/feature New feature or request comp/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have labels Jun 6, 2026
@teknium1 teknium1 merged commit b91aade into main Jun 6, 2026
23 checks passed
@teknium1 teknium1 deleted the hermes/hermes-0f554cf7 branch June 6, 2026 06:35
changman pushed a commit to changman/hermes-agent that referenced this pull request Jun 10, 2026
…ned to another provider (NousResearch#40286)

Switching the main model never touches auxiliary slot pins (they're
independent, sticky per-task overrides). A user who switches main away
from a now-unpaid provider keeps paying 402s on every background aux call
until they manually reset those pins — silently, with no UI signal.

- /api/model/set scope:'main' now returns stale_aux: slots still pinned
  to a provider different from the new main (additive field).
- Desktop Model Settings shows a switch-time notice after Apply AND a
  persistent banner when any loaded aux slot mismatches the main provider,
  both wired to the existing 'Reset all to main' action.
- Never auto-clears pins — a dedicated cheaper aux model is a legitimate
  config; surface-and-offer instead of nuking.
- Fixes a stale pre-existing assertion in the panel test (main model now
  renders via selectors, not a standalone label).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants