DeepSeek Harness 插件

nicecx/dsh-reset-handoff

Star 数 ★ 0 分类 开发与运行时 收录于 2026-09-02

把 DSH 重置请求经带版本的 JSON 协议交给外部运维 agent:预检快照、重启前成熟度门禁(无待审批、磁盘充足、冷却期)、重启、健康检查与业务恢复,结果投递回发起会话。

安装

# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)

dsh plugin --profile web add github:nicecx/dsh-reset-handoff

装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本——pnpm 默认拦截,所以安装可能停在 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWEDERR_PNPM_IGNORED_BUILDS;dsh 会打印出需要添加的确切键名,把它加进该 profile 的 pnpm-workspace.yamlallowBuilds 下,重跑一次即可装上。放行构建本身就是一次信任判断:请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。

README

DSH 从不自己重启自己。 一个宿主插件,把「重置」请求经带版本号的 JSON 协议交给外部运维 agent——预检快照 → 重启 → 健康检查 → 恢复业务——重启后再把结果投递回发起会话。

为什么需要它

一个长期运行的 DeepSeek Harness(DSH)实例有很多需要重启的理由:重载插件/配置、应用设置、从卡死状态恢复。但 DSH 内部的 agent 不应该自己重启 DSH

  • 重启会杀死发出重启的那个进程,agent 根本没机会看到结果;
  • agent 看不到当前有哪些业务在跑(其他活跃会话、relay 通道、待跑任务);
  • 如果重启失败,没有谁留下来诊断和恢复。

安全的做法是 handoff(托管):DSH 写一个请求,一个独立的外部运维 agent(这里是 Hermes Agent)读取它,带着预检/健康检查/恢复执行重启,再写一个结果,DSH 重启后读回来。

工作原理

[DSH]  agent 调用 reset_handoff(reason)
         │  写 request.json(JSON 协议)
         │  (可选)触发外部执行方
         ▼
[外部] 运维 agent 读 request.json
         │  1. preflight — 快照活跃会话、relay 状态、待跑任务
         │  2. GATE     — 重启前成熟度门禁(见下)
         │  3. restart  — 重启 dsh web 服务(macOS launchd)
         │  4. health   — 轮询 http://127.0.0.1:3080 直到 200(带超时)
         │  5. recover  — 校验 relay/auth-proxy 自愈,列出被打断会话
         │  6. result   — 写 result.json(status done/failed + 各阶段明细)
         ▼
[DSH]  重启后插件读 result.json,把可读摘要投递回发起会话(followup),
        让当初请求的 agent 能继续它被打断的工作。

重启前成熟度门禁

参考执行器在条件不成熟时拒绝重启,检查:

  1. 无待审批/待回答诉求 —— relay pending.jsonpending 列表为空(否则重启会丢审批栈)。
  2. 磁盘空间充足 —— 至少 MIN_FREE_DISK_MB(默认 500MB)。
  3. 冷却期 —— 距上次重启至少 RESTART_COOLDOWN_SEC(默认 60s),防崩溃循环。

任一条件不满足,执行器写 result.jsonstatus: "failed"restart: { ok: false, gated: true }、以及一个列出每个未通过条件的 gate 数组——并且不重启。请求方(或用户)看到确切原因后,自行决定何时安全再试。

工具

工具 用途
reset_handoff(reason, scope?) 提交一次重置请求给外部运维 agent,绝不在进程内重启 DSH
reset_status() 查询最近一次请求及其结果(只读)

两个工具都注册为宿主级,所有会话的 agent 都能在需要重置时调用。

协议(v1)

插件与执行方完全解耦——只共享 ~/.dsh/reset-handoff/ 下的两个 JSON 文件(可用 DSH_RESET_HANDOFF_DIR 覆盖):

request.json(DSH 写):

{
  "schema": "dsh-reset-handoff/request",
  "version": 1,
  "id": "<uuid>",
  "requestedAt": "2026-08-30T12:00:00+08:00",
  "reason": "重新加载插件配置",
  "sessionId": "<发起会话 id>",
  "requester": "dsh-reset-handoff",
  "scope": { "restartDshWeb": true, "healthCheck": true, "recoverInterrupted": true }
}

result.json(执行方写):

{
  "schema": "dsh-reset-handoff/result",
  "version": 1,
  "requestId": "<uuid>",
  "status": "done",
  "startedAt": "...",
  "finishedAt": "...",
  "preflight": { "liveSessions": ["..."], "relay": { }, "hermesJobs": ["..."] },
  "restart": { "ok": true },
  "health": { "ok": true, "checks": [ { "name": "dsh-web http :3080", "ok": true, "detail": "200" } ] },
  "recovery": { "resumed": ["..."], "report": "..." },
  "recoveryAction": {
    "ok": true,
    "attempts": [ { "attempt": 1, "restart": { "ok": true }, "time": "..." } ],
    "diag": { "keyErrors": [], "logTail": "..." }
  },
  "gate": [ { "name": "relay 无待审批/待回答诉求", "ok": true } ]
}

执行方恢复契约(让"recover DSH 本身"真正成立的部分):重启后健康检查不通过时,执行方必须尝试恢复,而不是只报失败:

  1. 诊断 —— 读 dsh web 错误日志尾部,提取关键错误(loader 失败、缺依赖如 undici、EADDRINUSE 多实例、OOM)。
  2. 重试 —— 最多 MAX_RESTART_ATTEMPTS(默认 3)轮重启,轮间冷却。
  3. 观察 —— 每轮重启后留初始化观察期(默认 120s)再判成败。
  4. 报告 —— 结果写进 recoveryActionattempts + diag),让请求方 agent 和人都能看到为什么失败、重试了几轮。

任何读写这两个文件的执行方都能驱动重置——Hermes、自研脚本、云函数。协议就是契约。

安装

dsh plugin --profile <profile> add github:<owner>/dsh-reset-handoff

可选执行方触发:配置 triggerCommand,让 reset_handoff 同时唤起外部 agent(默认无——执行方可改为轮询 request.json)。配置结构见 cordis.patch.yml

执行方(Hermes 示例)

hermes/reset_agent.py 提供了一个参考执行器(纯 Python,零依赖)。它应放在 Hermes 的 profile(reset-agent)里,由 hermes cron run <job> 触发:

python3 reset_agent.py            # 执行五步流程
python3 reset_agent.py --dry-run  # 只打印流程,不真正重启

要求

  • 带 web profile 的 DeepSeek Harness(宿主插件)。
  • 外部执行方能重启 dsh web 服务(macOS launchctl kickstart -k com.dsh.web,或对应操作系统/init 的等价命令)。

License

MIT

内容来自项目 README(GitHub)↗

链接

同类插件

查看整个分类 →

社区评论

评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。