Skip to content

About

Roundtable (圆桌讨论) multi-agent discussion plugin for DeepSeek Harness

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Repository files navigation

dsh-roundtable

圆桌讨论(Roundtable)—— DeepSeek Harness 的多智能体圆桌讨论插件。多个成员按固定顺序发言,会议主持人逐轮汇总,最终把整场讨论落成一份会议纪要 Markdown。

  • 成员是真实的 subagent,各自跑在自己的模型上(可跨 provider)。
  • 全程用 ask_user_question 内联卡片引导,用户不用手敲选项、不会输错。
  • 成员发言以普通聊天文字流逐条输出,没有特殊面板。
  • 会话按话题自动命名,结束时写出结构化的会议纪要文件。

目录

  1. 仓库结构
  2. 工作原理
  3. 三个插件包
  4. 模型侧工具
  5. 会话事件
  6. 会议纪要格式
  7. 要求
  8. 安装
  9. 使用
  10. 配置
  11. 开发
  12. 已知限制
  13. License

仓库结构

dsh-roundtable/                 ← 仓库根 = 可安装的 bundle(package.json 声明 dsh.bundle.patch)
├── cordis.patch.yml            bundle 的 patch 层:插入下面三行
├── packages/
│   ├── roundtable/
│   │   ├── roundtable/        @neomei/dsh-roundtable     宿主引擎
│   │   └── tool-roundtable/   @neomei/dsh-tool-roundtable 模型侧工具
│   └── client/
│       └── ui-roundtable/     @neomei/dsh-client-ui-roundtable 侧边栏入口
├── skill/
│   └── SKILL.md               圆桌讨论 skill(对话式引导)
├── install.sh                 一键安装脚本
├── README.md
└── LICENSE                     MIT

仓库根同时是 DSH bundle:package.json 里 dsh.bundle.patch 指向 cordis.patch.yml,该 patch 一次插入全部三行;根的 dependencies 把三个 @neomei/* 包装进 profile。所以按 GitHub URL 安装一次即可(见安装)。

包 作用
仓库根(dsh-roundtable) bundle:一次安装引入全部三行;它自己不注册任何插件
@neomei/dsh-roundtable 宿主引擎:单轮执行器、成员运行器、主持人汇总、纪要序列化、roundtable/* 事件与落盘/跨进程恢复
@neomei/dsh-tool-roundtable 模型侧工具:roundtable / roundtable_models / roundtable_title
@neomei/dsh-client-ui-roundtable 侧边栏「新讨论组」入口:新建会话并发起圆桌讨论
skill/SKILL.md 圆桌讨论 skill:卡片式引导 + 逐成员发言 + 汇总 + 写纪要

工作原理

侧边栏「新讨论组」
   └─> 新建会话,发送「圆桌讨论」
         └─> roundtable skill 接管
               ├─ 问话题(ask_user_question 输入卡片)
               │     └─> roundtable_title 把会话名设为话题
               ├─ 逐个加成员:角色 → 人设 → 模型(roundtable_models 给运行时列表)
               │     └─ 问「还要再加一个吗?」直到否
               ├─ 逐成员发言:
               │     roundtable 工具(单成员 + synthesize:false)
               │     └─> 真实 subagent 在该成员自己的模型上运行
               │     └─> 发言以普通聊天消息逐条输出
               ├─ 主持人汇总本轮纪要
               ├─ 问「继续下一轮 / 终止讨论」
               └─ 终止 ──> 写出会议纪要 Markdown

关键点: 每个成员是 ctx.subagents.start(provider, …) 启动的真实子代理,agentOptions.provider/model 决定它跑在哪个模型上(与宿主无关,可跨 provider)。成员跑完一个,输出一个,按顺序。


三个插件包

@neomei/dsh-roundtable(宿主引擎)

提供 ctx.roundtable 服务,核心是单轮讨论:

const run = ctx.roundtable.start({
  topic: string,
  members: RoundtableMember[],   // 数组顺序即发言顺序
  parent: Agent,                 // 调用方 agent(落盘到它的 session)
  synthesize?: boolean,          // 默认 true;false = 只跑成员、不产出综合方案
  provider?: string,             // 覆盖引擎默认的 subagent provider
  outputFile?: string,           // 停止时写纪要的路径(不给则不落盘文件)
  signal?: AbortSignal,
})
const { stopReason, agentsStarted, rounds } = await run.result

成员结构:

interface RoundtableMember {
  id: string          // 唯一标识
  label: string       // 显示名,如「架构师」
  persona?: string    // 角色遮蔽
  agentOptions?: {    // 该成员的独立模型路由
    provider?: string
    model?: string
    maxTokens?: number
  }
  toolFilter?: ToolRestriction
  maxDepth?: number
}
  • 校验:名单非空、无重复 id、不超过 maxMembers(默认 8);成员显式设置的 agentOptions.provider 必须在 ctx.llm 已注册。
  • 终止原因 stopReason:completed / cancelled / error。
  • 成员失败(模型/传输错误)会让整轮落定为 error(不会把空/残缺发言当成正常发言)。

引擎配置(Cordis Config):

interface Config {
  provider?: string     // 默认 'spawn':成员与主持人 subagent 跑在哪个 provider
  maxMembers?: number   // 默认 8
}

@neomei/dsh-tool-roundtable(模型侧工具)

注册三个工具(见模型侧工具),并把 roundtable 工具的使用引导注入 system prompt。

@neomei/dsh-client-ui-roundtable(侧边栏入口)

在侧边栏底部注册「新讨论组」按钮:解析当前/最近 Workspace → 新建会话 → 发送「圆桌讨论」→ 交给 skill。按钮在无法解析目标 Workspace 时禁用。


模型侧工具

roundtable

跑一轮多智能体讨论,返回纪要。

{
  topic: string           // 讨论话题,必填
  members: Array<{        // 成员,数组顺序即发言顺序,必填
    id: string
    label: string
    persona?: string
    provider?: string
    model?: string
  }>
  synthesize?: boolean    // 默认 true
}

返回:

{
  stopReason: 'completed' | 'cancelled' | 'error'
  markdown: string        // 会议纪要 markdown(synthesize:true 时含综合方案)
  utterances: Array<{     // 每个成员的原文(synthesize:false 时用这个)
    memberId: string
    label: string
    text: string
  }>
}
  • synthesize: true(默认):跑完整一轮 + 主持人汇总,返回带纪要/综合方案的 markdown。
  • synthesize: false:只跑成员、跳过主持人汇总,render 直接给成员原文 —— 这是 skill 逐成员发言用的模式。
  • 非 completed 落定(成员失败/取消)会抛错,工具结果成为 isError,宿主能感知失败。

roundtable_models

列出运行时已注册的 LLM provider 与模型,供成员模型卡片选择(不读 settings.yaml,直接读 ctx.llm)。

{}  // 无参数
// 返回
{
  default?: { provider: string; model: string }   // 调用 agent 的当前模型
  providers: Array<{
    provider: string
    name: string
    models: Array<{ id: string; name: string }>
  }>
}

单个 provider 列模型失败(缺凭证/非法目录)会被跳过,不拖垮整张卡片。

roundtable_title

把当前会话标题设为给定标题(通常是话题)。

{ title: string }   // 必填
// 返回 { title: string }

会话事件

引擎通过 ctx.events 发出三个 roundtable/* 事件,落盘到调用方 parent 的 Session(recorder 投影),也支持跨进程恢复:

事件 载荷 含义
roundtable/start RoundtableInfo { id, roster, topic, outputFile? } 讨论开启(固定名单 + 话题)
roundtable/round-end { discussionId, minutes } 一轮落定(纪要 + 成员发言)
roundtable/end { discussionId, stopReason } 讨论终止

这三个事件是 log-only 类型,走 session.append 落盘;recoverRoundtableDiscussions 可以从事件日志里重建未终止的讨论。


会议纪要格式

serializeRoundtableMarkdown 确定性输出:

# <话题> 会议纪要

## 参会人员

- **架构师**(anthropic · claude-3)
- **会议主持人**(主持人)

## 第 1 轮

**议题:** <本轮话题>

**纪要:** <本轮纪要+结论>

## 综合方案            ← 仅多轮 + synthesize 开启时出现

### 第 1 轮纪要
…
  • 每轮只渲染高层纪要(议题 + 纪要),不逐字罗列成员发言。
  • 「综合方案」只在多轮讨论且 synthesize: true 时产出,聚合各轮纪要。

要求

  • DSH(DeepSeek Harness):宿主需支持 dsh.bundle / dsh.profile.bundles。三个插件行已在 0.2.0-rc.2 上实测(导入 + 启动 + 真实圆桌跑通 + 客户端 bundle 下发),宿主两行也在 0.1.5-rc.2 / 0.1.0-rc.6 上可加载。

  • 客户端包(@neomei/dsh-client-ui-roundtable)只面向 0.2 的客户端契约,peer 写成 >=0.2.0-rc.2:DSH 0.2 删掉了 @deepseek-ai/dsh-client-runtime,会话/工作区服务迁到 dsh-api-session-controller + dsh-api-workspace-controller + uiWorkspace,图标名也从 IconUserOutline16 变成 IconUserOutlineMedium,Workspace 快照不再有 recentWorkspaceId。宿主两个包(引擎 / 工具)不依赖这些,仍是 >=0.1.0-rc.6。

  • 插件包的 @deepseek-ai/dsh-* peer 依赖写成范围(>=…),不要 pin 精确版本。DSH 会逐条核对:

    semver.satisfies(runtimeVersion, peerRange, { includePrerelease: true })

    精确 pin(如 0.1.0-rc.6)只对那一个 runtime 成立 —— 换任何一个 DSH 版本,安装都会被判 incompatible-version 并整体回滚(CLI 与 GUI 都会),profile 里什么都没有。注意 ^0.1.0-rc.6 同样不行:0.x 的 caret 上界是 <0.2.0,照样挡掉 0.2.0-rc.2。>= 才能在多个 runtime 上通用;要加上界就写成 >=0.2.0-rc.2 <0.3.0 这种范围。

    pnpm check:bundle 会检查这条约定。

  • 这些 peer 包由宿主自己提供(profile 默认 autoInstallPeers: false,不会装成第二份),range 只用于兼容性核对与 pnpm peers check 提示。

  • pnpm(profile 侧安装用;DSH Desktop 自带)。


安装

方式 A:GitHub URL 一键安装(推荐)

在 DSH 侧边栏的 Plugins 页面填仓库地址,或直接用命令行:

dsh plugin --profile desktop add github:NeoMei/dsh-roundtable

装完完全重启 DSH Desktop:启动时 DSH 会把该依赖选入 dsh.profile.bundles,应用它 cordis.patch.yml 里的三行 insert,并从 npm 装齐三个 @neomei/* 包。

仓库根就是 bundle,靠这两个字段成立:

字段 值 作用
dsh.bundle.patch ./cordis.patch.yml 让 DSH 把它当插件层而不是普通依赖(缺了它安装会被回滚)
dependencies 三个 @neomei/* patch 里三行 name 能被解析到
  • URL 结尾不要带 /:https://github.com/NeoMei/dsh-roundtable 才会被识别为 git 仓库。
  • 固定版本:github:NeoMei/dsh-roundtable#<ref>(分支 / tag / commit)。

报 ERR_PNPM_NO_MATCHING_VERSION … @neomei/dsh-roundtable@0.1.0-rc.7(while installing the dependencies of dsh-roundtable@0.1.0-rc.7)怎么办? 这不是仓库的问题:仓库根只是 bundle 的“接线图”,三个 @neomei/* 包本体走 npm。上面那个版本还没发上去时会报这个错 —— 先把三个包发到 npm(见文末发布),再装。pnpm view @neomei/dsh-roundtable versions 可以确认已发布的版本。

方式 B:一键安装脚本

curl -fsSL https://raw.githubusercontent.com/NeoMei/dsh-roundtable/main/install.sh | bash

或 clone 后 ./install.sh。脚本只做两件事:把 bundle 装进 profile、复制 skill。它不再改写 profile 的 cordis.patch.yml —— 手写 insert 会和 bundle 自带的 patch 撞 entry id,而且往模板里的 [] 后面追加文档会直接把 patch 文件写成非法 YAML。

./install.sh --ref v0.1.0-rc.7     # 固定 git ref(分支 / tag / commit)
./install.sh --packages            # 备选:从 npm 装三个 @neomei/* 包
./install.sh --profile DIR         # 指定 profile(默认 ~/.dsh/profiles/desktop)
./install.sh --tgz-dir DIR         # 离线:三个本地 tarball
./install.sh --dry-run             # 只预演,不执行
./install.sh --help                # 全部选项

方式 C:手动(npm / tarball)

cd ~/.dsh/profiles/desktop
pnpm add @neomei/dsh-roundtable@0.1.0-rc.7 \
         @neomei/dsh-tool-roundtable@0.1.0-rc.7 \
         @neomei/dsh-client-ui-roundtable@0.1.0-rc.7

三个包各自也声明了 dsh.bundle.patch,所以不用手写 patch:重启后 DSH 会把它们选入 dsh.profile.bundles,各带一行。

安装 skill

mkdir -p ~/.agents/skills/roundtable
cp skill/SKILL.md ~/.agents/skills/roundtable/SKILL.md

从源码构建(贡献者)

普通用户跳过。构建需在 deepseek-harness checkout 里进行,产出的是官方 @deepseek-ai/* 命名的包;要发成 @neomei/* 需在打包后把包名(及 tool-roundtable 对 dsh-roundtable 的交叉引用)改名为 @neomei/*。仓库里已提交构建产物 lib/,所以 git / tarball 安装都不需要先构建。

与目标 DSH 同版本的 deepseek-harness checkout 里:

# 把三个包放进 checkout:
#   packages/roundtable/roundtable
#   packages/roundtable/tool-roundtable
#   packages/client/ui-roundtable
pnpm build:lib:host      # 构建宿主(引擎 + 工具)
pnpm build:lib:client    # 构建客户端 bundle

只重建客户端 bundle 时不必跑整条流水线:lib/types/**(tsc 产物)已随仓库提交,tsdown.config.ts 用的是 harness 的 clientBundle 预设,所以

cd packages/client/ui-roundtable && npx tsdown     # 用已提交的 lib/types 重新产出 lib/client.js

即可。注意该预设需要一个完整 checkout(packages/client/tsdown.client.ts、平台模块表、以及仓库生成的 /remote 契约);干净 checkout 里 tsc -b 会因为那些生成文件缺失而报一堆 Cannot find module '@deepseek-ai/dsh-*/remote',那是 harness 自身 codegen 未跑,不是本插件的问题。改客户端源码后请顺带对目标 DSH 跑一次类型检查(把 @deepseek-ai/* 指到目标版本已发布的包即可),因为 dsh.client.inject 的失效条目是静默的。

然后每个包打包:

cd packages/roundtable/roundtable && pnpm pack
cd packages/roundtable/tool-roundtable && pnpm pack
cd packages/client/ui-roundtable && pnpm pack

得到三个 tarball:

  • neomei-dsh-roundtable-0.1.0-rc.7.tgz
  • neomei-dsh-tool-roundtable-0.1.0-rc.7.tgz
  • neomei-dsh-client-ui-roundtable-0.1.0-rc.7.tgz

装进 profile:

cd ~/.dsh/profiles/desktop
pnpm add /path/to/neomei-dsh-roundtable-0.1.0-rc.7.tgz \
         /path/to/neomei-dsh-tool-roundtable-0.1.0-rc.7.tgz \
         /path/to/neomei-dsh-client-ui-roundtable-0.1.0-rc.7.tgz

重启

完全重启 DSH Desktop,宿主插件才会加载。


使用

  1. 点侧边栏底部「新讨论组」。
  2. 自动新建会话并发送「圆桌讨论」,skill 开始用卡片引导。
  3. 按卡片依次输入/选择:话题 → 成员(角色 → 人设 → 模型,可加多人)→ 开始。
  4. 成员逐个发言(普通聊天消息);主持人每轮汇总后问「继续下一轮 / 终止讨论」。
  5. 选「终止」后,主持人写出会议纪要 Markdown 并给出文件路径。

用户可随时在卡片里输入额外意见,会折入下一轮话题。


配置

位置 项 默认 说明
引擎 roundtable provider spawn 成员与主持人 subagent 的 provider
引擎 roundtable maxMembers 8 单场讨论成员上限
工具 tool-roundtable toolName roundtable roundtable 工具的注册名

成员模型不在此处配置 —— 由 skill 用 roundtable_models 的运行时列表让用户逐个选择。


开发

源码的 peerDependencies 写 @deepseek-ai/dsh-*: >=0.1.0-rc.6(peer,由宿主提供,不随插件安装)。在 checkout 内:

pnpm vitest run packages/roundtable packages/client/ui-roundtable   # 单元测试(host 125+ / client)
pnpm tsc -b tsconfig.host.json                                     # 宿主类型检查
pnpm tsc -b tsconfig.client.json                                   # 客户端类型检查

说明:宿主引擎 + 工具可用发布的 rc.6 包独立做类型检查。多轮宿主循环(host.ts / driver.ts 的 claimSteer)与 web 客户端 bundle 依赖 harness 内部的宿主循环 / client-runtime API,需在 checkout 内构建与类型检查。


已知限制

  • 成员发言非流式:成员是各自子会话里的真实 subagent,发言要等该成员跑完才作为一条消息出现(这是 DSH subagent 的固有约束)。
  • 多轮宿主循环(host.ts)是代码库里保留的另一种驱动方式,未接线到当前 skill 流程;当前由 skill 驱动多轮。
  • @deepseek-ai/dsh-* 用范围 >=0.1.0-rc.6(不是 pin):精确 pin 会让校验直接拒绝安装并回滚;核心包由宿主提供,升级 DSH 后仍建议重跑 pnpm check:bundle 与一次真实圆桌。
  • DSH 的兼容性校验只认 @deepseek-ai/dsh / @deepseek-ai/dsh-* 这两个前缀的 peer;其他 peer(如 @deepseek-ai/cordis、@neomei/*)不参与判定。
  • 安装必须让仓库根被识别成 bundle:dsh.bundle.patch 与 cordis.patch.yml 缺一不可,否则 DSH 视其为普通依赖 —— GUI 里表现为安装被回滚,CLI 里表现为 declares no dsh.bundle — installed as a plain dependency。
  • 成员模型选择依赖宿主的 ctx.llm 注册表;roundtable_models 列不出的 provider 会被跳过。
  • 客户端「新讨论组」的目标 Workspace 现按 0.2 的投影自行推导(最近被更新的 Session 所在 Workspace,相同时按宿主顺序),与 shell 的 New Session 回退规则一致;0.2 的客户端不再暴露「当前 Session」选择,所以不再优先「当前会话所在的 Workspace」。
  • dsh.client.inject 里失效的包名不会报错:客户端模块系统对 inject 是软解析(if (dependency !== undefined)),缺包只是不预载,不会抛错 —— 所以升级 DSH 后要主动核对这张表(本次就是靠类型检查才发现 dsh-client-runtime 已经不存在)。

发布

三个 @neomei/* 包要分别发布(npm 不允许重复发布同一版本,所以每次发布前先把三个 package.json 的 version 一起改掉,并同步根 package.json 的 dependencies):

pnpm check:bundle                                   # 先过守卫
for p in packages/roundtable/roundtable packages/roundtable/tool-roundtable packages/client/ui-roundtable; do
  (cd "$p" && npm publish --access public --tag latest)   # 会要求浏览器 / OTP 授权
done
pnpm install                                        # 刷新 pnpm-lock.yaml,随发布一起提交

发完 pnpm view @neomei/dsh-roundtable versions 应能看到新版本;只发了一部分的话,GitHub URL 安装会在解析依赖时报 ERR_PNPM_NO_MATCHING_VERSION。

install.sh 的 skill 下载会先取 releases/download/v<版本>/SKILL.md,取不到就回落 main 上的 skill/SKILL.md,所以发布 npm 包不依赖 GitHub Release;要固定版本安装时才需要打 tag(git tag v<版本> && git push --tags)。


License

MIT

About

Roundtable (圆桌讨论) multi-agent discussion plugin for DeepSeek Harness

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages