feat(gui): make desktop setup flow real and testable

Add a GUI-first setup gate and runtime state API so desktop onboarding is safe, iterative, and works with isolated fresh-mode installs. Scaffold and wire the desktop shell/runtime pieces so this branch runs end-to-end without disturbing existing user installs.
This commit is contained in:
Brooklyn Nicholson
2026-04-25 19:48:02 -05:00
parent edc78e258c
commit 648da6a8d1
38 changed files with 14234 additions and 528 deletions

View File

@@ -0,0 +1,44 @@
param(
[string]$Out = "$PSScriptRoot\..\gui\src-tauri\sidecars\hermes-runtime",
[string]$Python = "python"
)
$Root = Resolve-Path "$PSScriptRoot\..\.."
Write-Host "Bundling Hermes GUI runtime"
Write-Host "repo: $Root"
Write-Host "out: $Out"
if (Test-Path $Out) {
Remove-Item -Recurse -Force $Out
}
New-Item -ItemType Directory -Force -Path $Out | Out-Null
Write-Host "-> Building dashboard"
npm --prefix "$Root\web" ci
npm --prefix "$Root\web" run build
Copy-Item -Recurse "$Root\web\dist" "$Out\web_dist"
Write-Host "-> Building TUI"
npm --prefix "$Root\ui-tui" ci
npm --prefix "$Root\ui-tui" run build
New-Item -ItemType Directory -Force -Path "$Out\ui-tui" | Out-Null
Copy-Item -Recurse "$Root\ui-tui\dist" "$Out\ui-tui\dist"
Copy-Item "$Root\ui-tui\package.json" "$Out\ui-tui\package.json"
Copy-Item "$Root\ui-tui\package-lock.json" "$Out\ui-tui\package-lock.json"
Copy-Item -Recurse "$Root\ui-tui\node_modules" "$Out\ui-tui\node_modules"
Write-Host "-> Creating Python runtime"
& $Python -m venv "$Out\venv"
& "$Out\venv\Scripts\python.exe" -m pip install --upgrade pip
& "$Out\venv\Scripts\python.exe" -m pip install -e "$Root[web,pty]"
@"
# Hermes GUI Runtime
Generated by apps/shared/bundle-runtime.ps1.
Set HERMES_GUI_RUNTIME_DIR to this directory before launching the Tauri shell.
"@ | Set-Content "$Out\README.md"
Write-Host "Runtime bundle ready: $Out"

View File

@@ -0,0 +1,41 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
OUT="${1:-"$ROOT/apps/gui/src-tauri/sidecars/hermes-runtime"}"
PYTHON="${PYTHON:-python}"
echo "Bundling Hermes GUI runtime"
echo "repo: $ROOT"
echo "out: $OUT"
rm -rf "$OUT"
mkdir -p "$OUT"
echo "→ Building dashboard"
npm --prefix "$ROOT/web" ci
npm --prefix "$ROOT/web" run build
cp -a "$ROOT/web/dist" "$OUT/web_dist"
echo "→ Building TUI"
npm --prefix "$ROOT/ui-tui" ci
npm --prefix "$ROOT/ui-tui" run build
mkdir -p "$OUT/ui-tui"
cp -a "$ROOT/ui-tui/dist" "$OUT/ui-tui/dist"
cp -a "$ROOT/ui-tui/package.json" "$ROOT/ui-tui/package-lock.json" "$OUT/ui-tui/"
cp -a "$ROOT/ui-tui/node_modules" "$OUT/ui-tui/node_modules"
echo "→ Creating Python runtime"
"$PYTHON" -m venv "$OUT/venv"
"$OUT/venv/bin/python" -m pip install --upgrade pip
"$OUT/venv/bin/python" -m pip install -e "$ROOT[web,pty]"
cat > "$OUT/README.md" <<EOF
# Hermes GUI Runtime
Generated by apps/shared/bundle-runtime.sh.
Set HERMES_GUI_RUNTIME_DIR to this directory before launching the Tauri shell.
EOF
echo "✓ Runtime bundle ready: $OUT"

View File

@@ -0,0 +1,33 @@
# GUI Runtime Contract
The GUI shell starts Hermes with a small, explicit environment.
## Environment
```text
HERMES_GUI=1
HERMES_WEB_DIST=<bundled web dist>
HERMES_TUI_DIR=<bundled ui-tui dir>
```
The native shell uses `127.0.0.1:9120` as its initial GUI port during dev.
Bundled builds should keep the port private to the local machine and expose it
through `/api/health` and `/api/runtime`.
The shell should also pass the selected profile through the normal Hermes CLI
profile mechanism once the profile picker is wired.
## Ports
Use `127.0.0.1` only. Start with the GUI default port, then fall back to a
free port if occupied. Show the chosen port in the tray menu.
## User Data
The installer owns app files. Hermes owns user state under `HERMES_HOME`.
Uninstallers must not delete user state unless the user explicitly asks.
## Update Model
MVP does not use Tauri's native updater. GUI runs `hermes update`, tails the
action log, notifies completion, then offers to restart the runtime.