前言¶
在 DeepSeek Harness(DSH)里跑 Agent 时,常见情况是:模型调用了 browser_tab_new、把 bash 或 subagent 丢到后台、或在 run_code 里起了临时进程和端口,会话结束或任务被打断后,这些资源仍留在宿主机上。靠提示词提醒「记得关掉」并不稳定,也不适合作为唯一治理手段。
dsh-resource-lease(维护者 r-ayin)把「打开即登记、到期或会话结束即回收」做成插件机制:资源在打开时自动或手动写入租约表,归属当前会话并带 TTL;回收由会话销毁、定时扫描和启动补偿等多条路径触发,不依赖模型是否记得收尾。插件在 SkillHub 分类为 admin-security(安全管理),当前版本 v0.0.1,许可证 MIT。
这是什么¶
一句话:资源租约治理——把浏览器标签页、后台 job、进程与端口等待回收对象登记为「会话拥有的租约」,用 TTL 与清扫逻辑自动收回;需要长期保留的条目可升级为 pinned。
- 仓库:github.com/r-ayin/dsh-resource-lease
- 目录页:skillhub.cn/plugins/r-ayin/dsh-resource-lease
- 运行环境:
package.json要求 Node >= 20,依赖 DSH 生态中的cordis、@deepseek-ai/dsh-llm、@deepseek-ai/dsh-tools等 peer 包。
DSH 社区插件由独立目录站点收录,与 DeepSeek / 幻方无官方从属关系;安装前请自行审阅源码与许可证。插件在当前 dsh 进程权限下执行回收(关 tab、杀 job、对进程发 SIGTERM),权限范围与宿主一致。
三层防线¶
下面按 README 中的设计,从登记、回收到策略分层说明。
1. 自动登记(零提示词依赖)¶
通过 tools/result 观察钩子,在资源创建时写入租约,无需在提示词里反复强调「登记资源」:
| 来源 | 租约类型 | 默认 TTL |
|---|---|---|
browser_tab_new |
browser-tab(tabId + 会话) | 240 分钟 |
bash / subagent / workflow 且 run_in_background |
job(jobId) | 360 分钟 |
run_code 等其它资源 |
需 Agent 调用 lease_register |
按登记参数 |
lease_register 支持 kind=process|port|custom;process/port 需带 pid。
2. 自动回收(多触发点冗余)¶
- 会话正常结束:
session/disposed时关闭该会话下全部 session 级租约。 - Daemon 周期扫:默认每 60s 处理 TTL 已过期的租约(会话挂死时的兜底)。
- 启动补偿:宿主启动约 10s 后扫一遍过期账;注册表持久化在
~/.dsh/resource-lease/leases.json(重启后仍能回收遗留项)。 - 浏览器空闲关实例:在
autoCloseBrowser为 true 时,空闲 10 分钟且实查无未登记 tab 才调用 browser 关闭;有未登记 tab 时不关,避免误伤共享 Chrome。
回收执行路径(README 实测说明):
- 浏览器 tab →
ctx.tools.execute('browser_tab_close') - job →
ctx.jobs.kill(jobId, sessionId, reason)(README 注明不宜依赖仅 Agent 作用域可见的job_kill工具) - process/port →
process.kill(pid, SIGTERM) - 资源已不存在(not found / ESRCH / already-finished)视为成功;
'unknown tool'不算成功——连续失败 3 次标failed并停止重试,可在面板中人工处理
3. 分类策略¶
- session(默认):随会话结束或 TTL 自动回收。
- pinned:用户表示「这个留着」时,通过
lease_pin升级,不参与自动回收。 - system:白名单(如 cron/watchdog、外部 Chrome 等不登记项天然豁免)。
Agent 工具面¶
| 工具 | 用途 |
|---|---|
lease_list |
列租约;默认当前会话活跃项,all=true 可看全部 |
lease_register |
手动登记 process/port/custom |
lease_pin |
pinned 升级或降级 |
lease_release |
立即关闭;force=true 时连 pinned 也关 |
lease_sweep |
立即扫一轮;可指定 sessionId 只清该会话 |
典型流程:后台起服务后 lease_register 登记端口与 pid → 任务结束用 lease_list 核对 → 临时资源 lease_release,长期保留 lease_pin。
对话面板¶
插件在 conversation.view 槽位提供 「资源租约」 面板:活跃租约表、单条关闭/固定、清扫过期,约 10s 自动刷新。宿主 HTTP API 路径为 /resource-lease/api/{leases,release,pin,sweep}。
配置¶
默认行为可通过包内 cordis.patch.yml 覆盖,README 给出的项包括:
| 配置项 | 含义(README 默认值) |
|---|---|
sweepIntervalMs |
清扫间隔,60s |
tabTtlMinutes |
浏览器 tab TTL,240 分钟 |
jobTtlMinutes |
后台 job TTL,360 分钟 |
autoCloseBrowser |
是否启用浏览器空闲关闭 |
browserIdleCloseMs |
浏览器空闲判定,10 分钟 |
keepClosedHours |
已关闭记录保留,72 小时 |
修改后按你当前的 DSH 插件加载方式重载配置即可。
安装与构建¶
已抓取资料中未给出 SkillHub 或 README 里的单行 dsh plugin add … 安装命令,此处不凭仓库名拼接命令。请从 SkillHub 目录页 或 GitHub 仓库 按页面说明安装到 DSH 环境。
若你需要从源码构建(README 说明可离线构建、无需 npm install 依赖安装步骤作为主路径):
# 宿主侧
bash scripts/build.sh
# DSH_CHECKOUT 会自动探测 ~/dsh-harness
# 客户端
bash scripts/build-client.sh
# tsc 输出 CJS,并用手工 __ModuleLoader__ 包装
# 开发热重载(DSH 内置流程)
dev_build_plugin → dev_inject_plugin / dev_reload_package
package.json 中 scripts.build 同样指向 bash scripts/build.sh。
适用场景与注意¶
适合:长时间跑 Agent、频繁开浏览器调试、大量 run_in_background job 或本地临时服务的开发与运维场景;需要一眼看到「当前会话占用了什么」并在 UI 或工具里收尾时。
注意:
- 自动登记覆盖 README 列出的钩子路径;其它资源务必
lease_register,否则不会进入租约表。 - 浏览器整实例关闭有「无未登记 tab」安全闸,不能替代你对共享环境的 tab 管理习惯。
- pinned 资源只有
lease_release(且force=true)或人工操作才会释放。 - 安装前检查源码与 MIT 许可证;回收动作与 dsh 同权限,生产环境请评估影响面。
结尾¶
dsh-resource-lease 把 Agent 遗留的 tab、job、进程和端口收成可查询、可 TTL、可固定的租约,用会话销毁、定时扫和启动补偿多条路径做回收,并暴露工具与「资源租约」面板。若你正在 DSH 里治理半自动资源生命周期,可从目录页或仓库 README 安装并核对 cordis.patch.yml。