DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

rh666666 /

rh666666/dsh-plugin-debug-mode

Verified

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

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@7c948bdd

dsh-plugin-debug-mode

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

它解决什么问题

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

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

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

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

怎么进入

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

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

敲完回车就开始了:这一条命令会连同你的描述直接开一轮对话,Agent 立刻开始分析, 不需要你再补一句「开始」。描述没写全也没关系——Agent 会先问你现象、期望与复现路径。

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

四个信号

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

调试期间的代码改动

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

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

埋点入口:任何能发 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 还会把端点与哈希已经填好的现成代码片段生成到 .dsh/debug-mode/tasks/<hash>/runtime/probe.http.md,覆盖 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=".dsh/debug-mode/tasks/<hash>/runtime/probe.browser.js"></script>
<script>
  dshProbe('buggy-demo.html:42:onclick', { list: todos.length })
</script>

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

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

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

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

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

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

total 在 items 为空时算成了 null

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

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

收尾会发生什么

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

  1. 按 dsh-debug:probe <hash> 与 dsh-debug:temp <hash> 标记逐块摘除探针与 临时探索代码(摘之前先备份到任务目录的 backups/,但绝不自动还原);
  2. 删除任务目录(日志、状态、探针桩一起消失);
  3. 在回复里给出三类账:修复(保留)/ 探针(已删)/ 临时改动(已还原)。

两件它不会做的事:

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

另外:Agent 可以不进调试

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

状态

v0.0.1 · M0–M6 + §16 的 R1–R6 + HTTP 探针通道全部落地,77 个测试全绿: /debug 与票据闸门、5 个信号工具、日志管道与摘要、唤醒闭环、交互面板、收尾对账、 防堆屎山机制(R1 工作区索引 + 窗口 diff、残留扫描与隔离区、停止规则、欠账看板) 全部就位;浏览器/远程运行时的 HTTP 探针通道也已补齐,整条流程不依赖任何命令。

唯一还没做的是人在真实 GUI 里点一次面板——那一步只有你能做。 详见 DESIGN.md §14 路线图与 §15 待验证清单(10 项里 9 项已闭合, 核实依据都写在那一节)。

先读 DESIGN.md(设计冻结稿)与 AGENTS.md(工程纪律)。

安装

# npm 安装(发布后)
dsh plugin --profile web add dsh-plugin-debug-mode

# 本地开发
dsh plugin --profile web add link:<本目录绝对路径>

安装后在任意会话里敲 /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,修复用 dsh-debug:change。收尾时宿主会拿 「工作区 diff 扫到的东西」和「你自报的清单」对账并点名漏网项—— 以扫描为准,不靠 Agent 自诚实。
  • 调试日志永不长期保存:任务关闭即删除,.dsh/ 自动 gitignore。
  • 面板常驻在输入框上方(conversation.input.dock,文档流兄弟节点, 不会被浮层遮住输入框),按 sessionId 归属,不会串到别的会话去; 默认折叠,只在轮到你复现时自动展开。
  • 调试期间输入框始终可用:按钮只能表达「还在 / 好了」,而「只在切换标签页之后才复现」 这种信息只有打字能说清。输入框里有没发出去的内容时,面板按钮会自动禁用, 免得同一条描述被送两遍。
  • 闸门不会把人卡死:任何硬闸门连续拒绝同一原因 3 次后自动降级为警告并把降级 写进面板;闸门依赖的扫描能力不可用时,面板直接显示「残留检测未生效」。

License

MIT

—/ 5

No ratings yet

Verified DSH bundle

Commit 7c948bdd613c

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