dsh-command-queue:agent 忙碌时斜杠命令排队,空闲后自动执行

前言

在 DeepSeek Harness(DSH)里,普通用户消息和斜杠命令走的是两条不同的通道:前者在 agent 忙碌时会进入 inbox 排队,回合结束再消费;后者通过 ctx.commands.execute() 直接调 handler,忙碌时没有排队语义。典型例子是 /compact:其 handler 会调用 compactNow() → agent.runMaintenance(),当 agent 非 idle 时会同步抛出 ManualCompactionError('busy'),你只会立刻看到「Compaction is unavailable because this process has an active compaction, or the agent is not idle.」——既不能排队,也没有重试。DSH 侧曾明确排除「把命令本身进队列」的方案,官方没有对应开关。

下面介绍社区插件 dsh-command-queue(维护者 kuyueliuhun-ctrl):在 host 侧包装 ctx.commands.execute(),让列入白名单的斜杠命令(默认只有 /compact)在 agent 忙时进入命令队列,等状态回到 idle 后再执行;并在浏览器里用接近原生消息队列的样式展示这份队列。插件分类为工作流,不改 DSH 源码,卸载可还原 execute 行为。

这是什么

dsh-command-queue 是 DSH 的 host + client 双面插件:host 负责排队与延迟执行,client(platform: "web")在 composer 上方、原生消息队列下方渲染「命令队列」面板。拦截点在 ctx.commands.execute();命令仍由原注册表解析,仍由 CommandRuntime 写 command/run 与 command/done 生命周期,只是执行时机被推迟到空闲窗口。

原生 agent inbox 队列条目只能是 UserMessage,且会在下一个 step 边界被取走——那时 agent 往往仍在 running,compactNow 仍会 busy。因此本插件另建一份队列,只复刻样式与挂载位置(槽位 conversation.input.dock,id:"command-queue" / order:30),与原生 id:"queue" 上下并排。

核心功能

忙碌时排队,空闲后执行

agent 正在跑回合时发送默认白名单内的命令(默认 /compact):

  1. 命令进入队列,输入框不冻结,可继续打字、继续排普通消息;
  2. composer 上方出现命令队列 UI:单条直接显示一行命令;多条折叠为「已排队命令 · N」可展开,每行带移除按钮;
  3. 回合结束、agent idle 后命令真正执行,transcript 里出现正常命令卡片(「执行中…」→「已完成 · Compacted N history items」等),队列中对应行消失。

队列为空时 client 面板不渲染(返回 null),不占视觉空间。

白名单与零回归

排队规则是白名单:只有名字列在 deferCommands 里的命令才可能排队,默认仅 compact。以下任一情况立即执行,不进队列:

  1. 不是合法命令语法(例如不以 / 开头、名称含大写、只有 /);
  2. 命令名不在 deferCommands 里(默认即绝大多数命令);
  3. 在强制立即名单里(内置 stop / cancel / abort / interrupt / halt,与用户配置的 immediateCommands / alwaysImmediateCommands 取并集);
  4. 在注册表里解析不到(ctx.commands.find 返回 undefined);
  5. agent 当前已是 idle。

排队逻辑自身抛错时会回落为原行为,不吞命令。卸载时会唤醒等待者,让在队命令尽快执行完。

浏览器面板与 /cmdqueue

面板约每 1.5s 轮询 host 快照;行右侧按钮可移除尚未执行的排队命令(被移除的命令不会执行)。面板数据走 /api 已鉴权路由(Host/Origin 围栏 + 签名 cookie),不用裸 webServer 路由。

不想开面板时,可用只读斜杠命令查看同一份队列:

/cmdqueue
→ 1 command(s) queued for this agent, waiting for it to become idle: /compact
→ No queued commands for this agent.

按 agent 隔离

队列按 agent 隔离,严格 FIFO 串行;一个 agent 空闲不会放行另一个 agent 的在队命令。

安装与启用

本包是手写 ESM / 浏览器 bundle,无编译步骤;lib/index.js 与 lib/client.js 即源码。客户端插件在页面加载时装配——安装或注入后需要刷新页面才会出现面板。

Node 引擎要求:>=22.19.0(见 package.json)。peer 依赖 @deepseek-ai/cordis(>=4.0.0-rc <5)。

方式 A:从 GitHub 装配进 profile(推荐,重启后仍在)

进入所用 profile 目录(示例为 web profile):

cd "$DSH_HOME/profiles/<profile>"          # 例如 ~/.dsh/profiles/web
npm install github:kuyueliuhun-ctrl/dsh-command-queue

把包名加入该 profile 的 package.json 里 dsh.profile.bundles 数组:

{ "dsh": { "profile": { "bundles": ["dsh-command-queue"] } } }

包自带 cordis.patch.yml,bundle 层会把 command-queue 插进 loader,无需手写 patch 条目。

方式 B:本地目录(开发)

npm install "file:/path/to/dsh-command-queue"

若使用 dsh-super-injector:

dev_install_package { "dir": "/path/to/dsh-command-queue", "profile": "web" }

方式 C:运行时注入(免重启,临时验证)

dev_inject_plugin   { "dir": "/path/to/dsh-command-queue" }
dev_plugin_status   {}

卸载

dev_uninject_plugin { "match": "dsh-command-queue" }

非注入器环境:从 dsh.profile.bundles 移除包名,再删除 node_modules 里对应包。

配置

无独立 schema,容错读取,全部可选。写在 profile 的 cordis.patch.yml 里 command-queue 条目下的 config:

- id: command-queue
  name: 'dsh-command-queue'
  config:
    deferCommands:                   # 主开关:只有列在这里的命令才排队(默认 ['compact'])
      - compact                      # 带不带前导 / 都可以
    verbose: true                    # 打开排队/执行日志(默认 false)
    pollIntervalMs: 250              # host 侧等空闲的轮询兜底间隔,50–5000(默认 250)
    exposeState: true                # 注册给浏览器面板的已鉴权路由(默认 true;false = 纯 host)
    immediateCommands:               # 强制立即:与内置名单取并集(v0.2.2 起不再整体替换)
      - export
    alwaysImmediateCommands:         # 与 immediateCommands 语义等价,同样取并集
      - my-control-command
  • deferCommands: [] 表示没有任何命令排队,等同于关闭排队功能。
  • 某命令同时出现在 deferCommands 与强制立即名单时,强制立即优先。
  • 默认只排 /compact 的原因:/permission、/plan、/goal 等会改会话状态,推迟到回合结束可能彻底失效;早期版本「除立即白名单外一律排队」曾带来这类回归,当前默认策略已收窄。

典型用法与故障排查

典型流程:在 agent 仍 busy 时输入 /compact → 在命令队列面板或 /cmdqueue 确认已排队 → 等当前回合结束 → 在 transcript 查看 compact 结果,队列行消失。

现象 处理要点
刷新后仍看不到面板 用 dev_plugin_status 确认 client ✓;若为 client ✗,可能是 pkgMeta 负缓存,重启 host
排队期间 transcript 无提示 设计如此:command/run 在 handler 调用前才写入,提示在队列面板
命令一直不执行 在等 idle;若 inbox 里消息不断,空闲窗口会被占用——用 /cmdqueue 或面板确认
/permission 等忙时不生效 若仍在旧规则版本,升级到默认只排 compact 的版本;检查是否误把状态类命令写进 deferCommands

开发侧可运行:

npm test      # node --test tests/*.test.mjs
npm run check # node --check lib/index.js && node --check lib/client.js
npm run build # 语法校验 + 全套测试

适用场景与注意

适合:经常在 agent 长回合进行中需要 /compact、又不想反复撞 busy 报错的用户;希望在 UI 里看见「还有哪些命令在等 idle」的团队。

注意:

  • 插件以当前 DSH host 进程权限运行,安装前请阅读 源码与 LICENSE(MIT),自行评估信任边界。
  • 社区目录 SkillHub 插件页 与 GitHub 仓库由维护者发布,与 DeepSeek / 幻方无官方从属关系;DSH 生态强调「一切皆插件」,本文事实以仓库 README 与 package.json 为准(当前 package 版本 0.2.2)。

结尾

dsh-command-queue 补上了 DSH 斜杠命令通道在 busy 时缺少排队语义的那一段:默认只推迟 /compact,其余命令保持立即执行;卸载可还原。更多实现细节见仓库 docs/INTERNALS.md。

  • 目录页:https://www.skillhub.cn/plugins/kuyueliuhun-ctrl/dsh-command-queue
  • GitHub:https://github.com/kuyueliuhun-ctrl/dsh-command-queue
羽毛球分组比赛记分
小程序二维码

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

Xiaoye