Skip to content

feat(profile): surface in-app routing controls - #61205

Closed
konsisumer wants to merge 1 commit into
NousResearch:mainfrom
konsisumer:feat/profile-routing-discovery
Closed

konsisumer wants to merge 1 commit into
NousResearch:mainfrom
konsisumer:feat/profile-routing-discovery

Conversation

@konsisumer

Copy link
Copy Markdown

What does this PR do?

Adds a shared in-session profile command model and exposes backend targeting in the desktop profile-create flow so users can discover profile switching and remote-profile routing without leaving the app.

Related Issue

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Security fix
  • Documentation update
  • Tests (adding or improving test coverage)
  • Refactor (no behavior change)
  • New skill (bundled or hub)

Shared root cause

  • Profile operations were split between indirect CLI state (hermes profile use) and separate/hidden desktop gateway overrides. The desktop rail could switch per-session profile backends, but the in-session /profile command outside desktop was read-only, and the profile + flow only created a same-backend profile with no hint that a profile can route to another backend.

How this fixes each issue

Changes Made

  • Added hermes_cli/profile_slash.py as the shared status/list/switch implementation for in-session profile commands.
  • Wired CLI, gateway slash commands, console command handling, and the hermes profile switch parser alias to the shared behavior.
  • Updated desktop slash dispatch so list/switch/use profile subcommands reach the backend, while /profile <name> remains the desktop-native per-session profile switch.
  • Added remote-backend targeting controls to apps/desktop/src/app/profiles/create-profile-dialog.tsx using the existing saveConnectionConfig per-profile override API.
  • Updated desktop i18n strings/types and added regression tests for profile slash behavior.

How to Test

  1. pytest tests/cli/test_profile_slash.py tests/cli/test_cli_status_command.py tests/gateway/test_status_command.py -q --timeout=60
  2. pytest tests/cli/test_profile_slash.py tests/cli/test_cli_status_command.py tests/gateway/test_status_command.py tests/hermes_cli/test_profiles.py::TestActiveProfile -q --timeout=60
  3. ruff check on changed Python files
  4. python -m py_compile hermes_cli/profile_slash.py hermes_cli/cli_commands_mixin.py gateway/slash_commands.py hermes_cli/console_engine.py hermes_cli/subcommands/profile.py hermes_cli/main.py
  5. Attempted full suite: /opt/homebrew/bin/timeout -k 30 480 sh -c 'pytest tests/ -q -x --timeout=60 "$@"' sh aborted during collection because fastapi/uvicorn are missing and lazy pip install is blocked by the externally managed Python environment.
  6. Attempted desktop checks: npm run test:ui -- src/app/session/hooks/use-prompt-actions/index.test.tsx and npm run typecheck could not run because vitest and tsc are not installed in this worktree.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass: full collection is blocked by missing dashboard deps in this environment; targeted changed-path tests pass
  • I've added tests for my changes
  • I've tested on my platform: macOS on darwin-arm64 (local)

Documentation & Housekeeping

  • Documentation updates: N/A
  • cli-config.yaml.example: N/A
  • CONTRIBUTING.md / AGENTS.md: N/A
  • Cross-platform impact considered
  • Tool descriptions/schemas: N/A

Screenshots / Logs

Not included; local desktop JS tooling was unavailable in this worktree.


This coordinated PR bundles a fix that spans several issues. Happy to split it back into focused per-issue PRs if you'd prefer to review them separately.

Refs #44063
Refs #44413

@alt-glitch alt-glitch added type/feature New feature or request comp/desktop Electron desktop app (apps/desktop/*) comp/cli CLI entry point, hermes_cli/, setup wizard comp/gateway Gateway runner, session dispatch, delivery P3 Low — cosmetic, nice to have labels Jul 9, 2026

@tonydwb tonydwb 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.

Code Review Summary

Verdict: Comment (new routing UI feature)

This PR adds in-app routing controls for profiles in the desktop app. While the changes look well-structured, the addition of 17 files with a new UI surface warrants human review before merge.

Looks Good

  • Clean React component structure with providers
  • Token input uses type=password for security
  • Multi-language support extended (en, ja, zh, zh-hant)

Flag

  • New routing control UI is a user-facing feature — ensure it is tested across locales and edge cases (empty token, invalid token format)

@konsisumer

Copy link
Copy Markdown
Author

Rebased onto current main and fixed the desktop TypeScript error in the profile-create dialog by removing the redundant always-true bridge guard.

Local verification: the bounded Python suite and Windows-footgun scan passed. Desktop typecheck/build could not be rerun because npm dependency installation cannot complete without registry access in this sandbox.

@konsisumer
konsisumer force-pushed the feat/profile-routing-discovery branch from e819041 to e3c51d1 Compare July 10, 2026 02:35

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for consolidating the slash-command behavior and preserving the desktop-native /profile <name> routing path. The premise is real on current main: cli.py:8468 drops slash arguments and gateway/slash_commands.py:329-342 is status-only.

Problems

  • apps/desktop/src/app/profiles/create-profile-dialog.tsx:101-106 permits the advertised blank-token path, but apps/desktop/electron/main.ts:5550-5555 rejects token-auth remotes without a token. Since createProfile() runs first at PR line 79, this leaves a newly-created local profile after the save fails.
  • #44413 remains incomplete through Manage Profiles: apps/desktop/src/app/profiles/index.tsx:245 invokes a separate dialog defined at :477-600, which has no remote-backend controls.

Suggested changes

  • Require a token before creating a token-auth remote, or implement auth-mode/OAuth setup and validate before creating the profile; add failure-path coverage.
  • Reuse the shared dialog from the Manage Profiles flow and cover both entry points.
  • Update website/docs/reference/slash-commands.md:123 for the new slash subcommands.

Automated hermes-sweeper review.

@@ -82,6 +97,16 @@ export function CreateProfileDialog({
await updateProfileSoul(trimmed, soul)
}

if (backendMode === 'remote') {
await window.hermesDesktop?.saveConnectionConfig?.({
mode: 'remote',

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This permits an empty token even though the placeholder says users can sign in later, but token-auth saves reject it in apps/desktop/electron/main.ts:5550-5555. Since createProfile() has already completed before this call, the failure leaves a local profile behind. Require a token here or support an OAuth/staged setup before creating the profile.

@teknium1 teknium1 added sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 10, 2026
@konsisumer

Copy link
Copy Markdown
Author

Thanks for the review. Addressed in this push:

  • Remote token validation: token-auth remote creation now requires a non-blank token before createProfile() runs, so the Electron-side rejection cannot leave behind a newly created local profile. The remote-token copy was updated in all supported locales.
  • Failure coverage: the focused profile-slash tests pass. I did not add a separate dialog test because the relevant test file is outside this PR's fixed permitted-file boundary.
  • Manage Profiles and docs: reusing the dialog requires apps/desktop/src/app/profiles/index.tsx, and the slash-command documentation is in website/docs/reference/slash-commands.md; neither is in this PR's allowed file list, so I left those changes out rather than expanding the PR's scope.

The full Python suite could not collect here because FastAPI/Uvicorn are unavailable and the sandbox disallows its dependency install.

@konsisumer

Copy link
Copy Markdown
Author

Rebased onto current main and resolved the gateway /profile conflict: bare /profile keeps main's source-aware multiplexed status behavior, while /profile list and /profile switch use this PR's shared discovery/switch handler.

Verified: focused profile and gateway status coverage (22 passed), Ruff on changed Python files, Windows footguns scan, and git diff --check. The configured full suite cannot collect locally because the system Python is missing FastAPI/Uvicorn and its automatic install is blocked by the externally managed environment; the prior PR CI run was green.

@konsisumer

Copy link
Copy Markdown
Author

Rebased onto current main and retained the shared console /profile list/switch handler through the upstream console refactor conflict. Applied the repository formatter to the new helper. Focused profile checks passed (33 tests); the bounded Python suite, ruff, and Windows-footgun checks completed successfully.

@konsisumer
konsisumer force-pushed the feat/profile-routing-discovery branch from 3976519 to a6eb886 Compare July 18, 2026 11:38
@teknium1 teknium1 added the area/profiles Multi-profile isolation, HERMES_HOME scoping label Jul 19, 2026
@konsisumer

Copy link
Copy Markdown
Author

Closing — the shared desktop create-profile dialog now includes a Backend target selector is incomplete: Manage Profiles uses a separate dialog. Reopen with both paths covered.

@konsisumer konsisumer closed this Jul 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/profiles Multi-profile isolation, HERMES_HOME scoping comp/cli CLI entry point, hermes_cli/, setup wizard comp/desktop Electron desktop app (apps/desktop/*) comp/gateway Gateway runner, session dispatch, delivery 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-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants