dsh-expert-suite
DSH(DeepSeek Harness)「专家体系」插件:为 DSH 带来完整的专家与专家团能力。
- 专家(Expert):单角色切换机制——「人设 + 方法论 + 工具白名单」,让 AI 以特定领域专家身份执行任务。
- 专家团(Expert Team):多 Agent 协作机制——团长自动拆解任务、按波次派工给成员子代理、整合交付。
- 三种创建方式:手动创建(工具 / 面板表单)、文件导入(JSON / Markdown)、AI 生成(自然语言描述 → 自动成稿入库)。
宿主要求:dsh web / DSH 桌面应用 ≥ 0.1.5-rc.1(已在 0.2.0-rc.2 上对齐验证),Node.js ≥ 20。
安装
方式一:dsh web(命令行)
dsh plugin --profile web add dsh-expert-suite
# 然后重启 dsh web
方式二:DSH 桌面应用(desktop profile)
桌面应用的 profile 由应用独占管理:先把 profile 的依赖与组合包选项编辑好,再用桌面运行时安装,最后重启应用。
-
完全退出 DeepSeek Harness 桌面应用。
-
编辑 $DSH_HOME/profiles/desktop/package.json:dependencies 加本包(本地源码用 link: / file:,发布后可用版本号),dsh.profile.bundles 追加 "dsh-expert-suite":
{
"dependencies": { "dsh-expert-suite": "link:C:/path/to/dsh-expert-suite" },
"dsh": { "profile": { "bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "dsh-expert-suite"] } }
}
-
用桌面安装自带的 CLI(或等价地在 profile 目录跑桌面运行时里的 pnpm)安装:
"<安装目录>\resources\runtime\cli\bin\dsh.cmd" plugin --profile desktop install
验证:$DSH_HOME/profiles/desktop/node_modules/dsh-expert-suite 出现(符号链接/实体目录),且 Node 能从该 profile 目录解析到它。
-
启动桌面应用。组合时若仍有 cannot resolve profile bundle 报错,执行上面的 install 后重试;报 skipping profile bundle ... incompatible 时按提示用 dsh plugin --profile desktop allow-version 授权或升级插件。
方式三:从源码(开发时)——把本包构建好(pnpm run build,产物在 dist/)后按上面的第 2、3 步引入;dist/ 缺失会让宿主在激活时报构建错误。
装完重启一次:插件加载时会把「专家模式」「专家团模式」两个预设自动铺到 $DSH_HOME/.agent-presets/(带版本戳,升级整目录重铺),重启后出现在预设选择器里。
快速上手
# 单专家
/expert-list # 浏览名册
/expert data_analyst # 召唤数据分析师(注入 persona + 工具白名单)
/expert data_analyst 帮我解读这份报表 # 召唤 + 立即发送第一句话(模型会直接回复)
/expert-dismiss # 退出专家模式
# 专家团(会话式:进入团队,和团长对话)
/team-list # 浏览团队
/team fullstack_delivery # 进入团队(打招呼、问团队能力、下任务都行)
/team fullstack_delivery 你好 # 进入团队并发送第一句话
# 之后正常对话:团长确认任务后才会按需派工给成员,打招呼就只是打招呼
# AI 创建(在会话里直接说)
请调用 expert_generate:我需要一个专门写技术文档的专家
请调用 team_generate:帮我组建一个能完成产品从设计到上线的团队
也可以全程用工具驱动:expert_list → expert_summon → expert_dismiss;团队侧 team_dispatch(团长按需派工)/ team_status / team_end,或 team_run(批量模式,一次性跑完整个任务)。
图形界面:设置 →「DSH 专家工坊」(或右下角悬浮按钮)打开浏览面板,可视化浏览 / 创建 / 导入专家与专家团。
数据模型与存储
$DSH_HOME/expert-suite/
├── experts/<id>.json 用户创建 / 导入 / AI 生成的专家
└── teams/<id>.json 用户创建 / 导入 / AI 生成的专家团
内置专家(8 位:数据分析师 / 内容写手 / 代码评审专家 / 产品经理 / UI 设计师 / 营销专家 / 全栈工程师 / 测试工程师)与内置团队(1 个「全栈交付团」,7 名成员覆盖需求 → 设计 → 实现 → 评审 → 测试 → 物料 → 数据验收)随包提供;同 id 时用户目录版本优先。内置定义不可删除(删除会返回 BUILTIN_READONLY 错误)。
专家字段:id / name / category / description / capabilities / expertise[] / exampleTasks[] / persona / model? / toolFilter[] / source。
团队字段:id / name / description / executionMode(serial|parallel|auto) / interventionMode(auto|step) / members[{expertId, order, responsibility}] / leadPersona? / source。
工具清单(17 个)
| 工具 | 说明 |
|---|
expert_list | 列出专家,支持 category 筛选 |
expert_get | 获取专家完整定义 |
expert_create | 创建 / 覆盖专家(definition 对象,zod 校验) |
expert_import | 从 JSON / Markdown 文件导入专家 |
expert_delete | 删除自定义专家(内置不可删) |
expert_summon | 召唤专家:注入 persona 到会话 + 启用工具白名单门禁 |
expert_dismiss | 退出专家模式 |
team_list / team_get / team_create / team_import / team_delete | 团队的同名管理操作 |
team_dispatch | (团长模式)按需派工一项子任务给成员,等待交付并返回 |
team_run | 批量模式:teamId + 自包含 objective 一次跑完全队并整合,返回 runId |
team_status | 查看运行状态(成员进度、日志、总结);缺省返回当前会话的活跃团队 |
team_message | action=send 与成员对话;action=continue 放行 step 模式暂停点 |
team_end | 结束团队(缺省结束当前会话的活跃团队),返回各成员交付供总结 |
expert_generate | 自然语言 → AI 生成专家定义并入库(save=false 可只预览) |
team_generate | 自然语言 → AI 从现有名册组团并入库 |
权限隔离
- 专家召唤:
toolFilter 白名单通过宿主 tools.guard()(单调拒绝,不可被后续监听器撤销)按 agent 生效;白名单外的工具调用被当场拒绝并说明原因。toolFilter 为空的专家不做限制。这是进程内强约束,不是提示词提醒。
- 团队成员:每次派工都是一次 one-shot 子代理(
ctx.subagents.start('spawn')),其 persona / toolFilter / maxDepth=1 由宿主在子代理创建窗口内落地(子代理提示词里看不到白名单外工具、也无法执行),且不能继续向下委派。
- 团长:默认
leadToolFace: 'coordinator'——只协调不执行(拒绝 bash/pwsh/write/edit);可在插件 Config 改为 full。
- 指定模型:专家定义里的
model 映射到子代理 agentOptions.model。注意这需要宿主的「子代理模型选择」opt-in 已开启,否则派工时会报错——内置专家默认不指定模型(继承会话路由)。
团队协作:会话式(默认)与批量(显式)
会话式协作(默认)——/team <团队id> 或面板「进入专家团」:把团长契约注入当前会话,你是在和团长对话。打招呼、问团队能力就只是对话;有实际任务时团长先澄清、再用 team_dispatch 按需派工给成员(每次派工 = 一次 one-shot 子代理,等待交付后整合回复你),不会一上来跑全队。随时 team_status 看派工记录,team_end 结束并把各成员交付留档供总结。
批量模式(显式)——team_run 工具:给定自包含总目标,团长一次拆解、按执行模式跑完所有相关成员并整合总结。适合"现在就把整件事跑完";交互式工作用会话式即可。
批量模式的执行模式(团队定义里的 executionMode):
serial:按 order 串行,后续成员能看到前序交付物。
parallel:全部成员同一波次并行(受 maxParallelMembers 限制,默认 4),团长最后整合。
auto:团长先做结构化规划(outputSchema 校验的波次计划),按波次执行;规划失败自动回退为按 order 串行并记入运行日志。
interventionMode: step:每位成员(或每个并行波次)交付后暂停,用 team_message(action=continue) 放行。
成员的「连续性」由提示词承载(后续派工带上前序交付物全文),子代理会话不做跨派工驻留——这是 v1 的刻意取舍,换取只依赖宿主最稳定的 API 面。
导入格式
JSON(专家 / 团队均可):直接是定义对象。
Markdown(仅专家):YAML frontmatter + 正文(正文 = persona):
---
id: tech_doc_writer
name: 技术文档专家
category: 写作
description: 面向开发者的技术文档写作
expertise: [技术写作, Vue, Vite]
exampleTasks:
- 把这份源码注释整理成教程
toolFilter: [read, write, grep, glob]
capabilities: |-
多行能力介绍……
---
你是资深技术文档工程师……(persona 正文)
DSH 专家工坊面板(Client)
Client 半边按宿主官方契约实现(window.__ModuleLoader__.load({ id, factory }) 自注册、require('react') 取平台 React、导出 { apply, inject })。面板本体是 Vue 3 SFC,通过 React 宿主组件以「孤岛」方式挂载。入口两个(均为已核实的官方 slot):
- 设置 →「DSH 专家工坊」分栏(
settings.section,主入口):专家 / 专家团两个页签,分类筛选、卡片浏览、创建表单、文件导入、删除。
- 右下角悬浮按钮(
shell.overlay):点击打开同一面板的独立浮层。
一键操作全部是真调用(不再复制命令):
- 召唤专家 →
POST /expert-suite/summon:服务端解析目标会话的 agent,注入 persona + 启用工具白名单门禁;
- 进入专家团 →
POST /expert-suite/run:注入团长契约进入会话式协作;弹窗里的第一句话可选(留空就直接进入对话);
- AI 生成 →
POST /expert-suite/generate:服务端以会话 agent 为父代理 spawn 生成器子代理,产物校验后入库。
会话定位:客户端从 slot props 探测当前会话 id(sessionId / session.id,或官方 useSessions 钩子按主视图挑选)随请求上报;拿不到时服务端从宿主 agents 注册表降级(唯一活跃会话直接用,多个则返回 409 并提示刷新重试)。
面板数据与动作都走宿主路由 /expert-suite/*(由本插件在 webserver 上注册;无 webserver 的 profile 自动降级为只读空态)。slot 注册失败只打告警,不影响任何宿主功能。
平台集成说明(哪些已核实、哪些需校准)
本插件的宿主集成点全部以宿主已发布包的类型声明与 0.2.0-rc.2 运行时实现为准,包括:
ctx.tools.register(defineTool(...))、ctx.tools.guard()
ctx.subagents.start('spawn', { parent, prompt, persona, toolFilter, maxDepth, agentOptions, outputSchema, signal }) → SubagentRun.result
ctx.skills.register(...)(运行时 skill,不落盘)
ctx.commands.register(...)(/expert、/team 等 host 平面命令)
ctx.webServer.register(...)(服务名注意:0.2.0 起为 webServer,0.1.5 线为 httpServer——本插件两个名字都挂 ctx.inject 回调、谁先就绪注册谁(幂等);webserver 自身要等 webStartup 才提供,不能假设 apply 时它已就绪;服务缺席时路由整体降级、插件照常工作)
agent.inject(createUserMessage(...)) / agent.followup(createUserMessage(...))(前者注入持久上下文,后者提交普通轮次并唤醒驱动——官方 /goal 命令同款模式)
ctx.agents.get(sessionId) / ctx.agents.list()(宿主 Agent 注册表;Agent 的 id 即会话 id,面板动作端点据此定位目标会话)
- 插件展示元数据:
locale/{en,zh}.json 的 meta.title/description + package.json 的 icon(宿主 readPluginMeta 经 ESM 解析读取,因此 exports 必须放出 ./locale/*.json)→ 插件列表显示「DSH 专家工坊」
- Client:
window.__ModuleLoader__.load({ id, factory }) 自注册 + require('react') 平台模块表;slot 注册用 ctx.slots.inject(name, () => ctx.slots.register(opts, Component))(已核实 slot:settings.section、shell.overlay)
两个值得知道的平台行为(已读 0.2.0-rc.2 源码核实):
- 链接安装的包(
link: / file:)内部 import 的 @deepseek-ai/* peer 包会被宿主重定向到安装副本——所以本包 peerDependencies 必须与运行时真实 import 一一对应(改 import 就要同步改 peers)。
- 桌面 profile 的 bundle 解析顺序是「安装目录优先、profile 目录兜底」;本地插件必须在
$DSH_HOME/profiles/desktop/node_modules 可解析(见「安装」)。
需要按宿主版本校准的接缝(已集中在单文件、失败只降级不爆炸):
src/client/slots.ts——client 加载协议、slot 注册形态与 slot 名。
- 预设目录铺设语义与
dsh-expert-team 一致($DSH_HOME/.agent-presets/ + 版本戳整目录重铺);不要手改重铺目录里的文件(会被覆盖),要定制请复制一份换 id。
inject 声明为 ['tools', 'subagents', 'skills', 'commands']——刻意不含 httpServer(避免无 webserver 的 profile 把插件挂起 PENDING;cordis 允许未 inject 的属性访问,探测失败自动降级)。
插件 Config
在 cordis.yml 的插件行里配置:
- insert:
- id: expert-suite
name: 'dsh-expert-suite'
config:
dataDir: '' # 缺省 $DSH_HOME/expert-suite
layPresets: true # 自动铺设两个预设
maxParallelMembers: 4 # 波次内最大并行子代理数
leadToolFace: 'coordinator' # coordinator | full
开发
pnpm install
pnpm run typecheck # TypeScript 严格模式(零错误为合并门禁)
pnpm run build # host(tsc → dist/)+ client(vite → dist/client.js)
本地装进 dsh 调试:按「方式二」用 file: 依赖引入,或 pnpm dsh web --patch ./cordis.patch.yml(patch 里的 name 改为本包 src/index.ts 的绝对路径可免构建热调)。
项目结构
dsh-expert-suite/
├── package.json # dsh.bundle / dsh.client 声明、exports、依赖
├── cordis.patch.yml # bundle patch(宿主入口行)
├── tsconfig.json # strict + NodeNext
├── vite.client.config.ts # client UMD 打包(CSS 注入 JS)
├── presets/ # 随包预设(专家模式 / 专家团模式)
│ ├── expert-mode/{preset.yml, agent.cordis.yml}
│ └── team-mode/{preset.yml, agent.cordis.yml}
└── src/
├── index.ts # 宿主入口(apply:装配全部能力)
├── config.ts # 插件 Config(Schemastery)
├── types.ts # 数据模型(zod)+ 运行状态类型
├── deps.ts # 工具层共享依赖与工具函数
├── ports.ts # 平台适配层(spawn / 门禁 / persona 注入 / skill 注册)
├── builtin/ # 内置专家(6)与内置团队(1),构建期静态导入
├── storage/ # expert-store / team-store / markdown frontmatter 解析
├── tools/ # expert-tools / team-tools / ai-tools
├── orchestrator/ # team-runner(波次执行引擎)/ prompts(团长与生成器提示词)
├── skills.ts # 运行时 skill 内容生成与全量注册
├── presets.ts # 预设铺设(版本戳)
├── commands.ts # 斜杠命令
├── routes.ts # 面板数据路由(httpServer 渐进增强)
└── client/ # DSH 专家工坊面板(Vue 3 SFC 孤岛 + 官方模块加载契约 + slot 注册)
License
MIT