dsh-diff-vis
让 AI 在对话中每修改一个文件,你就立刻看到它改了什么。
DSH(DeepSeek Harness)插件:拦截 write / edit 工具调用,在对话流的工具卡片位置直接渲染 git 风格文件差异——支持上下对比与左右对比,逐行高亮,零 git 依赖(自研行级 diff 算法)。
适合小说创作、文档写作、代码协作等一切让 AI 反复改文件、而你想盯住每一处改动的场景。
特性
| 特性 | 说明 |
|---|---|
| 🎯 零依赖 | 不调用 git、不依赖任何外部 diff 工具;行级 LCS + 前后缀裁剪,纯 JS 实现 |
| 📍 原位展示 | 差异直接渲染在对话流中对应 write/edit 工具卡片上,无需离开对话框 |
| ↕️ 上下对比 | 删除红行 / 新增绿行 / 灰色上下文,@@ 行号块 @@ 头部,git diff 同款布局 |
| ↔️ 左右对比 | 双栏并排;被修改的行在同一水平线左旧右新,行号对齐 |
| ✨ 行内高亮 | 变化的具体词语额外黄底标出(共同前缀/后缀保留),一眼看到"改了哪个词" |
| 💾 偏好记忆 | 你选过的视图(左右/上下)自动保存到 .diff-vis-prefs.json,之后的卡片默认跟随 |
| 🖱️ 点击打开 | 点击卡片头部文件名,直接在工作区打开该文件 |
| 🛡️ 大文件保护 | 超过 4M 差分单元格自动降级为整体替换视图,进程不卡死 |
安装
方式一:命令行一键安装(推荐)
DSH CLI 内置插件管理:dsh plugin --profile <名字> add <包>,它把命令转发给该 profile 目录下的 pnpm,支持 GitHub 仓库、本地路径等 pnpm 支持的全部来源。
# 从 GitHub 直接安装
dsh plugin --profile web add github:roushanyyzz/dsh-diff-vis
安装后:
- 包已装进
~/.dsh/profiles/web/node_modules;本包已声明dsh.bundle(指向包内cordis.patch.yml),dsh plugin add会自动把它加入dsh.profile.bundles组合层并插入插件行,无需手改。 - 若未自动加入(如通过手动 pnpm 安装),可在
~/.dsh/profiles/web/cordis.patch.yml中追加:
- insert:
- id: diff-vis
name: 'dsh-diff-vis'
- 重启
dsh web生效。设置页内通常也有「插件」管理入口(Web UI 设置 → 插件)。
本机参考:
~/.dsh/profiles/web/package.json里已有两个从 GitHub 直装的插件(github:Noob-stupid/dsh-plugin-hub、github:omdsh-dev/dsh-genui),机制与上文完全一致。
方式二:作为动态会话插件(不打包、即用型)
在任意 DSH 会话中对 Agent 说:
读取 dsh-diff-vis/plugin.js 与 src/host.js、src/client.js,
用 cordis_define(kind: 'new', idPrefix: 'difv', name: 'diff-vis',
purpose: '捕获 write/edit 修改并在对话卡片中展示 git 风格差异',
code: { host: <src/host.js 内容>, client: <src/client.js 内容> })
定义插件,然后用 cordis_run 激活(批准 Client 授权)。
特点:无需打包与重启,会话内即时生效;但插件随进程内存存在,重启后需重新定义。适合尝鲜与开发测试。
卸载
卸载命令行安装的版本(方式一)
dsh plugin --profile web rm dsh-diff-vis # 等价于该 profile 下执行 pnpm remove;同时自动从 bundles 组合层移除
然后:
- 若你曾手动在
~/.dsh/profiles/web/cordis.patch.yml里追加过diff-vis的 insert 行,一并删除。 - 重启
dsh web生效。 - 可选:删除偏好文件
.diff-vis-prefs.json(视图偏好记录,位于运行工作区根目录)。
停用动态会话版本(方式二)
在 DSH 会话中让 Agent 执行:
cordis_stop # 仅暂停(定义与授权保留,可随时 cordis_run 恢复)
cordis_undefine # 彻底移除该动态插件(difv-1)
架构
Host(进程侧) Client(浏览器侧)
┌─────────────────────┐ ┌──────────────────────────┐
│ tools/pre-execute │ │ tool.call.toolview │
│ 写前读取旧内容快照 │ diff.v1.* │ key: 'write' / 'edit' │
│ tools/result │ ← JSON RPC → │ · 拉取本次差异记录 │
│ 写后计算行级差异 │ │ · 渲染 unified / split │
│ harness.handle │ │ · 视图偏好 get/setPref │
└─────────────────────┘ └──────────────────────────┘
数据流:AI 调用 write/edit → 插件在执行前读取磁盘旧内容 → 工具执行成功 → 计算行级 diff(旧 vs 新)→ 控制台卡片通过 RPC 拉取并渲染。
使用
满足以下任一情况,卡片即自动出现:
- AI 调用
write写入新文件 → 显示全部新增(绿色) - AI 调用
edit修改已有文件 → 显示精确的删行/增行与行内变化
卡片操作:
- 右上角 上下对比 / 左右对比 切换视图;选择会被记住,之后的卡片默认使用该视图
- 点击卡片头部文件名在工作区打开文件
注:
write/edit工具卡片的默认样式会被本插件的卡片替换;若某次调用的修改发生在插件生效前(如插件刚加载),卡片会显示兜底提示。
已知边界
- 差异记录保存在进程中:插件重启后历史卡片显示兜底提示,之后的修改照常捕获
- 目前覆盖
write/edit两个文件改写工具;bash/pwsh等命令产生的文件变化暂不追踪(架构留有扩展点,欢迎 PR) - 每个卡片最多处理 8 万行输入;超大文件显示"文件过大"提示
项目结构
dsh-diff-vis/
├── lib/
│ ├── index.js # 发布版 Host 入口(ESM,export apply)
│ └── client.js # 发布版 Client 入口(ESM,export apply)
├── src/
│ ├── host.js # 动态插件 Host 半段(函数体文本)
│ └── client.js # 动态插件 Client 半段(函数体文本)
├── plugin.js # 动态插件装配入口(node plugin.js 打印 cordis_define 参数)
├── cordis.patch.yml # bundle 补丁声明(install 时自动插入组合)
├── package.json # 发布包声明(main / exports ./client / files)
├── README.md
├── README.en.md # English README
└── LICENSE # MIT
lib/与src/逻辑一致:lib/是发布/安装形态(ESM 模块),src/是动态会话形态(函数体文本)。改功能时请同步两处。
开发
node plugin.js # 校验动态装配并打印定义参数
No comments yet. Be the first to write one.