Två buggar som hittades vid test mot riktiga servern:
1. Dispatchen (`void runConnect()`) låg överst i filen, ovanför module-level
const CONFIG_DIR/CRED_FILE. runConnect:s synkrona del (fram till första
await) kördes då under modul-init medan de const:erna var i TDZ → loadCreds()
fick undefined path → returnerade null → klienten körde alltid nytt
device-flöde istället för att återuppta. Flyttad sist i filen.
2. Hook-porten var hårdkodad (8788) → flera daemon-instanser på samma host
krockade (EADDRINUSE) och kraschade. Nu: bind hook-porten FÖRST på en
ephemeral port (om AGENT_HELM_HOOK_PORT ej satt) och skicka faktiska porten
till agenten; bind-fel är icke-fatalt (kör vidare utan hook).
Verifierat mot rcai.brasse-pc.eu: resume återupptar rätt session, --new ger en
parallell session, två instanser kör samtidigt med var sin hook-port.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U68YyHsxU91ecsen84WQV4
Ersätter den delade AGENT_HELM_TOKEN med en riktig auth-modell:
- Webben loggar in med lokala konton ELLER OIDC (Authentik/Keycloak/…), valt
per server. Inloggning ger en HMAC-signerad cookie; WS autentiseras via cookien.
- Klienten (daemon) kopplas via device-flödet (RFC 8628-likt): `agent-helm connect`
skriver ut en URL, du loggar in + godkänner i webben, och får ett klient-token
som identifierar din användare. Token sparas i ~/.config/agent-helm/.
- Sessioner är per användare (web ser bara sina egna; admin ser alla). Flera
klient-instanser = flera parallella sessioner; --new tvingar ny, annars resume.
- Identitet är utbytbar (lokal/OIDC) men device-flödet + sessionerna är alltid
agent-helms egna → funkar för vem som helst som hostar detta, med eller utan IdP.
- Bootstrap-admin via env (engångs) eller first-run-setup i UI:t. Klient-creds
kan listas/återkallas; minimal admin-UI (skapa användare, konfigurera OIDC).
Nya filer: server/store.ts (JSON-store, scrypt, cookies), server/oidc.ts
(auth-code+PKCE), web/lib/api.ts. Verifierat end-to-end lokalt (login → device
→ approve → daemon-WS → web ser sessionen; web utan cookie nekas).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U68YyHsxU91ecsen84WQV4
- daemon: byt node-pty -> @homebridge/node-pty-prebuilt-multiarch (N-API-
prebuilds för x64+arm64, ingen kompilering); esbuild-bundle av daemonen
- .gitea/workflows/release.yaml: på tag v* bygger pkg båda arkitekturerna på
Pi-runnern (utan QEMU — prebuilds för båda finns) och publicerar som
Gitea-release-assets via API
- install.sh: 'curl -fsSL .../install.sh | sh' — detekterar arch, hämtar rätt
binär från senaste releasen, lägger agent-helm i PATH, skapar config.env +
valfri systemd-user-service (Arch/Ubuntu)
- deploy/client-build/package.json: pkg-config (assets för prebuilds)
- DEPLOY.md: klient-installationssektion
Verifierat lokalt: pkg-binär (x64, 83 MB) startar, node-pty spawnar pty,
ansluter och input/output funkar end-to-end.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- pnpm-workspace.yaml: allowBuilds för esbuild + node-pty (pnpm 11 ersätter
onlyBuiltDependencies-listan)
- pnpm-lock.yaml: committa låsfilen
- server: @xterm/headless + @xterm/addon-serialize är CommonJS — default-
importera värdet och ta typen via 'import type' (annars ESM-named-export-fel
i runtime trots att typecheck passerar)
- daemon: städa pty-processen även vid SIGTERM
Verifierat lokalt: alla paket typecheckar, web bundlar (vite), och rök-test av
server<->daemon<->klient passerar (token-auth, registrering, snapshot,
input->pty->output).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
README beskriver agent-helm — fjärrstyrning av Gemini CLI-sessioner från
mobil/webb. Dokumenterar komponenter (daemon/server/web/hooks), repo-struktur,
dataflöde, de två åtskilda input-kanalerna, samt fallback-navigering
(piltangenter + Enter rakt till pty) så att sessioner kan styras oavsett om
BeforeTool/Notification-hooks är uppsatta eller fungerar.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>