夜雨聆风学习资料网

ARTICLE · 1333770

NamiDSH:读懂插件式Agent架构

NamiDSH:读懂插件式Agent架构

NamiDSH 是一个把 Agent 插件架构缩小到可阅读规模的教学项目。它最值得学的是服务依赖、插件生命周期和工具拦截如何配合;“完整复现”和“逐行一致”需要附上版本与测试范围。

项目由 aa1143 开源,代码采用 MIT 许可证。本文固定 NamiDSH 提交 629e9ef,在 Node.js 26.10.0 上运行现成测试、类型检查和两条离线 HTTP 请求,并把兼容性脚本分别指向 npm 发布版 Cordis 与 DSH 当前 vendored 源码。没有调用收费模型,也没有进行生产压力测试。

仓库:https://github.com/aa1143/NamiDSH

配套交互讲解:https://namiai.tech/dsh/

上游 DSH:https://github.com/deepseek-ai/deepseek-harness

“一千行”到底包括哪些代码?

README 的“一千来行”是帮助理解规模的说法,不能直接当作全仓库统计。按当前提交的 .ts 文件物理行数计算,包含注释和空行:

范围文件数行数
packages/cordis/src9899
全部 packages,包含 Cordis201,549
网页入口 apps 的 TypeScript134
原有 tests2265

HTML 界面、文档、配置和锁文件不在上述 TypeScript 数字里。作者比较文章中的 679 行,特指剔除注释、空行后的 Cordis 核心,并非整个带 UI 的应用。

目录树有 Cordis 加 11 个 Agent 相关包。文章中的“11 个包”和仓库中 12 个包目录因此并不矛盾。tool-time 等演示组件也提醒我们:文件职责可以映射到 DSH,但不是每个文件都有完全相同的上游实现。

它的价值是把学习路径压短。用整个 DSH 的“一百多万行”与一个教学子集直接相除,得不出等价功能压缩率。

Cordis 为什么像 Agent 的主板?

把 Agent 循环、模型和工具写进一个文件,最初很省事;当模型要替换、工具要审批、连接要重建时,修改就开始互相牵连。

NamiDSH 用三种角色拆开这些变化:服务定义说明有什么能力,提供者实现能力,消费者只按服务名使用。llm 管理模型适配器,llm-deepseek 和 llm-mock 提供不同实现;agent-loop 依赖 llm、tools、sessions、systemPrompt,不关心具体模型厂商。

Context 是插件获得的上下文,Fiber 是插件实例及生命周期的管理者。消费者先挂上、服务后到位也能工作:依赖不齐就等待,到齐后启动;提供者卸载时,依赖者先清理,再等待后续服务恢复。

资源回收同样归属于插件。用 ctx.effect 登记工具、连接和监听的撤销函数,卸载时自动清理,避免只把插件对象删掉,却留下仍会触发的监听器。

这里的错误隔离指框架管理加载失败和生命周期影响,不代表插件运行在独立进程、独立内存或权限沙箱里。错误服务的依赖者仍会受影响;同进程插件也不能视为相互不信任的租户。

一次提问怎样经过插件系统?

网页请求从 webserver 的 POST /api/chat 进入,创建或找到会话,再调用 agentLoop.run()。循环先写入用户事件,组合系统提示词和历史消息,然后通过模型服务发起流式请求。

如果模型返回工具调用,tools 经过执行前、执行中、执行后三道 waterfall 管线,把结果写回会话,再请求模型生成回答。默认最多 8 轮,避免无限调用工具;这限制的是轮数,并不是完整的成本预算系统。

前置监听可以批准或拒绝调用,执行管线可以接超时或沙箱,后置监听可以处理结果。但这些是扩展位置:拥有一个可挂沙箱的事件,不等于当前已经配置了沙箱。

仓库的 Agent 测试给了一个很好的小实验:挂审批插件,拦住 get_time;卸载审批插件,调用恢复;拔掉时间工具,工具表随之改变;拔掉 llm 服务,Agent 循环自动停止。它演示的是组件生命周期如何改变实际行为。

会话保存在内存 Map 中,记录是只追加的事件数组,发给模型的消息从日志推导。它适合解释事件日志思想,但当前没有落盘恢复、长期记忆、历史压缩或同会话并发串行化。重启可恢复的 Agent,还需要独立的状态设计。

14 个场景,真的逐行一致吗?

仓库的 npm test 顺序运行兼容性脚本和 Agent 测试。兼容性脚本主要记录 14 个场景的状态输出,比较时要额外运行两次并执行 diff;单独看到脚本退出成功,并不等于完成了两套实现的等价性检验。

本次结果如下:

实际执行结果与范围
原有 npm test成功退出,14 个兼容性场景输出完成,Agent 层断言通过
npm run checkTypeScript 检查通过
同一兼容性脚本对比 npm @deepseek-ai/cordis@4.1.0两边均 114 行,1 行不同
对比 DSH 提交 fcc0ad4 的 vendored Cordis源码经 esbuild 转换后运行,同样 1 行不同
无模型 Key 的 HTTP 请求首页 200;时间、目录两条请求均收到工具事件和完成事件

差异出现在第 9 个场景的 waterfall:迷你版输出 RAN LS,上游两种实现输出 RAN UNDEFINED。检查源码后可以解释:迷你版把原事件参数继续交给最后的默认函数,上游以 inner() 调用默认函数。测试默认函数依赖参数 c,于是结果不同。

这不是一次模型回答质量退化,也不是 14 个场景全部失效。它说明当前版本下,原样脚本的“114 行完全一致”未能复现。作者当时使用的上游提交未在这份说明中锁定,不能倒推作者历史结果造假。实用的做法是固定双方提交、运行同一脚本并归档差异,而不是只转发兼容性口号。

作者还主动记录过另一处有意差异:插件返回包装对象上的 update() 绑定方式不同,测试选择 ctx.fiber.update() 绕开它。项目本身已经给了读者充分理由,把它当作精选行为模型,而非完整兼容替代品。

离线能跑,究竟跑了什么?

无 API_KEY 或 DEEPSEEK_API_KEY 时,入口选择 llm-mock。它用规则识别时间、目录等词,产生工具调用,再把工具结果组成回答。这里没有下载本地语言模型,也没有离线推理能力基准。

本次在临时工作目录只放一个 fixture.txt,启动本地服务后,向 HTTP 接口询问时间和项目文件。两条请求分别触发 get_time、list_dir,SSE 流均以 done 结束,目录结果确实包含测试文件。没有配置模型密钥。

这足以证明网页服务到循环、工具、会话和事件流的主链可以在假模型下运行。它不能证明真实模型的工具选择、复杂任务规划、断线恢复或浏览器界面交互已经通过测试;本次没有执行浏览器自动操作。

首次安装仍需取得仓库和开发依赖。所谓零运行时依赖,不是首次搭建完全不联网;原生运行 TypeScript 也不替代 tsc 的类型检查。

文件工具与生产部署,还要补什么?

最值得做的练习,是沿着边界继续读源码。tool-fs 用 resolve、relative 检查路径,能挡住直接的 ../ 越界;但没有把符号链接目标解析后再次验证。

在完全自建的临时夹具中,本次确认直接父目录访问被拒绝,而工作目录内指向夹具外普通文件的符号链接仍可读取。没有接触真实私人文件,也未测试任何在线服务。结论限于:当前路径检查是词法边界,不能作为强文件沙箱。

另外,read_file 对大文件先完整 readFile 再切字符串,因此 maxBytes 既不是严格的读取内存上限,也不是精确的 UTF-8 字节截断。让教学样例处理大型不可信输入前,需要调整真正的读取方式。

转向实际服务时,优先补齐以下能力:

  • 在 HTTP 和工具入口验证数据,设置请求体、文件、超时和总预算上限。
  • 明确工具权限;对敏感文件处理符号链接与竞态,必要时用操作系统隔离。
  • 为会话增加持久化、失败恢复、同会话调度和取消传播验证。
  • 保持本地监听默认值;若开放到网络,另做认证、访问控制与部署审查。
  • 为插件更新、依赖失效、审批撤销和资源回收写可重跑的行为测试。

怎样用它学会搭自己的框架?

需要 Node.js 22.18 或以上。可用一个空工作目录开始,避免第一次演示就把日常项目交给工具读取:

git clone https://github.com/aa1143/NamiDSH.git
cd NamiDSH
npm ci --ignore-scripts
npm test
npm run check
env -u API_KEY -u DEEPSEEK_API_KEY WORKSPACE="$(mktemp -d)" npm start

浏览器打开 http://localhost:3000。空目录没有文件可列出,可以先询问时间,再往临时目录放一个测试文本。

第一遍先运行离线应用与测试,观察“少一个服务,哪些插件会停止”。第二遍按 context → registry → fiber → reflect → events 读核心,把创建、加载、依赖变化和卸载各画出一条路径。

第三遍只做一个改动:沿用测试中的前置管线,加一个明确拒绝某类工具的插件,再验证卸载后行为恢复。第四遍替换一个模型适配器,检查循环是否真的无需知道厂商。接入真实模型时,费用与数据流向需要单独确认。

最后才对照 DSH 的 vendor/cordis、packages/core/agent-loop 和 packages/core/tools,研究教学版省去的隔离、调度、复杂 effect 与诊断机制。此前的 DSH Go 分析也解释了:手机界面和底层 Harness 是不同层次:https://blog.mushroom.cv/blog/dsh-go-android-harness-phone-agent-review/

Mycelium Protocol 的判断是:NamiDSH 把运行时最难讲清的依赖与清理变得可以实验,这就是它的教学价值。是否适合生产,应由具体权限、恢复能力和负载测试决定。

常见问题

它是 DeepSeek 官方发布的吗?

这是 aa1143 的社区教学项目。可对照官方 DSH 的架构学习,不能将其描述为 DeepSeek 官方精简发行版。

离线模式能完成任意任务吗?

不能。默认离线适配器是规则假模型,主要演示时间和目录工具。真实推理要接模型适配器;已有离线演示不代表附带本地大模型。

14 个场景是否证明完整兼容?

不能。它们覆盖选定的生命周期行为,且本次对当前上游运行原样脚本发现一行 waterfall 差异。完整兼容还需要版本锁定、更多异常与并发场景。

能直接公开部署吗?

当前默认监听 127.0.0.1,适合本机学习。公开服务需要另外设计认证、输入限制、工具权限、状态持久化与隔离,不能把教学检查当作安全认证。

一手资料与复核范围

NamiDSH 源码固定版本:https://github.com/aa1143/NamiDSH/tree/629e9efcb121b2805a2f3c48565144b732c0ff7f

作者的差异说明:https://github.com/aa1143/NamiDSH/blob/629e9efcb121b2805a2f3c48565144b732c0ff7f/docs/07-compare.md

DSH 对照提交:https://github.com/deepseek-ai/deepseek-harness/tree/fcc0ad462172522aaf5c93a7b2e01f6b9f0b0159/vendor/cordis

测试日志、114 行对照和离线请求证据随本文源材料保存。封面为模块化教学的示意照片,不是 NamiDSH 硬件产品。


© 2026 Author: Mycelium Protocol. 本文采用 CC BY 4.0 授权——欢迎转载和引用,须注明作者姓名及原文链接,不得去除署名后以原创发布。

🍄 原文发布于 blog.mushroom.cv
关于本号 · 免责声明
🍄 Mushroom Research Blog 是非营利、免费公开的个人科技观察博客与公众号 XStack18,不接受商业合作、不代表任何企业或机构立场,也不谋求商业利益。我们以个人视角客观中立地记录和分析 AI、Web3 等领域的最新模型发布与技术动态,希望帮更多人获得有价值的一手科技认知,而非碎片化的信息噪音。
⚠️ 文中介绍的开源代码与模型,仅供学习交流与技术借鉴。它们大多仍处于早期阶段,有待进一步研究和验证,请勿直接用于工作或生产环境;如需采用,请先自行充分测试,并核实其许可证与安全性。
本文为作者基于公开信息的个人研究与观点整理,不代表文中提及公司/产品/模型的官方立场;文中引用的第三方商标、图片、数据等版权归原权利人所有,如有疏漏或侵权,请联系 hello@mushroom.cv,我们会尽快核实处理。内容仅为技术科普,不构成投资、法律等专业建议。
🍄
Mycelium Protocol
数字公共物品 · 开源免费无许可
🎵 表达者 | 🎨 创造者 | 🔨 建设者
🪵 Infras | 🦠 Protocols | 🕸️ Networks
📍 blog.mushroom.cv · Apache 2.0

回首页,搜索你想要的文档

在首页搜索框输入关键词,快速定位资料

文库首页搜索指引 立即搜索

相关学习资料