前言¶
DSH 的 agent 常遇到一类任务:等构建产物落地、等下载完成、等日志追加某一行、等子进程退出。这些任务本身不难,难的是必须等外部事件。常见的做法是让 agent 反复 sleep 加轮询,代价是上下文被轮询吃掉,或者把当前回合卡死,用户插不上话;DSH 一旦重启,未完成的等待就直接丢了。
下面介绍的 dsh-durable-wait(中文名「守候」)解决的就是这个问题:agent 登记一次等待就结束当前轮次,插件在后台按固定间隔检查条件,条件成立时自动叫醒原会话继续干活。
这是什么¶
dsh-durable-wait 是一个 DSH 插件,由 Yyhy110421 维护,许可证 MIT,在社区目录里归在工作流分类下。它不改变原有用法,只是补上一个持久等待的轮子:等待状态落盘,DSH 重启后继续检查。
它不做的事也很明确:不监听文件系统事件(靠轮询)、不杀进程、不读文件内容。
核心功能¶
1、三个宿主工具:wait_create 登记等待,wait_list 查看当前等待,wait_cancel 取消等待。
2、三类等待条件:文件出现(file-exists)、文件修改(file-changed)、进程退出(process-exit)。
3、当前轮次立即结束:wait_create 返回后 agent 可以把这一轮正常收尾,不阻塞用户。
4、唤醒原会话:条件成立后按会话状态决定是立即 followup,还是排队等会话空闲,或离线时尝试 agents.resume。
5、状态落盘:等待状态写在 DSH_HOME/data/durable-wait.json,设置写在 DSH_HOME/data/durable-wait-settings.json,DSH 重启后继续检查;终态条目默认保留 7 天。
等待的判断全部在本地完成,没有额外依赖。
安装与启用¶
在 DSH 里打开 设置 → 插件管理器,安装下面任一来源:
github:Yyhy110421/dsh-durable-wait
或者安装本地目录:
file:E:\DSH\projects\dsh-durable-wait
装完重启 DSH。两点注意:
1、file: 安装是实体拷贝,改了源码要卸载再装,不是热更新。
2、插件管理器里的「更新」只适用于 npm 注册表插件,本插件不发布 npm。
安装后菜单里出现 设置 → 守候,用于配置参数和查看等待列表。源码和许可证建议在安装前先过一遍,插件是以当前 DSH 进程权限运行的。
典型用法¶
等文件出现¶
{
"kind": "file-exists",
"path": "E:\\build\\release\\app.exe",
"note": "等构建产物",
"timeoutMinutes": 30
}
file-exists 只判断路径是否存在,不做内容检查。
等文件修改¶
{
"kind": "file-changed",
"path": "E:\\logs\\build.log",
"note": "等日志追加",
"timeoutMinutes": 20
}
file-changed 的基线是创建等待那一刻的 mtime 和文件大小:
- 创建时文件已存在:mtime 或大小变化才算成立;
- 创建时文件不存在:文件出现就算成立。
所以「日志追加了内容」如果恰好没改变 mtime 和大小,不会被判定为成立。
等进程退出¶
{
"kind": "process-exit",
"pid": 12345,
"note": "等渲染进程结束",
"timeoutMinutes": 60
}
只检查进程是否还存在,不会杀进程。PID 可能被系统复用:进程退出后 PID 立刻被别的进程占用,这个等待可能不会触发。需要强关联时,优先等产物文件或日志。
查看和取消¶
wait_list
wait_cancel { "id": "wait-..." }
wait_create 返回的等待对象里带 id、status、expiresAt。
叫醒规则¶
条件成立后的行为,按会话状态分四种:
1、会话在线且空闲:直接 followup,下一轮继续。
2、会话在线但正在跑:保持「待叫醒」,等它空闲再叫,不插队。
3、会话不在线:尝试 agents.resume 一次,失败就标 undelivered,不循环重试。
4、自动叫醒关闭:条件成立只改状态,不叫醒。
被叫醒时消息以 【守候】 开头,包含等待 ID、条件类型和目标、备注、成立时间。agent 被叫醒后应先 wait_list 确认,再继续原任务,不要重复创建同一个等待。
状态字段¶
等待状态 status:
| status | 含义 |
|---|---|
| active | 正在等 |
| fired | 条件已成立 |
| cancelled | 被 wait_cancel 取消 |
| expired | 超过 timeoutMinutes |
投递状态 delivery:
| delivery | 含义 |
|---|---|
| pending | 条件已成立,等会话空闲 |
| delivered | 已叫醒 |
| undelivered | 叫醒失败(会话不在线且恢复失败,或 followup 抛错) |
| none | 不需要叫醒(已取消、已超时、创建时已满足、或关闭了自动叫醒) |
设置页¶
设置 → 守候:
- 默认超时(分钟):新建等待不传
timeoutMinutes时使用; - 轮询间隔(秒):2–60,默认 2;
- 最多同时等待:1–200,默认 50;
- 条件成立时自动叫醒会话:关掉后只记录状态;
- 等待列表:目标、状态、剩余时间、叫醒状态;
- 取消进行中的等待。
设置保存在 DSH_HOME/data/durable-wait-settings.json。
安全边界¶
插件只做了很窄的一件事:
- 文件类只做
stat,进程类只做process.kill(pid, 0)存在性检查; - 不杀进程、不改目标文件、不读文件内容;
- 只接受绝对路径,避免相对路径随工作目录漂移;
- 备注限 500 字,不要写验证码、密码、API Key;
- 最多同时 200 条等待,防止状态文件无限增长;
- 叫醒消息只包含等待目标和备注,不含文件内容或进程输出。
适用场景与注意¶
适合这类场景:agent 需要等一个外部事件(产物文件、日志变化、子进程结束),且这一步可以异步化,之后还有活儿要干。不适合的场景:需要秒级响应的等待(默认 2 秒轮询)、需要精确感知文件内容变化的等待、以及依赖 PID 强关联的进程等待。
几个务必留意的点:
1、插件以当前 DSH 进程权限运行,能访问该进程能访问的文件和 PID,安装前先检查源码与许可证(MIT)。
2、file: 安装是拷贝,改源码后不会自动生效。
3、本插件不发布 npm,插件管理器的「更新」对它无效。
4、等待状态依赖 DSH_HOME/data/ 落盘,换 DSH_HOME 会丢等待。
5、叫醒是「下一轮用户消息」,不会打断正在执行的回合。
结尾¶
dsh-durable-wait 把「等外部事件」从 agent 反复轮询的笨办法,换成一次登记加一次叫醒。它覆盖文件出现/修改和进程退出三类常见条件,状态落盘可跨重启,权限面也控制得很窄。
目录页:https://www.skillhub.cn/plugins/Yyhy110421/dsh-durable-wait
GitHub:https://github.com/Yyhy110421/dsh-durable-wait