DeepSeek Harness 源码解析 · 第 38 讲
DeepSeek Harness 源码解析系列 第 38 讲:扩展系统与自修改(extensions) 基于 DeepSeek Harness 源码 · 2026-09-21 💡 本讲一句话: 前 37 讲分析的都是"Agent 怎么干活",这一讲是"Agent 怎么给自己加新工具"——模型现场写 JavaScript,Host 半在 node:vm 沙箱里跑、Client 半在浏览器闭包里跑,版本不可变、升级要审批、失败可回滚。读完你会明白:自修改不是 eval 一把梭,而是一整套身份/版本/状态机设计。 一、"一切皆插件"的最后一块拼图:Agent 修改自己的运行时 DeepSeek Harness 构建在 Cordis 之上,核心信条是 everything is a plugin——工具、服务、UI 全是插件。但前面所有插件都是 人写死的 。extensions 子系统补上了最后一块:让模型在对话中现场编写插件代码,动态挂载到当前正在运行的 DSH 进程里,用完还能撤掉。 源码位于 packages/extensions/ ,由四个包组成(仓库 README 原话:"the agent modifies its own runtime"): 包 角色 挂载点 tool-cordis 模型可见的 7 个工具 + @pluginId 注入 ctx.tools / ctx.systemPrompt cordis-host-runner 版本注册表、node:vm 沙箱、run 状态机 ctx.dynamicCordisRunner cordis-client-runner 浏览器半:闭包求值 + host.call RPC client face(dshClient) ui-cordis 全局面板 + define/run 卡片(React) client slots 一个关键设计决策:每个动态包都是"双半"(dual-half)—— Host 半 跑在 DSH 的 Node.js 进程里,能碰文件、网络、Agent; Client 半 跑在浏览器页面里,负责 UI。两半之间只能走 JSON RPC。这个拆分贯穿本讲所有代码。 先立一个预期管理:sandbox.ts 的模块注释写得很直白——这套沙箱"keeps cooperative packages inspectable and disposable but is not containment: host-realm helper functions remain an escape route"。它防的是 模型手滑 (误用 API、泄漏状态),不是防恶意代码。这个定位决定了后面所有守卫的形态:报错信息都是"教学式"的,告诉模型正确的做法。 二、模型的七件工具:inspect → define → run → stop/undefine tool-cordis/src/index.ts (530 行)的 apply() 是入口:先注入一段 107 行的系统提示词( CORDIS_SYSTEM_PROMPT ,教模型完整工作流和常见错误),再注册 Inspect Provider,最后逐个注册工具。注意注册方式——全部走 ctx.effect() / ctx.tools.register() ,符合仓库"registrations are effects"的约定:插件卸载时自动反注册。 📄 packages/extensions/tool-cordis/src/index.ts (第 35-58 行,节选) export function apply(ctx: Context) { // Cordis Loader 加载本插件时调用,ctx 是运行时上下文 ctx.systemPrompt.section({ name: 'tool:cordis', order: 115, text: CORDIS_SYSTEM_PROMPT }) // 注入专属提示词段:order=115 决定它在 system prompt 中的位置;内容是完整工作流 + 高频错误清单 for (const provider of hostInspectProviders(ctx)) { // 遍历第一方…