bgjobs
独立于 DSH 进程的后台任务(schtasks 托管):bgjob_submit/bgjob_status 工具、网页「后台任务监控」实时面板、可选完成后通知创建者 agent(notify 参数);支持可选 dsh 沙箱(read-only/workspace-write)约束后台任务文件效果。关 DSH 亦不影响任务运行。 适合Windows用户在后台运行长耗时任务、脚本或MCP工具。
설치
$
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 起可用。)