Skip to content

feat(dashboard): port read-only views to daemon SDK via WS bridge#37

Open
Codename-11 wants to merge 1 commit into
feature/v3-foundationfrom
feature/dashboard-daemon-bridge
Open

feat(dashboard): port read-only views to daemon SDK via WS bridge#37
Codename-11 wants to merge 1 commit into
feature/v3-foundationfrom
feature/dashboard-daemon-bridge

Conversation

@Codename-11
Copy link
Copy Markdown
Owner

Summary

  • Adds a vanilla-JS daemon bridge (arc-client-bridge.js) that speaks the same binary-mux WebSocket protocol as @axiom-labs/arc-client, so the dashboard talks to the v3 daemon without pulling the Node SDK into the browser.
  • Ports profiles.js (profile.list) and overview.js (health.get + agent.list) to the new bridge, falling back to the existing HTTP API when the daemon isn't running.
  • Adds a /ws subprotocol-routed proxy (arc-daemon) that forwards browser WS upgrades to 127.0.0.1:7272, rewriting the daemon's 101 response to echo the subprotocol so strict WS clients accept the handshake. Returns 502 when the daemon is offline.
  • Adds GET /api/daemon-token (localhost-only) so in-browser code can read ~/.arc/auth.json#rootToken without the secret leaving the loopback interface.

Test plan

  • npx tsc --noEmit — clean
  • npx vitest run packages/dashboard/tests/bridge.test.ts — 7 tests pass (frame codec byte-for-byte identity with @axiom-labs/arc-client, readDaemonRootToken / isLocalRequest helpers)
  • All 31 dashboard tests pass (bridge + 24 pre-existing)
  • All 4 daemon integration tests still pass (no regression)
  • E2E: auth.login + health.get + profile.list through the proxy succeed
  • E2E: /api/daemon-token returns 503 and /ws returns 502 when daemon isn't running (graceful HTTP fallback)

Notes

  • Does NOT touch chat.js or styles/*.css per the worktree instructions (pre-existing WIP).
  • Legacy text-frame /ws path is preserved for existing components; only upgrades that advertise Sec-WebSocket-Protocol: arc-daemon are routed to the daemon.
  • ensureArcClient() caches a live connection but re-tries on failure so callers don't permanently lock into HTTP when the daemon comes up later.

Generated with Claude Code

Adds a vanilla-JS daemon bridge that speaks the same binary-mux WebSocket
protocol as `@axiom-labs/arc-client` so the dashboard can talk directly
to the v3 daemon without pulling the Node SDK into the browser bundle.

- `public/components/arc-client-bridge.js` (new) — frame codec + RPC /
  subscribe client that mirrors `packages/client/src/frame.ts` +
  `protocol.ts` byte-for-byte. Exposes `ensureArcClient()` which lazily
  fetches the daemon token from the dashboard and opens a WS, retrying
  on failure so the HTTP fallback stays working until the daemon is up.
- `public/components/profiles.js` — prefers `profile.list` over the WS
  when the daemon is reachable; falls back to `/api/profiles` otherwise.
- `public/components/overview.js` — augments `/api/overview` with live
  `health.get` + `agent.list` results from the daemon.
- `src/api.ts` — new `daemonToken` handler (localhost-only) plus
  `readDaemonRootToken` + `isLocalRequest` helpers.
- `src/server.ts` — registers `/api/daemon-token` and proxies
  `/ws` upgrades that carry the `arc-daemon` subprotocol to 127.0.0.1:7272.
  Rewrites the daemon's 101 response to echo the subprotocol (strict WS
  clients reject handshakes that don't). Returns 502 when the daemon is
  offline so the dashboard degrades cleanly to HTTP.
- `tests/bridge.test.ts` (new, 7 tests) — proves the bridge codec
  round-trips byte-identically with the authoritative client codec, and
  exercises the `daemonToken` helpers.

Typecheck clean; all 31 dashboard tests pass. E2E smoke verified:
auth.login + health.get + profile.list all succeed through the proxy;
`/api/daemon-token` returns 503 and `/ws` returns 502 when the daemon
isn't running.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant