dsh-ask-guard: Add a timeout guard for ask_user_question to prevent turns from hanging indefinitely.

前言

如果你在 DeepSeek Harness(DSH)里用过 ask_user_question,可能遇到过这样的场景:agent 提了一个问题,问题卡片通过 mux WebSocket 单次推送到浏览器。一旦页面被切到后台、笔记本休眠,或者连接进入半开状态,这一帧就丢了——客户端没有心跳,感知不到问题存在,工具就一直等下去。实测观察到过 6 小时以上的挂起,唯一的恢复手段是手动按 Stop。上游反馈见 deepseek-ai/deepseek-harness#1554(discussion)。

dsh-ask-guard 就是针对这个问题的一个插件:丢失或未回答的问题会以结构化的 ASK_TIMEOUT 结束,而不是让回合永远挂起。下面介绍它的原理、安装和配置。

这是什么

dsh-ask-guard 是 DSH 中 ask_user_question 的超时守卫插件,由 Q1hangL 维护,当前版本 0.1.0,许可证为 MIT(README 与 package.json 均有标明)。它体现的是 DSH「一切皆插件」的思路:不改 harness 本体,通过一个工具执行包装器补上官方 dsh-tool-call-timeout-policy 覆盖不到的空档——后者只强制执行工具插件声明的预算(budget),而 ask_user_question 没有声明任何预算,所以此前始终无人兜底。

工作机制

插件做的事可以拆成三步:

1、注册一个 tools/execute 包装器,为每次 ask_user_question 调度设置协作式截止时间(deadline)。

2、截止时间触发时,等待中的 provider 中止处理器被触发:web provider 会广播 question/resolved cancelled,把卡住的输入框(composer)清理掉。

3、包装器把归一化后的中止替换为结构化错误结果(code: ASK_TIMEOUTname: AskTimeoutError),并附带一条面向模型的消息,agent 因此可以优雅地结束回合,而不是阻塞在那里。

这里有两个值得注意的设计:

  • 超时是协作式的。由 @deepseek-ai/dsh-timeout 通过 exec.signal 发出通知,web user-questions provider 响应这个信号并真正终止,而不是只在工具层假超时。
  • 其他工具原样通过。包装器只针对 ask_user_question,不影响其余工具的执行路径。

安装与启用

官方安装命令:

dsh plugin --profile web add dsh-ask-guard

装完后重启 dsh web。插件是一个 dsh.bundle 包,reconcile 时补丁行会自动加入 profile 组合,不需要手动改组合文件。

如果想从 git checkout 安装:

dsh plugin --profile web add github:Q1hangL/dsh-ask-guard

依赖方面,插件的 peerDependencies 为 @deepseek-ai/dsh-timeout ^0.1.0-rc.6@deepseek-ai/dsh-tools ^0.1.0-rc.6@deepseek-ai/schemastery ^3.18.1,安装前可以确认一下环境版本。

配置超时时间

只有一个配置项 timeoutMs,即单次 ask_user_question 调用的截止时间,默认 300000 ms(5 分钟)。

要调整的话,在 profile 的 cordis.patch.yml 里加一段,例如改成 10 分钟:

- id: ask-guard
  config:
    timeoutMs: 600000

数值按你的实际交互节奏定:问题通常几分钟内会被回答,默认值就够;如果提问后经常要离开一段时间再回来,可以适当调大。

关于恢复

先说明一下现状:页面刷新(F5)本来就能重新同步待回答问题——主机向重连的客户端重放未回答的问题。装了这个插件之后,即使不刷新页面,回合也不会永远挂起,超时后会以 ASK_TIMEOUT 收场。两者解决的是同一个问题的不同层面:刷新恢复的是「问题还在等回答」的场景,插件兜住的是「问题根本没送达」的场景。

运行测试

如果你要改源码或验证行为,仓库里带了测试,跑法是标准两步:

npm install
node --test

适用场景与注意

适合谁:在 web 界面使用 DSH、并且依赖 ask_user_question 做人机交互的开发者。只要你有过「agent 卡在等回答上、只能按 Stop」的经历,这个插件就是对症的。

两点提醒:

1、插件以当前 dsh 进程的权限运行,安装前建议先看一遍源码和许可证。代码在 GitHub 上可以完整审阅,许可证为 MIT。

2、超时值不要设得过短,否则正常节奏下还没来得及回答的问题会被误判为超时结束。

结尾

dsh-ask-guard 解决的是一个很具体的问题:让丢失或未回答的提问以结构化的 ASK_TIMEOUT 收场,agent 能优雅结束回合,而不是无限等待。实现不复杂,机制也克制——只包 ask_user_question,其余工具不碰。如果你的工作流里有类似的挂起问题,值得一试。

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

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

Xiaoye