# dsh-ptc-diff-card [简体中文](README.md) · [English](README.en.md) DSH Web GUI 插件:让 **PTC 模式**下的 `edit`/`write` 显示和标准模式一样的 diff 卡片。 ## 解决什么问题 PTC(Programmatic Tool Calling)模式下,agent 在 `run_code` 程序里调用 `edit`/`write`。 这些调用被记录成嵌套的 `tool/ptc-dispatch` 事件,在 `run_code` 卡片下面渲染成通用行: 展开只有结果文本 `The file ... has been updated successfully`,没有 diff 卡片。 官方 Tool 层的 diff 推导在 `packages/client/ui-tool` 的 `diffCardModel` 里,第一行就把嵌套调用排除了: ```ts if (block.parentCallId !== undefined) return null ``` 而卡片需要的数据其实都在——嵌套块上有调用参数(`file_path`/`old_string`/`new_string`/`content`) 和落盘的 `meta.diffs`(已应用 hunks)。 ## 效果 - 嵌套的 `edit`/`write` 行变成标准文件卡片:标题、工作区相对路径、输入大小、`+新增 -删除`; - 展开就是官方 `DiffBlock`:语言标签、换行/复制、路径行、增删着色、`⋯ 其余 N 行` 折叠; - 失败的调用不画 diff,标题显示错误首行、展开是原始输出(与官方一致); - 根调用(标准模式)外观与官方逐字一致,因为整行是照官方实现的复刻。 ## 原理 在 `tool.call.toolview` 这个 keyed slot 上注册自己的 `edit`/`write` 视图,`priority: -1` 覆盖官方行(低优先级渲染),插件卸载自动还原。行本身复刻官方文件行(同一套 `DisclosureRow`/`DiffBlock` 原语 + 一份 vendor 的官方样式表),diff 推导沿用官方逻辑, 只去掉「根调用限定」: | 调用状态 | diff 来源 | |---|---| | 成功 settle 且 `meta.diffs` 非空 | 记录的实际 hunks(路径回写成入参拼写) | | `write` 新建 / 调用进行中 | 由入参推导的整文件 diff | | 失败 / 中断 | 不画 diff | ## 安装 作为普通 DSH bundle 挂到某个 profile: ```sh # 本地目录(开发) dsh plugin --profile add link:D:/dsh-plugins/dsh-ptc-diff-card # 从 GitHub dsh plugin --profile add "github:GrounzerLiu/dsh-ptc-diff-card" # 从 npm(已发布后) dsh plugin --profile add dsh-ptc-diff-card ``` 然后把 `dsh-ptc-diff-card` 加进该 profile `package.json` 的 `dsh.profile.bundles`, 重启应用生效。 ## 兼容性与边界 - 目标:DSH `>= 0.2.1-rc.2`(`engines.dsh`),Web GUI(`platform: web`)。 - 只接管 `edit` 和 `write`;`str_replace_editor`/`apply_patch` 等未覆盖。 - 行样式是从 ui-tool 0.2.1-rc.3 vendor 的一份拷贝,应用大改版后如需同步外观要重新 vendor。 - 与同样以 `priority: -1` 抢占 `edit`/`write` 的插件(如 `dsh-diff-viewer`)不能共存: 同 key 同优先级会被 DSH 拒。本插件会捕获并打日志,让官方行继续接管,不会让整个插件加载失败。 - 不自动展开 diff,行为与标准模式一致。 ## 开发 ```sh pnpm install pnpm run check # typecheck + 纯逻辑断言 + 构建 pnpm run build # 只构建 lib/index.js 与 lib/client.js ``` `source` 结构: ``` src/index.ts 宿主半身:inert 的 Loader 入口(浏览器半身的挂载点) src/client/index.tsx slot 注册(edit/write,priority -1) src/client/row.tsx 行组件(preparing / dispatched-settled 两态) src/client/model.ts 行状态、路径、diff 推导 src/client/tool-row.module.css vendor 的官方行样式 scripts/model-check.ts 纯逻辑断言(Node 原生 type stripping,无额外依赖) ``` 浏览器半身按 DSH 客户端插件格式打包:platform 模块表(`react`、`@deepseek-ai/cordis`、 `ui-slots`、`ui-primitives`…)保持 external,其余内联;CSS Modules 编译成哈希类名 + 一个 `