tlewa/dsh-better-choice:给 DSH 选择题卡片加备注与旁问

前言

DSH 的 ask_user_question 在交互上有两个常见缺口:选项文字往往只有一句话,用户想补充约束只能塞进 custom 输入框;卡片期间模型不会回答「这个选项到底是什么意思」这类追问,想确认信息得跳出当前流程另开一轮。下面介绍的插件针对这两点做了增强,不改变原有的选择协议。

这是社区目录页上的 tlewa/dsh-better-choice,由 TLEWA 维护,分类为客户端插件,GitHub 星标数为 1(截至 2026-11-06),npm 最新版本 1.0.4,许可证 MIT。一句话定位:给 DSH 的通用问题卡片补上「按选项的补充框」和「卡片内旁问模型」,左键选择、跳过、翻页、倒计时等官方行为全部保留。

插件概览

安装前先看清适用范围。它只接管 DSH 客户端的通用选择题卡片,计划审查(plan-review)、审批等非通用问题卡片仍走官方组件。宿主要求为 DSH 0.2.0-rc 族(engines.dsh: >=0.2.0-rc.1 <0.3.0-0,客户端内置包 ^0.2.0-rc.1),Node.js 20+;作者标明已在 DSH 0.2.2-rc.1 上验证。

它包含两个半边:

  1. 客户端:挂在浏览器半边,向 conversation.composer 链式槽注册,priority: -10(官方默认 0),先于官方组件被询问;
  2. 宿主:一个自己的命令 bc-ask,用来跑旁问子代理;
  3. 样式:由官方问题卡 CSS 派生并加 bc_ 前缀,避免污染其他插件。

识别不到通用 PendingQuestion 载体时,增强卡片返回 null,自动落回官方组件。

核心能力

右键选项写补充

右键任意选项,即选中该项(若尚未选中)并在该选项下方展开补充说明输入框。填写内容不会替换选项,而是作为该选项的附注,提交时与所选项一起交给模型:

{
  "answers": [
    {
      "id": "question-id",
      "selected": ["方案 B"],
      "custom": "方案 B: 先灰度 5%,观察一小时再全量"
    }
  ]
}

没有填写任何附注时,请求与官方完全一致,不额外生成 custom。单选、多选都按选项分别保存补充内容,切换选项不会串稿。多选提交时一行一个附注:

方案 A: 需要保留旧接口
方案 C: 下个迭代再删

多选时给未勾选的选项写了备注,提交文本会标注 (未选),便于模型分清语气。

卡片内旁问

问题卡片底部有「先问一句」输入区,用来基于当前会话上下文回答用户的疑问,例如「这两个选项在生产环境下的差别是什么」「选 B 的话需要改哪些文件」。旁问的工作方式:

  1. 以 fork 子代理复用当前会话已完成的上下文、模型与工具声明,delivery: 'caller' 让它挂在当前命令调用上,不排队等父回合;
  2. 旁问内容只显示在卡片里,不提交、不污染主对话,也不替用户做出选择;
  3. 子代理执行期挂 tools.guard,一切工具调用都被拒绝,不改文件,不继续原任务;输出上限 32000 tokens(不超过父会话上限)。

交互上的细节:把光标放进旁问框,卡片会显示「已暂停」,倒计时停住,失焦后自动恢复;点「提问」后卡片进入等待,不再因为等回答而超时;线程按题分开保存,切题再回来仍能看到原来的问答;回答中可点「取消旁问」中止,每个线程最多保留 20 轮。旁问回答目前是完成后整段出现,不是逐字流式显示。

安装与启用

下面命令来自 README。作者推荐从 npm 安装。

从 npm 安装(推荐):

  1. 打开侧边栏插件页 → 安装插件;
  2. 输入包名并确认:
   dsh-better-choice
  1. 安装完成后硬刷新(Ctrl+Shift+R);若宿主半边未生效,重启桌面端。

固定版本:

dsh-better-choice@1.0.1

命令行等价写法:

dsh plugin --profile desktop add dsh-better-choice@1.0.1

仓库的 lib/ 是可直接运行的产物,从 GitHub 安装不需要本地构建:

https://github.com/TLEWA/dsh-better-choice

固定到标签:

https://github.com/TLEWA/dsh-better-choice#v1.0.3

或直接安装 Release 附件:

https://github.com/TLEWA/dsh-better-choice/releases/latest/download/dsh-better-choice.tgz

命令行等价写法:

dsh plugin --profile desktop add github:TLEWA/dsh-better-choice#v1.0.3

从源码安装:

git clone https://github.com/TLEWA/dsh-better-choice.git
cd dsh-better-choice
npm install
npm run build
npm test
dsh plugin --profile desktop add .

安装或升级后硬刷新页面。宿主命令 bc-ask 未注册时,旁问框会提示失败,重启桌面端即可。

典型用法

  1. 等模型发起一个普通的选择题;
  2. 想补充约束:右键选项,写完后正常提交;
  3. 想先确认信息:在底部旁问框提问,看完回答再选;
  4. 两者可以同时使用,旁问内容不会进入最终答案。

右键在触控板上通常是双指点按;没有右键的设备仍可正常左键作答,只是用不到补充框。

实现要点

旁问通过本插件自己的命令 bc-ask 完成,客户端把问题、全部问题卡片、已写备注和本线程之前的旁问序列化后交给宿主。宿主侧的机制:

  • 用 ctx.subagents.startActivation({ provider: 'fork', delivery: 'caller' }) 启动 fork 子代理,seed 是父会话最后一个 turn/end 之前的已完成回合,当前尚未完成的 tool-call 回合不进入 seed;
  • 只追加一条尾部 user 消息(旁问模式 + 问题卡片 + 之前的旁问 + 本次问题),不改 system、不改工具声明、不重写历史;
  • 子代理继承父会话的 provider / model / reasoningEffort,maxTokens 取 min(32000, parent.maxTokens);
  • 父调用的 signal 与 30 分钟 watchdog 一起透传;
  • 子代理不把问答写回父 session,父会话只落 command/run、subagent/catalog 与 command/done,且 recordInput: false 不记录问题正文。

因为 fork 子代理复用了父会话已完成回合的前缀,provider 可以命中已有 prompt cache。作者实测主请求与紧随其后的 fork 子请求都会报告非零 cacheReadTokens,并随父会话已完成回合增长(本机 DeepSeek 路由为自动前缀缓存)。

适用场景与注意

这个插件适合在生成环境决策场景里用 ask_user_question 的项目:需要按选项补充约束,或想在当前会话上下文里先问清选项含义再作答。它解决的是信息密度问题,不解决选择本身。

几条限制来自 README:

  1. 只接管通用选择题,计划审查、审批等卡片保持官方实现;
  2. 旁问固定在当前会话的模型上,不提供单独选择模型或推理强度的入口;
  3. 旁问是只读的,需要读文件、跑命令才能回答的问题,应直接在对话里问;
  4. fork seed 只包含父会话最后一个已完成回合,正在等待回答的那一轮不会进入 seed;
  5. 旁问回答完成后整段出现,不是逐字流式显示,超长回答受 32K 输出上限约束;
  6. 没有右键输入的设备无法使用补充框,但左键作答完全不受影响。

需要注意权限边界:插件以当前 dsh 进程的权限运行。安装前应先打开源码与许可证核对,本插件为 MIT,NOTICE.md 列明了具体复用范围(问题卡组件结构与样式派生自 dsh-question-note,旁问交互参考了 dsh-btw 的设计)。DSH 升级若改动问题卡内部结构,识别失败时增强卡片不接管,官方问题卡仍可用;旁问接口变化时会报错,但不影响正常作答。

目录与来源

目录页:https://www.skillhub.cn/plugins/TLEWA/dsh-better-choice
GitHub:https://github.com/TLEWA/dsh-better-choice
npm:https://www.npmjs.com/package/dsh-better-choice

总结一下:它做的是「选项附注」与「卡片内旁问」两件小事,接入点都在官方 composer 链上,识别不到通用问题卡就自动退回官方组件,对现有选择流程的改动面很小。如果你在用 DSH 的 ask_user_question 做决策收集,可以先装 npm 包硬刷新试一轮,再决定是否需要固定版本。

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜