# Knowledge Interaction Surfaces Hono Server API And Streaming

> 覆盖 Blade Hono 服务的路由装配、Session/Task 控制器、SSE replay/live 切换、 WebSocket 终端、静态资源、认证、错误映射与资源关闭。进入时机：新增 HTTP API、 修改 Web 事件协议、处理同名 Session、调试断线重连、服务容量或 shutdown。 不包含： 浏览器端 Zustand 投影（见 ../web-client/）、SessionEventLog 内部存储（见 ../../session-state-and-context/）。关键词：BladeServer, createSessionRouteController, OrderedSseEgress, Bus, Last-Event-ID, SessionRef, Hono, SSE, terminal WebSocket。

- Skill: `echovic/knowledge-interaction-surfaces-hono-server-api-and-streaming` (Agent Skill)
- Install (CLI): `npx skillmds@latest add echovic/knowledge-interaction-surfaces-hono-server-api-and-streaming`
- Raw SKILL.md: https://api.skillmd.com/api/skills/echovic/knowledge-interaction-surfaces-hono-server-api-and-streaming/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: echovic (https://skillmd.com/u/echovic)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/echovic/knowledge-interaction-surfaces-hono-server-api-and-streaming

---


## Module Structure

Server 是 Web 与自动化客户端的协议适配层：它拥有活动 run、Runtime residency、SSE
订阅者和 Web Browser Session，但 durable transcript 与任务事实仍由 Session 服务持有。

### Directory Layout
- `packages/cli/src/server/server.ts` — Hono 装配、认证/CORS、静态资源和网络生命周期
- `packages/cli/src/server/routes/session.ts` — Session、run、消息、交互和 SSE 主控制器
- `packages/cli/src/server/routes/task.ts` — 顶层任务提交、重试、diff 与交付 API
- `packages/cli/src/server/routes/events.ts` — 跨 Session 的看板安全全局事件流
- `packages/cli/src/server/routes/terminal.ts` — Bun/Node WebSocket PTY 适配
- `packages/cli/src/server/routes/` — 配置、Provider、MCP、插件、Hooks 等管理 API
- `packages/cli/src/server/OrderedSseEgress.ts` — replay/live 原子切换与有界写入
- `packages/cli/src/server/sessionRef.ts` — Session 复合身份规范化
- `packages/cli/src/server/WebBrowserSessionRegistry.ts` — Web 专用 Browser Runtime 所有权

### Key Entry Points
- `BladeServer.listenAsync()` in `packages/cli/src/server/server.ts` — 启动 Bun 或 Node 服务
- `createSessionRouteController()` in `packages/cli/src/server/routes/session.ts` — 创建路由与 Runtime 管理器
- `dispatchTask()` on `SessionRouteController` — Web、定时任务共用的任务派发入口
- `OrderedSseEgress.finishInitialization()` in `packages/cli/src/server/OrderedSseEgress.ts` — replay 到 live 的切换点
- `resolveSessionRef()` in `packages/cli/src/server/routes/session.ts` — 解析精确 Session 所属工作区

## Gotchas
- `sessionId` 不是 Server 内的完整身份；路由、活动 run、Runtime、锁和 Browser Registry 必须使用规范化的 `projectPath + sessionId`，同名多工作区且未给路径时应返回 409 而不是猜测 (`packages/cli/src/server/sessionRef.ts`, `packages/cli/src/server/routes/session.ts`)
- Session SSE 初始化必须先订阅 Bus 并缓冲 live，再写 connected、按 JSONL `seq` 回放、去重排序后切到 live；先回放再订阅会产生不可修复的事件空窗 (`packages/cli/src/server/routes/session.ts`, `packages/cli/src/server/OrderedSseEgress.ts`, `git:121ea8fc`)
- 只有 committed event 能携带 SSE `id`；ephemeral delta 在 replay 窗口直接丢弃，不能推进 `Last-Event-ID` (`packages/cli/src/server/bus.ts`, `packages/cli/src/server/OrderedSseEgress.ts`)
- `EventSource` 首次连接不能自定义 `Last-Event-ID` header，因此 Server 同时接受 `lastEventId` query；删除 query 支持会破坏页面刷新后的 durable resume (`packages/cli/src/server/routes/session.ts`)
- Session SSE 与 `/events` 全局 SSE 不可互换：全局流只投影白名单化的看板字段，明确排除 prompt 和私有执行细节 (`packages/cli/src/server/routes/events.ts`)
- 慢 SSE subscriber 的 overflow、写超时或 sequence regression 只终止该 subscriber，不能取消 server-owned Agent run 或影响其他订阅者 (`packages/cli/src/server/OrderedSseEgress.ts`, `docs/reference/surface-egress.md`)
- 活动 run 收到新 message 时走 durable steering/follow-up，不启动第二个 run；同时切换模型、权限、reasoning、tier、verbosity、style 或 output schema会返回冲突 (`packages/cli/src/server/routes/session.ts`)
- pending permission 既可能在内存 run 中，也可能只剩磁盘交互记录；响应路由必须先匹配精确 run，再通过 `SessionInteractionService.respondAndRecover()` 冷恢复 (`packages/cli/src/server/routes/permission.ts`, `packages/cli/src/server/routes/session.ts`)
- API 未设置 `BLADE_SERVER_PASSWORD` 时整体无认证；启用 Basic Auth 后根页面与静态资源仍公开，只有 API 路径受保护 (`packages/cli/src/server/server.ts`, `packages/cli/src/commands/serve.ts`)
- CORS 默认只放行 localhost、127.0.0.1 和 Tauri origin，额外来源必须通过 `--cors`；监听 `0.0.0.0` 不会自动放宽 CORS (`packages/cli/src/server/server.ts`, `packages/cli/src/cli/network.ts`)
- Node 与 Bun 的 PTY/WebSocket 适配不同，但最后一个终端 subscriber 断开时都会杀掉 PTY；Terminal 面板重连不会保留无人订阅的进程 (`packages/cli/src/server/routes/terminal.ts`)
- 删除 Session 时还要释放 Web Browser Runtime、活动 review/run、Runtime residency 和任务 worktree；只删 transcript 会留下进程与浏览器资源 (`packages/cli/src/server/routes/session.ts`, `packages/cli/src/server/WebBrowserSessionRegistry.ts`)

## Architecture
- `server.ts` 创建一个 SessionRouteController，并把同一 controller 注入 TaskRoutes 和 TaskScheduler，使 HTTP 手工任务、Web 操作和 schedule 复用相同准入与恢复逻辑 (`packages/cli/src/server/server.ts`)
- SessionController 分开管理 hydrated Session、active/recent run、Runtime initialization/disposal 与 residency lease；并发请求通过按 SessionRef 分片的 mutex 串行化消息和交付 (`packages/cli/src/server/routes/session.ts`)
- Runtime residency 只缓存可驱逐的 idle Runtime；active turn、pending interaction 或其他 pin 会阻止驱逐，容量满时映射为带资源详情的 429 (`packages/cli/src/server/routes/session.ts`, `packages/cli/src/server/error.ts`)
- `Bus` 是进程内扇出，不是持久消息队列；durable replay 始终从 `SessionEventLog` 读取，Bus 只承载当前进程 live 事件 (`packages/cli/src/server/bus.ts`, `packages/cli/src/server/routes/session.ts`)
- BrowserRoutes 在 SessionController 下共享精确 SessionRef 和全局 Browser admission，但 Web 测试浏览器由独立 registry 持有，不复用 Agent 的 browser runtime (`packages/cli/src/server/routes/browser.ts`, `packages/cli/src/server/WebBrowserSessionRegistry.ts`)
- Hono 顶层 `onError` 将容量和已分类 `BladeServerError` 保留为稳定状态码，其余错误收敛为 500 JSON envelope (`packages/cli/src/server/server.ts`, `packages/cli/src/server/error.ts`)

## Decisions
- Server 将 run 生命周期与 HTTP 请求解耦，请求返回 202 后由 Runtime 持续执行；SSE viewer 断开不等于取消任务，显式 abort 路由才改变 run (`packages/cli/src/server/routes/session.ts`)
- 静态资源使用内存原文/压缩缓存，Brotli 与 gzip 按 q 值选择，hash asset 长缓存而 `index.html` no-cache，以支持单进程直接托管 Web build (`packages/cli/src/server/server.ts`)
- 全局事件流采用字段级投影而不是透传 BusEvent，避免多项目任务看板获得 Session prompt、工具参数或私有结果 (`packages/cli/src/server/routes/events.ts`)
- Bun `listen()` 是同步专用入口，跨运行时命令使用 `listenAsync()`；Node fallback 只在异步入口组装 HTTP 与 `ws` upgrade (`packages/cli/src/server/server.ts`)

## Patterns
- 每个写 API 先解析 TypeBox schema，再解析精确 SessionRef，再进入 keyed lock/Runtime lease；新增写端点应保持该顺序以避免校验失败后占用运行资源 (`packages/cli/src/server/routes/session.ts`, `packages/cli/src/server/routes/task.ts`)
- Session run 的终态顺序是刷新 durable metadata、发送 `session.completed`/`session.error`、发送 idle/error status，最后释放 admission、Agent 和 Runtime lease (`packages/cli/src/server/routes/session.ts`)
- Server 输出的工具 metadata 经过 allowlist 投影，展示正文再按表面字符预算裁剪；Browser 诊断与 shell background 元数据另有严格字段校验 (`packages/cli/src/server/routes/session.ts`, `packages/cli/src/tools/display/ToolResultProjector.ts`)
- 服务关闭是幂等 single-flight：停止网络接入、关闭 SessionController、停止 scheduler/GC、重置 workspace 资源，并保留首个清理错误 (`packages/cli/src/server/server.ts`)
- Session Browser Registry 在从 Map 删除引用后再 dispose，批量关闭使用 `allSettled` 回收全部 Runtime 后才抛首个错误 (`packages/cli/src/server/WebBrowserSessionRegistry.ts`)

## Dependencies
- HTTP/SSE 使用 Hono，终端 WebSocket 使用 Bun WebSocket 或 `ws` + Node upgrade，PTY 使用 `bun-pty` 或 `node-pty`；跨运行时修改必须验证两条启动路径 (`packages/cli/src/server/server.ts`, `packages/cli/src/server/routes/terminal.ts`)

