DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

rh666666 /

rh666666/dsh-plugin-debug-mode

Verified

完全由 DSH 写的 DSH 插件,用于复刻 Cursor 中的 Debug 模式。

★ 2 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@39ae4feb

dsh-plugin-debug-mode

npm:dsh-plugin-debug-mode · npmjs.com/package/dsh-plugin-debug-mode GitHub:https://github.com/rh666666/dsh-plugin-debug-mode

DSH(DeepSeek Harness)插件:Cursor Agent 式的 Debug 模式。 让 Agent 别猜——它自己在你的代码里埋探针,把现场取回来;你复现一次,然后二选一。

它解决什么问题

「点了保存之后列表偶尔不刷新。」

传统流程是 Agent 读代码 → 猜一个原因 → 改 → 你试 → 没好 → 再猜一轮。 Debug 模式把这件事反过来:先在代码里装仪表,再让现象自己说话。

你:现象描述
 └─ Agent 分析 → 在可疑路径埋探针(每处都带可摘除标记)
      └─ 探针把记录交给宿主,落进 <用户临时目录>/dsh-debug-mode/tasks/<hash>/<hash>.log
           (临时目录不可写时回退到 <你的仓库>/.dsh/debug-mode/,回退会在面板上明说)
           └─ 你复现一次
                └─ Agent 通过「读取日志」拿到摘要(异常全量、分组计数、省略量显式)
                     └─ 面板弹出,你选:
                          [ 问题已解决 ]              → 删日志 + 删掉本次全部探针代码
                          [ 问题复现,需要进一步修复 ] → 日志**保留**(Agent 还没读它)

整个流程不需要 Agent 运行任何命令。 它的动作只有两种:给调试服务发信号 (dsh_debug_* 工具)+ 在你的源代码里埋点/改代码。"跑起来复现"是你的事。 这不是洁癖——有一次真实调试里,工作区所在的 D:\ 归 SYSTEM 所有、当前账号缺 「更改权限」,于是所有 shell 命令在执行前的授权阶段就被系统拒绝了; 而同一时刻编辑文件完全正常。能挡住整个流程的,恰恰是流程本来就不需要的那一步, 所以现在这条被写成了硬约束。

怎么进入

只有一个入口:斜杠命令。

/debug 保存之后列表偶尔不刷新,十几分钟出现一次

敲完回车就开始了:这一条命令会把你写的描述原样作为一条用户消息发出去, 同时由宿主的系统提示注入本次调试的准则(与 Plan 模式同一种形态:模式态走注入、 用户输入走消息)。所以对话里只有你自己说的那句话,不会出现一大段"你没说过"的指令, 也不需要你再补一句「开始」。描述没写全也没关系——Agent 会先问你现象、期望与复现路径。

没写描述时不会凭空发一条消息:票据照签,直接在下一条消息里说现象即可。

不识别对话意图、不做工具栏按钮。埋探针是在改你的代码库,这个动作必须由你显式发起, 不能由模型推断出来。dsh_debug_start 工具必须持有 /debug 签发的票据才放行—— 无票调用一律被宿主拒绝(这是硬校验,不是提示词里的一句叮嘱)。

四个信号

信号 谁触发 做什么
启动调试 /debug 之后由 Agent 调用 首次进入调试模式;生成唯一哈希,创建日志、探针桩与现成代码片段。同一任务的哈希此后不变
汇报埋点 Agent 交卷:记录分析结论与两份清单,然后把球交回给你复现
进一步调试 Agent 开下一轮:这时才清空日志(哈希不变)。注意顺序——用户点「复现」时日志是保留的,Agent 必须先将 dsh_debug_read 读它,再 continue
读取日志 Agent 把日志内容以摘要形式输出给 Agent,无需 Agent 自己去翻文件
结束调试 Agent(由用户「已解决」驱动) 清掉本次任务的全部调试标记(探针/临时块整块删,fix/change 只删注释);证明干净时才删除任务目录

调试期间的代码改动

调试不只是「埋点 → 读日志」——改代码本身也是调试手段,但轮次有讲究:

  • 第 1 轮默认不改代码,只取证。没看到数据之前猜的修法一旦改掉原始行为, 后面的日志就再也证不出真相了。(闸门只在出现 dsh-debug:change 标记时拒绝—— 埋探针本身不算改行为。)
  • 第 2 轮起可以「先按假设改,再埋点验证」,但改完必须再埋点,用日志证明 「改之前复现、改之后不复现」。
  • 探针和修复分开记账:探针用 dsh-debug:probe <hash> 包裹,临时代码用 dsh-debug:temp(tmp 也认),改动用 dsh-debug:change <hash> 标记。收尾时 清掉所有调试标记:probe / temp 整块删除,fix / change 只删标记注释、 代码原样保留——整体 git checkout 回滚是被明令禁止的收尾方式。

产物放在哪

调试产物默认落用户临时目录(os.tmpdir()/dsh-debug-mode/tasks/<hash>/), 和你的工作区分开——所以它不会跟着 git status、不会被编辑器索引、也不会被当成项目文件; 每次任务结束都随任务一起删除。

  • 临时目录不可写时(只读沙箱、受限账号等)自动回退到 <你的仓库>/.dsh/debug-mode/, 并且会显示提示——回退同时写进任务的备注、待办清单与 dsh_debug_start 的返回正文, 不会让你事后发现"日志不见了"。
  • 环境变量 DSH_DEBUG_MODE_TMP 可以把临时根指到别处(工具参数 tempDir 优先级更高)。
  • 代价要说清楚:因为用的是系统临时目录,系统清理临时文件时,在途任务的产物可能 被删掉。那会让这个任务没法继续(日志没了、桩也没了),需要重新 /debug 开一个。

埋点入口:任何能发 HTTP 的语言都一样

写日志这件事只有宿主一份实现。 探针不需要自己格式化时间戳、自己截断、自己数上限、 自己保证字段序——它只要把一条 JSON POST 过去:

# GET 是自检:先确认通道活着,再让用户去复现
curl -s 'http://127.0.0.1:<DSH 端口>/dsh-debug-mode/probe?h=<hash>'

# POST 写一条(只有 probe 是必填)
curl -s -X POST 'http://127.0.0.1:<DSH 端口>/dsh-debug-mode/probe?h=<hash>' \
  -H 'content-type: text/plain' \
  --data-binary '{"probe":"app.py:42:enter","data":{"order_id":"A1"}}'

路径是固定的:/dsh-debug-mode/probe,任务哈希走查询串 ?h=。 宿主地址与端口由插件自己算出来(DSH_WEB_URL,回退到 webServer.port), 所以你不需要告诉 Agent 地址——它拿到的就是一条可以直接用的完整 URL。 只有目标不在本机时(容器里、另一台机器上)才需要把 127.0.0.1 换成可达地址, 路径与哈希一个字都不要动。

dsh_debug_start 还会把端点与哈希已经填好的现成代码片段生成到任务目录下的 runtime/probe.http.md(绝对路径在 dsh_debug_start 的返回里给出),覆盖 curl / Python / Node / Ruby / Go / PHP / PowerShell / Java —— 复制粘贴就能用。

这条通道带来的两件事:

  • 语言无关:字段序、带时区的时间戳、8 KiB 单行截断、16 MiB 总量上限、并发追加, 全部由宿主强制。所以不存在"某个语言的桩把协议实现错了"这种失败模式。
  • 可自检:GET 一眼看出通道通不通。投递是尽力而为的(探针不许拖慢被调试的程序), 所以"通道是死的"与"埋点没执行到"的现象本来一模一样——现在它们可区分。

两条桩还会在加载时自己写一条 debug-mode:ready:

  • 看得到 ready ⇒ 桩是通的 ⇒ 日志里没有你的探针 = 那段代码没走到;
  • 看不到 ready ⇒ 桩根本没被加载 ⇒ 去查 import 路径 / <script src> / 进程重启过没有。

什么时候不走 HTTP

场合 用什么
热路径(每帧 / 每请求上千次) HTTP + 调用方聚合(每 N 次或每 X ms 一条)
进程可能硬崩,要求"崩溃前最后几条必须落盘" Node 文件桩(同步追加,不缓冲)
运行时没有网络栈 按指南 §六 自写文件桩

浏览器页面

如果被调试的是在浏览器里打开的 HTML 页面(尤其是 file:// 直接打开的静态页), 用宿主给的经典脚本桩,把记录 POST 回宿主(走 DSH 自己的 HTTP 载体, 所以你不需要为了调试去起一个本地服务器):

<script src="http://127.0.0.1:<DSH 端口>/dsh-debug-mode/stub.js?h=<hash>"></script>
<script>
  dshProbe('buggy-demo.html:42:onclick', { list: todos.length })
</script>

桩由宿主即时伺服(GET /dsh-debug-mode/stub.js?h=<hash>),所以页面里没有一行指向 某个本地文件——经典 <script src> 不受 CORS 限制,这条通道对 file:// 打开的页面同样 能用,你不需要为了调试去起一个本地服务器。若页面自己的 CSP 只允许 'self',把宿主 origin 加进 script-src,或者把落盘副本(dsh_debug_start 返回的 runtime/probe.browser.js)的内容整段粘进页面里。

记录会按同一份行协议落进任务日志(task 由宿主写死,字段序只有一处真相)。

面板:输入框上方那张可折叠的卡片

从任务创建到任务结束,输入框正上方常驻一张小卡片。它在文档流里(不是浮层), 所以不会挤动输入框、也不可能挡住它;而且默认是收起来的—— 只有轮到你做决定时才自动展开:

▸ 调试模式 · #deadbeef · 第 2 轮 · Agent 正在埋点/排查       312 行 · 48 KB

轮到你了,它自己展开,并且只说两件事——结论一句话 + 你要做什么:

▾ 调试模式 · #deadbeef · 第 2 轮 · 轮到你复现并选择          312 行 · 48 KB

total 在 items 为空时算成了 null

请按这个顺序复现:
  1. 打开保存对话框
  2. 清空标题后点保存
  3. 回到列表页

也可以不用按钮:直接在输入框里描述现象,同样算「还在」。
  [ 问题已解决 ]   [ 问题复现,需要进一步修复 ]
  • 点头部那一行即可折叠/展开;折叠之后那一行仍然说清现在轮到谁。
  • 那份复现清单是 Agent 交卷时给出来的——过去它不存在,你面对"请复现"只能凭记忆 猜一遍当初怎么触发的。
  • 只有等你在面板上做过选择,Agent 才被允许收尾(dsh_debug_end 会校验这一点)。
  • 输入框始终可用:想补充「只在切换标签页之后才复现」这种信息,直接打字就行。 输入框里有没发出去的内容时,两个按钮会自动禁用——免得同一条描述被送两遍。
  • 工作区不是 git 仓库(或 git 不可用)时,面板会直接说 「未检测到 git:收尾只清理你报备的文件」,而不是假装还在保护整个仓库。
  • 宿主不再做全仓扫描,所以大仓库上不会再有「扫描被截断 / 只覆盖一部分」这类降级。

收尾会发生什么

选择「问题已解决」之后,宿主会:

  1. 在账本 + git 改动文件里清掉本次任务的全部调试标记:probe / temp 块 整块摘除,fix / change 只删标记注释、标注的代码原样保留(摘之前先备份到 任务目录的 backups/,但绝不自动还原);
  2. 复扫这些文件,确认不再有本任务标记或 dsh-debug: 记号;
  3. 只有证明干净时才删除任务目录(日志、状态、探针桩一起消失); 没清干净时目录保留,并写一份 residual.json 说明原因;
  4. 在回复里给出两类账:修复代码(保留)/ 调试标记(已清)。

不再遍历全仓库:清理范围 = Agent 报备的文件(probeFiles / changedFiles 等) + git status 看到的改动文件。所以:

  • 有 git 时,Agent 漏报的改动也会被 git 兜住;
  • 没有 git 时只认报备清单——Agent 没报的文件,收尾不会碰;
  • 大仓库不会有「扫描被截断」的问题,因为压根不做全仓扫描。

两件它不会做的事:

  • 不会回滚你的修复。 git checkout / git stash 整体回滚是明令禁止的收尾方式。
  • 不会静默保留。 如果扫到"既不是本次任务、也不能确认是修复"的块 (陌生哈希、残缺标记、配对有歧义),收尾会暂停一次,把清单交回来, Agent 会逐条问你三选一:保留 / 删除(先看 diff)/ 我自己处理。

另外:Agent 可以不进调试

/debug 是你发起的,但它不是契约。如果 Agent 读完代码就看出根因(空指针、 明显拼写错误、缺一次 await……),它应当直接告诉你根因并改代码, 而不是为了走流程先埋一圈探针。票据会自己过期,你下次想调试时重新 /debug 即可。

状态

v1.1 · 全部测试全绿:/debug 与票据闸门、5 个信号工具、日志管道与摘要、唤醒闭环、 交互面板、收尾对账、防堆屎山机制(git 改动检测 + 账本清理、隔离区、停止规则、 欠账看板)全部就位;浏览器/远程运行时的 HTTP 探针通道也已补齐,整条流程不依赖任何命令。

唯一还没做的是人在真实 GUI 里点一次面板——那一步只有你能做。

变更见 CHANGELOG.md,开发纪律见 AGENTS.md。

安装

推荐:在 DSH 的插件管理界面里装。

打开侧边栏的插件页,在安装框里输入包名即可:

dsh-plugin-debug-mode

它会按当前 DSH 版本去注册表取包(默认 npm,取不到时自动换镜像源),装完即生效; 如果有依赖需要构建脚本,页面会把待批的包名列出来,确认后再装。

命令行等价做法:

dsh plugin --profile web add dsh-plugin-debug-mode

需要装指定版本时在包名后加版本号,例如 dsh-plugin-debug-mode@1.1.0。

其它渠道:

# GitHub 直装
dsh plugin --profile web add github:rh666666/dsh-plugin-debug-mode

# 克隆到本地再挂载(改代码调试时最方便)
git clone https://github.com/rh666666/dsh-plugin-debug-mode.git
dsh plugin --profile web add link:<克隆下来的目录绝对路径>

安装期不需要构建,也不需要 node_modules:本插件零运行时依赖,而且 lib/client.js 是提交进 git 的生成物——仓库里已经带着它,所以从 npm 装、从 git 装、 link: 本地挂载拿到的东西是一样的(只有你改了 src/client.js 才需要重跑 scripts/build-client.mjs,见下面的「开发」)。

装完在任意会话里敲 /debug <现象描述> 即可——命令会自动出现在宿主的命令面板里。

开发

node scripts/build-client.mjs      # 生成 lib/client.js(改了 src/client.js 必须重跑)
node --test test/*.test.mjs        # 全部单测(零依赖,会先自动重建客户端产物)

零运行时依赖:插件本体只用 Node 内置模块,因为探针桩会被复制进你的项目里执行。 浏览器半也只有一份手写的 src/client.js,由一个 30 行的构建脚本包成 DSH 要求的 window.__ModuleLoader__.load({ id, factory }) 形式——没有打包器,也没有 node_modules。

设计要点

  • 日志是 JSONL,字段序固定(ts, task, probe, level, msg, data)—— 追加写天然多进程安全,崩溃最多丢半行,grep 依然好使。
  • 探针桩永不抛异常、不持有 fd:可观测性代码不许把被调试的程序搞挂。 单任务日志到 16 MiB 就停止追加(并写一条 debug-mode:overflow), 免得一个跑飞的循环把磁盘写满。
  • 探针代码用 dsh-debug:probe <hash> start/end 包裹,可被机器整块摘除; 临时探索用 dsh-debug:temp(tmp 也认),修复用 dsh-debug:change。收尾时 宿主会把「git 看到的改动」和「你自报的清单」并起来核对——两份都在,不靠单方。
  • 调试日志永不长期保存:任务关闭即删除,.dsh/ 自动 gitignore。
  • 面板常驻在输入框上方(conversation.input.dock,文档流兄弟节点, 不会被浮层遮住输入框),按 sessionId 归属,不会串到别的会话去; 默认折叠,只在轮到你复现时自动展开。
  • 调试期间输入框始终可用:按钮只能表达「还在 / 好了」,而「只在切换标签页之后才复现」 这种信息只有打字能说清。输入框里有没发出去的内容时,面板按钮会自动禁用, 免得同一条描述被送两遍。
  • 闸门不会把人卡死:任何硬闸门连续拒绝同一原因 3 次后自动降级为警告并把降级 写进面板;没有 git 时面板会直说「只按报备文件清理」。
  • 清理不遍历全仓库:清理范围 = 账本(probeFiles / changedFiles / 桩引用 / 还原点)+ git status 的改动文件。没有 git 时只按账本,所以提示词会要求 Agent 把碰过的文件报全;有 git 也不会去读没改过的文件。

License

MIT

—/ 5

No ratings yet

Verified DSH bundle

Commit 39ae4feba7bf

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout