dsh-loopx-plugin
loopx-project/loopxLoopX——面向长周期 Agent 的提供商中立、本地优先状态内核与控制平面:在 DeepSeek Harness 执行层之上持久化 Goal、Todo、门禁、证据、配额、恢复与交接状态;插件负责引导安装 CLI 与技能、准入有界的同会话续跑,并为精确绑定的工作循环提供本地 GoalBar。
Antigravity 式 run_command:短命令在可配置窗口(默认 10 秒)内同步返回结果,长命令自动晋升为 ctx.jobs 后台任务并推送完成通知——命令经 ctx.shell 执行,受会话沙箱与审批管线约束。
让长命令不再卡死对话:短命令即时返回结果,长命令自动转入后台,跑完主动汇报——复刻 Google Antigravity 的 run_command 工作流体验。对话式开发里最影响手感的事,莫过于一条构建、训练或下载命令把整个会话挂住。本插件把 Antigravity 的「超时竞争」工作流带到 DeepSeek Harness:
参数命名对齐 Antigravity 官方的run_command合约(CommandLine/Cwd/WaitMsBeforeAsync),模型侧习惯零成本迁移。
ctx.shell 执行器运行,受会话沙箱模式约束:confining executor 在位的部署中,越界文件操作以 [sandbox: file access denied under mode] 标记呈现(升级面在位的组合还会附带与原生 shell 工具逐字一致的同轮升级提示);danger-full-access 会话不设限是该模式自身的语义,不是插件旁路。注意该词汇表约束的是写效果——读操作在任何模式下都不受限。ctx.approval 审批管线:审批禁用的会话中升级会被自动拒绝(fail-closed),不存在绕过路径。ctx.jobs 未组合时工具直接报错(fail loud):每个 run_command 调用都必须保持可收集、可停止。可在 profile 的 cordis.patch.yml 或主配置中通过条目的 config 字段覆盖;非法类型在加载时即抛错(fail loud)。为保证树外 link/path 挂载时的最小运行时依赖,校验由插件内置安全实现。
字段 · 类型 · 默认值 · 说明 waitMsBeforeAsync · int ≥ 0 · 10000 · 同步等待毫秒数(对齐 Antigravity 10 秒标准);设为 0 则直接后台启动
# cordis.patch.yml 覆盖配置示例
- insert:
- id: dsh-plugin-background-tasks
name: dsh-plugin-background-tasks
config:
waitMsBeforeAsync: 10000 # 统一标准:10 秒run_command通过挂载的 DSH shell 执行器运行系统命令(Windows 为 PowerShell 家族,Linux/macOS 为 bash)。
参数 · 类型 · 必填 · 默认值 · 描述 command · string · 是 · - · 待执行的完整命令行字符串 cwd · string · 否 · 会话工作区 · 命令执行的工作目录;相对路径按会话身份解析 description · string · 否 · - · 任务简短说明(同时作为 job 列表标签) sandbox_permissions · string · 否 · - · 仅限对刚发生的沙箱拒绝做一次性同轮加宽重试;需配 justification 并经用户审批(仅 confining 组合广告此参数) justification · string · 否 · - · 与 sandbox_permissions 成对出现的给用户的一句话理由
同步等待窗口是部署级配置(waitMsBeforeAsync,默认 10 秒),模型侧没有时机参数——这是刻意设计:时机决策权属于操作者。窗口内完成则内联返回;超窗或调用中止自动转入后台,结果经完成通知送达。killed 结算并在 stderr 带错误,绝不悬挂。[Command moved to background] 与 JobId(command-N),并附一行明确的反轮询指引——勿在通知到达前轮询,继续独立工作或结束本轮即可被完成通知自动唤醒;运行中的每次读取正文同样携带该提示,终态读取与官方 [status: ...] 收尾格式不受影响。此后用原生 job_* 工具管控,完成通知由 jobs 消费面自动投递。dsh plugin --profile web add github:yaopushen/dsh-plugin-background-tasks编译产物 lib/ 随库提交,GitHub 直装免构建。
本插件遵循标准 DSH Bundle 规范,自带 dsh.bundle 补丁声明与随包预设:
# 1. 注册安装到指定 profile(例如 web profile)
dsh plugin --profile web add "dsh-plugin-background-tasks@link:D:/DEEPSEEK/dsh-plugin-background-tasks" -w
# 2. 检查配置层生效状态(权威诊断,应显示 - id: dsh-plugin-background-tasks)
dsh --profile web --dump-config | Select-String background
# 3. 启动 DSH Web
dsh web组合前提:profile 需组合 ctx.shell 执行器(缺省 fail loud)、@deepseek-ai/dsh-jobs-local + @deepseek-ai/dsh-tool-jobs(jobs 缺省时调用即报错);confining executor 在位时需 ctx.sandboxPolicy(缺失则加载即抛错,与原生 shell 工具同一判据)。
树外路径挂载的依赖解析:插件以绝对路径挂载在宿主工作区之外时,Node 需要能从本目录解析 @deepseek-ai/* 运行时包。运行 scripts/link-deps.ps1 一次即可幂等建立指向 harness 工作区的 junction(要求 harness 已构建)。
插件加载时会自动把 preset/background-shell/ 释放到 $DSH_HOME/.agent-presets/background-shell/:
run_command 为唯一单入口,无需在系统提示词中增加说教规则。$DSH_HOME 下的副本(或删除该目录让安装器重建)。dsh-plugin-background-tasks/
├── package.json # Bundle 声明、files 导出白名单
├── cordis.patch.yml # Bundle 默认挂载补丁
├── preset/ # 随包附带预设(自动释放)
│ └── background-shell/ # 单入口 Shell 派生预设(agent.cordis.yml / preset.yml)
├── scripts/
│ └── link-deps.ps1 # 树外路径挂载时的依赖 junction 接线(幂等)
├── src/
│ ├── index.ts # 函数插件入口(inject ['tools','shell','systemPrompt'];split-composition fail loud)
│ ├── config.ts # fail-loud 配置解析器(默认 10s 等待窗口)
│ ├── tools.ts # run_command Consumer(晋升竞争、审批升级、jobs 注册)
│ ├── shell-exec.ts # 纯适配层(workdir 解析、outcome 映射、读渲染、竞速器)
│ ├── preset-installer.ts # 预设幂等自动释放辅助器
│ ├── format.ts # 防 Markdown 围栏击穿工具
│ └── types.ts # 强类型定义
├── lib/ # 编译产物(随库提交,供 link 挂载免构建部署)
├── tests/
│ ├── test-shell-exec.mjs # 纯适配层回归(27 用例,无宿主依赖)
│ └── test-tool-execute.mjs # 编排层集成回归(fake ctx,16 用例)
└── dev/ # 内部研发基线与 changelog(不入发布包,见 dev/README.md)run_command tool schemaThe tool's name, description (with configured wait window), parameters (command, cwd, wait_ms, description, plus the escalation pair only when a confining executor is mounted), and the string output contract.
Fixed while the plugin is mounted: one tool schema entry per prompt assembly.
Prefix-stable: schema text is identical across turns unless deployment overrides waitMsBeforeAsync or the composition's confinement changes which parameters are advertised.
A standing system-prompt section (tool:run_command) teaching the failure classes observed in the wild on bare compositions: verbatim script-fragment semantics (never whole-command quoting), SINGLE-quote wrapping for SSH remote arguments (bash-style \" nesting mangles silently), and byte-truth file comparison idioms using built-ins (fc.exe /b, Get-FileHash, CRLF counting) with Compare-Object's set-semantics caveat.
Fixed while the plugin is mounted: roughly 100 tokens per prompt assembly.
Prefix-stable.
Delivered natively by the jobs consumer (tool-jobs), not by this plugin: an episodic user-role system message with job id, label, terminal status/detail, and the output tail capped by the registry.
Conditional: proportional to the output tail, once per promoted job that finishes non-killed and unreported.
Append-only: each notice enters the session log as an ordinary user-role message and never replaces prior content.
jobs.start runs its preflight; a rejected registration kills the partial start, but the process does briefly exist outside the registry in that failure window.@deepseek-ai/dsh-jobs-local (+ tool-jobs) every call fails loudly; there is no sync-only degradation, because a command that outlives its turn must remain collectable.waitMsBeforeAsync is operator-owned; models cannot extend or skip it per call (by design — timing decisions caused models to block their own turns for minutes). Long-running daemons pay the full window once per start; there is no executor timeout inside the window because promotion, not killing, is the release path.dev/,不随 npm 包发布。MIT