hermes-agent/apps/desktop/src/components
brooklyn! 1a3e608524
feat(desktop): per-profile remote gateway hosts (#39778)
* feat(desktop): per-profile remote gateway hosts

Profile switching silently failed whenever the desktop was connected to a
remote backend: the rail routed non-active profiles to a local pool backend,
but spawnPoolBackend hard-threw "Profiles are unavailable when connected to a
remote Hermes backend", and the renderer swallowed the error into an infinite
reconnect backoff while still marking the profile active. Remote was also a
single app-global setting, so there was no way to give a profile its own host.

Add per-profile remote hosts so each profile can point at its own backend:

- connection.json gains a validated `profiles` map; profileRemoteOverride()
  (pure, unit-tested) selects an explicit per-profile remote.
- resolveRemoteBackend(profile) precedence: per-profile override → env override
  → global remote → local spawn. spawnPoolBackend now connects to a profile's
  remote (no local child) instead of throwing; startHermes resolves the primary
  profile's remote.
- coerce/sanitize connection config are scope-aware (global vs named profile)
  and preserve each other's entries; IPC get/save/apply/test thread an optional
  profile. Per-profile apply drops only that profile's pool backend.
- Settings → Gateway adds an "Applies to" scope selector reusing the existing
  URL/token/OAuth/test UX per profile.

Tests: connection-config pure suite (+6) and desktop platform suite pass;
tsc/eslint/vitest clean.

* refactor(desktop): DRY per-profile remote helpers

Share connectionScopeKey + normAuthMode from connection-config.cjs (drop the
main.cjs copy), collapse the scope/auth ternaries, route the env remote through
buildRemoteConnection, and fold the duplicated remote-block validation into
buildRemoteBlock. No behavior change; pure suite + live E2E still green.
2026-06-05 12:14:18 +00:00
..
assistant-ui feat(desktop): concurrent multi-profile gateway sockets 2026-06-04 20:44:19 -05:00
chat chore(desktop): zero eslint/typecheck debt + prettier pass (#39100) 2026-06-04 14:10:38 +00:00
pane-shell Add Hermes desktop app (#20059) 2026-05-31 17:46:56 -05:00
ui feat(desktop): long-press a rail profile to pick its color 2026-06-04 20:12:37 -05:00
Backdrop.tsx Add Hermes desktop app (#20059) 2026-05-31 17:46:56 -05:00
boot-failure-overlay.tsx fix(desktop): offer remote sign-in on a gated-gateway boot failure (#39402) 2026-06-04 17:28:29 -07:00
boot-failure-reauth.test.ts feat(desktop): per-profile remote gateway hosts (#39778) 2026-06-05 12:14:18 +00:00
boot-failure-reauth.ts fix(desktop): offer remote sign-in on a gated-gateway boot failure (#39402) 2026-06-04 17:28:29 -07:00
desktop-install-overlay.tsx chore(desktop): zero eslint/typecheck debt + prettier pass (#39100) 2026-06-04 14:10:38 +00:00
desktop-onboarding-overlay.test.tsx feat(desktop): add 'choose provider later' skip to first-run onboarding (#39483) 2026-06-04 19:40:54 -07:00
desktop-onboarding-overlay.tsx feat(desktop): add 'choose provider later' skip to first-run onboarding (#39483) 2026-06-04 19:40:54 -07:00
error-boundary.tsx chore(desktop): zero eslint/typecheck debt + prettier pass (#39100) 2026-06-04 14:10:38 +00:00
gateway-connecting-overlay.tsx feat(desktop): session hygiene, archive, media streaming + connecting overlay (#37099) 2026-06-01 20:41:34 -05:00
haptics-provider.tsx Add Hermes desktop app (#20059) 2026-05-31 17:46:56 -05:00
model-picker.tsx chore(desktop): zero eslint/typecheck debt + prettier pass (#39100) 2026-06-04 14:10:38 +00:00
model-visibility-dialog.tsx chore(desktop): zero eslint/typecheck debt + prettier pass (#39100) 2026-06-04 14:10:38 +00:00
notifications.tsx feat(desktop): per-session profile switching + cross-profile sessions 2026-06-04 16:35:34 -05:00
page-loader.tsx Add Hermes desktop app (#20059) 2026-05-31 17:46:56 -05:00
prompt-overlays.tsx feat(desktop): concurrent multi-profile gateway sockets 2026-06-04 20:44:19 -05:00
status-dot.tsx Add Hermes desktop app (#20059) 2026-05-31 17:46:56 -05:00