DeepSeek Harness: 组合包 bundle 与 profile

最后更新:2026-08-31

一个 DSH 项目可能需要多种运行配置——Web UI 开发用一套、Headless 部署用一套、CI 测试用一套。Profile 是具名的组装方案,Bundle 是可分发的配置+代码包。两者组合,让 DSH 的部署像切换频道一样简单。

💡 提示:profile 是"选哪些插件",bundle 是"插件怎么配"。profile 选组合,bundle 配细节。理解这个分层,你就掌握了 DSH 的配置架构。

📋 前置知识:已完成 12-local-plugin.md,理解 cordis.yml 配置

1. 你将学到


2. profile:具名组装

Bundle 与 Profile 结构

(1) profile 概念

profile 是一组预设的插件组合方案,用名称标识:

TEXT 📖 仅展示
web profile:       → 包含 Web UI 插件、交互式工具
headless profile:  → 无 UI,纯 API + 脚本执行
ci profile:        → 最小插件集,仅测试所需

(2) 配置 profile

package.json 中声明 profile:

JSON
{
  "name": "my-dsh-project",
  "dsh": {
    "profiles": {
      "web": {
        "description": "Web UI mode for interactive development",
        "plugins": [
          "@deepseek-ai/dsh-web-app",
          "@deepseek-ai/dsh-plugin-tools-interactive"
        ]
      },
      "headless": {
        "description": "Headless mode for automation",
        "plugins": [
          "@deepseek-ai/dsh-headless",
          "@deepseek-ai/dsh-plugin-tools-basic"
        ]
      }
    }
  }
}

(3) ▶ 示例 3

BASH
# 使用 web profile
pnpm dsh web --profile web

# 使用 headless profile
pnpm dsh headless --profile headless

(4) profile 的组成

组成 说明
插件列表 包含哪些插件
描述 profile 的用途说明
默认配置 插件的默认参数

3. bundle:配置+代码的分发格式

(1) bundle 概念

bundle 是 profile + 配置 + 代码的打包格式,可以像 npm 包一样分发:

TEXT 📖 仅展示
profile:  选哪些插件
bundle:   插件 + 配置 + 版本锁定 → 可分发的包

(2) ▶ 示例 2

TEXT 📖 仅展示
dsh-bundle-my-team/
├── package.json        ← dsh.bundle 字段
├── cordis.yml          ← 默认配置
├── plugins/
│   ├── team-tools/     ← 内置插件
│   └── team-lint/      ← 内置插件
└── profiles/
    ├── web.yml         ← web profile 配置
    └── headless.yml    ← headless profile 配置

(3) ▶ 示例 3

JSON
{
  "name": "@my-team/dsh-bundle",
  "version": "1.0.0",
  "dsh": {
    "bundle": true,
    "profiles": {
      "web": "./profiles/web.yml",
      "headless": "./profiles/headless.yml"
    },
    "baseConfig": "./cordis.yml",
    "plugins": [
      "./plugins/team-tools",
      "./plugins/team-lint"
    ]
  }
}

(4) 安装 bundle

BASH
# 从 npm 安装
pnpm add @my-team/dsh-bundle

# 使用 bundle 的 profile 启动
pnpm dsh web --bundle @my-team/dsh-bundle --profile web

4. dsh-base / dsh-web-app / dsh-headless

(1) 内置 bundle

DSH 提供三个内置 bundle:

bundle 说明 包含的核心插件
dsh-base 最小基础集 core, llm, sessions, trajectory
dsh-web-app Web UI 完整版 dsh-base + web-ui, interactive-tools
dsh-headless 无 UI 版 dsh-base + headless-runner, basic-tools

(2) 依赖关系

100%
graph TB
    BASE[dsh-base<br/>core + llm + sessions] --> WEB[dsh-web-app<br/>+ Web UI + 交互工具]
    BASE --> HEADLESS[dsh-headless<br/>+ Headless runner + 基础工具]

(3) 默认行为

不加 --bundle 参数时,DSH 默认使用 dsh-web-app

BASH
# 等价于 pnpm dsh web --bundle dsh-web-app
pnpm dsh web

(4) 选择基础 bundle

BASH
# 最小 bundle(仅核心)
pnpm dsh web --bundle dsh-base

# Web UI bundle(默认)
pnpm dsh web --bundle dsh-web-app

# Headless bundle
pnpm dsh headless --bundle dsh-headless

5. 配置层组合顺序

(1) 多层配置叠加

DSH 的最终配置由多层叠加而成,从下到上优先级递增:

100%
graph TB
    L1[Layer 1: Bundle 默认配置<br/>cordis.yml] --> L2[Layer 2: Profile 配置<br/>profiles/web.yml]
    L2 --> L3[Layer 3: 项目配置<br/>项目 cordis.yml]
    L3 --> L4[Layer 4: Patch 配置<br/>cordis.patch.yml]
    L4 --> L5[Layer 5: CLI 参数<br/>--patch, --config]

(2) 叠加规则

TEXT 📖 仅展示
Bundle 默认: { plugins: [core, llm], port: 5173 }
Profile:     { plugins: [+web-ui], debug: true }
项目配置:    { plugins: [+my-tool], port: 8080 }
Patch:       { plugins: [+debug-tool] }

最终:        { plugins: [core, llm, web-ui, my-tool, debug-tool],
              port: 8080, debug: true }

(3) 插件列表合并

操作 效果
新插件 直接追加
同名插件 后层覆盖前层
$insert 追加到列表末尾
$replace 替换同名插件

(4) 配置值合并

TEXT 📖 仅展示
低层: { a: 1, b: { x: 1, y: 2 } }
高层: { b: { y: 3, z: 4 }, c: 5 }

结果: { a: 1, b: { x: 1, y: 3, z: 4 }, c: 5 }

嵌套对象深度合并,标量值直接覆盖。


6. patch overlay 机制

(1) cordis.patch.yml

patch 文件是最高优先级的配置覆盖,适合开发时临时调整:

YAML
# cordis.patch.yml
plugins:
  debug-tools:
    $insert: ./dev-plugins/debug-tools
  llm:
    config:
      debug: true
      logRequests: true

(2) --patch 参数

BASH
# 应用 patch 层
pnpm dsh web --patch

# 不应用 patch
pnpm dsh web

(3) 多环境 patch

TEXT 📖 仅展示
config/
├── cordis.yml              ← 基础配置
├── cordis.patch.dev.yml    ← 开发环境 patch
├── cordis.patch.staging.yml ← 预发布 patch
└── cordis.patch.prod.yml   ← 生产 patch

切换环境:

BASH
# 开发
cp config/cordis.patch.dev.yml cordis.patch.yml
pnpm dsh web --patch

# 生产
cp config/cordis.patch.prod.yml cordis.patch.yml
pnpm dsh web --patch

(4) CLI 直接覆盖

最高优先级的配置方式:

BASH
# 直接覆盖端口
pnpm dsh web --config.port=8080

# 直接覆盖 LLM 模型
pnpm dsh web --config.plugins.llm.config.model=deepseek-reasoner

❓ 常见问题

Q profile 和 bundle 是什么关系?
A bundle 包含 profile。一个 bundle 可以定义多个 profile(web/headless/ci 等),启动时选择一个 profile。
Q 不写 dsh 字段可以用 DSH 吗?
A 可以。DSH 默认使用 dsh-web-app bundle 和默认配置。dsh 字段只在需要自定义时才写。
Q bundle 和 npm 包有什么区别?
A bundle 是 npm 包的超集——它是一个 npm 包,但包含额外的 dsh.bundle 字段,告诉 DSH 如何加载配置和插件。
Q 配置层冲突时怎么排查?
A--dump-config 查看最终配置: bash pnpm dsh web --patch --dump-config 这会显示所有层叠加后的结果,方便定位冲突来源。
Q 可以不使用任何内置 bundle 吗?
A 可以,用 --bundle dsh-base 只加载最小核心集,然后通过 cordis.yml 自行组装。
Q patch 文件应该提交到 git 吗?
A 开发用 patch 可以提交(方便团队共享),生产用 patch 不应提交(含敏感配置)。建议 .gitignore 排除 cordis.patch.prod.yml。 ---

📖 小节


📝 作业

1. ⭐ 基础题:在项目的 package.json 中添加 dsh.profiles 字段,定义 webheadless 两个 profile。分别用两个 profile 启动 DSH,对比加载的插件列表。

2. ⭐⭐ 进阶题:创建一个 cordis.patch.dev.yml,在开发模式下加载 debug-tools 插件并开启 LLM 请求日志。用 --patch 启动,用 --dump-config 验证 patch 层的覆盖效果。

3. ⭐⭐⭐ 挑战题:创建一个完整的 bundle 包,包含一个自定义 profile、两个内置插件、一份默认配置。发布到本地 npm registry(或用 file: 协议引用),从另一个项目安装并使用这个 bundle 启动。

Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏