Skip to content

HTTP Server

pawaca edited this page Aug 30, 2026 · 1 revision

HTTP Server

Edge replaces the upstream Node.js HTTP server with Cloudflare Workers' fetch() handler.

Upstream reference: HTTP Server

What Upstream Provides

dsh-host-webserver is a Node.js HTTP plugin providing ctx.webServer with named route registration, index.html transformation, and a fallback handler. It does not belong to the agent loop — it is pure browser HTTP delivery. Other plugins register functional routes including /api bridges and HMR streams.

Route matching is fixed: exact table first, then longest prefix, then fallback. The composite /api handler dispatches to Typert Gateway first (for @Remote methods), then falls through to ApiProxy (for orchestration operations).

What Edge Changed

Replacement Workers fetch() replaces Node.js HTTP

DshEdgeInstance.fetch() replaces upstream's ctx.webServer. Requests dispatch through 6 points in order — first match wins:

# Handler Protocol URL example Status
1 handleEdgeRemote() A: Typert /api/commands/list ⚠️ Manual stub
2 handleTypertRpc() A: Typert /api/goals/edit ✅ Auto-routed
3 openDownlink() WebSocket /api/events.mux
4 apiFetch() B: apiproxy /api/session.prompt ⚠️ Reimplemented
5 parseSessionRoute() C: Edge REST /api/sessions/:id/prompt ✅ Edge-owned
6 Assets fallback Static /index.html

Why three protocols

A: Typert Remote (slash format: goals/edit) — cordis Service 的 @Remote methods, auto-discovered by TypertGatewayService. Client calls ctx.remote.goals.edit(). Fully upstream — Edge only routes the HTTP request to the gateway.

B: apiproxy (dot format: session.prompt) — orchestration operations coordinating multiple Services. Upstream provides ApiProxyService (cordis plugin) for this, but Edge can't install it due to unsatisfied dependencies. Edge hand-writes createEdgeApi() (~800 lines) as a simplified substitute. This is the largest upstream reimplementation in Edge.

C: Edge REST (path params: /sessions/:id/...) — session lifecycle operations that upstream handles through in-process apiproxy calls. Edge needs separate HTTP endpoints because these cross the Worker → DO boundary. Not new business logic — transport bridges between two Cloudflare runtimes.

Replacement DO hibernation replaces Node.js WebSocket

Edge uses Durable Object's hibernation API (WebSocketPair, ctx.acceptWebSocket(), ctx.getWebSockets(channel)) instead of Node.js HTTP upgrade. Sockets tagged 'mux' / 'host' survive DO hibernation.

What Edge Did NOT Change

  • Routing priority (Typert before ApiProxy), envelope format, dual-channel push
  • Client-side connection logic (all 33 client plugins work unchanged)

Performance Characteristics

Dispatch: 6 checks max (regex, string, prefix). Sub-millisecond, dominated by handler work.

WebSocket broadcast: O(connected clients) per frame, typically 1–3 tabs. DO hibernation keeps sockets alive without isolate cost.

Architecture Summary

Component Category Upstream
Workers fetch() Replace ctx.webServer
DO hibernation WebSocket Replace Node.js HTTP upgrade
Typert routing Bridge Connection.rpc.intercept
createEdgeApi() ⚠️ Reimpl ApiProxyService plugin

Key observation: The HTTP server is the most completely replaced upstream component. The functional contract is preserved — same routing priority, same envelope format, same dual-channel WebSocket. The client can't tell whether the server is Node.js or Workers. The main design debt is createEdgeApi(): ~800 lines of reimplemented apiproxy handlers that could be eliminated by satisfying ApiProxyService's dependencies.

TODO

TODO: Remove handleEdgeRemote stub — blocked on SkillRegistry gaining @Remote decorators. (#95)

TODO: Replace createEdgeApi() with ApiProxyService — blocked on satisfying 4 missing dependencies: directoryPicker, subagents, sessionQuery, userQuestions. (#96)

English

中文

Clone this wiki locally