From fa25b41728586513c450b24673651bf3c455ad8a Mon Sep 17 00:00:00 2001 From: George Pickett Date: Sun, 15 Feb 2026 14:52:25 -0800 Subject: [PATCH] Docs: update architecture after SSH consolidation --- ARCHITECTURE.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 33450cd..4df5fcc 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -31,6 +31,7 @@ This keeps feature cohesion high while preserving a clear client/server boundary - **Studio settings** (`src/lib/studio`, `src/app/api/studio`): local settings store for gateway URL/token and focused preferences (`src/lib/studio/settings.ts`, `src/app/api/studio/route.ts`). `src/lib/studio/coordinator.ts` now owns both the `/api/studio` transport helpers and shared client-side load/patch scheduling for gateway and focused settings. - **Gateway** (`src/lib/gateway`): WebSocket client for agent runtime (frames, connect, request/response). Session settings sync transport (`sessions.patch`) is centralized in `src/lib/gateway/GatewayClient.ts`. Connect failures from the Studio WS proxy are preserved as `GatewayResponseError` codes (parsed from `connect failed: ...`) so `useGatewayConnection` can gate auto-retry via `resolveGatewayAutoRetryDelayMs`. The OpenClaw control UI client is vendored in `src/lib/gateway/openclaw/GatewayBrowserClient.ts` with a sync script at `scripts/sync-openclaw-gateway-client.ts`. - **Studio gateway proxy server** (`server/index.js`, `server/gateway-proxy.js`, `server/studio-settings.js`): custom Next server that terminates browser WS at `/api/gateway/ws`, loads upstream gateway URL/token server-side, injects auth token when needed, and forwards frames to the upstream gateway. +- **Gateway SSH helpers** (`src/lib/ssh/gateway-host.ts`): shared SSH target resolution and JSON-over-SSH execution for server routes. `runSshJson` centralizes `ssh -o BatchMode=yes` invocation, JSON parsing, and actionable error extraction; callers with large payloads (for example base64 media reads) can opt into a higher `maxBuffer` rather than duplicating `spawnSync` calls. - **Gateway-backed config + agent-file edits** (`src/lib/gateway/agentConfig.ts`, `src/lib/gateway/agentFiles.ts`, `src/lib/gateway/execApprovals.ts`, `src/features/agents/components/AgentInspectPanels.tsx`): agent create/rename/heartbeat/delete and per-agent overrides via `config.get` + `config.patch`, agent file read/write via `agents.files.get` and `agents.files.set`, and per-agent exec approvals via `exec.approvals.get` + `exec.approvals.set`. - **Heartbeat helpers** (`src/lib/gateway/agentConfig.ts`): resolves per-agent heartbeat state (enabled + schedule) by combining gateway config (`config.get`) and status (`status`) for the settings panel, triggers `wake` for “run now”, and owns the heartbeat type shapes and gateway config mutation helpers. - **Session lifecycle actions** (`src/features/agents/state/store.tsx`, `src/app/page.tsx`): per-agent “New session” calls gateway `sessions.reset` on the current session key and resets local runtime transcript state. @@ -110,6 +111,7 @@ Flow: - Gateway connect failures that close with `connect failed: ...` are preserved as `GatewayResponseError` codes so auto-retry gating can be code-driven (instead of message-driven). - Gateway browser client truncates close reasons to WebSocket protocol limits (123 UTF-8 bytes) to avoid client-side close exceptions on long error messages. - **Filesystem helpers**: server-only filesystem operations live at the API route boundaries. Home-scoped path autocomplete is implemented directly in `src/app/api/path-suggestions/route.ts`. These helpers are used for local settings and path suggestions, not for agent file edits. +- **Remote gateway tools over SSH**: some server routes execute small scripts on the gateway host (for example agent-state operations and remote media reads). Shared helpers in `src/lib/ssh/gateway-host.ts` own SSH invocation and JSON parsing so routes do not hand-roll `spawnSync` error handling. - **Tracing**: `src/instrumentation.ts` registers `@vercel/otel` for telemetry. - **Validation**: request payload validation in API routes and typed client/server helpers in `src/lib/*`. @@ -125,6 +127,7 @@ Flow: - **Shared `agents.list` helper layer**: gateway and local config paths now consume one pure helper module for list parsing/writing/upsert behavior; trade-off is one more shared dependency, but it reduces semantic drift and duplicate bug surface. - **Single gateway settings endpoint**: `/api/studio` is the sole Studio gateway URL/token source; trade-off is migration pressure on any older local-config-based callers, but it removes ambiguous ownership and dead paths. - **Shared client settings coordinator module**: `src/lib/studio/coordinator.ts` now owns `/api/studio` transport plus load/schedule/flush behavior for gateway + focused state; trade-off is introducing a central client singleton, but it removes wrapper indirection and duplicate timers/fetch paths. +- **Single shared JSON-over-SSH helper**: server routes that need to run a gateway-side script over SSH should use `runSshJson` in `src/lib/ssh/gateway-host.ts` (and opt into a larger `maxBuffer` when expecting large payloads) rather than duplicating `spawnSync` + JSON parsing; trade-off is one shared dependency, but it reduces drift risk and keeps error surfacing consistent. - **Vendored gateway client + sync script**: reduces drift from upstream OpenClaw UI; trade-off is maintaining a sync path and local copies of upstream helpers. - **Feature-first organization**: increases cohesion in UI; trade-off is more discipline to keep shared logic in `lib`. - **Node runtime for API routes**: required for filesystem access and tool proxying; trade-off is Node-only server runtime.