dsh-question-timeout-protection
IdentifiedA plugin for dsh: once ask_user_question times out, the content you entered will remain in the UI or model context.
dsh提问超时保护插件: 一旦模型提问超时,将你的回答草稿保留在UI或上下文中,而不是直接丢弃。
功能
- 右上角倒计时: 问答对话框右上角显示本次问答的剩余等待时间,并随剩余时间递减;到插件自己的截止时间后不再渲染倒计时(等结算回执把卡片收走), 也不显示「0秒后超时」
- 临近超时警示: 剩余时间进入警示秒数(默认 5 秒)时红字闪烁;到截止时间后停止闪烁, 只保留通道故障类提示
- 无限等待: 正在进行的问答在倒计时右侧显示「无限等待」按钮, 点击后倒计时冻结并显示「已暂停」, 直到用户提交才结束; 历史提问与已结算回答的只读卡片不显示倒计时与这个按钮
- 问答无限等待开关: 对话框模型选择控件左侧有「问答无限等待」开关, 开启后每一条提问都自动进入无限等待(与手动点一次「无限等待」等价, 正在等待的那条也会立刻冻结), 关闭后新提问回到倒计时计时行为; 开关状态跨刷新保留, 已经冻结的提问不因关闭开关而恢复倒计时, 由用户提交结束
- 选中底色: 单选题选中后, 选项前的方形按钮填充底色
- 提问标识气泡: 只在超时并把草稿记入内存后, 于提问工具调用处出现一个气泡按钮, 点开在气泡旁弹出只读悬浮卡片查看该次草稿; 宿主自带的「回答」气泡与它功能冲突, 由插件气泡统一承接
- 超时草稿保存: 问答超时后把已选选项与已输入内容保存到内存
- 上下文注入: 默认开启,超时前把草稿快照交给服务端,到期时随工具的 pending 返回值按题带回模型上下文,每题带自己的已选与补充;超时语义由同一个 pending 结果说明,模型须在回复末尾告知用户出现过提问超时以及对该草稿的处理与决策
- 草稿记入气泡: 超时后把草稿记入对应提问工具处的气泡按钮,点击在气泡旁弹出只读悬浮卡片,该次提问不再提供作答入口
- 超时收尾: 有草稿时注入开启则草稿随工具返回值交给模型,卡片由插件收起, 注入关闭则只收起卡片; 超时那一刻没有任何选择与输入(草稿为空)时同样由插件把卡片关闭, 不留下答不了的对话框; 超时草稿兜底关闭, 草稿快照连续上报失败, 或「无限等待」上报失败时交还宿主原版路径, 卡片保持可继续作答
- 不做兜底继续回答: 已接管的超时问答不提供继续回答的兜底; 交还宿主的三种情况不由插件收尾, 卡片保持可继续作答
功能立场
本插件只做一件事: 让提问的等待过程可见,可暂停,并且超时不丢内容. 以下列出边界,便于判断某个需求是否属于本插件.
做什么
- 让等待时长可见: 在问答对话框右上角显示本次问答的倒计时,临近超时红字闪烁
- 让等待可暂停: 在倒计时右侧提供「无限等待」按钮,点击后本次问答的倒计时暂停,直到用户提交才结束; 对话框工具栏另有一个「问答无限等待」开关,开启后后续每条提问都自动进入无限等待
- 让提问可辨识: 给单选选中态加方形底色; 超时并记录草稿后, 在提问工具位置加提问标识气泡
- 让超时不丢内容: 把已选选项与已输入内容保存到内存,并记入该次提问的气泡供只读查看
- 按配置把超时草稿送进上下文: 超时前把草稿快照交给服务端, 到期时随工具的 pending 返回值按题带回草稿本身, 不夹带任何附加文本; 超时说明同样只出现在工具的 pending 结果里, 是否重新提问由模型决定
不做什么
- 不接管宿主卡片的渲染与文案: 只在其 DOM 上做增强,隐藏宿主自带的倒计时,等待状态文案与「慢慢回答」按钮以及收起/展开控件,不改写宿主文案
- 不修改用户的预设: 通过在 agent 作用域注册同名工具就近遮蔽,用户无须改预设
- 不替用户作答: 超时不会自动勾选任何选项,也不会把草稿当成正式回答提交
- 不替模型决策: 是否重新提问,如何处理草稿由模型决定,插件只负责把信息送到位
- 不兜底继续回答: 插件接管超时的那些问答一律收起卡片; 中英界面下同时隐藏宿主的「回答」入口, 其他界面语言下入口可能保持可见. 以下三种情况交给宿主原版处理: 超时草稿兜底关闭, 草稿快照连续上报失败, 或「无限等待」上报失败
- 不做持久化: 草稿只保存在客户端内存里, 插件不落盘; 刷新后本页记录的气泡与草稿都会丢, 仍在等待的提问会按宿主持久化的草稿重新评估, 满足接管条件时由插件收起卡片并重建气泡; 已结算的行不回显
- 不新增自定义 RPC 或存储: 草稿只经工具的返回值回到模型, 状态同步只挂宿主自己的 HTTP 服务, 同源访问; 唯一的本地存储是「问答无限等待」开关的状态
机制
- 宿主默认使用阻塞式提问,提问不会超时;本插件在 agent 作用域注册同名的
ask_user_question,以就近遮蔽接管提问等待,不需要改动你的预设 - 超时由插件自己计时: 宿主卡片在客户端接管或开始编辑回答时会暂停自己的定时器,插件用同一时长再赛跑一次,保证到期一定返回 pending 并进入兜底流程(用户点过「无限等待」时改为继续阻塞)
- 工具走宿主的 timed 等待: 卡片与选项由宿主界面提供;倒计时由插件自绘在卡片右上角,按插件自己的截止时间渲染(已拿到截止时间的卡片, 聚焦或编辑都不会让它暂停);模型应当显式传等待秒数, 漏传时使用插件配置里的等待时长, 仍然按限时提问处理;模型传
-1表示这次必须由用户回答, 走宿主阻塞提问, 不启用倒计时与超时兜底 - 客户端适配器只增强宿主界面的 DOM: 在卡片里插入自绘倒计时与「无限等待」按钮, 在工具栏插入「问答无限等待」开关, 给单选选中态加底色, 在提问工具行插入气泡按钮;提问进行中就把草稿快照持续上报给服务端, 超时后把草稿存在内存里并收起卡片, 草稿是否随工具的返回值交给模型由服务端的兜底范围决定;草稿为空时同样由插件关闭卡片
- 配置由客户端经宿主
configForms服务实时读取,因此在插件详情页改动勾选立即影响行为,不需要保存或刷新
兼容性
- dsh:
>=0.2.1-rc.1 <=0.2.2-rc.1 - 运行时: Node.js >= 20(插件自身要求; dsh 0.2.2-rc.1 起宿主需要 Node.js >= 24.9)
安装
尚未发布到 npm;可从本仓库构建后以包目录或 tarball 安装:
pnpm pack
dsh plugin --profile <profile> add release/dsh-question-timeout-protection-0.1.0.tgz
pnpm pack 会先构建,打包完成后 tarball 自动移入 release/ 目录. 也可以直接从源码安装(把包名换成 github:JularDepick/dsh-question-timeout-protection#<提交>),此时 prepare 负责构建;pnpm 10 及以上默认拦截构建脚本,需要先把本包加入允许构建的名单,否则装上去没有 dist/ 产物.
配置
配置页位于插件详情页顶部的插件级配置区块,不在「包含的组件」里;其中只有「注入到上下文」一个勾选可以调整,其余能力随插件启用状态固定生效,列表中只做说明.
| 配置项 | 取值 | 默认值 | 界面 | 说明 |
|---|---|---|---|---|
fallback | ui / context / both | both | 可改一项 | 超时兜底;界面只给「注入到上下文」勾选,默认勾选,勾上写 both,不勾写 ui. 界面保留草稿恒定开启,所以不会再出现 context. 勾选变化即写入,无需保存 |
cardEnhancements | 布尔 | true | 固定特性 | 界面增强: 右上角倒计时与警示闪烁, 单选选中底色, 提问标识气泡, 隐藏宿主的收起/展开控件与等待文案; 超时接管与注入由 draftFallback 决定, 这个开关只管装饰; 关闭后以上装饰都不出现, 超时收尾照常执行(卡片仍会被收起与锁定), 只是宿主「回答」入口与等待文案不再被隐藏; 工具栏的「问答无限等待」开关也随之移除, 因为自动冻结走的就是这条装饰链路 |
infiniteWait | 布尔 | true | 固定特性 | 提供倒计时右侧的「无限等待」按钮, 点击后本次问答倒计时暂停, 直到用户提交; 关闭后这个按钮与工具栏的「问答无限等待」开关一并移除 |
draftFallback | 布尔 | true | 固定特性 | 超时收尾开关: 关闭后客户端不再收尾卡片, 也不再上报草稿, 这一轮交还宿主原版路径(提问仍由插件按时结算); 开启时按兜底范围把草稿交给工具返回值或只收起卡片 |
warningSeconds | 数字 | 5 | 不暴露 | 进入红字闪烁警示的剩余秒数 |
timeoutSeconds | 数字 | 120 | 不暴露 | 模型没有显式传等待秒数时使用的等待时长, 取值 1 至 2147483 秒 |
界面保留草稿是必选行为: 超时后草稿总留在内存里,并记入该次提问工具处的气泡按钮,点击气泡会在其旁边弹出只读悬浮卡片. 只要超时收尾开着,客户端就在提问还没超时时把草稿快照上报给服务端,是否交给模型完全由服务端按这份配置决定: 勾选「注入到上下文」(默认开启)时草稿随工具的 pending 返回值按题带回模型上下文;取消勾选时只收起卡片,不把草稿交给模型. 超时说明与草稿都在同一个 pending 结果里,提示该轮提问已超时,用户没有正式提交,并要求模型在最后告知用户超时与对该草稿的处理决策. 已接管的问答一律收起卡片, 中英界面下同时隐藏宿主「回答」入口(其他界面语言下入口可能保持可见), 不再提供继续回答的入口; 草稿为空时同样由插件关闭卡片, 这种情况不产生气泡. 三种情况交还宿主: 超时收尾关闭, 草稿快照连续上报失败, 或「无限等待」上报失败; 这三种情况不收卡片也不交草稿, 该轮仍按超时结算, 卡片保持可继续作答, 其中后两种会在超时之前把倒计时位置换成「草稿无法送达」或「无法无限等待」(两者只显示其一), 交还后卡片按宿主原样还原; 超时收尾关闭时既不上报也没有失败提示. 卡片增强关闭时以上装饰全部不发生(没有倒计时, 无限等待按钮, 气泡, 工具栏开关), 但超时收尾照常: 该收的卡片仍会被收起与锁定, 草稿仍按上面的配置上报并交给模型, 只是宿主「回答」入口与等待文案不再被隐藏.
已知限制
- 依赖宿主界面结构: 卡片与工具行靠宿主类名后缀,
data-question-key,data-chat-call-id,aria-checked等特征定位, 宿主控件按中英文标签识别, 工具栏开关靠模型选择按钮的无障碍标签(选择模型/Select model)与[class*="standardControls"]容器定位, 各处查询收敛在当前会话容器(data-conversation-session)内, 多会话界面下不会把开关挂到别的对话框上; 宿主改动这些结构或文案时对应增强会静默失效, 识别标签与选择器集中在src/constants.ts, 少量结构定位字面量留在src/client/adapter.ts, 两处都要跟着同步 - 不做持久化: 草稿只在客户端内存里, 刷新后气泡与草稿记录都会丢, 仍在等待的提问会按宿主持久化的草稿重新评估并在满足接管条件时接管, 已结算的行不回显; 刷新时若宿主卡片已经处于编辑或等待状态(界面显示「会一直等你回答」, 或带秒数的「已暂停」), 插件无法还原截止时间, 在卡片回到计时态之前不显示倒计时与「无限等待」, 卡片在超时结算前保持宿主原样, 但工具仍按原超时结算, 草稿照常上报
- 「无限等待」与草稿上报共用一条带令牌的通道, 通道挂在宿主自己的 HTTP 服务上, 与界面同源: 页面先取到通道令牌再上报, 令牌取不到时这两个能力都不生效; 同机其他网页因为来源对不上而拿不到令牌, 伪造不了上报; 令牌端点与上报端点还会核对请求的 Host 是否为本机回环地址(127.0.0.1 / localhost / [::1]), 防止其他域名解析到本机后伪造来源, 因此宿主绑定到非回环地址(如局域网 IP)或经反向代理以非回环域名访问时, 这条通道会被拒绝, 两个能力都不可用; 这条边界只覆盖浏览器网页: 不带来源的请求视为宿主页面自己, 同机的其它进程仍可取到令牌并伪造上报与草稿; 没有网页客户端(没有宿主 HTTP 服务)的部署里这两个能力都不可用: 服务端仍会按超时结算这一轮提问, 但草稿不会进入模型上下文, 「无限等待」也不会生效
- 插件自行计时: 到期后插件自己按超时结算并释放宿主那边的前台等待, 用户在超时那一刻之前真正提交的答案优先采用
- 界面语言: 宿主 0.2.2 起提供 8 种界面语言, 插件当前只识别中文与英文标签; 其他语言界面下倒计时, 无限等待按钮与工具栏开关不出现, 插件自绘的草稿气泡与配置页文案回退英文; ja 的「回答」与中文同形会被隐藏, 其余语言下宿主「回答」入口与等待文案大多保持可见; 卡片关闭退化为隐藏类且提交按钮不锁定(输入框仍被禁用, 卡片已整体隐藏), 超时结算与草稿上报仍正常
- 多标签页同时打开同一会话时, 服务端按调用标识只保留一份草稿快照, 后上报的标签页会覆盖先到的那份
- 气泡里的草稿记录只保留最近 200 条, 更早的气泡不再可点开
- 推荐项预选: 宿主 0.2.2 打开卡片时会预选带推荐标记的选项; 插件按投影里的选项原文剥掉这些预选值(单选取第一个, 多选取全部), 未点过的题只保留用户真正选中的其他项, 刷新后从宿主持久化草稿恢复的非预选真实选择同样保留; 多选时点过任一选项后, 其余预选项按宿主自己的提交口径一并保留
- 只是点了「跳过」而没有任何选择与输入时, 草稿按空处理, 这次超时由插件关闭卡片
- 草稿按题合并三处来源, 优先级为宿主持久化记录(用户每次改动同步写入的权威值) > 当前显示题的实时值(宿主记录里没有这一题时才用) > 插件自己的快照; 读实时值时已选标签取的是宿主给读屏用的文案, 其中的「(推荐)」这类后缀可能被省略
- 注入给模型的超时说明目前只有中文, 英文界面下模型收到的仍是中文说明(工具自身的英文说明不受影响); 草稿按结构化字段提交, 只读悬浮卡片里的标签不出现在模型侧
- 注入开启但草稿快照没有送达服务端时(页面未打开, 状态通道不可用, 令牌取不到, 上报失败, 或草稿超过单次上报上限 256 KiB), 模型拿不到草稿内容; 一次快照都没收到时工具的 pending 结果会带上 draftMissing 说明, 模型据此知道「没有草稿」不等于用户没有输入; 连续失败达到三次后该轮判定通道不可用: 插件不再接管, 卡片交还宿主继续可作答, 插件气泡不出现; 从判定起到这轮超时结算前, 卡片倒计时位置显示「草稿无法送达」; 草稿超过上限时显示「草稿过长, 未送达」, 这一条不计入连续失败次数, 避免一份长文把整条通道判成不可用; 两条提示与「无法无限等待」互斥, 优先显示前两者
开发
pnpm install
pnpm build
pnpm typecheck
pnpm run check:translation
许可证
本项目采用 Apache License 2.0 授权,版权声明见 COPYRIGHT.
Copyright (c) 2026 JularDepick
相关链接
Comments
Loading…
Similar plugins
by Yebeimu
A DSH plugin: collect pending ask_user_question prompts from other sessions and answer them without leaving the current one.
★ 0
MIT
JavaScript
Oct 23, 2026
dsh plugin --profile web add dsh-sideaskby Q1hangL
Cooperative timeout guard for ask_user_question: lost or unanswered questions resolve as a structured ASK_TIMEOUT instead of hanging the turn forever.
★ 2
MIT
JavaScript
Aug 14, 2026
dsh plugin --profile web add dsh-ask-guardA sidebar assistant plugin for the Web interface, allows users to select any text, displays the model’s reasoning process and final answer in a floating panel.
★ 0
dsh plugin --profile web add dsh-sidehelperby urzeye
DSH web plugin: a realtime conversation outline panel (user questions + markdown headings) for the DeepSeek Harness Web GUI.
★ 19
↓ 54/wk
MIT
TypeScript
Aug 26, 2026
dsh plugin --profile web add dsh-outlineby kk112222
Per-session question index for the DSH Web UI: a time-proportional dot rail on the right edge and an expandable chain panel showing every user question with its time, including branch/subagent session
★ 1
↓ 315/wk
MIT
JavaScript
Sep 13, 2026
dsh plugin --profile web add dsh-chat-indexby anye-99
DSH plugin: after each completed answer, ask the session model for 3 clickable follow-up suggestions and fill the input box on click.
★ 0
MIT
JavaScript
Oct 17, 2026
dsh plugin --profile web add dsh-next-step-suggest