feat: WS request proxy — Phase 2 (#210) #214

Merged
xiaomo merged 2 commits from feat/210-ws-gateway-phase2 into main 2026-05-13 03:06:29 +00:00
Owner

What

Phase 2 of #210: Dashboard API 请求通过 Gateway → WebSocket → 本地 serve 代理,替代 HTTP fetch 经 tunnel。

Why

Phase 1 建立了 WS 连接,但请求仍走 HTTP fetch。CF Workers 不能 fetch localhost(403),所以 WS 代理是让 Dashboard 正常工作的关键。

Changes

Gateway (packages/workflow-gateway/)

  • src/ws-protocol.ts新增 WsRequest/WsResponse 类型 + 严格解析器
  • src/agent-socket.ts — DO 新增 proxy POST 路由:发 WsRequest 到 WS → 等 WsResponse(30s 超时 504,无连接 503)
  • src/index.ts/api/agents/:agent/* 优先走 DO WS 代理,503 时 fallback 到 HTTP fetch
  • package.json — exports 增加 ./ws-protocol

Agent (packages/cli-workflow/)

  • src/commands/serve/ws-client.ts — 收到 WsRequest 后 fetch localhost:PORT,回传 WsResponse
  • src/commands/serve/serve.ts — 传 localPort 给 WS client
  • package.json — 依赖 @uncaged/workflow-gateway

Testing

#213 验证:

  • Step 1: serve 启动 WS 连接成功
  • Step 2: workflows 列表通过 WS 代理返回
  • Step 3: threads 列表通过 WS 代理返回
  • Step 4: Dashboard 端到端(主人正在看)
  • Step 5: agent 不可达时返回 404(不挂起)
  • Step 6: WsRequest/WsResponse id 匹配

Ref

## What Phase 2 of #210: Dashboard API 请求通过 Gateway → WebSocket → 本地 serve 代理,替代 HTTP fetch 经 tunnel。 ## Why Phase 1 建立了 WS 连接,但请求仍走 HTTP fetch。CF Workers 不能 fetch localhost(403),所以 WS 代理是让 Dashboard 正常工作的关键。 ## Changes ### Gateway (`packages/workflow-gateway/`) - `src/ws-protocol.ts` — **新增** WsRequest/WsResponse 类型 + 严格解析器 - `src/agent-socket.ts` — DO 新增 proxy POST 路由:发 WsRequest 到 WS → 等 WsResponse(30s 超时 504,无连接 503) - `src/index.ts` — `/api/agents/:agent/*` 优先走 DO WS 代理,503 时 fallback 到 HTTP fetch - `package.json` — exports 增加 `./ws-protocol` ### Agent (`packages/cli-workflow/`) - `src/commands/serve/ws-client.ts` — 收到 WsRequest 后 fetch `localhost:PORT`,回传 WsResponse - `src/commands/serve/serve.ts` — 传 `localPort` 给 WS client - `package.json` — 依赖 `@uncaged/workflow-gateway` ## Testing #213 验证: - ✅ Step 1: serve 启动 WS 连接成功 - ✅ Step 2: workflows 列表通过 WS 代理返回 - ✅ Step 3: threads 列表通过 WS 代理返回 - ⬜ Step 4: Dashboard 端到端(主人正在看) - ✅ Step 5: agent 不可达时返回 404(不挂起) - ✅ Step 6: WsRequest/WsResponse id 匹配 ## Ref - RFC: #210 - Testing: #213 - Depends on: #212 (Phase 1)
xingyue added 2 commits 2026-05-12 06:42:45 +00:00
- Add AgentSocket Durable Object (holds one WS per agent name)
- Add /ws/connect route with GATEWAY_SECRET auth
- Add ws-client.ts with auto-reconnect (exponential backoff 1s-30s)
- serve defaults to WS mode (no cloudflared needed)
- Keep --tunnel-url and --no-tunnel as fallback options
- Endpoints list merges KV heartbeat + DO WebSocket status

Testing: #211
- Add ws-protocol.ts with WsRequest/WsResponse types + parsers
- AgentSocket DO: proxy POST handler, pending request map, 30s timeout
- /api/agents/:agent/* routes through DO WS when connected, falls back to HTTP
- ws-client handles incoming WsRequest, fetches local serve, returns WsResponse
- startGatewayWsClient accepts localPort for request handling

Testing: #213
xingyue force-pushed feat/210-ws-gateway-phase2 from e84650ccf5 to ec3c97b200 2026-05-13 03:05:13 +00:00 Compare
xiaomo approved these changes 2026-05-13 03:06:24 +00:00
xiaomo left a comment
Owner

Clean implementation. Good type-safe WS protocol parsers, proper error handling with fallback from WS→direct fetch, no convention violations. LGTM.

Clean implementation. Good type-safe WS protocol parsers, proper error handling with fallback from WS→direct fetch, no convention violations. LGTM.
xiaomo merged commit 1664d68b50 into main 2026-05-13 03:06:29 +00:00
This repo is archived. You cannot comment on pull requests.
No Reviewers
No Label
2 Participants
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: uncaged/workflow#214