feat(dashboard): add profiles management page#16419
Conversation
|
Follow-up context from manual QA of the Profiles page:
I had briefly opened a separate PR against the old/split web UI repo for this, but this belongs in this |
Copy profile dashboard changes onto a fresh branch under the vincez-hms-coder account. Includes: - Profiles dashboard route and sidebar entry - Profile lifecycle REST endpoints - SOUL.md read/write support - i18n labels and helper text updates - Targeted profile API tests Test plan: - pytest tests/hermes_cli/test_web_server.py -k profile -q - cd web && npm run build
Co-authored-by: Copilot <copilot@github.com>
10961b6 to
4c0cc77
Compare
There was a problem hiding this comment.
Pull request overview
Adds a minimal “Profiles” management surface to the dashboard and backs it with new REST endpoints for profile lifecycle + SOUL.md editing, while also tightening up dashboard UI imports and adding targeted tests around the new behavior.
Changes:
- Add dashboard Profiles page (list/create/rename/delete, SOUL.md editor, copy setup command).
- Add FastAPI REST endpoints for profiles and extend clone behavior to copy skills on
--clone. - Update i18n + refactor dashboard UI imports away from the
@nous-research/uiroot barrel, with new regression tests.
Reviewed changes
Copilot reviewed 37 out of 37 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| web/src/plugins/registry.ts | Switch UI imports to browser-safe per-component paths. |
| web/src/plugins/PluginPage.tsx | Switch Spinner import to per-component path. |
| web/src/pages/SkillsPage.tsx | Switch UI imports to per-component paths. |
| web/src/pages/SessionsPage.tsx | Switch UI imports to per-component paths. |
| web/src/pages/ProfilesPage.tsx | New Profiles management page UI (CRUD + SOUL.md edit). |
| web/src/pages/LogsPage.tsx | Switch UI imports to per-component paths. |
| web/src/pages/EnvPage.tsx | Switch UI imports to per-component paths. |
| web/src/pages/CronPage.tsx | Switch UI imports to per-component paths; use local H2. |
| web/src/pages/ConfigPage.tsx | Switch UI imports to per-component paths. |
| web/src/pages/ChatPage.tsx | Switch Button import; replace Typography with local component. |
| web/src/pages/AnalyticsPage.tsx | Switch UI imports to per-component paths. |
| web/src/lib/api.ts | Add profiles REST client methods + ProfileInfo type. |
| web/src/i18n/zh.ts | Add Profiles nav + page translations (zh). |
| web/src/i18n/types.ts | Extend translations typing with profiles keys. |
| web/src/i18n/en.ts | Add Profiles nav + page translations (en). |
| web/src/components/ui/confirm-dialog.tsx | Switch Button import to per-component path. |
| web/src/components/ToolCall.tsx | Switch ListItem import to per-component path. |
| web/src/components/ThemeSwitcher.tsx | Switch Button/ListItem imports; use local Typography. |
| web/src/components/SlashPopover.tsx | Switch ListItem import to per-component path. |
| web/src/components/SidebarFooter.tsx | Switch Typography to local component. |
| web/src/components/PlatformsCard.tsx | Switch Badge import to per-component path. |
| web/src/components/OAuthProvidersCard.tsx | Switch UI imports to per-component paths. |
| web/src/components/OAuthLoginModal.tsx | Switch UI imports; use local H2. |
| web/src/components/NouiTypography.tsx | New local Typography/H2 components. |
| web/src/components/ModelPickerDialog.tsx | Switch UI imports to per-component paths. |
| web/src/components/ModelInfoCard.tsx | Switch Spinner import to per-component path. |
| web/src/components/LanguageSwitcher.tsx | Switch Button import; use local Typography. |
| web/src/components/ChatSidebar.tsx | Switch Button/Badge imports to per-component paths. |
| web/src/components/AutoField.tsx | Switch Select/Switch imports to per-component paths. |
| web/src/App.tsx | Add /profiles route + nav item; refactor UI imports; add Users icon. |
| tests/hermes_cli/test_web_server.py | Add API tests for profile endpoints and SOUL.md flows. |
| tests/hermes_cli/test_profiles.py | Ensure clone-config copies source profile skills. |
| tests/hermes_cli/test_dashboard_profiles_nav_label.py | Static assertion on Profiles nav copy in en.ts. |
| tests/hermes_cli/test_dashboard_browser_safe_imports.py | Static check preventing @nous-research/ui root-barrel imports. |
| hermes_cli/web_server.py | Implement minimal profile REST endpoints (list/create/rename/delete + SOUL.md). |
| hermes_cli/profiles.py | Extend --clone behavior to also copy skills from source. |
| hermes_cli/main.py | Update CLI messaging to mention skills are cloned. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds a minimal Profiles management feature to the dashboard, backed by new REST endpoints in hermes_cli.web_server and supporting profile lifecycle + SOUL.md editing.
Changes:
- Add
ProfilesPageUI and wire it into dashboard routing + navigation. - Add profile REST endpoints (list/create/rename/delete, setup-command, open-terminal, SOUL.md get/put) and extend profile cloning to copy skills.
- Add i18n strings and targeted pytest coverage; update dashboard imports to avoid
@nous-research/uiroot barrel.
Reviewed changes
Copilot reviewed 37 out of 37 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| web/src/plugins/registry.ts | Switch to browser-safe UI imports |
| web/src/plugins/PluginPage.tsx | Switch Spinner to direct import |
| web/src/pages/SkillsPage.tsx | Switch UI imports to direct paths |
| web/src/pages/SessionsPage.tsx | Switch UI imports to direct paths |
| web/src/pages/ProfilesPage.tsx | New profiles management page UI |
| web/src/pages/LogsPage.tsx | Switch segmented/spinner/switch imports |
| web/src/pages/EnvPage.tsx | Switch UI imports to direct paths |
| web/src/pages/CronPage.tsx | Switch UI imports; use local H2 |
| web/src/pages/ConfigPage.tsx | Switch UI imports to direct paths |
| web/src/pages/ChatPage.tsx | Switch Button import; local Typography |
| web/src/pages/AnalyticsPage.tsx | Switch UI imports to direct paths |
| web/src/lib/api.ts | Add profile API methods + ProfileInfo |
| web/src/i18n/zh.ts | Add Profiles nav + page translations |
| web/src/i18n/types.ts | Add profiles translation typings |
| web/src/i18n/en.ts | Add Profiles nav + page translations |
| web/src/components/ui/confirm-dialog.tsx | Switch Button import to direct path |
| web/src/components/ToolCall.tsx | Switch ListItem import to direct path |
| web/src/components/ThemeSwitcher.tsx | Switch UI imports; local Typography |
| web/src/components/SlashPopover.tsx | Switch ListItem import to direct path |
| web/src/components/SidebarFooter.tsx | Use local Typography component |
| web/src/components/PlatformsCard.tsx | Switch Badge import to direct path |
| web/src/components/OAuthProvidersCard.tsx | Switch UI imports to direct paths |
| web/src/components/OAuthLoginModal.tsx | Switch UI imports; local H2 |
| web/src/components/NouiTypography.tsx | New local Typography/H2 primitives |
| web/src/components/ModelPickerDialog.tsx | Switch UI imports to direct paths |
| web/src/components/ModelInfoCard.tsx | Switch Spinner import to direct path |
| web/src/components/LanguageSwitcher.tsx | Switch Button import; local Typography |
| web/src/components/ChatSidebar.tsx | Switch Badge/Button to direct imports |
| web/src/components/AutoField.tsx | Switch Select/Switch to direct imports |
| web/src/App.tsx | Add Profiles route/nav; local Typography |
| tests/hermes_cli/test_web_server.py | Add profile endpoint API tests |
| tests/hermes_cli/test_profiles.py | Verify clone-config copies skills |
| tests/hermes_cli/test_dashboard_profiles_nav_label.py | Static test for nav label copy |
| tests/hermes_cli/test_dashboard_browser_safe_imports.py | Enforce no root-barrel UI imports |
| hermes_cli/web_server.py | Add profile management REST endpoints |
| hermes_cli/profiles.py | Clone-config now copies skills too |
| hermes_cli/main.py | Update CLI messaging re: cloned skills |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Merge resolved conflicts in web/src/{i18n/{en,zh,types}.ts,lib/api.ts}
by keeping both this branch's `profiles` additions and upstream's new
`models` page additions.
Copilot review feedback:
- Implement POST /api/profiles/{name}/open-terminal endpoint (already
present); align Windows branch to `cmd.exe /c start "" <cmd>` so it
matches the new test and spawns a fresh window instead of /k reusing
the parent console.
- Move backslash escaping out of the macOS AppleScript f-string
expression (Python <3.12 disallows backslashes inside f-string
expression parts).
- Patch `_get_wrapper_dir` via monkeypatch in
test_profiles_create_creates_wrapper_alias_when_safe so the test no
longer writes to the real `~/.local/bin`.
- Extend test_dashboard_browser_safe_imports to scan `.ts` files in
addition to `.tsx`.
- Switch upstream's new ModelsPage.tsx away from the `@nous-research/ui`
root barrel onto per-component subpaths to satisfy the stricter scan.
- Fix NouiTypography `leading-1.4` -> `leading-[1.4]` so Tailwind
actually emits the line-height for the `sm` variant.
- Guard ProfilesPage.openSoulEditor against out-of-order responses by
tracking the latest requested profile via a ref.
- Replace ProfilesPage's hand-rolled setup command with a fetch to
`/api/profiles/{name}/setup-command` so the copied command always
matches what the backend would actually run (handles wrapper-alias
collisions and reserved names correctly).
- Wire SOUL.md textarea label `htmlFor` -> textarea `id` so screen
readers and clicking the label work as expected.
Follow-up: rebased on
|
| # | File | Fix |
|---|---|---|
| 1 | hermes_cli/web_server.py |
POST /api/profiles/{name}/open-terminal was already implemented in the prior round; no further change needed. |
| 2 | hermes_cli/web_server.py |
Windows branch now uses cmd.exe /c start "" <cmd> (matches the test and spawns a new window instead of /k reusing the parent console). |
| 3 | tests/hermes_cli/test_web_server.py |
test_profiles_create_creates_wrapper_alias_when_safe now monkeypatches hermes_cli.profiles._get_wrapper_dir to a tmp_path, so the test no longer writes to the real ~/.local/bin. |
| 4 | tests/hermes_cli/test_dashboard_browser_safe_imports.py |
Static scan now covers both *.tsx and *.ts (so plugins/registry.ts is enforced too). |
| 5 | web/src/components/NouiTypography.tsx |
leading-1.4 → leading-[1.4] (valid Tailwind arbitrary-value syntax). |
| 6 | web/src/pages/ProfilesPage.tsx |
openSoulEditor now tracks the latest requested profile via a useRef and ignores stale async responses. |
| 7 | web/src/pages/ProfilesPage.tsx + web/src/lib/api.ts |
handleCopyTerminalCommand now fetches GET /api/profiles/{name}/setup-command so the copied command always matches what the backend would actually run (handles wrapper-alias collisions / reserved names correctly). |
| 8 | web/src/pages/ProfilesPage.tsx |
SOUL.md textarea now has an id={\soul-editor-${p.name}`}and thehas a matchinghtmlFor` (a11y + click-to-focus). |
Drive-by fixes uncovered while running the test suite
- Pre-existing
SyntaxErrorin the macOS branch ofopen_profile_terminal_endpoint— af'…{command.replace("\\\\", …)}…'had a backslash inside the f-string expression, which Python <3.12 rejects. Hoisted the escape into a localescapedvariable; module now parses. web/src/pages/ModelsPage.tsx(added onmainbetween the original PR and now) was importingButton, Spinner, Stats, Badgefrom the@nous-research/uiroot barrel, which violates the (now stricter) browser-safe-import scan. Switched it to per-component subpaths to keep the suite green.
Verification
pytest tests/hermes_cli/{test_web_server.py,test_profiles.py,test_dashboard_browser_safe_imports.py,test_dashboard_profiles_nav_label.py}— 222 passed. The only red tests are 3 inTestPtyWebSocket(KeyError: 'bytes'fromstarlette'sWebSocketTestSession); they reproduce identically onupstream/main, so they are environment / pre-existing onmainand unrelated to this PR.cd web && npm run build— clean (tsc passes, Vite producesweb_dist/).
Re-requested Copilot review. Happy to address anything else.
…board-profiles-hms-coder feat(dashboard): add profiles management page
…board-profiles-hms-coder feat(dashboard): add profiles management page
…board-profiles-hms-coder feat(dashboard): add profiles management page
…board-profiles-hms-coder feat(dashboard): add profiles management page
…board-profiles-hms-coder feat(dashboard): add profiles management page

Summary
Test Plan