Back to home

Dis2017

dsh-run-guard

No description

Stars
1
Language
JavaScript
Created
Aug 16, 2026
Updated
Aug 16, 2026

Introduction

🛡️ dsh-run-guard

DeepSeek Harness 插件 · Agent 运行节奏守护 — 一体两面,让 LLM 在长任务中既不会「推理死循环停不下来」,也不会「想完就停不干活」。

GitHub stars dsh-plugin License


✨ 功能特性

能力方向说明
guard(刹车)拦截推理死循环监听 llm/stream 流,滑动窗口重复率检测 + 硬性上限双保险,死循环在 1~2 秒内被中断(而非空转数分钟),并给出中文原因提示
continue(油门)防止提前停摆turn 正常结束后自动续跑:有未完成 todo 时注入状态续跑;无 todo 但模型「想完就停」(最后只有推理、无正文无工具调用)时注入简洁提示续跑
pause_work 暂停人工控制模型可随时调用 pause_work 工具主动暂停,两路都不会再自动继续

核心设计:刹车与油门共用一套状态感知,互不干扰——guard 中断的 turn 以 error 结束,continue 天然不会误推;continue 推进的新 turn 若再次死循环,guard 立刻拦截。闭环自洽。


🎯 为什么需要它

DeepSeek V4 Flash 配合 reasoningEffort: max 在长任务中会出现两种典型异常:

  1. 想完就停:模型输出完整思考后直接正常结束 turn,没有正文、没有工具调用,留下未完成的任务——表现为「不干活」。
  2. 推理死循环:模型推理进入重复空转(实测单步可输出 10.9 万块、132 万字符垃圾推理),持续数分钟不停——表现为「停不下来」。

DeepSeek Harness 的 agent loop 本身对这两种异常都没有调控机制。本插件在两端补齐:guard 保证它不会无限干活,continue 保证它不会不干活


🧠 工作原理

模型推理流 ──► llm/stream (waterfall) ──► [guard] 滑动窗口重复率 + 硬闸
                                            │ 触发:注入 REASONING_GUARD 错误中断
                                            ▼
                                   turn 以 error 结束(不静默重试,用户可见)
                                            ▲
                                            │ 天然抑制:continue 只在 completed 触发
                                            │
turn/end (completed) ──► [continue] 有 todo → 注入状态续跑(计数上限)
                              └─────── 无 todo + 想完就停 → 注入简洁提示续跑(无上限)
                              └─────── pause_work 已标记 → 不续跑
扩展点用途
llm/stream(waterfall)guard:包装每次模型调用,拦截 reasoning 死循环
session/eventcontinue:跟踪 turn 生命周期、todo 状态、产出判定
systemPrompt.contextcontinue:预防层——有未完成 todo 时注入状态与引导
tools.registercontinue:注册 pause_work 暂停工具

🚀 快速开始

安装(GitHub 发布版,推荐)

dsh plugin --profile web add "github:Dis2017/dsh-run-guard#v0.1.2"

dsh plugin add 检测到包内 dsh.bundle 声明后自动挂载:追加进 profile 的 bundles 列表,插件行由 bundle patch 提供。

验证

  1. 重启 GUI
  2. 打开 设置 → 插件 → Plugin list,确认 dsh-run-guardMounted / Enabled
  3. 正常使用:死循环会被 1~2 秒内中断并显示原因;「想完就停」后会自动收到续跑提示

开发模式(绝对路径挂载,改代码即时生效)

# ~/.dsh/profiles/web/cordis.patch.yml
- insert:
    - id: run-guard
      name: /绝对/路径/dsh-run-guard/lib/index.js?v=1

⚙️ 配置

配置项默认说明
enabledtrue总开关
guard.enabledtrue死循环拦截开关
guard.windowChars2000滑动窗口大小(字符)
guard.substrLen32重复检测子串长度
guard.repeatRatio0.7窗口重复率阈值(≥ 触发)
guard.checkEvery50每 N 块检测一次(降频)
guard.maxBlocks10000硬闸:单次调用推理块数上限
guard.maxChars500000硬闸:单次调用推理字符数上限
continue.enabledtrue自动继续开关
continue.maxAutoFollowups3有 todo 场景连续无产出续跑上限

🧪 测试

pnpm install
pnpm test

54 个单元/集成测试,覆盖:

  • guard 检测器:死循环触发、正常流不误报、硬闸、滑动窗口精确性、极端配置
  • 流拦截:透传、中断、顺序保持、退化降级
  • continue:todo 续跑、想完就停续跑、暂停抑制、计数上限、UI 投影恢复
  • 两 half 集成:guard 中断不误推、continue 推进的新 turn 死循环被拦截

🔧 故障排查

Cannot read properties of undefined (reading 'prepare')

根因:profile 顶层 node_modules 出现了第二份 @deepseek-ai/dsh-tools 副本(通常由插件把 @deepseek-ai/* 放进 dependencies 引起,pnpm hoisted 会提升)。DSH 的 TOOL_RUNTIME_SCHEDULER 是 Symbol,双实例下跨实例读取为 undefined。

修复:把 @deepseek-ai/* 移回 peerDependencies(宿主单例),清理 profile 顶层副本后重启。

cd ~/.dsh/profiles/web
pnpm remove <出问题的插件>
# 确认 node_modules/@deepseek-ai/ 已清空
ls node_modules/@deepseek-ai/
# 重启 dsh web

历史会话打开卡死

根因:死循环推理被全量落盘(单 step 可达 132 万字符),GUI 打开时前端处理巨型事件。

修复:本插件的 guard 保证之后不会再产生;存量会话需清理数据(结构保留、清空死循环文本)或归档。


🤝 开发

仓库结构

dsh-run-guard/
├── lib/
│   ├── index.js      # 合并入口:嵌套配置 + 按子开关挂载
│   ├── guard.js      # 刹车 half:检测器 + llm/stream 拦截 + 中断文案
│   └── continue.js   # 油门 half:自动继续 + pause_work
├── test/             # 54 个测试(guard / stream / continue / index / integration)
├── cordis.patch.yml  # bundle patch(dsh plugin add 自动挂载)
└── scripts/

迭代流程

git commit -m "fix: ..."
git push origin main
git tag v0.1.3 && git push origin v0.1.3
dsh plugin --profile web add "github:Dis2017/dsh-run-guard#v0.1.3"   # 或 remove + add 升级

依赖约定(重要)

  • @deepseek-ai/*peerDependencies(宿主提供单例),绝不能放 dependencies
  • 业务依赖(裸 schemastery 等)→ dependencies
  • 测试用的 dsh 依赖 → devDependencies(镜像 peer 版本,不随安装)

违反此约定会导致上述 prepare 错误。


📄 许可证

MIT © 2026 Dis2017