前言¶
DeepSeek Harness(简称 dsh)是 DeepSeek 开源的 Agent 运行时,核心理念是「一切皆插件」:模型、工具、会话、沙箱、调度和 UI,都可以在配置层替换或扩展,而不必改 Harness 核心源码。网页端日常使用时,智能体一旦调用 write / edit 改文件,对话里就会出现一块默认的 Diff 卡片(官方组件叫 DiffBlock)。文件不大时还能扫一眼;改动一多,行号错位、词级变化看不清、超长上下文把页面撑满,审阅成本会明显上去。
社区维护者 lehhair 做了一款界面增强插件 dsh-diff-viewer,专门接管这两类工具调用的 diff 渲染。它不改 Harness 核心,装上之后把展开后的 diff 卡换成 PiUI 风格的查看器,卸掉即还原官方行。下面按目录页和 GitHub 仓库交叉核实后的信息,说明它是什么、怎么装、怎么用。
需要先说明两点背景。第一,DeepSeek Harness 目前仍是开发者预览版,核心插件和 API 还会变。第二,DeepSeek Harness 插件库 是独立的社区目录,用来检索和对照安装命令,与 DeepSeek / 幻方没有官方从属关系,不能当成官方应用商店。
这是什么¶
dsh-diff-viewer 是一款面向 DSH 网页界面 的界面增强插件,由 lehhair 维护,仓库为 lehhair/dsh-diff-viewer。npm 包名是 @dsh-external/dsh-diff-viewer,当前版本 0.1.0,主要语言是 TypeScript。社区目录把它归在「界面增强」,GitHub 仓库带有 dsh-plugin topic。截至 2026-08-17,GitHub 显示 17 个 star;目录页上的数字可能滞后,以仓库页面为准。
一句话定位:它通过 ui-tool 的 diff-card 链式槽位,替换 write / edit 工具调用里默认的 DiffBlock,把展开后的差异卡换成 PiUI 风格的 DiffViewer。GitHub 简介里的 “Private” 对应的是 package.json 里 "private": true(未发布到 npm 公共源),仓库本身是公开的。
它解决的问题很具体:官方工具行的外壳保留,只换中间那张 diff 卡。工具行的折叠、状态点、错误摘要仍走官方 FileMutationRow 那一套;真正要看的增删、词级高亮、上下文折叠和大文件渲染,交给插件自己的查看器。
工作机制¶
插件走的是 keyed 接管,不是去改 Harness 源码。
ui-tool 的 tool.call.toolview 槽是开放的 key 域。同一 key 上,更低的 priority 会阴影掉已注册的实现(最低优先渲染)。插件在客户端注册 edit 和 write 两个键,priority 设为 -1,从而接管官方的 FileMutationRow。接管后的行会复用官方 ToolRow 样式,以及 DisclosureRow、StateDot 等平台组件,只把展开后的 diff 卡换成 PiUI 风格 DiffViewer。
这一点和仓库源码对得上:
- 客户端入口
src/client/index.tsx向tool.call.toolview注入上述两个 key。 - 宿主入口
src/index.ts的apply()是空函数,注释写明界面完全在浏览器侧,宿主没有额外行为。 package.json里dsh.client.platform为web,并 inject@deepseek-ai/dsh-client-runtime。cordis.patch.yml只是把@dsh-external/dsh-diff-viewer插入当前 profile 的层栈,这就是简介里说的 host patch:它是 bundle 层的插入,不是给 Harness 打核心补丁。
因此卸载后官方行会回来。源码注释还提到这套 keyed slot 出现在 rc.5 一带;Harness 仍在预览期,后续槽位语义若有调整,需要再对照仓库 README。
diff 数据从工具调用的 callView / resultView 里 card: 'diff' 意图提取:执行中用调用时的 diff,完成后用已经应用的 hunks。如果执行出错、根本没有 diff 卡,插件不会硬画一张空图,而是退回官方行的错误摘要和 IN/OUT 卡。
核心功能¶
以下能力来自仓库 README 与 package.json 描述,不是演示环境里的主观观感。
1、unified 单栏是默认布局。同一条 gutter 并排显示旧行号和新行号,避免左右栏错位。也可以切到 split 双栏(源码里的 viewMode)。容器够宽时会按宽度自动改布局:源码以约 800px 为界,窄栏保持 unified,宽栏切到左右分栏。官方默认约 748px 的消息列会保持单栏;如果同时使用同一维护者的 dsh-home-ui 并把信息流放宽,diff 会跟着变成分栏。纯新增或纯删除会强制 unified,避免另一侧完全空白。
2、变更条和行背景。新增是实心绿条,删除是条纹红条;行背景会延伸到当前最宽的那一行,扫块状改动时更清楚。
3、词级高亮。行内改动叠加绿 / 红标记,并用 Shiki 做语法着色(README 称为 highlightLines)。依赖里能看到 shiki、@shikijs/langs 和 diff。
4、上下文折叠。连续未变更行会收成「N 行未变更」,可以向上、向下或全部展开,不必把整份文件铺开。
5、窗口化渲染。固定行高做窗口化,大 diff 不会一次性挂载全部行。展开后的 diff 不限制高度、也不套一层滚动容器,内容直接撑开;横向滚动条是 sticky 的,悬停时才显现。
6、复制和页脚统计。支持复制,页脚格式为 └ +A -R · N file(s),用来看新增、删除行数和涉及文件数。
安装与启用¶
社区目录页给出的安装命令原文是:
dsh plugin add github:lehhair/dsh-diff-viewer
目录页同时提示:如需可复现安装,可写成 dsh plugin add github:lehhair/dsh-diff-viewer#commit。这条命令反映的是目录站的通用写法,不要直接拿来装这个插件。
维护者 README 写得很明确:GitHub 源码里没有构建产物 lib/(被 .gitignore 忽略),而包入口指向 lib/index.js,用 github:lehhair/dsh-diff-viewer 装源码会在启动时报找不到文件。这和官方文档《打包与安装插件》里「git 安装拉到的是源码、不会自动跑 build」是同一类问题。本仓库也没有给 git 安装准备可用的 prepare 构建脚本,开发环境还依赖旁边一份本地 deepseek-harness checkout,不适合当普通安装路径。
推荐:安装 GitHub Release 的构建产物¶
README 推荐每次发版后由 GitHub Actions 打好的 tarball。releases/latest 始终指向最新版,当前已发布的是 v0.1.0(2026-08-15,说明为 devDeps stripped from tarball)。插件声明了 platform: web,应装进 web profile:
# 直接用 latest 资产 URL(永远是最新版):
dsh plugin --profile web add "https://github.com/lehhair/dsh-diff-viewer/releases/latest/download/dsh-external-dsh-diff-viewer.tgz"
# 重启 dsh web 生效
dsh web
如果希望可复现、不想跟着 latest 浮动,把 URL 换成带版本号的资产,例如当前的 v0.1.0:
dsh plugin --profile web add "https://github.com/lehhair/dsh-diff-viewer/releases/download/v0.1.0/dsh-external-dsh-diff-viewer.tgz"
装完后可以用下面的命令确认配置层里已经出现该组合包,再重启正在运行的 Web 服务。只刷新浏览器通常不够,因为宿主代码和浏览器代码都在启动时加载:
dsh --profile web --dump-config
升级时的缓存¶
README 有一条实际限制:pnpm 会按 URL 缓存 tarball。一直用同一个 latest 链接时,仓库发了新版本,本地仍可能命中旧包。升级失败或发现装到旧版时,按仓库说明先卸再清缓存后重装:
dsh plugin --profile web remove @dsh-external/dsh-diff-viewer
pnpm store prune
dsh plugin --profile web add "https://github.com/lehhair/dsh-diff-viewer/releases/latest/download/dsh-external-dsh-diff-viewer.tgz"
pnpm store prune 作用在本机 pnpm store。Windows 上 README 还提到可以删 %LOCALAPPDATA%\pnpm\store 里对应缓存,Linux / macOS 则以本机 pnpm store 路径为准。
卸载¶
dsh plugin --profile web remove @dsh-external/dsh-diff-viewer
卸掉之后重新启动 web profile,write / edit 的工具行会回到官方 DiffBlock。
开发环境(从源码)¶
只在本地改插件时才走源码。README 要求 devDependencies 用 link: 指向旁边的 deepseek-harness checkout,然后:
pnpm install && pnpm run check # typecheck + test + build
dsh plugin --profile web add /path/to/dsh-diff-viewer
Windows 上 dsh plugin add <本地目录> 可能碰到 pnpm link: 的 junction 问题,README 建议先 npm pack 再 dsh plugin add *.tgz。普通使用不必走这条路径。
典型用法¶
装好并重启 dsh web 之后,没有额外的配置项要填。在网页对话里让智能体修改或写入某个文件,展开对应的 write / edit 工具行,默认 DiffBlock 应被 PiUI 风格的 DiffViewer 替换。
可以按下面的顺序自检:
- 让智能体对一个小文件做一次行内修改(例如只改函数名或字符串)。展开工具行后,应能看到词级红绿标记,而不是整行一块色。
- 让它改一个更长的文件,中间夹着大段未变更代码。未变更区应折叠成「N 行未变更」,可以按需展开。
- 把浏览器窗口或信息流拉宽(或搭配
dsh-home-ui的宽屏模式)。容器够宽时,同一份 diff 会从 unified 切到 split;缩回去则回到单栏。 - 故意制造一次会失败的编辑(例如路径不存在)。没有 diff 卡时,应仍显示官方错误摘要,而不是插件自己的空查看器。
同一维护者在 dsh-home-ui 的说明里,把「dsh-home-ui 开宽屏 + dsh-diff-viewer」写成桌面宽屏的推荐组合:信息流放宽后,diff 按容器宽度自动分栏。这是可选搭配,不是本插件的安装前提。
适用场景与注意事项¶
适合谁:已经在用 DeepSeek Harness 网页界面、需要经常审阅智能体 write / edit 结果的人。尤其是改动文件较大、只关心词级差异,或希望宽屏下左右对比的场景。
不覆盖什么:
- 它只接管
edit/write这两个会产出 diff 卡的工具键,不是通用的 Git diff 浏览器,也不替代终端里的git diff。 dsh.client.platform为web,headless / 纯终端 profile 装了也不会出现这块界面。dsh.plugin.json里engines.dsh写的是>=0.0.1,范围很宽,并不等于已经在每一版预览构建上验证过。Harness 仍在开发者预览,槽位和官方 FileMutationRow 若有变化,插件可能需要跟着升级。
安装前务必自己看源码和许可证。插件以当前 dsh 进程的权限运行,安装时也可能执行代码,不在 agent 沙箱里。仓库 package.json 将许可证声明为 BSD-3-Clause;GitHub 仓库页面目前没有单独的 LICENSE 文件,API 的 license 字段为空,不能只凭目录页「社区开源、可免费安装」四个字跳过核对。
另外,package.json 的 "private": true 表示作者没有把它发到 npm 公共源,所以不要去跑 dsh plugin add @dsh-external/dsh-diff-viewer 指望从 registry 拉包。按 README 用 Release tarball 即可。
小结¶
dsh-diff-viewer 做的事情很收束:在 DSH 网页界面里,用 PiUI 风格的 DiffViewer 替换 write / edit 的默认 DiffBlock,保留官方工具行外壳,补上单栏 / 双栏、词级高亮、上下文折叠和窗口化渲染。它是社区插件,不是 DeepSeek 官方组件;社区目录可以当检索入口,真正能用的安装方式以仓库 README 为准——装 Release 构建产物,不要直接 github: 拉源码。
目录页:https://deepseek-harness-plugin.com/zh-CN/plugins/dsh-diff-viewer/
GitHub:https://github.com/lehhair/dsh-diff-viewer