dsh-durable-wait: Register the agent for waiting and wake the session when the condition is met.

前言

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

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

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

Xiaoye