← 返回列表
⚠ 装前注意
@gorban/dsh-job-stop
基本兼容但装前注意:未发布到 npm registry,仅可从源码安装 · 最近上游提交 2026/9/21 · 已提供中文文档
DeepSeek Harness (dsh) 插件:从会话头部任务列表中停止正在运行的后台任务,需通过确认对话框操作。
综合分
29.8
GitHub 分
29.8
用户评分
—
★ Stars
0
周下载量
—
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add gorban/dsh-job-stop未发布到 npm registry,仅可从源码安装,改用 GitHub 源安装
信任档位:已验证本站已于 1 天前真实安装成功
- 是什么
- dsh 原生插件 · chat
- 装得上吗
- 本站已真实安装成功(非静态推断)
- 安全吗
- 本站尚未对该插件做风险分级(暂未覆盖,不等同于无风险)
- 还在维护吗
- 活跃:最近一次提交在 5 天前
档位由下列信号合成:本站实装验证(真实安装,当前最高到 L4)· 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。下方各区块是它的证据明细。 验证判据与等级说明 →
🟢实装验证通过· 2026/9/25
由本站实装验证器在真实 dsh 环境安装成功,非静态推断。
数据截至 2026/9/22(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
安装兼容性检查⚠ 装前注意
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✗npm 包@gorban/dsh-job-stop(未发布到 npm,仅可源码安装)
✓Node 引擎要求 >=22.19 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明
未发布到 npm registry,仅可从源码安装
验证方式:npm registry 存在性 + package.json 静态校验 · 最后验证 2026/9/22 15:34:14
依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-jobs@deepseek-ai/dsh-llm@deepseek-ai/dsh-session@deepseek-ai/schemastery用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动
README
由 DeepSeek 最新模型翻译生成@gorban/dsh-job-stop
npm
license
dsh
从 DeepSeek Harness Web 会话头部停止正在运行的后台任务——将鼠标悬停在其在后台任务列表中的行上,点击停止标志,在对话框中确认,该对话框会重述完整命令。
悬停在正在运行的任务行上,然后确认停止
悬停在正在运行的行上会用停止按钮覆盖其动画状态点;对话框会在取消任何内容之前重述命令、类型、状态、已用时间和任务 ID。
它的作用
会话头部的后台任务列表变得可供人类操作,而不仅仅是可读:
- 悬停在正在运行的行上,动画状态点会被红色停止按钮覆盖,并带有工具提示和可访问名称,两者都会指明任务(Stop background job: )。
- 激活它,会打开内置确认对话框——与会话重命名和工作区删除对话框使用的相同 Modal + Button 组合——在取消任何内容之前重述完整命令、任务类型、状态、已运行时长及其注册表 ID。
- 确认后,宿主通过 ctx.jobs 终止任务,该行会从普通推送帧变为 stopping,然后变为 killed,并且所属代理会被告知有人类停止了它的任务。
一切都已本地化(英语和简体中文)且可通过键盘访问:停止按钮可获得焦点,并在 :focus-visible 时显示自身,Escape 关闭对话框,prefers-reduced-motion 禁用淡入淡出效果。
它为何存在
ctx.jobs 已经运行了每个后台 bash/pwsh/PTY/子代理任务,并且 dsh-tool-jobs 已经暴露了 job_kill——给模型。Web 列表(dsh-client-ui-jobs)是一个刻意只读的投影,其自身的 README 指出了推迟取消的原因:
行是只读的——……取消还欠一个面向模型的决策,而该接缝并未回答:kill() 将终端投递标记为已报告,因此针对当前契约编写的中断会让模型相信其任务仍在运行。
这就是此插件解决的全部问题,而设计说明 2026-08-08-web-background-job-display 将 stopping 留在 wire union 中,正是为了让此阶段不需要更改 wire。两个后果塑造了实现:
1. 必须告知模型。 JobRegistry.kill 会设置 reported = true,并且 dsh-tool-jobs 会跳过已报告任务的完成通知。因此,在成功终止后,此插件会注入自己的插件来源通知(当代理忙碌时使用 inject,当代理空闲且 notice: wakeup 时使用 followup),否则模型会继续等待一个已不存在的任务。
2. 已经结束的任务不得被终止。 对终端记录调用 kill 还会设置 reported,这会吞掉模型仍然应得的完成通知。因此,只要任务已离开 running 状态,端点就会报告 already-finished,而不调用 kill。
安装
从 npm 安装——预构建,因此安装无需构建步骤,也无需 allowBuilds 批准:
dsh plugin --profile web add @gorban/dsh-job-stop
从 GitHub 安装——不涉及 npm 账号:
dsh plugin --profile web add github:gorban/dsh-job-stop
从发布 tarball 安装——适用于无法访问 npm 或 GitHub 源码归档的主机:
dsh plugin --profile web add https://github.com/gorban/dsh-job-stop/releases/latest/download/dsh-job-stop.tgz
然后重启 dsh(插件行会在配置文件加载时挂载)。该命令会添加依赖,并且由于 package.json 声明了 dsh.bundle,会将包列入 dsh.profile.bundles,从而应用其 cordis.patch.yml 行。
需要 dsh 0.1.2-alpha.1 或更新版本,声明为 engines.dsh,以便 Plugin Market 的主机感知过滤器能够读取它:此列表渲染所依据的 jobsBySession 镜像,以及停止端点所声明的 ctx.connection.fetch 路由接缝,都是在该版本中首次发布的。
随附的 @deepseek-ai/dsh-client-ui-jobs 行可以保持启用:此插件以较低的优先级在该条目自己的插槽单元 id(job-list)下注册其列表,因此标题栏只保留一个控件,只读列表被遮蔽而不是重复。此插件在该行禁用时也能正确渲染,因为它读取的是同一个 jobsBySession 镜像。
工作原理
主机部分(src/index.ts)在 Connection fetch 注册表上声明一个经过身份验证的路由:
ctx.connection.fetch.register({
path: '/api/dsh-job-stop/kill',
methods: ['POST'],
requestBody: 'buffered',
fetch: request => handleStop(ctx, config, request),
})
选择该注册表是经过深思熟虑的,而且它不是显而易见的选择。ctx.webServer.register({ kind: 'exact', path: '/api/...' })——插件最先想到的模式——会在 Connection 的 /api 前缀路由之前匹配 Web 服务器的精确表,因此它会在 requestRejection 之前运行,从而处于主机/Origin 信任和浏览器身份验证围栏之外。对于提示开关来说这没问题,但对于会改变状态的 kill 来说是错误的,因此此端点改为在共享 fetch 处理器上声明,此时围栏已经运行。
然后处理器会:
- 验证 { sessionId, jobId } 并拒绝格式错误的请求体(400);
- 使用 ctx.agents.get(...) 解析 Session 的确切活动 Agent,并在不存在时拒绝(409)——id 是可预测的,因此边界是授权而非保密,并且注册表会按该 Agent 来围栏 kill;
- 使用 ctx.jobs.get(...) 读取作业,绝不使用 ctx.jobs.read(...):read 会消耗作业唯一的输出游标,并会静默取走模型的 job_output 永远看不到的字节;
- 对于已离开 running 状态的作业,报告 already-finished,否则调用 ctx.jobs.kill(...),并在 requested 时投递通知。
浏览器部分(src/client/)遮蔽内置的列表条目并添加悬停交互。它仅通过那一个 POST 与注册表通信;作业状态仍通过推送的 jobsBySession 镜像到达,因此不涉及轮询或乐观行状态。
配置
- id: job-stop
name: "@gorban/dsh-job-stop"
config:
notice: wakeup # 或:quiet
maxConsecutiveWakes: 3 # 该插件可在其自身输入之间为每个 agent 开启的轮次
| 选项 | 默认值 | 含义 |
| --- | --- | --- |
| notice | wakeup | wakeup 会在空闲的所属 agent 上开启一个轮次,使其立即得知(一次模型请求,与 dsh-tool-jobs 为其自身完成通知提供的默认行为相同)。quiet 会让该账户保持待处理状态,直到其他事件唤醒该 agent。无论哪种方式,忙碌的 agent 都会被注入。 |
| maxConsecutiveWakes | 3 | 在该 agent 自身的人类输入之间,该插件可在单个 agent 上开启的轮次数。与 dsh-tool-jobs 中同名限制保持一致,原因也相同:一阵停止不应各消耗一次模型请求。超出预算后改为注入账户,因此模型仍会得知——只是不会为此被唤醒。 |
要求
每个依赖项都由该插件所运行的 dsh 安装提供,并从宿主机的模块图中解析——该插件不将自己固定到任何 harness 构建:
| 运行时 | 用途 |
| --- | --- |
| ctx.jobs、ctx.agents | 注册表和所有者围栏 |
| ctx.connection.fetch | 已认证路由(@deepseek-ai/dsh-client-connection) |
| @deepseek-ai/dsh-jobs、dsh-session、dsh-llm、schemastery | 作业/会话 id、带标识的通知消息、配置 schema |
| @deepseek-ai/dsh-client-ui-primitives、dsh-client-ui-slots、dsh-client-locale、dsh-client-ui-conversation、React | 列表、对话框和插槽契约 |
这些被刻意不声明为 peerDependencies。声明它们会使独立的 pnpm install 尝试从 npm 获取 harness 包,并且至少有一个已发布的版本范围目前会解析到一个构建,其依赖树依赖于 @deepseek-ai/dsh-type-meta,而该包不在公共注册表上。因此,该插件安装时完全不需要对 harness 代码进行网络解析。
开发
pnpm install
pnpm build # 宿主部分 -> lib/index.js,浏览器部分 -> lib/client.js
pnpm test # 构建,然后运行宿主部分行为测试套件(node --test)
两半都由 tsdown 通过 build/tsdown.client.ts 构建,它将浏览器包输出为一个 window.__ModuleLoader__.load({ id, factory }) 闭包,其 id 是本包发布时的名称——浏览器模块系统会拒绝注册任何其他 id 的包。
发布
npm version patch # 或 minor/major;提交并打标签
git push --follow-tags
然后为该标签发布一个 GitHub Release。这一个操作会附加预构建的 dsh-job-stop.tgz 资源(上面的 tarball 安装路径指向它),并且一旦设置了 NPM_PUBLISH_ENABLED,就会发布到 npm。发布说明就是插件市场在更新时展示的内容,所以要为用户而写,而不是当作提交日志。.github/workflows/release.yml 记录了必须一次性配置好的 npm 可信发布者设置。
客户端这一半不会被构建进行类型检查(npm 上已发布的 rc 包早于槽位契约以及本插件所针对的 jobsBySession 镜像)。若要改为针对真实检出进行类型检查:
DSH_CHECKOUT=/path/to/deepseek-harness node scripts/typecheck-harness.mjs
该项目横跨插件和 harness 源码,并且仅在本仓库 src/ 内的错误上失败;harness 自身的 guest 诊断会作为一条说明报告。在改动槽位注册或宿主路由之后值得运行它,因为这两处正是过时的已发布类型会掩盖真实错误的地方。
已知限制
- 只有 running 行提供停止操作。 stopping 任务已经在结束中;再次提供停止它只会是对同一结果的第二次请求。
- 对话框重述的是注册表所发布的内容。 对于 bash,那就是完整命令(args.command,未截断),这正是对话框值得打开的原因。如果生产者发布的是截断的标签,对话框就只能拿到那个。
- 没有活跃 Agent 的 Session 无法停止其任务(409)。终止操作由那个确切的属主实例所限定,猜测一个实例会构成授权漏洞。
- 停止任务不会从记录中移除其 run_in_background 卡片;该卡片从来就不是实时更新的,而列表才是结果可读的地方。
- 该遮蔽依赖一个单元格 id。 如果上游重命名了 job-list 槽位条目,本插件的条目就不再替换它,两个列表都会渲染。修复方法是把这里的 id 改一行。
- 记录的终止原因是固定的英文字符串(stopped by the user from the background-job list),保持稳定以便在日志和任务的最终 detail 中可被 grep;它不是面向用户的文案。
许可证
MIT