lcc815
dsh-debate-plugin
No description
- Stars
- 0
- Language
- TypeScript
- Created
- Aug 15, 2026
- Updated
- Aug 15, 2026
Introduction
dsh-debate-plugin
DeepSeek Harness 的辩论插件:/debate 人工命令发起一场正反对抗辩论,双方由立场锁定的 subagent 逐轮交锋,可选五段式中立评审;Web 端为每场辩论渲染专属卡片。
- 逐轮 one-shot:每个辩手发言都是一个独立 subagent(persona 锁立场、对方上次发言注入 prompt),任何一轮异常即 fail-loud 终止
- 中立评审:结构化五段输出——双方核心论点 / 论证质量 / 精彩交锋 / 未决分歧 / 综合评价
- 完全独立:不写任何 session 事件、不注册投影;辩论记录存插件自己的 JSONL store,Web 卡片经 RPC 拉取
- 命令输出:命令先返回“辩论已开始”确认,后台继续运行;完整辩论记录由 Web 卡片通过 Remote 轮询获取并渲染
- 逐步完善中
安装
前提:宿主 profile 的 bundle 组合提供全部 peer 依赖(@deepseek-ai/dsh-base 即可覆盖)。
# 在 deepseek-harness checkout(或任意 dsh 安装位置)内
pnpm dsh plugin --profile debate add /path/to/dsh-debate-plugin
pnpm dsh --profile debate --dump-config # 应出现 "# == dsh-debate-plugin" 配置层
- 本地路径安装建立 link/junction 直连:插件仓库内
pnpm build后产物立即生效,无需重新安装 - git / registry 安装走包内
prepare脚本(tsdown 构建lib/index.js与lib/client.js),devDependencies 随安装就位
用法
从命令菜单选择 /debate(或输入 /debate <辩题> 后发送):
/debate [--rounds N] [--no-judge] <辩题>
--rounds N 逻辑轮数(每轮正反各一次发言),2-12,默认 3
--no-judge 跳过评审环节
示例:
/debate 人工智能将取代程序员
/debate --rounds 2 --no-judge 远程办公利大于弊
运行中 Web 卡片显示"进行中"并每 1 秒轮询增量;辩手的本地 subagent 输出会以流式文本展示,并通过 MarkdownText 渲染 Markdown。完成后展示辩题、轮次流(正方 / 反方 · 开篇立论 / 驳论 / 结辩)与评审面板。运行中的辩论可从卡片中止;失败时记录错误并以失败态展示。
配置
schemastery 字段(写入 profile 配置):
| 字段 | 类型 | 默认 | 说明 |
|---|---|---|---|
provider | string | spawn | 正反辩手与评审 subagent 使用的 provider 名 |
dataDir | string | ~/.dsh-debate-plugin/debates.jsonl | 辩论记录 JSONL 文件路径 |
架构
首版走完全独立路线(B 路线):外部插件的自定义 session 事件尚无法进入 harness 的持久事件词汇表,因此辩论数据不落会话日志,全部住在插件自己的存储里。
graph LR
U["/debate 命令"] --> C["command.ts 解析"]
C --> E["engine.ts DebateService"]
E --> S1["subagent 正方"]
E --> S2["subagent 反方"]
E --> S3["subagent 评审"]
E --> ST["store.ts JSONL last-wins"]
C -->|admission CommandResult| SL["session log command/run + command/done"]
W["client DebateCard"] -->|RPC getByCommand| E
SL -->|CommandNode fold| W
- host 半(
lib/index.js):手动解析参数并立即 admission → 后台逐轮ctx.subagents.start;本地子会话的assistant/chunk/assistant/message事件折叠为节流的live快照,写入 JSONL。DebateService extends TypertRemoteService,暴露list/get/getByCommand读方法和cancel控制方法 - client 半(
lib/client.js):手写 Remote 贡献(全严格 zod codec)经$mount挂载,嵌套 consumer plugin(injectremote.debate)认领conversation.chat.commandviewslot 的debatekey,把通用命令卡升级为辩论卡;轮询传输失败时保留最后快照 - 构建约束:lib 半永不 minify(Typert 网关靠方法参数名反射发现 Remote);client 半复刻官方 client preset 的 loader 契约——
window.__ModuleLoader__.load工厂包裹、平台模块 external(冻结模块表)、CSS Modules 经 lightningcss 内联并自注入<style data-plugin>
Model Experience / Known Limitations
- 命令需经命令菜单 claim 发送:程序化填充或粘贴的完整命令行不经输入状态机,会作为普通消息发给模型
- 命令-only 会话(无任何用户消息)保持 Hero 界面,不渲染消息流与卡片——在有消息流的会话里执行
/debate才能看到卡片;回放历史会话时卡片按 commandId 重新拉取记录 - 无凭证 fail-loud:headless 在 boot 阶段即
MISSING_CREDENTIAL退出;web 模式凭证惰性校验,辩论在第一个辩手 subagent 处失败并落失败记录 - npm 上
@deepseek-ai/dsh-*发布不完整(web-app 依赖链 404):开发联调需本地 checkout(见下节);运行时 peer 一律由宿主 profile 提供 --rounds被 clamp 到 [2, 12];中止经 abort 信号传播,已完成轮次保留在记录里
开发
pnpm typecheck # scripts/patch-dts.mjs 物化 @deepseek-ai/* 类型 + tsc
pnpm test # vitest:engine / store / prompts / command / client 五组
pnpm build # tsdown:lib/index.js + lib/client.js
scripts/patch-dts.mjs从同级目录的 deepseek-harness checkout 把消费到的@deepseek-ai/*包物化进 node_modules(声明文件里的.ts相对后缀重写为.js);无 checkout 时安静跳过,外部贡献者可正常 install/build- devDeps 刻意不装
@deepseek-ai/*(pnpm-workspace.yaml里autoInstallPeers: false) - 联调:
pnpm dsh plugin --profile debate add <本仓库路径>后,在 checkout 里pnpm dsh --profile debate(web,默认 http://127.0.0.1:3080)或 headless 一次性任务 - 版本对齐:本地 checkout(0.1.0-rc.5)领先 npm(0.0.1-rc.1);本插件只使用两版间稳定的 API 面(subagents / commands / typert / client slots)
License
MIT