Profile 与组合包机制¶
如何在同一个代码库上,组装出 Web GUI 桌面版、CLI 终端版与无头自动化(Headless)引擎?
在 DeepSeek Harness 中,不同形态的产品(CLI、Web 服务、自动化评测)并不是通过冗余的多入口代码拼凑出来的,而是通过 Profile(组装画像) 与 Bundle(组合包) 机制以声明式的方式构建出来的。
核心文件速查¶
| 路径 | 职责 | 重要度 |
|---|---|---|
packages/bundle/base/ |
基础组合包:LLM、Tools、Session、Sandbox、Settings | ⭐⭐⭐ |
packages/bundle/web-app/ |
Web GUI 组合包:浏览器前端、BFF 网关、WebSocket | ⭐⭐⭐ |
packages/bundle/headless/ |
一次性运行器组合包:纯终端任务执行,零 Web 开销 | ⭐⭐ |
packages/boot/app-boot/src/profiles.ts |
Profile 加载器与 Patch 覆盖叠加算法 | ⭐⭐⭐ |
什么是 Bundle(组合包)?¶
组合包是一组预先打包好的 Cordis 插件配置集合。每个组合包在 package.json 中通过 dsh.bundle 声明自己的入口描述:
┌────────────────────────────────────────────────────────────┐
│ dsh-base (核心底座) │
│ - @deepseek-ai/dsh-session-persistence-sqlite │
│ - @deepseek-ai/dsh-llm-deepseek │
│ - @deepseek-ai/dsh-agent-loop │
│ - @deepseek-ai/dsh-tool-fs / tool-bash / tool-subagent │
│ - @deepseek-ai/dsh-sandbox-policy │
└─────────────────────────────┬──────────────────────────────┘
│
┌───────────────┴───────────────┐
│ │
┌─────────────▼──────────────┐ ┌──────────────▼──────────────┐
│ dsh-web-app (Web 组合包) │ │ dsh-headless (无头组合包) │
│ - dsh-webserver │ │ - dsh-cmdline-runner │
│ - dsh-api-gateway │ │ - dsh-output-formatter │
│ - dsh-frontend-static │ │ - (No Web / No WebSocket) │
└────────────────────────────┘ └─────────────────────────────┘
声明式 Patch 覆盖系统(cordis.patch.yml)¶
在 DSH 中,插件配置并不是死板写死在源码中的。任何层级的配置都可以被上层通过 cordis.patch.yml 无侵入覆盖!
叠加顺序(从底至顶):¶
- Bundle 声明的默认条目(如
dsh-base中预设的 DeepSeek 模型参数); - Profile 级别的
cordis.patch.yml; - 用户 Home 目录的全局配置(
~/.dsh/cordis.patch.yml); - CLI 命令行参数
--patch <file.yml>。
# 示例:通过 cordis.patch.yml 替换默认的 LLM 适配器
# 定位 target: @deepseek-ai/dsh-llm-deepseek,并将其覆盖为自定义 Provider
- target: "@deepseek-ai/dsh-llm-deepseek"
disabled: true
- target: "@deepseek-ai/dsh-llm-custom"
config:
model: "deepseek-chat"
temperature: 0.2
max_tokens: 8192
调试当前组装树¶
如果你想知道当前运行环境实际加载了哪些插件、它们各自的配置是什么,只需运行:
dsh --profile web --dump-config
该命令会完整打印当前合并完毕的 Cordis 运行时插件树。你看到的每一个插件条目、每一个配置项,都可以随时用你自己的 patch 进行替换。
本章思考与自测¶
- 思考题:假设你要为 DSH 增加一个全新的飞书机器人(Feishu Bot)入口,你应该修改
apps/web源码,还是新建一个packages/bundle/feishu-bot组合包?为什么? - 自测题:DSH 为什么禁止在
cordis.yml中使用任意 Node 代码动态 require 模块,而强制要求纯声明式的 patch 机制?这种设计给系统带来了什么优势?