bitsmug/dsh-bgjobs ↗★ 2

bgjobs

提供独立于DSH进程的后台任务提交与监控面板 适合Windows用户在后台运行长耗时任务、脚本或MCP工具。

套件
bgjobs
相容性
待驗證
Harness 依賴範圍
>=0.1.0-rc.1 <0.1.1-0 || >=0.1.1-rc.1 <0.1.2-0 || >=0.1.2-alpha.0 <0.2.0-0 || >=0.2.0-rc.1 <0.3.0-0
版本
0.2.1
授權
MIT
最近更新
2026年10月8日

安裝

$npx -p @deepseek-ai/dsh dsh plugin --profile web add github:bitsmug/dsh-bgjobs

使用(agent 工具)

  • bgjob_submit(name, command, workdir, [wait], [notify], [notify_mode]) — 提交后台任务(command 为 bat 语法);wait=提交后原地等待的秒数(0/缺省不等待;>0 语义同 bgjob_wait 全缺省——等本会话任一任务先结束,无会话信息时回退等刚提交任务);
  • bgjob_submit_pwsh(name, command, workdir, [wait], [sandbox], [justification], [notify], [notify_mode]) — 提交后台任务(command 为 PowerShell 语法,UTF-8 日志、exit 语义安全);wait 同上;沙箱任务(sandbox 非 off)经独立 runner 拉起,需要真 node(console 子系统,优先与 DSH 同源的那份,见近期更新 v0.1.91);找不到 ⇒ 提交时直接报错(不会出现「日志空白 + 假 exit 0」的假成功);
  • bgjob_submit_mcp(name, workdir, tool, [arguments], server | server_config, [timeout_seconds], [wait], [notify], [notify_mode]) — 把一次 MCP 工具调用提交为后台任务(第三引擎,同样由 schtasks 托管、面板可见、可 wait/notify)。server 是设置页登记的 server 名,server_config 是内联配置(stdio 或 streamable-http),二者二选一。任务里连接该 server 调用一次工具,结果写日志与 /result.json(含执行通道),退出码 0 成功 / 1 工具报错 / 2 连接或调用失败 / 3 超时;timeout_seconds 缺省不限时(该 server 在设置页登记了 timeoutMs 时以它为准),也可传任意正数秒。默认关闭,需先在设置页打开「MCP 任务」开关(未开启时调用会被拒绝);与 DSH 一致,会话访问模式(read-only 等)不限制 MCP 任务。建议先用 bgjob_mcp_tools 确认工具名;
  • bgjob_mcp_tools(server | server_config, [refresh]) — 列出该 MCP server 的注册工具(工具名/描述/必填字段名),提交前用它确认工具名与参数形状;结果有缓存,refresh: true 强制刷新;同样受「MCP 任务」开关限制;
  • bgjob_status(jobId) — 查询状态 / 退出码 / 日志尾部;仅用于查看当前状态,不要拿它循环轮询(等待用 bgjob_wait);
  • bgjob_wait(jobId | jobIds, [timeoutSeconds], [logic]) — 等待后台任务结束并立即返回退出码与日志尾部(timeoutSeconds 缺省 = 设置页「默认等待超时」,该设置未配置=不限时(一直等到任务结束);显式传 0/负数 = 本次强制不限时,传正数才到点返回 timedOut: true 快照)。两种模式(logic):
    • any(缺省):单个 jobId 等该任务;jobIds 数组 = 任一先结束即返回(any 竞速,返回完成者 + 其余 pending)——并行提交多个任务时的默认姿势:先拿到先处理,其余用 pending 继续等,不必等齐;两者都缺省 = 等本会话任务任一结束;
    • all(合取):等一批任务全部成功才返回 allDone: true + 每个任务的退出码/日志尾;任一任务失败即立刻返回 failed: true + failedJobId + 已结束者的 results + 其余 pending(非 0 退出码,或被清理/找不到都算失败),不再等齐;超时返回部分状态可续等。只在「必须全部成功才能继续」且「一个失败就马上停」时使用——只想边拿边推进请用缺省的 any;jobIds 缺省 = 本会话全部任务;
  • bgjob_list — 列出当前 agent 会话提交的全部任务(id/状态/退出码),配合 wait 工具缺省使用。
  • bgjob_kill(jobId, [force], [reason]) — 终止任务的进程(进程树)。★ 只终止进程、不删记录:job 目录 / 中央索引 / 注册表全部保留,终止后仍可用 bgjob_status / bgjob_list 查到它,记录要清得另外用 bgjob_delete。被终止的任务补写非 0 退出码(1,taskkill /F 记录的真值)+ exitCodeSource: 'killed' / killedAt / killedBy(reason 会记进 killedBy)⇒ bgjob_wait 拿到失败口径,绝不会被读成「成功完成」。若没有可终止的活进程 ⇒ 什么都不做(不杀、也不删任何记录),返回 mode: 'absent' + note 说明。返回值 mode 三态:kill(终止了活进程)/ absent(未发现活进程 ⇒ 什么都没做)/ unknown(无法判定)。unknown 时默认不动作并回 needsForce: true,须显式 force: true 才继续——force 只用于越过这道门槛(不是「更用力地杀」),对 kill / absent 两种情形毫无影响;
  • bgjob_delete(jobId, [force]) — 删除任务的记录(job 目录 + 计划任务注册 + 中央索引)。★ 只删记录、不杀进程:仍有活进程时会被拒绝(回 mode: 'kill' + error,提示先 kill 再 delete)——绝不越界杀进程,否则会造出「面板看不见、进程还在跑」的孤儿。mode 三态:delete(只删了记录)/ kill(有活进程 ⇒ 拒绝)/ unknown(无法判定)。unknown 的门槛同 bgjob_kill(默认不删任何记录 + needsForce: true,显式 force: true 才继续);
  • 不要用 sleep 轮询:等结果用 bgjob_wait;不要用 sleep / Start-Sleep / timeout,也不要用「循环 bgjob_status」代替(占住回合、收不到新消息)。

直接对 AI 说一句即可(说清工作目录、任务名,以及要不要等结果 / 通知):

把「clone Linux 内核源码到 D:\work\linux,再 make -j16 编译」这条长链路放后台跑,跑完通知我(notify: on-exit)——别让编译占着对话。

并行起两个后台任务:一边下载数据集、一边重新编译;谁先完成就先给我看结果,另一个继续跑(any 竞速,不必等齐)。

用 pwsh 引擎把 D:\data 下 30 个 CSV 批量转成 UTF-8;我要全部成功才继续,任何一个失败就立刻停下来(logic: 'all')。

把一次 MCP 调用提交成后台任务:server glm 的 web_search,query=「大模型最新进展」,跑完把结果发回本会话。

  • 任务输出实时写入 \.dsh\bgjobs\\stdout.log;
  • 退出后 \.dsh\bgjobs\\exitcode.txt 写入退出码,网页弹 Toast;
  • 完成后默认不打扰会话;需要让 agent 主动得知并收尾时,传 notify: on-exit(或 on-completion 仅成功 / on-fail 仅失败),并可选 notify_mode(wakeup 空闲唤醒 / quiet 仅入收件箱 / always);
  • 交付标记(notify 视图):每个任务标注「结果是否已交付到会话上下文」——完成通知投递成功(已通知·notify)或某次 bgjob_wait 返回了它(已通知·wait)即交付;bgjob_pending_list 列出本会话尚未交付的任务(notify 视图),bgjob_wait 缺省(含 logic: 'all')只从这个视图等——已交付的结果不会重复返回。面板/离线 GUI 均有「已通知/待通知」标记。

使用须知

  • workdir 必须是 DSH 工作区内的绝对路径;
  • 任务默认「仅用户登录时运行」:关 DSH/终端不影响,但注销 Windows 会终止任务;
  • 命令不要自带 > log 类重定向(插件已整体重定向并保证 UTF-8);
  • 沙箱:sandbox 只约束文件效果(写工作区/临时区外会被拒),网络不受限;它是"尽力而为"而非数学边界——工作目录若落在 Everyone 可写的位置会失效;沙箱任务的任务目录对本地用户可读(脚本文本可见);bat 引擎任务恒为全权限,受限会话需开启「全权限」才能提交;
  • 受限会话里请求超出会话模式的权限会弹窗审批,justification 说明理由即可;面板的**「全权限」开关不改变会话访问模式**(不改 DSH 的 mode)——它只决定这种「更宽请求」是弹窗审批(关)还是直接放行(开),任务仍按 resolved 模式落盘。
  • MCP 任务:默认关闭(设置页开启);任务被 kill 时会按记录的 pid 回收其 stdio MCP server 子进程(delete 只删记录、不杀进程;若 server 子进程仍活着,delete 会拒绝并提示先 kill);每个 server 在设置页可切「预热 / 冷启动 / 禁用」三态——禁用会让 bgjob_submit_mcp / bgjob_mcp_tools 拒绝该 server 并断开其常驻连接(「列出工具」仍可用);「预热」连接只在 DSH 存活期有效,不改变"任务脱离 DSH 也能跑";离线 CLI/GUI 只读查看、终止进程与删除记录 MCP 任务,不在离线侧提交 MCP;mcp-servers.json、导出文本与任务目录的 mcp.json 都含明文密钥,分享/归档前请脱敏。
  • 等待被停止 ≠ 任务失败:agent 等待任务时你点「停止/打断」,本次等待会以错误结束(错误文案写明各任务当前状态并提示可续等)。这是 DSH 的取消语义——调用方取消后,成功返回的东西送不到模型,只能以错误形态呈现;任务本身继续后台运行、不标记已交付,agent 可再次 bgjob_wait 续等。等待期间收到其它 agent 的消息则正常返回让路(stoppedBy: 'message'):该返回不含消息正文,但这次调用会声明终结当前回合——DSH 随即把你/它发来的消息作为正式用户消息投递给 agent(排在本轮之后的排队消息亦然);agent 不应再用等待或阻塞操作顶替它。
  • MCP 超时收尾有 1–2 秒宽限:MCP 任务超时/失败后 host 会关闭连接并回收 server 子进程(关连接本身要等约 2 秒),所以 result.json 里的 durationMs 可能比 timeoutMs 多 1–2 秒(同文件也记了 timeoutMs 便于对照)。
  • ✅ 已修复:运行中的「沙箱 pwsh」任务现在能真正停下来了——以前面板「删除」和离线 CLI kill 会返回成功、任务却还在跑(还从面板列表里消失,于是你既看不见也管不了,任务目录也删不掉;受限会话下 pwsh 任务默认就进沙箱,所以这类任务都可能中招)。现在 kill 只终止整棵进程树、不再删记录(并补写非 0 退出码 1 —— 那是 taskkill /F 在内核里记录的真值:退出码由终止方传入,我们拿不到"任务自己"的码(任务由 schtasks 起、我们不持有句柄),所以"被终止"只能靠 exitCodeSource:'killed' 这个来源标记认,计划任务列表里的 Last Result 分不清"自己报了 1"与"被杀成 1",不能当证据 ⇒ 等待/通知都按失败口径报,不会被读成"成功完成"),delete 才删记录且只在没有活进程时执行(有活进程会明确拒绝并提示先 kill);★ 反过来,kill 遇到"没有活进程"时什么都不做、也什么都不删(如实回 mode:'absent' + 「未发现该任务的活进程」;要清记录是调用方自己再调一次 delete —— kill 不会替它转成删除);成功就是成功、失败会明确报错,不再有"假成功"。机制细节(pid 文件 + 树杀 + 核验 + 语义边界)见 docs/developer.md 的「kill / delete 语义」与「边界与已知限制」。(v0.2.0-alpha 起可用。)