DeepSeek Harness 源码解析 · 第 41 讲
DeepSeek Harness 源码-Host 层与 Runtime Diagnostics 第 41 讲:webserver 路由语义、plugin-inventory 只读投影、invariants 注册表 💡 本讲一句话 Host 层把"浏览器能连上的东西"收敛成一个不认识 harness 概念的 HTTP 载体(webserver)加一个只读状态投影(plugin-inventory);Runtime Diagnostics 则让每个包用隔离的子 fiber 自持契约检查——宿主侧的纪律是:路由冲突 fail loud、单请求错误不杀进程、诊断失败不污染主上下文。 一、Host 家族:web GUI 的另一半 前面几讲一直在 Agent/Session/Compaction 这条"智能侧"链路上走。但 dsh 的 web GUI 还有另一半—— 宿主侧(host) :浏览器连进来的 API 网关、HTTP 服务器、目录选择器、插件清单投影。 packages/host/README.md 把家族关系写得很清楚: 📄 packages/host/README.md(L5-L18,节选) The host side of the dsh web GUI: the API gateway every client shape shares, and the plain HTTP server it rides on. // 宿主侧 = 所有客户端形态共享的 API 网关 + 它骑乘的纯 HTTP 服务器 | Package | Role | ctx key | // 家族表:包 → 角色 → cordis 上下文键 | apiproxy/ | Shared host API gateway and wire contract | ctx.apiProxy | // 传输无关的线协议层(第 42 讲细讲) | webserver/ | HTTP route carrier | ctx.webServer | // 本讲主角:路由注册载体,不认识任何 harness 概念 | frontend-static/ | SPA dist server on the webserver fallback seat | consumes ctx.webServer | // 消费 fallback 座位来发静态资源 | plugin-inventory/ | Read-only projection of current Loader entries | Remote pluginInventory/list | // 本讲配角:Loader 状态的只读投影 注意 README 里那句关键定位: "apiproxy remains transport-independent" ——网关协议与 HTTP 载体解耦,webserver 只是"骑乘"它的其中一种传输。本讲聚焦 webserver(路由语义 + 错误围堵)和 plugin-inventory(只读投影),再深入 packages/runtime-diagnostics/invariants/ ——每个包自持契约检查的注册表。 二、WebServer:路由注册的四种座位 packages/host/webserver/src/index.ts (266 行)把 HTTP 路由收敛成四种"座位":exact、prefix、upgrade、fallback。核心设计是 注册即契约 ——重复注册直接抛错,而不是后到者覆盖先到者: 📄 packages/host/webserver/src/index.ts(L59-L131) export class WebServer extends Service { // 路由载体服务:只认 HTTP,不认识 session/agent/harness(宿主侧薄层) static Config: z<Config> = z.object({ // 配置 schema:绑定地址 + 端口(0 = OS 分配随机端口) host: z.union([z.const('127.0.0.1'), z.const('0.0.0.0')]).required(), …