DSH 快速参考手册
DSH 快速参考手册
便于快速回忆 dsh 的核心概念、架构和插件开发流程。
一、dsh 是什么
dsh(DeepSeek Harness)是一个基于 Cordis 插件框架的 agent 运行时。
核心思想:一切都是插件——模型适配器、工具注册表、会话管理、agent 循环本身都是插件,都可以替换。
与 Cordis 的关系
| 概念 | 类比 |
|---|---|
| Cordis | Linux 内核(IoC 容器 + 插件生命周期 + 事件系统) |
| dsh | Ubuntu(在 Cordis 之上组装了一套 agent 系统) |
| dsh 的各个包 | Ubuntu 预装的软件 |
dsh --profile | apt install + 启动脚本 |
dsh 插件 = Cordis 插件,没有独立的插件规范。
与 Codex 的类比
dsh 是 C/S 架构:
- 服务端:Cordis 插件树(agent-loop、tools、llm 等)
- 客户端:
dsh web(浏览器 GUI)、dsh headless(CLI)、ACP、JSON-RPC - 外部客户端:open-design、Python SDK 等通过协议调用
二、核心概念:Profile / Bundle / Patch
三者关系
Profile = 多个 Bundle 的有序叠加 + 配置覆盖层
Bundle = 1 个 Patch + 代码 + package.json
Patch = 1 个 YAML 配置文件(引用插件,不含代码)
配置层叠顺序(后者覆盖前者)
1. Bundle 1 的 cordis.patch.yml(dsh-base)
2. Bundle 2 的 cordis.patch.yml(dsh-web-app)
3. ...
4. Profile 自己的 cordis.patch.yml
5. $DSH_HOME/cordis.patch.yml(机器级全局偏好)
6. --patch <path> overlay(命令行临时覆盖)
官方 Profile
| Profile | 组成 | 用途 |
|---|---|---|
web | dsh-base + dsh-web-app | 浏览器 GUI |
headless | dsh-base + dsh-headless | 命令行一次性运行 |
dsh web # 启动浏览器 GUI
dsh --profile headless "任务描述" # 命令行执行
三、插件开发
3.1 最简方式(不需要 clone 仓库)
在任意目录创建 TypeScript 文件,使用 --patch 加载:
// my-plugin.ts
import type { Context } from '@deepseek-ai/cordis' // type-only,运行时擦除
export const name = 'greet-tool'
export const inject = ['tools']
export function apply(ctx: Context) {
ctx.tools.register({
name: 'greet',
description: 'Greet someone by name.',
parameters: {
type: 'object',
properties: {
name: { type: 'string', description: 'The name to greet' },
},
required: ['name'],
},
async execute(args: { name: string }) {
return `Hello, ${args.name}!`
},
})
}
# my-patch.yml
- insert:
- id: greet-tool
name: '/absolute/path/to/my-plugin.ts'
dsh web --patch ./my-patch.yml
关键点:
import type运行时擦除,不触发模块解析ctx.tools.register()接受原始 JSON Schema,不需要defineTool- 不需要
package.json,不需要node_modules
3.2 defineTool vs 原始 JSON Schema
defineTool | 原始 JSON Schema | |
|---|---|---|
| 来自 | @deepseek-ai/dsh-tools | 无需导入 |
| 类型安全 | ✅ args 有完整类型 | ❌ args 需手动标注 |
| 运行时效果 | 完全一样 | 完全一样 |
| 是否必须 | 否 | 否 |
defineTool 是编译时的类型辅助函数,不是运行时必需品。
3.3 正式 Bundle 开发
// package.json
{
"name": "dsh-my-plugin",
"type": "module",
"dsh": {
"bundle": {
"patch": "./cordis.patch.yml"
}
},
"dependencies": {
"@deepseek-ai/dsh-tools": "^0.1.0"
}
}
# cordis.patch.yml
- insert:
- id: my-plugin
name: 'dsh-my-plugin'
# 安装到 profile
dsh plugin --profile demo add ./my-plugin
# 或从 GitHub
dsh plugin --profile demo add github:you/my-plugin
# 或发布到 npm 后
dsh plugin --profile demo add dsh-my-plugin
3.4 判断一个项目是否是 dsh 插件
检查三点:
package.json中有@deepseek-ai/cordis依赖- 入口文件导出
apply(ctx: Context)函数 - (可选)
package.json中有dsh.bundle声明
grep -r "apply(ctx" src/ --include="*.ts"
grep "@deepseek-ai/cordis" package.json
grep "dsh.bundle" package.json
四、插件类型
4.1 工具插件(Tool)
给模型暴露可调用的工具:
ctx.tools.register({
name: 'greet',
parameters: { type: 'object', properties: { ... }, required: [...] },
async execute(args) { return 'result' },
})
4.2 Hook 插件
拦截 agent 生命周期,返回决策:
ctx.on('tools/pre-execute', async (exec, next) => {
if (!allowed(exec)) return { kind: 'deny', reason: 'Denied' }
return next() // 放行
})
可用拦截点:agent/session-start、agent/pre-step、agent/request、tools/pre-execute、tools/post-execute、agent/turn-stopping
4.3 Service 插件
暴露新服务 ctx.xxx 给其他插件使用:
import { Service, type Context } from '@deepseek-ai/cordis'
export default class MyService extends Service {
constructor(ctx: Context) {
super(ctx, 'myService') // 注册为 ctx.myService
}
doSomething() { /* ... */ }
}
4.4 提示词插件
往系统提示词注入内容:
ctx.systemPrompt.section({
id: 'my-context',
content: '注入到系统提示词中的内容',
order: 100,
})
4.5 UI 插件
监听会话事件,渲染界面(详见第五节)。
4.6 LLM 适配器插件
ctx.llm.registerAdapter(new MyCustomAdapter())
4.7 协议驱动插件
对接外部协议(ACP、JSON-RPC)到 ctx.agents。
4.8 MCP 插件
每个 MCP server 一个插件:发现工具 → ctx.tools.register()。
五、UI 插件与 Slot 系统
核心思路
数据驱动渲染,不是 DOM 操作。
Session 事件流 → 插件匹配事件 → 构建状态 → 生成视图数据 → React 组件渲染
Slot(插槽)机制
UI 不是"到处放扩展点",而是用 slot 系统——只有关键区域有 slot:
// 注册组件到插槽
ctx.slots.inject('conversation.chat.node', () => ctx.slots.register({
name: 'conversation.chat.node',
key: 'my-thing',
}, MyComponent))
已有插槽列表
对话区域:conversation.chat.node(消息节点)、conversation.composer(输入框)、conversation.input.model(模型选择)、conversation.details.tool(工具详情)等
侧边栏:sidebar.settings、sidebar.workspaces
设置页面:settings.section、settings.general.item、settings.plugins.tab 等
工具相关:tool.call.toolview
插槽的限制
| 操作 | 能否通过插件实现 |
|---|---|
| 往已有插槽添加新组件 | ✅ 能 |
| 修改已有组件的渲染逻辑 | ❌ 不能,要 fork |
| 修改已有组件收到的数据 | ✅ 能(通过事件拦截) |
| 移除已有组件 | ❌ 不能,要 fork |
| 改 CSS 样式 | ✅ 能(注入 style) |
六、TypeScript 结构化类型(给 Java 程序员)
TypeScript 的类型检查是结构化类型(类似 Go 的隐式接口),不是 Java 的名义类型:
interface Person { name: string; age: number }
function greet(p: Person) { ... }
// 以下全部合法,不需要 implements 声明:
greet({ name: 'Alice', age: 30 }) // 对象字面量
const dog = { name: 'Rex', age: 5, breed: 'Husky' }
greet(dog) // 多了字段也行
只要结构匹配,就是合法的。 所以 ctx.tools.register() 可以接受任何结构匹配的对象,不需要通过 defineTool 创建。
七、dsh 与外部工具的集成
双向调用关系
方向 A: 外部工具驱动 dsh
open-design ──stdio 协议──→ dsh
方向 B: dsh 调用外部工具
dsh ──MCP 协议──→ open-design / 其他 MCP server
使用方式决定入口
| 使用方式 | 入口 | 谁启动谁 |
|---|---|---|
| 直接用 dsh | dsh web / dsh headless | 你启动 dsh |
| 通过 open-design | open-design 桌面应用 | open-design 启动 dsh 子进程 |
| 通过 Python SDK | Python 脚本 | SDK 启动 dsh 子进程 |
MCP 是核心标准
当前主流 agent 工具(dsh、Claude Code、Codex、Cursor 等)都在往"既能独立用,又能被别人调用"的方向走。MCP 协议是这个趋势的核心——它让 agent 和工具之间的关系变成"插头和插座",谁都能连谁。
八、常用命令速查
# 启动
dsh web # 浏览器 GUI
dsh --profile headless "任务" # 命令行执行
dsh --profile web --dump-config # 查看组合配置
# 插件管理
dsh plugin --profile demo add ./my-plugin # 安装插件到 profile
dsh plugin --profile demo remove my-plugin # 移除插件
dsh --profile demo --patch ./extra.yml # 临时叠加配置
# 从源码运行(在 deepseek-harness 仓库内)
pnpm dsh web --patch ./scratch-plugin/cordis.yml
九、文档索引
| 主题 | 链接 |
|---|---|
| 架构总览 | docs/architecture.md |
| 第一个插件 | docs/user/develop/basic/index.md |
| 工具开发 | docs/user/develop/basic/tool.md |
| Bundle/Profile | docs/user/develop/basic/publish.md |
| Extension Cookbook | docs/cookbook/extension-cookbook.md |
| Cordis 教程 | docs/cordis-tutorial/index.md |
| Slot 系统 | .agents/notes/implemented/architecture/2026-07-22-slot-type-chain-implementation.md |