@bitseek/hermes-webui 0.1.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +213 -0
- package/bin/hermes-webui.mjs +588 -0
- package/package.json +25 -0
- package/scripts/sync-vendor.mjs +74 -0
- package/templates/launchd/com.bitseek.hermes-webui.plist +21 -0
- package/templates/systemd/hermes-webui.service +13 -0
- package/templates/windows/hermes-webui-task.ps1 +3 -0
- package/vendor/agent-frontend-shell/.bitseek-source.json +6 -0
- package/vendor/agent-frontend-shell/.dockerignore +7 -0
- package/vendor/agent-frontend-shell/.env.docker.example +89 -0
- package/vendor/agent-frontend-shell/.env.example +34 -0
- package/vendor/agent-frontend-shell/.github/FUNDING.yml +3 -0
- package/vendor/agent-frontend-shell/.github/workflows/browser-smoke.yml +42 -0
- package/vendor/agent-frontend-shell/.github/workflows/docker-smoke.yml +233 -0
- package/vendor/agent-frontend-shell/.github/workflows/native-windows-startup.yml +132 -0
- package/vendor/agent-frontend-shell/.github/workflows/release.yml +57 -0
- package/vendor/agent-frontend-shell/.github/workflows/tests.yml +88 -0
- package/vendor/agent-frontend-shell/.vscode/launch.json +59 -0
- package/vendor/agent-frontend-shell/.vscode/settings.json +13 -0
- package/vendor/agent-frontend-shell/AGENTS.md +80 -0
- package/vendor/agent-frontend-shell/ARCHITECTURE.md +1658 -0
- package/vendor/agent-frontend-shell/BUGS.md +52 -0
- package/vendor/agent-frontend-shell/CHANGELOG.md +7295 -0
- package/vendor/agent-frontend-shell/CONTRIBUTING.md +205 -0
- package/vendor/agent-frontend-shell/CONTRIBUTORS.md +107 -0
- package/vendor/agent-frontend-shell/DESIGN.md +173 -0
- package/vendor/agent-frontend-shell/Dockerfile +91 -0
- package/vendor/agent-frontend-shell/LICENSE +21 -0
- package/vendor/agent-frontend-shell/README-CUSTOM.md +76 -0
- package/vendor/agent-frontend-shell/README.md +705 -0
- package/vendor/agent-frontend-shell/ROADMAP.md +351 -0
- package/vendor/agent-frontend-shell/SPRINTS.md +147 -0
- package/vendor/agent-frontend-shell/TESTING.md +1932 -0
- package/vendor/agent-frontend-shell/THEMES.md +170 -0
- package/vendor/agent-frontend-shell/api/__init__.py +1 -0
- package/vendor/agent-frontend-shell/api/agent_health.py +392 -0
- package/vendor/agent-frontend-shell/api/agent_sessions.py +782 -0
- package/vendor/agent-frontend-shell/api/auth.py +592 -0
- package/vendor/agent-frontend-shell/api/background.py +87 -0
- package/vendor/agent-frontend-shell/api/clarify.py +238 -0
- package/vendor/agent-frontend-shell/api/commands.py +124 -0
- package/vendor/agent-frontend-shell/api/compression_anchor.py +134 -0
- package/vendor/agent-frontend-shell/api/config.py +5178 -0
- package/vendor/agent-frontend-shell/api/dashboard_probe.py +255 -0
- package/vendor/agent-frontend-shell/api/extensions.py +253 -0
- package/vendor/agent-frontend-shell/api/gateway_chat.py +435 -0
- package/vendor/agent-frontend-shell/api/gateway_watcher.py +230 -0
- package/vendor/agent-frontend-shell/api/goals.py +608 -0
- package/vendor/agent-frontend-shell/api/helpers.py +474 -0
- package/vendor/agent-frontend-shell/api/kanban_bridge.py +1255 -0
- package/vendor/agent-frontend-shell/api/metering.py +194 -0
- package/vendor/agent-frontend-shell/api/models.py +4210 -0
- package/vendor/agent-frontend-shell/api/oauth.py +770 -0
- package/vendor/agent-frontend-shell/api/onboarding.py +1046 -0
- package/vendor/agent-frontend-shell/api/passkeys.py +365 -0
- package/vendor/agent-frontend-shell/api/profiles.py +1499 -0
- package/vendor/agent-frontend-shell/api/providers.py +2175 -0
- package/vendor/agent-frontend-shell/api/request_diagnostics.py +160 -0
- package/vendor/agent-frontend-shell/api/rollback.py +320 -0
- package/vendor/agent-frontend-shell/api/routes.py +13990 -0
- package/vendor/agent-frontend-shell/api/run_journal.py +284 -0
- package/vendor/agent-frontend-shell/api/runner_client.py +156 -0
- package/vendor/agent-frontend-shell/api/runtime_adapter.py +431 -0
- package/vendor/agent-frontend-shell/api/session_discoverability.py +640 -0
- package/vendor/agent-frontend-shell/api/session_events.py +45 -0
- package/vendor/agent-frontend-shell/api/session_lifecycle.py +208 -0
- package/vendor/agent-frontend-shell/api/session_ops.py +207 -0
- package/vendor/agent-frontend-shell/api/session_recovery.py +655 -0
- package/vendor/agent-frontend-shell/api/skill_usage.py +32 -0
- package/vendor/agent-frontend-shell/api/startup.py +128 -0
- package/vendor/agent-frontend-shell/api/state_sync.py +187 -0
- package/vendor/agent-frontend-shell/api/streaming.py +7048 -0
- package/vendor/agent-frontend-shell/api/system_health.py +167 -0
- package/vendor/agent-frontend-shell/api/terminal.py +410 -0
- package/vendor/agent-frontend-shell/api/turn_journal.py +214 -0
- package/vendor/agent-frontend-shell/api/updates.py +1261 -0
- package/vendor/agent-frontend-shell/api/upload.py +322 -0
- package/vendor/agent-frontend-shell/api/usage.py +26 -0
- package/vendor/agent-frontend-shell/api/workspace.py +867 -0
- package/vendor/agent-frontend-shell/api/workspace_git.py +1261 -0
- package/vendor/agent-frontend-shell/api/worktrees.py +357 -0
- package/vendor/agent-frontend-shell/bootstrap.py +492 -0
- package/vendor/agent-frontend-shell/ctl.sh +427 -0
- package/vendor/agent-frontend-shell/docker-compose.custom.yml +26 -0
- package/vendor/agent-frontend-shell/docker-compose.three-container.yml +168 -0
- package/vendor/agent-frontend-shell/docker-compose.two-container.yml +147 -0
- package/vendor/agent-frontend-shell/docker-compose.yml +57 -0
- package/vendor/agent-frontend-shell/docker_init.bash +459 -0
- package/vendor/agent-frontend-shell/docs/CONTRACTS.md +207 -0
- package/vendor/agent-frontend-shell/docs/EXTENSIONS.md +212 -0
- package/vendor/agent-frontend-shell/docs/ISSUES.md +23 -0
- package/vendor/agent-frontend-shell/docs/UIUX-GUIDE.md +196 -0
- package/vendor/agent-frontend-shell/docs/advanced-chat-setup.md +83 -0
- package/vendor/agent-frontend-shell/docs/docker.md +337 -0
- package/vendor/agent-frontend-shell/docs/onboarding-agent-checklist.md +207 -0
- package/vendor/agent-frontend-shell/docs/onboarding.md +202 -0
- package/vendor/agent-frontend-shell/docs/remote-access.md +75 -0
- package/vendor/agent-frontend-shell/docs/rfcs/README.md +53 -0
- package/vendor/agent-frontend-shell/docs/rfcs/agent-source-boundary.md +70 -0
- package/vendor/agent-frontend-shell/docs/rfcs/canonical-session-resolution.md +124 -0
- package/vendor/agent-frontend-shell/docs/rfcs/hermes-run-adapter-contract.md +1079 -0
- package/vendor/agent-frontend-shell/docs/rfcs/turn-journal.md +195 -0
- package/vendor/agent-frontend-shell/docs/rfcs/webui-run-state-consistency-contract.md +157 -0
- package/vendor/agent-frontend-shell/docs/supervisor.md +280 -0
- package/vendor/agent-frontend-shell/docs/troubleshooting.md +132 -0
- package/vendor/agent-frontend-shell/docs/ui-ux/index.html +863 -0
- package/vendor/agent-frontend-shell/docs/ui-ux/two-stage-proposal.html +768 -0
- package/vendor/agent-frontend-shell/docs/why-hermes.md +489 -0
- package/vendor/agent-frontend-shell/docs/workspace-git.md +92 -0
- package/vendor/agent-frontend-shell/docs/wsl-autostart.md +126 -0
- package/vendor/agent-frontend-shell/eslint.runtime-guard.config.mjs +35 -0
- package/vendor/agent-frontend-shell/extensions/bitseek-design-system.md +330 -0
- package/vendor/agent-frontend-shell/extensions/branding/assets/apple-touch-icon.png +0 -0
- package/vendor/agent-frontend-shell/extensions/branding/assets/empty-logo.svg +739 -0
- package/vendor/agent-frontend-shell/extensions/branding/assets/favicon-192.png +0 -0
- package/vendor/agent-frontend-shell/extensions/branding/assets/favicon-32.png +0 -0
- package/vendor/agent-frontend-shell/extensions/branding/assets/favicon-512.png +0 -0
- package/vendor/agent-frontend-shell/extensions/branding/assets/favicon-512.svg +745 -0
- package/vendor/agent-frontend-shell/extensions/branding/assets/favicon.ico +0 -0
- package/vendor/agent-frontend-shell/extensions/branding/assets/favicon.svg +745 -0
- package/vendor/agent-frontend-shell/extensions/branding/assets/titlebar-icon-v2.svg +751 -0
- package/vendor/agent-frontend-shell/extensions/branding/assets/titlebar-icon-v3.svg +739 -0
- package/vendor/agent-frontend-shell/extensions/branding/assets/titlebar-icon.svg +745 -0
- package/vendor/agent-frontend-shell/extensions/branding/branding.js +112 -0
- package/vendor/agent-frontend-shell/extensions/branding/config.json +14 -0
- package/vendor/agent-frontend-shell/extensions/branding/manifest.json +53 -0
- package/vendor/agent-frontend-shell/extensions/index.js +67 -0
- package/vendor/agent-frontend-shell/extensions/loader/hermes-loader.js +77 -0
- package/vendor/agent-frontend-shell/extensions/manifest.json +16 -0
- package/vendor/agent-frontend-shell/extensions/pages/ai-teammates/page.css +333 -0
- package/vendor/agent-frontend-shell/extensions/pages/ai-teammates/page.js +487 -0
- package/vendor/agent-frontend-shell/extensions/pages/manifest.json +6 -0
- package/vendor/agent-frontend-shell/extensions/pages/registry.css +56 -0
- package/vendor/agent-frontend-shell/extensions/pages/registry.js +302 -0
- package/vendor/agent-frontend-shell/extensions/themes/bitseek/index.css +93 -0
- package/vendor/agent-frontend-shell/extensions/themes/bitseek/index.js +98 -0
- package/vendor/agent-frontend-shell/install.sh +63 -0
- package/vendor/agent-frontend-shell/mcp_server.py +567 -0
- package/vendor/agent-frontend-shell/package.json +12 -0
- package/vendor/agent-frontend-shell/pyproject.toml +56 -0
- package/vendor/agent-frontend-shell/pytest.ini +3 -0
- package/vendor/agent-frontend-shell/requirements.txt +5 -0
- package/vendor/agent-frontend-shell/server.py +624 -0
- package/vendor/agent-frontend-shell/start.ps1 +210 -0
- package/vendor/agent-frontend-shell/start.sh +65 -0
- package/vendor/agent-frontend-shell/static/apple-touch-icon.png +0 -0
- package/vendor/agent-frontend-shell/static/boot.js +1990 -0
- package/vendor/agent-frontend-shell/static/commands.js +1402 -0
- package/vendor/agent-frontend-shell/static/favicon-192.png +0 -0
- package/vendor/agent-frontend-shell/static/favicon-32.png +0 -0
- package/vendor/agent-frontend-shell/static/favicon-512.png +0 -0
- package/vendor/agent-frontend-shell/static/favicon-512.svg +18 -0
- package/vendor/agent-frontend-shell/static/favicon.ico +0 -0
- package/vendor/agent-frontend-shell/static/favicon.svg +20 -0
- package/vendor/agent-frontend-shell/static/i18n.js +15389 -0
- package/vendor/agent-frontend-shell/static/icons.js +92 -0
- package/vendor/agent-frontend-shell/static/index.html +1506 -0
- package/vendor/agent-frontend-shell/static/login.js +177 -0
- package/vendor/agent-frontend-shell/static/manifest.json +53 -0
- package/vendor/agent-frontend-shell/static/messages.js +3521 -0
- package/vendor/agent-frontend-shell/static/onboarding.js +800 -0
- package/vendor/agent-frontend-shell/static/panels.js +7995 -0
- package/vendor/agent-frontend-shell/static/pwa-startup.js +83 -0
- package/vendor/agent-frontend-shell/static/sessions.js +5165 -0
- package/vendor/agent-frontend-shell/static/style.css +4774 -0
- package/vendor/agent-frontend-shell/static/sw.js +173 -0
- package/vendor/agent-frontend-shell/static/terminal.js +632 -0
- package/vendor/agent-frontend-shell/static/ui.js +8997 -0
- package/vendor/agent-frontend-shell/static/vendor/js-yaml/4.1.0/js-yaml.min.js +2 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_AMS-Regular.ttf +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_AMS-Regular.woff +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_AMS-Regular.woff2 +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Fraktur-Bold.woff +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Fraktur-Regular.woff +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Main-Bold.ttf +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Main-Bold.woff +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Main-Bold.woff2 +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Main-BoldItalic.woff +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Main-Italic.ttf +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Main-Italic.woff +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Main-Italic.woff2 +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Main-Regular.ttf +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Main-Regular.woff +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Main-Regular.woff2 +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Math-BoldItalic.woff +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Math-Italic.ttf +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Math-Italic.woff +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Math-Italic.woff2 +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_SansSerif-Bold.woff +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_SansSerif-Italic.woff +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_SansSerif-Regular.woff +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Script-Regular.ttf +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Script-Regular.woff +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Script-Regular.woff2 +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Size1-Regular.ttf +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Size1-Regular.woff +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Size1-Regular.woff2 +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Size2-Regular.ttf +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Size2-Regular.woff +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Size2-Regular.woff2 +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Size3-Regular.ttf +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Size3-Regular.woff +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Size3-Regular.woff2 +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Size4-Regular.ttf +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Size4-Regular.woff +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Size4-Regular.woff2 +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Typewriter-Regular.woff +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/katex.min.css +1 -0
- package/vendor/agent-frontend-shell/static/vendor/katex/0.16.22/katex.min.js +1 -0
- package/vendor/agent-frontend-shell/static/vendor/smd.min.js +29 -0
- package/vendor/agent-frontend-shell/static/workspace.js +680 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Advanced chat setup
|
|
2
|
+
|
|
3
|
+
Two optional features for self-hosted Hermes WebUI deployments. **Most users need neither** — the defaults (in-process chat, no prefill) work out of the box.
|
|
4
|
+
|
|
5
|
+
## Session recall prefill
|
|
6
|
+
|
|
7
|
+
WebUI can attach ephemeral prefill messages to new browser-originated
|
|
8
|
+
agent turns. This is useful when a deployment already has a local recall or
|
|
9
|
+
router script for Joplin, Obsidian, Notion, llm-wiki, or another third-party
|
|
10
|
+
notes source and wants browser chat to know where durable context lives.
|
|
11
|
+
|
|
12
|
+
Prefer a compact router-style prefill (for example, "Joplin has the durable
|
|
13
|
+
project context; use the available notes/search tools before answering
|
|
14
|
+
detail-dependent questions") instead of dumping the full note corpus into every
|
|
15
|
+
new browser session. The prefill should point the agent toward retrieval; the
|
|
16
|
+
notes/search tools should provide the specific facts on demand.
|
|
17
|
+
|
|
18
|
+
Static JSON remains supported through `prefill_messages_file` or
|
|
19
|
+
`HERMES_PREFILL_MESSAGES_FILE`. For dynamic recall, opt in explicitly with a
|
|
20
|
+
WebUI-specific script hook:
|
|
21
|
+
|
|
22
|
+
```yaml
|
|
23
|
+
webui_prefill_messages_script:
|
|
24
|
+
- python3
|
|
25
|
+
- /path/to/notes_recall.py
|
|
26
|
+
webui_prefill_messages_script_timeout: 5
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
or:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
HERMES_WEBUI_PREFILL_MESSAGES_SCRIPT="python3 /path/to/notes_recall.py" \
|
|
33
|
+
HERMES_WEBUI_PREFILL_MESSAGES_SCRIPT_TIMEOUT=5 \
|
|
34
|
+
./ctl.sh restart
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The script may print either an OpenAI-style JSON message list, a JSON object with
|
|
38
|
+
a `messages` list, or plain text; plain text is wrapped as one `user` prefill
|
|
39
|
+
message so dynamic recall text becomes ordinary context instead of an extra
|
|
40
|
+
system instruction. If the hook must provide system-level guidance, emit JSON
|
|
41
|
+
messages with an explicit `role: "system"` entry instead. Script output is capped
|
|
42
|
+
at 256 KiB before parsing. Parsed prefill context is then bounded by
|
|
43
|
+
`webui_prefill_context_max_chars` or `HERMES_WEBUI_PREFILL_CONTEXT_MAX_CHARS`
|
|
44
|
+
(default: 12,000 characters; set to `0` to disable). When a dynamic script
|
|
45
|
+
exceeds the budget and a compact static prefill file is configured, WebUI falls
|
|
46
|
+
back to that file. If no compact fallback is available, WebUI injects a short
|
|
47
|
+
retrieval instruction instead of sending the oversized note/body payload with
|
|
48
|
+
every new browser turn. The browser only receives a compact status event
|
|
49
|
+
(`source`, `label`, message count, compaction metadata, and redacted errors),
|
|
50
|
+
never the prefill message bodies.
|
|
51
|
+
|
|
52
|
+
## Gateway-backed browser chat
|
|
53
|
+
|
|
54
|
+
By default, browser chat runs through WebUI's in-process legacy runtime. Advanced
|
|
55
|
+
self-hosted deployments can opt into routing new browser turns through a running
|
|
56
|
+
Hermes Gateway API server while preserving the existing WebUI `/api/chat/start`
|
|
57
|
+
and `/api/chat/stream` browser contract:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
HERMES_WEBUI_CHAT_BACKEND=gateway \
|
|
61
|
+
HERMES_WEBUI_GATEWAY_BASE_URL=http://127.0.0.1:8642 \
|
|
62
|
+
HERMES_WEBUI_GATEWAY_API_KEY=... \
|
|
63
|
+
./ctl.sh restart
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`HERMES_WEBUI_CHAT_BACKEND` is intentionally strict: only `gateway`,
|
|
67
|
+
`api_server`, or `api-server` enable the bridge. Generic truthy values such as
|
|
68
|
+
`1` or `true` are ignored so existing deployments do not change execution
|
|
69
|
+
ownership accidentally. If `HERMES_WEBUI_GATEWAY_API_KEY` is omitted, WebUI falls
|
|
70
|
+
back to `API_SERVER_KEY` when present. When Gateway returns HTTP 401, WebUI
|
|
71
|
+
reports a `gateway_auth_error` that points at this WebUI↔Gateway key mismatch
|
|
72
|
+
rather than showing the Gateway's generic provider-style "Invalid API key" body.
|
|
73
|
+
`/api/health/agent` also includes a redacted `gateway_chat` block so operators can
|
|
74
|
+
see whether gateway mode, base URL, and API-key presence are configured without
|
|
75
|
+
exposing the key value. That `gateway_chat` field is an operator diagnostic
|
|
76
|
+
payload only; it is not currently rendered as a user-facing health banner in the
|
|
77
|
+
browser UI.
|
|
78
|
+
|
|
79
|
+
The bridge is best used by operators who already run Hermes Gateway/API Server
|
|
80
|
+
locally and want browser-originated chat to use the same runtime/tool path as
|
|
81
|
+
messaging surfaces. Attachments, cancellation, approvals, and clarify prompts
|
|
82
|
+
still follow WebUI's current compatibility path and may not match every messaging
|
|
83
|
+
surface until the runtime-adapter migration is complete.
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
# Hermes WebUI — Docker setup guide
|
|
2
|
+
|
|
3
|
+
This is the comprehensive Docker reference. For a 5-minute quickstart, see the [README Docker section](../README.md#docker).
|
|
4
|
+
|
|
5
|
+
## TL;DR — pick one
|
|
6
|
+
|
|
7
|
+
| Setup | When to use | File |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| **Single-container** (recommended) | You just want chat working. WebUI runs the agent in-process. | `docker-compose.yml` |
|
|
10
|
+
| **Two-container** | You want isolation between gateway (CLI/Telegram/cron) and chat UI. | `docker-compose.two-container.yml` |
|
|
11
|
+
| **Three-container** | Two-container PLUS the dashboard for monitoring. | `docker-compose.three-container.yml` |
|
|
12
|
+
| **All-in-one image** (community fork — third-party, not maintained by us) | Podman 3.4 / multi-arch / supervisord-style preference. | [sunnysktsang/hermes-suite](https://github.com/sunnysktsang/hermes-suite) — see [#1399](https://github.com/nesquena/hermes-webui/issues/1399) for the original discussion |
|
|
13
|
+
|
|
14
|
+
If something stops working, **start with the single-container setup** — it's the simplest path and fixes most permission/UID/path-mismatch issues by construction.
|
|
15
|
+
|
|
16
|
+
## Production image security model
|
|
17
|
+
|
|
18
|
+
The production Docker image is hardened for the normal single-tenant container threat model:
|
|
19
|
+
Hermes WebUI assumes one operator controls the container, mounted Hermes home, and workspace.
|
|
20
|
+
The image does **not** install `sudo`, does not add runtime users to a sudo group, and does not
|
|
21
|
+
grant `NOPASSWD` escalation. If an agent/tool process gains a shell as `hermeswebui`, it should
|
|
22
|
+
not be able to become root with a passwordless sudo command.
|
|
23
|
+
|
|
24
|
+
The entrypoint still starts as `root` for a narrow init phase because Docker bind mounts often need
|
|
25
|
+
UID/GID alignment and ownership preparation before the app can read `~/.hermes`, `/workspace`,
|
|
26
|
+
`/app`, and `/uv_cache`. After that setup, `docker_init.bash` re-execs itself as the unprivileged
|
|
27
|
+
`hermeswebui` user and starts the server there. Init scratch files under `/tmp/hermeswebui_init`
|
|
28
|
+
are owner-only (`0700` directory, `0600` files), not world-writable.
|
|
29
|
+
|
|
30
|
+
For multi-tenant or hostile-container environments, rebuild with your own runtime user, mount policy,
|
|
31
|
+
and supervisor assumptions. Development images that need package-manager convenience should add
|
|
32
|
+
those tools in a dev-only Dockerfile instead of reintroducing passwordless sudo to production.
|
|
33
|
+
|
|
34
|
+
## 5-minute quickstart (single container)
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
git clone https://github.com/nesquena/hermes-webui
|
|
38
|
+
cd hermes-webui
|
|
39
|
+
cp .env.docker.example .env
|
|
40
|
+
# Edit .env if needed (most users can skip this on Linux)
|
|
41
|
+
docker compose up -d
|
|
42
|
+
open http://localhost:8787
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
That's it for a real personal Docker install. Your existing `~/.hermes`
|
|
46
|
+
directory is mounted, your `~/workspace` is browsable, and the WebUI
|
|
47
|
+
auto-detects your UID/GID from the mounted volume.
|
|
48
|
+
|
|
49
|
+
The single-container setup runs the WebUI only. It can create cron jobs and run
|
|
50
|
+
them manually from the Tasks panel. In Docker, scheduled jobs require the Hermes gateway daemon
|
|
51
|
+
to tick while you are away. If System Settings shows `Gateway not configured`,
|
|
52
|
+
use `docker-compose.two-container.yml`,
|
|
53
|
+
`docker-compose.three-container.yml`, or run `hermes gateway` separately before
|
|
54
|
+
relying on offline scheduled runs. See [Scheduled jobs and the gateway daemon](#scheduled-jobs-and-the-gateway-daemon) below for the full background and verification steps.
|
|
55
|
+
|
|
56
|
+
For troubleshooting, reinstall, or onboarding reproduction trials, do not mount
|
|
57
|
+
your real `~/.hermes` unless you intentionally want to test real state. Use an
|
|
58
|
+
isolated Hermes home and follow
|
|
59
|
+
[`docs/onboarding-agent-checklist.md`](onboarding-agent-checklist.md) instead.
|
|
60
|
+
|
|
61
|
+
> **Linux note**: run Compose as the user who owns the Hermes home. The command
|
|
62
|
+
> `sudo docker compose up -d` can make Compose expand `${HOME}` as `/root`, so
|
|
63
|
+
> the default `${HOME}/.hermes` bind mount becomes `/root/.hermes` instead of
|
|
64
|
+
> your user's real Hermes directory. Prefer adding your user to the `docker group`
|
|
65
|
+
> and running `docker compose up -d`; if you must preserve the caller environment
|
|
66
|
+
> for a one-off root run, use `sudo -E docker compose up -d` and verify the
|
|
67
|
+
> rendered mount with `docker compose config` first.
|
|
68
|
+
|
|
69
|
+
## Scheduled jobs and the gateway daemon
|
|
70
|
+
|
|
71
|
+
**Symptom**: Cron jobs created in the Tasks panel never fire. System Settings shows the orange "Gateway not configured" pill, and the Tasks panel shows the same banner above the job list.
|
|
72
|
+
|
|
73
|
+
**Cause**: Scheduled cron ticks are not driven by the WebUI itself. The gateway daemon ticks the scheduler every 60 seconds; without one running, scheduled jobs sit idle. "Run now" / "Trigger" buttons still work because the WebUI handles those in-process.
|
|
74
|
+
|
|
75
|
+
**Fix**: Run a gateway container alongside the WebUI. The two-container compose file is the recommended path:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
cp .env.docker.example .env
|
|
79
|
+
docker compose -f docker-compose.two-container.yml up -d
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The three-container layout adds the dashboard but is otherwise the same shape. If you must stay single-container, you can run `hermes gateway` inside the container as a long-lived background process, but the compose split is sturdier.
|
|
83
|
+
|
|
84
|
+
**Verify**: Once the gateway is up, the System Settings pill should turn green and the Tasks banner disappear. From the host:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
docker compose -f docker-compose.two-container.yml exec hermes-agent hermes gateway status
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
If the service name differs in your compose file, `docker compose -f docker-compose.two-container.yml ps` lists the running services.
|
|
91
|
+
|
|
92
|
+
Refs #2785.
|
|
93
|
+
|
|
94
|
+
## What goes wrong (and how to fix it)
|
|
95
|
+
|
|
96
|
+
### 1. "Permission denied" at startup
|
|
97
|
+
|
|
98
|
+
**Symptom**: Container starts but immediately crashes, logs show:
|
|
99
|
+
```
|
|
100
|
+
PermissionError: [Errno 13] Permission denied: '/home/hermeswebui/.hermes/...'
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Cause**: The container's user (UID 1000 by default) can't read your bind-mounted directory because your host files are owned by a different UID.
|
|
104
|
+
|
|
105
|
+
**Fix**: Set `UID` and `GID` in `.env` to match your host:
|
|
106
|
+
```bash
|
|
107
|
+
echo "UID=$(id -u)" >> .env
|
|
108
|
+
echo "GID=$(id -g)" >> .env
|
|
109
|
+
docker compose down && docker compose up -d
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
On macOS, host UIDs start at 501. On Linux, the first interactive user is usually UID 1000.
|
|
113
|
+
|
|
114
|
+
> **macOS Docker Desktop**: if UID mapping still misbehaves after the env fix, try toggling **Settings → General → File sharing implementation** between VirtioFS and gRPC-FUSE. Different implementations preserve UIDs across the host/container boundary differently.
|
|
115
|
+
|
|
116
|
+
### 2. ".env file mode 0640 → permission denied" (#1389)
|
|
117
|
+
|
|
118
|
+
**Symptom**: You set `HERMES_HOME_MODE=0640` (or some other group-readable mode) on your host `.env` file, container starts, then errors out:
|
|
119
|
+
```
|
|
120
|
+
[security] fixed permissions on .env (0o640 -> 0600)
|
|
121
|
+
failed to load .env: open .env: permission denied
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**Cause**: WebUI's `fix_credential_permissions()` startup hook enforces 0600 by default. This is the right thing for a clean install but conflicts with operator-set modes.
|
|
125
|
+
|
|
126
|
+
**Fix**: Set one of these env vars in your `.env`:
|
|
127
|
+
- `HERMES_SKIP_CHMOD=1` — bypass the fixer entirely
|
|
128
|
+
- `HERMES_HOME_MODE=0640` — allow group bits, only strip world-readable
|
|
129
|
+
|
|
130
|
+
Both are documented in `api/startup.py::fix_credential_permissions()`.
|
|
131
|
+
|
|
132
|
+
> ⚠️ **Multi-container warning**: `HERMES_HOME_MODE` has DIFFERENT semantics in the agent image vs. the WebUI:
|
|
133
|
+
> - **WebUI**: credential FILE mode threshold (`0640` allows group bits on `.env`)
|
|
134
|
+
> - **Agent**: `HERMES_HOME` *directory* mode (default `0700`)
|
|
135
|
+
>
|
|
136
|
+
> `0640` on a directory has no owner-execute bit, so the agent can't traverse its own home → bricked. For multi-container setups, use `HERMES_HOME_MODE=0750` (group-traversable) or `0701` (x-only). The compose files have per-service comments that match each side's semantics.
|
|
137
|
+
|
|
138
|
+
### 3. "Workspace appears empty even though my files are there"
|
|
139
|
+
|
|
140
|
+
**Symptom**: WebUI loads but `/workspace` shows no files.
|
|
141
|
+
|
|
142
|
+
**Cause**: Same as #1 — UID mismatch on the bind mount.
|
|
143
|
+
|
|
144
|
+
**Fix**: Same as #1 — match host UID/GID via `.env`.
|
|
145
|
+
|
|
146
|
+
### 4. "Two-container setup: WebUI can't find agent source" (#858)
|
|
147
|
+
|
|
148
|
+
**Symptom**: WebUI logs at startup:
|
|
149
|
+
```
|
|
150
|
+
!! WARNING: hermes-agent source not found.
|
|
151
|
+
!! Looked in: /home/hermeswebui/.hermes/hermes-agent
|
|
152
|
+
!! /opt/hermes
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**Cause**: The agent's source (`/opt/hermes` inside the agent container) needs to be exposed to the WebUI container via a shared volume. The two-container compose file does this via `hermes-agent-src` named volume, but if you're using bind mounts incorrectly the path won't resolve.
|
|
156
|
+
|
|
157
|
+
**Fix**: Use the named volumes that ship with `docker-compose.two-container.yml` — don't replace them with bind mounts unless you know what you're doing. The agent container writes its source to `/opt/hermes`, and the WebUI mounts that volume at `/home/hermeswebui/.hermes/hermes-agent`.
|
|
158
|
+
|
|
159
|
+
If you must use a bind mount: pick a host path, then mount it to `/opt/hermes` in the agent container AND `/home/hermeswebui/.hermes/hermes-agent` in the WebUI container.
|
|
160
|
+
|
|
161
|
+
### 5. "Tools (git, node, etc.) missing in two-container setup" (#681)
|
|
162
|
+
|
|
163
|
+
**Symptom**: You ask the agent to run `git status` in chat and it errors with `command not found`.
|
|
164
|
+
|
|
165
|
+
**Cause**: This is **architectural, not a bug**. In the two-container setup, agent processes started by the WebUI run **inside the WebUI container**, not the agent container. The WebUI image doesn't include git/node by design (it's a UI image, not a tool host).
|
|
166
|
+
|
|
167
|
+
**Workarounds**:
|
|
168
|
+
- **Single-container setup** (`docker-compose.yml`) — everything in one container, no boundary
|
|
169
|
+
- **Custom WebUI image** — extend the `Dockerfile` to install the tools you need
|
|
170
|
+
- **Combined image** ([sunnysktsang/hermes-suite](https://github.com/sunnysktsang/hermes-suite)) — community fork that ships agent+webui+dashboard in one container
|
|
171
|
+
|
|
172
|
+
### 6. "config.yaml not loaded"
|
|
173
|
+
|
|
174
|
+
**Symptom**: You have a `config.yaml` in your host `~/.hermes/`, but the WebUI shows "no model configured" or doesn't pick up your custom providers.
|
|
175
|
+
|
|
176
|
+
**Cause**: Either the file isn't readable (UID/GID issue, see #1) or it's not in the expected path inside the container.
|
|
177
|
+
|
|
178
|
+
**Fix**:
|
|
179
|
+
- Verify: `docker exec hermes-webui ls -la /home/hermeswebui/.hermes/config.yaml`
|
|
180
|
+
- If it doesn't exist: your host bind mount is pointing at the wrong directory.
|
|
181
|
+
- If it exists but is unreadable: see #1 for the UID/GID fix.
|
|
182
|
+
|
|
183
|
+
### 7. "On Podman: can't share .hermes between containers"
|
|
184
|
+
|
|
185
|
+
**Symptom**: Two-container setup works on Docker but fails on Podman with permission errors no matter what UID/GID you set.
|
|
186
|
+
|
|
187
|
+
**Cause**: Podman 3.4 (Ubuntu 22.04 default) has limited support for `userns_mode: keep-id` across multiple containers — files written by one container appear with a different UID in the other.
|
|
188
|
+
|
|
189
|
+
**Fix**: Either upgrade to Podman 4+ (which fixes this), or use the [single-container setup](#5-minute-quickstart-single-container), or use the [community all-in-one image](https://github.com/sunnysktsang/hermes-suite).
|
|
190
|
+
|
|
191
|
+
### 8. "API base URL set to localhost fails from Docker" (#3012)
|
|
192
|
+
|
|
193
|
+
**Symptom**: A provider, local model server, webhook, or custom API works on the host at `http://localhost:<port>`, but fails when the same URL is configured in Hermes WebUI running in Docker.
|
|
194
|
+
|
|
195
|
+
**Cause**: Inside a container, `localhost` means *that container*, not your laptop/host. The WebUI process cannot reach host services through `127.0.0.1` unless the service is running inside the same container.
|
|
196
|
+
|
|
197
|
+
**Fix**: Point Docker-hosted WebUI at the host gateway name instead:
|
|
198
|
+
|
|
199
|
+
- Docker Desktop on macOS/Windows: `http://host.docker.internal:<port>`
|
|
200
|
+
- Podman: `http://host.containers.internal:<port>`
|
|
201
|
+
- Linux Docker Engine: either publish the host service on the Docker bridge address, or add a host-gateway alias to your compose service:
|
|
202
|
+
|
|
203
|
+
```yaml
|
|
204
|
+
services:
|
|
205
|
+
hermes-webui:
|
|
206
|
+
extra_hosts:
|
|
207
|
+
- "host.docker.internal:host-gateway"
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Then configure the URL as `http://host.docker.internal:<port>`. Also ensure the host service binds to an address reachable from containers (not only a loopback interface the Docker bridge cannot reach) and that your host firewall allows the connection.
|
|
211
|
+
|
|
212
|
+
## Multi-container architecture
|
|
213
|
+
|
|
214
|
+
The two- and three-container setups use **named Docker volumes** (not bind mounts) by default for a reason: named volumes solve the UID/GID problem by construction. Docker creates the volume's root directory with the correct ownership, all containers reading/writing to it see the same files, no host-side permission setup required.
|
|
215
|
+
|
|
216
|
+
```
|
|
217
|
+
┌─────────────────────────────────┐
|
|
218
|
+
│ hermes-home (volume) │
|
|
219
|
+
│ (config, sessions, state, ...) │
|
|
220
|
+
└─────────────────────────────────┘
|
|
221
|
+
↑ ↑
|
|
222
|
+
│ rw │ rw
|
|
223
|
+
│ │
|
|
224
|
+
┌──────────────┐ │ │ ┌──────────────┐
|
|
225
|
+
│ hermes-agent │────┘ └────│ hermes-webui │
|
|
226
|
+
│ (port 8642) │ │ (port 8787) │
|
|
227
|
+
└──────────────┘ └──────────────┘
|
|
228
|
+
│ ↑
|
|
229
|
+
│ rw │ ro
|
|
230
|
+
↓ │
|
|
231
|
+
┌─────────────────────────┐ │
|
|
232
|
+
│ hermes-agent-src (vol) │─────────────────────┘
|
|
233
|
+
│ (agent's Python source) │
|
|
234
|
+
└─────────────────────────┘
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
The WebUI container doesn't ship with the agent's Python deps — at startup it runs `uv pip install /home/hermeswebui/.hermes/hermes-agent` to install them from the shared volume. The WebUI mount is read-only; the agent container is the only writer.
|
|
238
|
+
|
|
239
|
+
## Upgrading the agent container
|
|
240
|
+
|
|
241
|
+
The `hermes-agent-src` named volume is initialised from the agent image's `/opt/hermes` on first `up`. Docker reuses the volume verbatim on every subsequent `up` — **even after `docker pull` of a newer agent image**. The cached volume content masks the new image's source tree, so a fresh `docker pull` of `nousresearch/hermes-agent:latest` does not by itself give you the new agent code, dependencies, or entrypoint.
|
|
242
|
+
|
|
243
|
+
This is the root cause of [#1416](https://github.com/nesquena/hermes-webui/issues/1416): the symptom looked like a missing entrypoint, but the entrypoint was actually present in the new image and hidden behind the stale named volume.
|
|
244
|
+
|
|
245
|
+
To upgrade the agent image cleanly, drop the source volume before recreating:
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
# Two-container setup
|
|
249
|
+
docker compose -f docker-compose.two-container.yml down
|
|
250
|
+
docker volume rm <project>_hermes-agent-src
|
|
251
|
+
docker compose -f docker-compose.two-container.yml pull
|
|
252
|
+
docker compose -f docker-compose.two-container.yml up -d
|
|
253
|
+
|
|
254
|
+
# Three-container setup
|
|
255
|
+
docker compose -f docker-compose.three-container.yml down
|
|
256
|
+
docker volume rm <project>_hermes-agent-src
|
|
257
|
+
docker compose -f docker-compose.three-container.yml pull
|
|
258
|
+
docker compose -f docker-compose.three-container.yml up -d
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Replace `<project>` with your Compose project name (the parent directory by default; check with `docker volume ls`). The `hermes-home` volume (config, sessions, state) is left untouched — only `hermes-agent-src` (the agent's installed Python source) is recreated.
|
|
262
|
+
|
|
263
|
+
> The single-container setup (`docker-compose.yml`) does not use `hermes-agent-src` and is not affected by this upgrade pattern — pulling a newer WebUI image and `docker compose up -d --force-recreate` is sufficient.
|
|
264
|
+
|
|
265
|
+
## What the multi-container setup isolates (and what it doesn't)
|
|
266
|
+
|
|
267
|
+
The two- and three-container setups give you **process, network, and resource isolation** between the gateway and the chat UI:
|
|
268
|
+
|
|
269
|
+
- Each service has its own PID namespace and lifecycle — the agent process can crash without taking down the chat UI and vice versa.
|
|
270
|
+
- The gateway API (port 8642) is bound by the agent service only; the WebUI cannot bind it. Other containers reach the gateway via the `hermes-net` Docker network.
|
|
271
|
+
- Resource limits (`deploy.resources.limits` in `docker-compose.three-container.yml`) apply per service, so you can cap the agent independently of the dashboard.
|
|
272
|
+
- Restart policies, log streams, and container health checks are scoped per service.
|
|
273
|
+
|
|
274
|
+
What multi-container does **not** isolate:
|
|
275
|
+
|
|
276
|
+
- **Filesystem boundary.** Both services share `hermes-home` (config, sessions, state), and the WebUI mounts the agent's installed source from `hermes-agent-src`. The WebUI mount is read-only (since v0.51.84), but the agent service still has write access, and both services share the home volume.
|
|
277
|
+
- **UID/GID boundary.** Both services default to `${UID:-1000}` so files written by one are readable by the other. If you align them to different UIDs you'll get permission errors on the shared volume.
|
|
278
|
+
- **Trust boundary on the agent source.** The WebUI installs Python dependencies from the shared `hermes-agent-src` volume at startup. The read-only mount means a compromised WebUI cannot rewrite the agent source, but it does run code from that volume.
|
|
279
|
+
|
|
280
|
+
If you need **filesystem isolation** between the chat UI and the agent (e.g. you don't trust the WebUI to read agent state), the multi-container setup is not enough — run the agent on a separate host and connect the WebUI to it via the gateway HTTP API. If you don't need any boundary, the single-container setup is simpler.
|
|
281
|
+
|
|
282
|
+
The direct source mount is a compatibility bridge, not the long-term API contract. The current source/API boundary inventory and decoupling task list live in [`docs/rfcs/agent-source-boundary.md`](rfcs/agent-source-boundary.md) for [#2453](https://github.com/nesquena/hermes-webui/issues/2453). If you customize the compose files with bind mounts, keep the WebUI-side agent source mount read-only unless you are intentionally doing local development; `docker_init.bash` warns at startup when that path is writable.
|
|
283
|
+
|
|
284
|
+
## Bind-mount migration (advanced)
|
|
285
|
+
|
|
286
|
+
If you really need to bind-mount an existing host `~/.hermes` (e.g. you're keeping config in dotfiles, sharing with a non-Docker `hermes` install, etc.):
|
|
287
|
+
|
|
288
|
+
```yaml
|
|
289
|
+
volumes:
|
|
290
|
+
hermes-home:
|
|
291
|
+
driver: local
|
|
292
|
+
driver_opts:
|
|
293
|
+
type: none
|
|
294
|
+
o: bind
|
|
295
|
+
device: /home/youruser/.hermes
|
|
296
|
+
hermes-agent-src:
|
|
297
|
+
driver: local
|
|
298
|
+
driver_opts:
|
|
299
|
+
type: none
|
|
300
|
+
o: bind
|
|
301
|
+
device: /opt/hermes-agent-source
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
**Critical requirements**:
|
|
305
|
+
|
|
306
|
+
1. The host directory MUST be readable by your container UID. Run `id -u` on the host and ensure `~/.hermes` is owned by that UID (or readable via group bits).
|
|
307
|
+
2. ALL containers sharing the volume must run as the SAME UID/GID. Set `UID=$(id -u)` and `GID=$(id -g)` in `.env`.
|
|
308
|
+
3. If you run Compose with sudo, do not rely on `${HOME}` defaults: `sudo` often changes `$HOME` to `/root`, so `${HERMES_HOME:-${HOME}/.hermes}` becomes `/root/.hermes`. Prefer running Docker as your user; otherwise pass absolute paths with `sudo -E`, for example `HERMES_HOME=/home/youruser/.hermes HERMES_WORKSPACE=/home/youruser/workspace sudo -E docker compose up -d`, and confirm the rendered bind mount with `docker compose config`.
|
|
309
|
+
4. If your host `.env` is mode 0640, set `HERMES_SKIP_CHMOD=1` or `HERMES_HOME_MODE=0640` so the startup hook doesn't try to enforce 0600.
|
|
310
|
+
|
|
311
|
+
## Reference
|
|
312
|
+
|
|
313
|
+
- [`docker-compose.yml`](../docker-compose.yml) — single container (recommended)
|
|
314
|
+
- [`docker-compose.two-container.yml`](../docker-compose.two-container.yml) — agent + webui
|
|
315
|
+
- [`docker-compose.three-container.yml`](../docker-compose.three-container.yml) — agent + dashboard + webui
|
|
316
|
+
- [`.env.docker.example`](../.env.docker.example) — environment variable template
|
|
317
|
+
- [`Dockerfile`](../Dockerfile) — single-container build
|
|
318
|
+
- [`docker_init.bash`](../docker_init.bash) — container entrypoint script
|
|
319
|
+
|
|
320
|
+
## Related issues
|
|
321
|
+
|
|
322
|
+
- #1416 — agent-image upgrade requires removing `hermes-agent-src` named volume (see [Upgrading the agent container](#upgrading-the-agent-container))
|
|
323
|
+
- #1389 — `HERMES_HOME_MODE` override (fixed in v0.50.254 — agent honors `HERMES_SKIP_CHMOD` and `HERMES_HOME_MODE`)
|
|
324
|
+
- #1399 — UID alignment in compose files (fixed in v0.50.260 via PR #1428 + this guide)
|
|
325
|
+
- #3012 — host `localhost` API URLs fail from Docker containers (use `host.docker.internal` / `host.containers.internal`)
|
|
326
|
+
- #3006 — `sudo docker compose` can mount `/root/.hermes` instead of the user's Hermes home
|
|
327
|
+
- #858 — two-container `/opt/hermes` path confusion
|
|
328
|
+
- #681 — tools running in WebUI container, not agent container (architectural)
|
|
329
|
+
- #668 — auto-detect UID/GID from mounted volume
|
|
330
|
+
- #569 — UID/GID detection priority order
|
|
331
|
+
|
|
332
|
+
If you hit a new failure mode not covered here, please [open an issue](https://github.com/nesquena/hermes-webui/issues/new) with:
|
|
333
|
+
|
|
334
|
+
1. Which compose file you used
|
|
335
|
+
2. The error from `docker logs hermes-webui`
|
|
336
|
+
3. `docker exec hermes-webui id` output
|
|
337
|
+
4. `docker exec hermes-webui ls -la /home/hermeswebui/.hermes` output
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# Agent-assisted onboarding checklist
|
|
2
|
+
|
|
3
|
+
This checklist is for an AI assistant helping a human install, reinstall, or
|
|
4
|
+
debug Hermes WebUI onboarding. It does not replace the human first-run wizard.
|
|
5
|
+
Use it before running bootstrap commands, inspecting logs, or recommending a
|
|
6
|
+
cleanup path.
|
|
7
|
+
|
|
8
|
+
If you are an AI assistant, read this file before assisting with onboarding,
|
|
9
|
+
bootstrap, provider setup, reinstall, or first-run support.
|
|
10
|
+
|
|
11
|
+
## Role split
|
|
12
|
+
|
|
13
|
+
The human operator owns:
|
|
14
|
+
|
|
15
|
+
- choosing the install path
|
|
16
|
+
- choosing the provider and model
|
|
17
|
+
- entering API keys, OAuth codes, and passwords
|
|
18
|
+
- approving any cleanup of a real Hermes home
|
|
19
|
+
- approving any external exposure outside localhost
|
|
20
|
+
|
|
21
|
+
The assistant owns:
|
|
22
|
+
|
|
23
|
+
- using isolated trial directories unless the human explicitly says otherwise
|
|
24
|
+
- checking non-secret status endpoints and logs
|
|
25
|
+
- explaining which step passed or failed
|
|
26
|
+
- collecting redacted evidence for Discord or GitHub support
|
|
27
|
+
- stopping before destructive cleanup, credential handling, or public exposure
|
|
28
|
+
|
|
29
|
+
## Hard safety rules
|
|
30
|
+
|
|
31
|
+
- Do not delete, move, or overwrite the real `~/.hermes` directory unless the
|
|
32
|
+
human explicitly asks for that exact action.
|
|
33
|
+
- Do not print API keys, OAuth tokens, cookies, full `.env` files, full
|
|
34
|
+
`auth.json` files, or password hashes.
|
|
35
|
+
- Do not modify real cron jobs, real sessions, real profiles, or real memory
|
|
36
|
+
files during an onboarding trial.
|
|
37
|
+
- Do not expose WebUI on a public interface without password protection and
|
|
38
|
+
explicit human approval.
|
|
39
|
+
- Do not proxy or tunnel local service checks such as `localhost`,
|
|
40
|
+
`127.0.0.1`, private LAN addresses, or Docker container loopback paths.
|
|
41
|
+
|
|
42
|
+
## Pre-flight
|
|
43
|
+
|
|
44
|
+
Confirm the basic context:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pwd
|
|
48
|
+
git branch --show-current
|
|
49
|
+
git rev-parse --short HEAD
|
|
50
|
+
python3 --version
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Check whether repo-local environment overrides will affect bootstrap:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
test -f .env && grep -n 'HERMES_HOME\|HERMES_WEBUI_STATE_DIR\|HERMES_WEBUI_PORT\|HERMES_WEBUI_HOST' .env
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
If `.env` exists, do not print the full file. Inspect only the specific
|
|
60
|
+
non-secret keys needed to understand the active Hermes home, WebUI state
|
|
61
|
+
directory, port, or host.
|
|
62
|
+
|
|
63
|
+
## Isolated local trial
|
|
64
|
+
|
|
65
|
+
Use an isolated Hermes home and WebUI state directory for a reinstall or support
|
|
66
|
+
trial. This keeps the test away from the operator's real memory, sessions,
|
|
67
|
+
profiles, credentials, and cron state.
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
mkdir -p ~/hermes-onboarding-test
|
|
71
|
+
HERMES_HOME=~/hermes-onboarding-test/.hermes \
|
|
72
|
+
HERMES_WEBUI_STATE_DIR=~/hermes-onboarding-test/webui \
|
|
73
|
+
HERMES_WEBUI_PORT=8789 \
|
|
74
|
+
python3 bootstrap.py
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Open:
|
|
78
|
+
|
|
79
|
+
```text
|
|
80
|
+
http://127.0.0.1:8789
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
The bootstrap writes a port-specific log under the selected WebUI state
|
|
84
|
+
directory:
|
|
85
|
+
|
|
86
|
+
```text
|
|
87
|
+
~/hermes-onboarding-test/webui/bootstrap-8789.log
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
For daemon-style installs, `ctl.sh` writes the daemon log to the active
|
|
91
|
+
`HERMES_HOME` by default:
|
|
92
|
+
|
|
93
|
+
```text
|
|
94
|
+
~/.hermes/webui.log
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
When using the isolated trial environment, prefer the bootstrap command above
|
|
98
|
+
unless the human specifically wants to validate `ctl.sh`.
|
|
99
|
+
|
|
100
|
+
## Non-secret evidence commands
|
|
101
|
+
|
|
102
|
+
After the server starts, collect status without secrets:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
curl -sS http://127.0.0.1:8789/health
|
|
106
|
+
curl -sS http://127.0.0.1:8789/api/onboarding/status
|
|
107
|
+
find ~/hermes-onboarding-test -maxdepth 3 -type f | sort
|
|
108
|
+
tail -n 120 ~/hermes-onboarding-test/webui/bootstrap-8789.log
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
When summarizing `/api/onboarding/status`, focus on:
|
|
112
|
+
|
|
113
|
+
- `completed`
|
|
114
|
+
- `system.hermes_found`
|
|
115
|
+
- `system.imports_ok`
|
|
116
|
+
- `system.config_path`
|
|
117
|
+
- `system.config_exists`
|
|
118
|
+
- `system.setup_state`
|
|
119
|
+
- `system.provider_configured`
|
|
120
|
+
- `system.provider_ready`
|
|
121
|
+
- `system.chat_ready`
|
|
122
|
+
- `system.current_provider`
|
|
123
|
+
- `system.current_model`
|
|
124
|
+
- `system.current_base_url`
|
|
125
|
+
- `system.env_path`
|
|
126
|
+
|
|
127
|
+
Do not paste the full payload if it contains unexpected sensitive local paths
|
|
128
|
+
or values. Redact paths and provider details when the human asks for a public
|
|
129
|
+
GitHub or Discord support report.
|
|
130
|
+
|
|
131
|
+
## Pass criteria
|
|
132
|
+
|
|
133
|
+
A local onboarding trial passes when:
|
|
134
|
+
|
|
135
|
+
- `/health` returns successfully.
|
|
136
|
+
- `/api/onboarding/status` returns JSON.
|
|
137
|
+
- The wizard appears when `completed` is false.
|
|
138
|
+
- The wizard stays out of the way when `completed` is true or
|
|
139
|
+
`HERMES_WEBUI_SKIP_ONBOARDING=1` is intentionally set.
|
|
140
|
+
- `system.hermes_found` and `system.imports_ok` match the expected bootstrap
|
|
141
|
+
state.
|
|
142
|
+
- `system.provider_ready` and `system.chat_ready` become true after the human
|
|
143
|
+
completes a provider path that should support chat.
|
|
144
|
+
- `system.config_path` and `system.env_path` point inside the intended isolated
|
|
145
|
+
`HERMES_HOME` during a trial.
|
|
146
|
+
- WebUI files are written under the intended `HERMES_WEBUI_STATE_DIR`.
|
|
147
|
+
|
|
148
|
+
If the human chooses a provider that must be completed in the CLI, passing can
|
|
149
|
+
mean the wizard correctly points them to `hermes model` or `hermes auth` rather
|
|
150
|
+
than trying to collect unsupported credentials in the browser.
|
|
151
|
+
|
|
152
|
+
## Failure triage
|
|
153
|
+
|
|
154
|
+
If the server does not start:
|
|
155
|
+
|
|
156
|
+
- check the bootstrap log
|
|
157
|
+
- check for a port conflict on `8789`
|
|
158
|
+
- confirm Python can run `bootstrap.py`
|
|
159
|
+
- confirm `.env` is not overriding the isolated directories or port
|
|
160
|
+
|
|
161
|
+
If onboarding reports `agent_unavailable`:
|
|
162
|
+
|
|
163
|
+
- confirm the bootstrap found or installed Hermes Agent
|
|
164
|
+
- check whether the running Python can import `run_agent.AIAgent`
|
|
165
|
+
- use `docs/troubleshooting.md`, especially the `AIAgent not available` flow
|
|
166
|
+
|
|
167
|
+
If onboarding reports `provider_incomplete`:
|
|
168
|
+
|
|
169
|
+
- confirm whether the provider is API-key based, OAuth based, or local
|
|
170
|
+
- let the human enter credentials or run the CLI auth flow
|
|
171
|
+
- do not ask the human to paste secrets into chat
|
|
172
|
+
|
|
173
|
+
If a local model server does not probe successfully:
|
|
174
|
+
|
|
175
|
+
- from native macOS/Linux, use `http://127.0.0.1:<port>/v1` when the server is
|
|
176
|
+
on the same host
|
|
177
|
+
- from Docker Desktop, use `http://host.docker.internal:<port>/v1`
|
|
178
|
+
- from another LAN machine, use the server's LAN IP and `/v1`
|
|
179
|
+
- remember that `localhost` inside a container is the container itself
|
|
180
|
+
|
|
181
|
+
If password or reverse-proxy behavior is confusing:
|
|
182
|
+
|
|
183
|
+
- keep the first pass on `127.0.0.1`
|
|
184
|
+
- require password protection before exposing WebUI beyond localhost
|
|
185
|
+
- include the reverse proxy shape in the support report without pasting tokens
|
|
186
|
+
or cookies
|
|
187
|
+
|
|
188
|
+
## Final support report
|
|
189
|
+
|
|
190
|
+
Use this shape when reporting results to the human, Discord, or GitHub:
|
|
191
|
+
|
|
192
|
+
```text
|
|
193
|
+
Install path:
|
|
194
|
+
OS / Python:
|
|
195
|
+
Repo commit:
|
|
196
|
+
Command used:
|
|
197
|
+
WebUI URL:
|
|
198
|
+
State isolation:
|
|
199
|
+
Health result:
|
|
200
|
+
Onboarding status summary:
|
|
201
|
+
Files created or changed:
|
|
202
|
+
Log excerpt:
|
|
203
|
+
Pass/fail:
|
|
204
|
+
Next recommended action:
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Redact secrets and private paths before posting publicly.
|