☰
基础深入理解DeepSeek Harness 架构【2】一架 dsh 是怎么被组装起来的
2026/10/2 8:27:54 网站建设 项目流程

第 2 章 一架 dsh 是怎么被组装起来的

上一章讲的是「零件」。这一章讲「装配线」:当你在终端敲下npx @deepseek-ai/dsh web并按下回车,接下来的几秒钟里,这台机器是怎么把几百个零件拼成能跑的应用的。

摘要:本章讲解dsh的「装配线」——当你在终端敲下npx @deepseek-ai/dsh web后,机器如何把几百个零件拼成能跑的应用。核心是「插件树」模型:组合包是零件包,profile 是装配单,patch 按 id 整体替换而非深度合并。五个内置 profile 共享dsh-base内核,只是外壳不同;--dump-config是打印装配单、也是你的改造清单。启动统一走具名 profile,由dsh-app-boot负责五步装配与失败处理;桌面版与 Python SDK 只是同一套架构在不同宿主上的延伸。

标签:dsh、插件树、profile、组合包、patch、app-boot、--dump-config

2.1 先看结果:启动之后你到底得到了什么

官方文档给了一句非常精确的描述,值得先记住:

运行中的dsh是一棵插件树,由启动时按序叠加的各层组合而成。

不是「一个进程加一堆模块」,而是一棵树。树上的每个节点是一个插件;层是叠加的,后叠的层可以修改先叠的层。理解这一点,后面所有关于配置和覆盖的规则都会变得自然。

2.2 两个核心名词:profile 与组合包

这两个词是这一章的关键,而且很容易混。用一句话区分:

  • 组合包(bundle)是「一包零件」。它是一个打包好的、可安装的插件集合,附带一份 patch 文件。

  • profile是「一张装配单」。它列出了这次启动要按顺序叠放哪些组合包,外加你自己的一层调整。

图 7|组合包是零件包,profile 是装配单;真正的行为由「装配单 + 四层 patch」共同决定。

2.3 五个内置 profile:同一套内核,五种外壳

官方随发行版交付五个 profile 模板。它们的关系是理解这整套设计的捷径:

profile它是什么什么时候用它
web浏览器应用。默认在http://127.0.0.1:3080启动 Web UI日常使用、开发调试。这也是npx @deepseek-ai/dsh web默认选的那个
headless不带服务器的「一次性运行器」跑批处理、脚本里临时问模型一次,不需要界面
sdkSDK JSON-RPC 服务器你想从自己的程序(TypeScript 或 Python)里驱动 dsh
acp仅用于自动化的 ACP 服务器接入支持 Agent Client Protocol 的编辑器或自动化客户端
sdk-minimal刻意的例外:一个拥有完整、显式 SDK 配置树的独立组合包,不叠加 dsh-base想要一棵最小、完全可控的配置树,不需要 base 那一大堆东西

其中dsh-base是web、headless、sdk、acp这四个 profile 共享的第一层,内容相当厚实:模型适配器、工具、持久化、沙箱(一个受限的执行环境。程序在里面能做什么、能碰哪些目录,都由外面的策略规定)与审批策略、设置、凭据、遥测。

各 profile 在 base 之上再加自己那一层:

组合包它额外增加了什么
dsh-base四个 profile 的共享第一层:模型适配器、工具、持久化、沙箱与审批策略、设置、凭据、遥测
dsh-web-app浏览器应用
dsh-headless不带服务器的一次性运行器
dsh-sdk-appSDK JSON-RPC 服务器
dsh-acp-app仅用于自动化的 ACP 服务器
dsh-sdk-minimal不应用dsh-base,自己拥有完整的显式 SDK 配置树(刻意的例外)


图 8|记住这张图,你就理解了「为什么 dsh 换一个外壳却像同一个产品」。

2.4 patch:按 id 覆盖,而不是深度合并

层叠机制靠的是 patch。规则很简单:

  • 一条 patch 按id定位某个条目,然后替换它的整个 config,或者插入一个新条目。

  • 不做深度合并——所以你要覆盖某个条目时,必须把你想保留的字段原样重述一遍。

陷阱

这是新手踩得最惨的一个坑:以为 patch 是「覆盖我改的那几个字段,其余保留」。不是。**它是整体替换。**官方文档在「已知限制」里专门写了一条:「用户 patch 会替换匹配到的整个配置——按 id 定位的 patch 不做深度合并,因此 profile 覆盖必须重述需要保留的组合包字段。」

2.5 最有用的一个命令:把装配单打印出来

想知道你的机器上到底启动了什么,官方给了现成的答案:

dsh--profileweb --dump-config

它会打印出这次启动实际生效的条目列表,并标注每一行来自哪个源文件、哪一层 patch。而且——

它打印出的任何条目,都可以由你自己的 patch 替换。

换句话说,--dump-config不只是诊断工具,它是你的改造清单。

两个容易混的端口

Web profile 默认端口是3080;Electron 桌面应用默认端口是19387,且可以由 profile 配置覆盖。这两个数字经常被搞混,配置文件里看到 19387 不要以为是错的。

2.6 应用启动器:为什么没有第二个可执行文件

官方在「应用启动」一节里定了一条纪律,非常能说明这套设计的性格:

Vendored CLI、仅用于构建和测试的可执行文件、进程内直接挂载插件以及私有浏览器 WebWorker 预览都不属于 Harness 应用启动器。

还存在一个脚本verify-application-entrypoints,专门把每个包 bin、可执行源码、根 demo、根脚本归入显式类别,并拒绝任何绕过dsh的 Node 应用路径。

这条纪律解决的是一个很现实的工程问题:如果每个人都用自己方便的方式启动应用,那么「这到底是哪种组合」就永远说不清楚了。现在只有一条路:通过具名 profile 启动。

自定义插件组合也只能由「profile + 有序 patch 文件」来表达,而不是另做一个可执行文件或内联一棵应用树。

2.7 启动器背后做了什么:app-boot

真正干活的库叫dsh-app-boot。它的职责链条可以简化为五步:

图 9|启动不是「能跑就行」,而是「要么完整跑起来,要么明确地失败给你看」。

官方还给了一整张「失败模式 × 处理方式」的表格,区分了optional 条目和required 条目的表现。这里摘出最常用的几条:

失败模式optional 条目required 条目
模块 import 失败或求值抛异常警告,继续终止启动
插件配置 schema 校验失败警告,继续终止启动
同步apply()抛异常警告,继续终止启动
注入的服务不可用警告,继续,条目等待依赖终止启动
HTTP 端口绑定失败警告,继续,但该端点不可用终止启动
条目缺失或被显式禁用忽略忽略

另外还有一句很实用的话:只要 required 列表里的modules或connection有一个启用的条目失败,Web 就无法成功启动。

app-boot 还做了一件贴心的事:如果你的应用持有终端,它会在进程退出前把终端交还,你的 shell 绝不会残留在 raw 模式。而且这个交还过程是有界的——卡住的清理只会延迟致命退出,不会取消它。

2.8 桌面版与 Python SDK:同一套架构,两个方向

官方文档用两节说明了两条「延伸线」,它们是同一套架构面对不同宿主环境的适配。

Electron 桌面应用

  • 它在签名资源里携带精确匹配的 dsh 生产运行时,并拥有保留的$DSH_HOME/profiles/desktop。

  • Electron 用 Electron Node 模式启动一个私有 Desktop Host;Host 调用共享的 CLI profile runner 与完整 Web 应用。

  • 窗口先立即加载打包好的 Web 资源,等启动注入完成后,在同一个文档里激活客户端插件。

  • Web 负责 RPC 与流;桌面载体把本地页面连接到已认证的 Host。

  • Node IPC 承载启动注入、就绪、致命错误与关闭。

  • 与 npm CLI 共享产品数据,但包、启用选择与锁文件保持独立。

Python SDK

  • 运行时 wheel 把普通的dshCLI 打包成deepseek-harness-sdk-runtime-<platform>-<arch>。

  • 客户端默认以显式 Harness home 启动dsh --profile sdk。

  • Python 侧暴露的是profile 选择与有序 patch 文件,而不是完整的 Cordis 树;持久外部插件通过dsh plugin安装。

关键

无论是 TypeScript SDK、Python SDK、桌面端还是 Web 端,**「配置组合」这件事永远只有一种表达方式:profile + 有序 patch 文件。**不存在「另一种配置方式」。记住这一点,你在任何宿主环境里都不会迷路。

2.9 这一章要带走的三句话

这一章要带走的三句话

  1. **运行中的 dsh 是一棵按序叠加出来的插件树。**组合包是零件包,profile 是装配单。

    1. **patch 是整体替换,不是深度合并。**覆盖时必须重述要保留的字段。

    2. **dsh --profile web --dump-config是你的改造清单。**打印出来的任何条目都能被你替换。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询