6 Commits

Author SHA1 Message Date
b3204de62e daemon: fixa TDZ-dispatch + hook-port-per-instans (flera klienter/host)
All checks were successful
build-and-push / build (push) Successful in 9s
release-client / build-release (push) Successful in 46s
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
2026-06-29 01:42:39 +02:00
94259b3456 auth: OIDC/lokal inloggning + device-flow för klienter, sessioner per användare
All checks were successful
build-and-push / build (push) Successful in 18s
release-client / build-release (push) Successful in 48s
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
2026-06-29 01:21:29 +02:00
98c4d13360 BeforeTool-hook + kort-vy (strukturerade godkännanden) + release på master-push
All checks were successful
build-and-push / build (push) Successful in 22s
release-client / build-release (push) Successful in 48s
Feature: strukturerade verktygsgodkännanden
- shared: protokoll för approval (daemon:approval, server:approval[-resolved],
  web:approval-decision, server:approval-decision)
- daemon: hook-läge ('agent-helm hook' — samma binär), lokal 127.0.0.1-endpoint
  som hooken POST:ar till, long-poll tills beslut; graceful default (allow) när
  ingen UI; timeout-fallback; skickar AGENT_HELM_HOOK_PORT till agentens env
- server: routar daemon:approval -> prenumeranter, beslut -> daemon + döljer kort
- web: reaktiv approvals-lista + kort-overlay (Tillåt/Neka), mobilanpassad

CI:
- release.yaml triggar nu även på master-push -> rullande 'latest'-release
  (versionerade releaser kvar på v*-taggar); install.sh hämtar 'latest'

Docs: hook-konfig (gemini settings.json) + hook-env i .env.example + DEPLOY.md.
Säkerhet: hook-endpoint binder endast 127.0.0.1; inga hemligheter i repot.

Verifierat lokalt: hook->daemon->server->kort->beslut->hook ger {"decision":"allow"};
alla paket typecheckar; web bygger.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 18:03:12 +02:00
a6e304fb53 Klient-distribution: självständiga binärer + curl|sh-installer
All checks were successful
build-and-push / build (push) Successful in 26s
release-client / build-release (push) Successful in 1m3s
- 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>
2026-06-28 17:24:21 +02:00
8af5fd9972 Fixa native builds + CJS-interop; lås beroenden; verifierad slice
- 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>
2026-06-28 14:42:01 +02:00
c58f73626e Scaffolda tunn vertikal slice: pnpm-monorepo (shared/daemon/server/web)
- shared: typat WebSocket-protokoll (daemon/server/web som enda sanning)
- daemon: node-pty kör agenten (default gemini), strömmar pty över WS,
  auto-reconnect; fast pty-storlek
- server: WS-mux + token-auth + session-registry + headless-xterm scrollback
  (SerializeAddon) + routing av input till rätt session
- web: Vue 3 + Vite + xterm.js, session-lista, mobil-layout och
  fallback-tangentbord (piltangenter/Enter/Esc/Tab/Ctrl-C) som skickar
  escape-sekvenser rakt till pty:n -> styr sessionen även utan hooks
- workspace: pnpm-workspace.yaml (onlyBuiltDependencies: node-pty, esbuild),
  tsconfig.base, .npmrc (retry-inställningar), .env.example

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 14:28:04 +02:00