给 DSH Agent 提供 5 种结构化差异比较(text/json/csv/markdown/patch),零依赖只读纯函数,替代重复起 bash 进程调用系统 diff。
ⓘ 此插件是大仓库 omdsh-dev/dsh-toolkit 的子包,星数与活跃度统计的是整个仓库。
- 语言
- TypeScript
- License
- MIT
- 分支
- main
安装
$ dsh plugin --profile web add github:omdsh-dev/dsh-toolkit#path:packages/dsh-tool-diff在终端中运行以上命令,通过 dsh CLI 安装此插件。可在右上角切换 Profile。 第一次用 dsh?看这篇新手教程
对话式安装
帮我安装 DeepSeek Harness 插件 omdsh-dev/dsh-toolkit/packages/dsh-tool-diff:先查看仓库 https://github.com/omdsh-dev/dsh-toolkit 确认安全性,然后执行安装命令并验证插件加载成功。
把这段指令粘贴给 DSH Web GUI 里的助手,由它代你完成安装与验证。
一句话定位
给 DSH Agent 提供一个零依赖的结构化差异比较工具,让 Agent 不用每次都起 bash 进程调用系统 diff,也能对 JSON/CSV/Markdown 做路径级、列级、块级的变更分析。
核心能力
- text action:行级 Myers diff,输出标准 unified diff(
---/+++/@@)与行号化操作列表 - json action:递归比较两个 JSON 值,输出
$.path形式的 add/remove/replace(支持$.user.name、$.items[0]、$['a.b']) - csv action:RFC 4180 解析后按主键或行号位置比较,报告 addedRows / removedRows / changedRows(列级)/ duplicateKeys
- markdown action:识别标题重命名、块路径(如
h2[1]/p[0]),代码块的语言/行数/内容变更单独进codeBlockChanges - patch action:在内存中生成 unified patch 并按 hunk 坐标验证能否应用到 before,校验
valid/targetMatchesAfter,绝不落盘
技术实现
- 语言: TypeScript(零运行时依赖,编译产物
lib/index.js) - 关键依赖:
@deepseek-ai/cordis(Cordis 服务注册)、@deepseek-ai/dsh-tools(defineTool工厂)、@deepseek-ai/dsh-invariants(invariants 服务的 companion 占位) - 架构模式: cordis 插件,通过
cordis.patch.yml在 profile layer stack 插入 row(idtool-diff);apply(ctx)中调用ctx.tools.register(defineTool(...))注册工具;同时导出diff-invariantcompanion 插件登记 invariant 所有权 - 入口文件:
src/index.ts(导出name/inject/apply),各算法分文件text-diff.ts/json-diff.ts/csv-diff.ts/markdown-diff.ts/patch.ts/limits.ts
适用场景
Agent 拿到"对比这两段内容"任务时(配置文件片段 diff、API 响应前后变化、表格行变更、Markdown 文档修订、生成可应用的 patch 又不希望落盘),调用 diff 工具一次返回结构化 JSON 报告,省去每次起 bash 进程,也避免手写对引号内逗号/嵌套数组/标题重命名这些边界条件容易出错的比较代码。
前置依赖与兼容性
| 依赖 | 最低版本 | 说明 |
|---|---|---|
| DSH | >= 0.1.0-rc.8 | 已在 npm @deepseek-ai/[email protected] 隔离 consumer 完成全链路验证 |
| Node | ^22.19.0 或 >=24.0.0 | package.json engines.node |
| Peer 依赖 | cordis ^4.0.1 / dsh-tools / dsh-invariants | 由 profile 层自动治愈安装 |
| 原生模块 | 无 | 纯 JS,零运行时依赖 |
| 平台 | 跨平台 | 不读文件、不联网、不调 git;Windows/macOS/Linux 表现一致 |
安装方式
dsh plugin --profile web add github:omdsh-dev/dsh-toolkit/packages/dsh-tool-diff
配置项
本插件没有全局配置文件,所有行为都通过工具调用参数控制:
| 配置 | 类型 | 说明 | 默认值 |
|---|---|---|---|
action | 必填字符串 | 选择比较模式:text / json / csv / markdown / patch | 无 |
before | 必填字符串 | 原内容文本(任何 action 的输入侧) | 无 |
after | 必填字符串 | 新内容文本 | 无 |
format | 字符串 | 输出格式:unified(text/patch 默认)/ structured(json/csv/markdown 默认)/ both | 按 action 而定 |
context | 0..20 整数 | unified diff 每段上下文行数 | 3 |
key | 字符串 | CSV 主键列名或 1-based 列下标;不传则按行号位置比较 | 不传 → 位置模式 |
delimiter | 字符串 | CSV 字段分隔符,单字符或 tab | , |
ignoreWhitespace | 布尔 | 比较时忽略空白差异(patch action 主动拒绝) | false |
ignoreCase | 布尔 | 比较时忽略大小写(patch action 主动拒绝) | false |
sortKeys | 布尔 | JSON 键排序后再比较和输出,变更列表稳定可复现 | true |
maxChanges | 1..10000 整数 | 单次最多报告多少变更;超出按字节二分截断 | 1000 |
常见问题
Q: 安装后注册了什么工具,能在哪些命令里看到?
A: 在 profile layer stack 里加一条 row id 为 tool-diff 的工具(tool 名为 diff),并附带 diff-invariant companion。dsh --profile web --dump-config | grep tool-diff 应该能输出这一行;headless profile 需要单独再装一次。
Q: 为什么不直接调 bash 或系统 diff?
A: 系统 diff 每次调用都会 fork 一个 bash 子进程(Windows 上尤其贵),且它只懂行级文本:JSON 只能给整段对比,看不到 $.user.name 这种路径级变更;CSV 不知道列对应关系。本插件是纯函数 + 零依赖,一次函数调用返回结构化 JSON。
Q: patch action 会不会真的去改文件?
A: 不会。patch 只在内存里把 hunks 应用到 before 行数组并与 after 逐行比对,输出 valid / targetMatchesAfter / errors。绝不调 git apply、不写文件、不联网。
Q: 输入文件特别大,是不是得先用 shell 切一下?
A: 单侧输入有 256 KiB 硬顶,行数 ≤ 50K,JSON 嵌套 ≤ 64 层,CSV ≤ 50K 行 / 512 列。超限工具层直接报错。输出整体不超过 64 KiB,超出会按 maxChanges 与字节预算二分截断并把 truncated 设为 true。
Q: CSV 里有中文表头、字段内含逗号或换行,能正确比对吗?
A: 能。解析按 RFC 4180:"" 转义、CRLF/BOM、引号内换行都已处理。分隔符可传 tab;不传 key 时按行号位置比,传列名后按主键匹配(keyed 模式下行顺序无关)。
Q: 重复 key 的 JSON 会被静默吞掉吗?
A: 不会。解析时遇到重复 key 由状态机扫描并在结果里以 duplicateKeys.before / duplicateKeys.after 分侧报告,同时把 equal 设为 false,不丢信息。
Q: web profile 装了,为什么 dsh run 调不到?
A: web 和 headless 是两个独立 profile,web 不会自动覆盖 headless。dsh run 默认走 headless profile,所以 headless 那侧也需要 dsh plugin --profile headless add ... 装一次。
Q: 怎么确认这个工具真的能跑?
A: 装完后跑 dsh run "用 diff 工具对比两段文本,让 AI 触发一次调用"。或者直接看 dsh --profile web --dump-config 里有没有 tool-diff 这一行。
上手难度
入门 — 不需要任何额外配置文件或环境变量,只要按 action/before/after 三个必填参数调用即可;所有可选参数都有合理默认值。
已知问题与限制
- 单侧输入 ≤ 256 KiB、最终 JSON 输出 ≤ 64 KiB,超出会按
maxChanges与字节二分截断或在入口直接报错 - 行数 ≤ 50K、JSON 嵌套 ≤ 64 层、CSV ≤ 50K 行 / 512 列;超出直接拒绝
- 单次执行硬超时 2000 ms(
timeoutMs: 2000),Myers diagonal 预算 2000、蛇步总预算 2000 万 patchaction 主动拒绝ignoreWhitespace和ignoreCase(精确文本协议),归一化比较请用textaction- CSV 若 before 或 after 任一侧存在重复主键,结果
equal一定为false,且重复行不参与匹配(行为确定性,避免错配) - 孤立 Unicode surrogate 会在入口被拒绝(
invalid Unicode),避免序列化阶段产生不一致 - 工具参数会写入会话日志,调用方不要传入密码、token 等敏感凭据
DSH 零依赖工具包 collection —— time / encoding / json / calculator / csv / regex / markdown / diff / stat / schema 十个确定性工具,统一入口一键安装。
为什么
DSH 生态仓库持续增长,单插件在 hub 中容易被淹没;collection 分类是辨识度最高的形态。本仓库把 10 个工具插件 vendored 冻结为 pack artifact 快照(各子仓库独立演进,当前源位于 omdsh-dev 组织下),统一工程、统一测试、统一维护。
定位(官方 Profile Bundle 生态方向):本仓库是 collection 与安装辅助仓库——每个子包都是可独立安装/启用/禁用/卸载的 bundle(dsh plugin --profile <p> add <子包>);collection 提供目录、清单与批量安装脚本。meta 包 @deepseek-ai/dsh-toolkit 保留为可选的原子挂载模型(见下文两种运行模型)。
分发边界:根 meta 包保持 private: true,用于 Git/collection 分发,不代表会发布到 npm registry。根目录已提交由当前 src 构建出的 lib/index.js 与 lib/types/index.d.ts,因此从 Git 安装时不依赖消费端 lifecycle;prepack 仍会在生成 pack artifact 前执行完整构建。
工具一览
| 工具 | 能力 | 用例数 |
|---|---|---|
time | ISO 8601 / 时区 / 日历运算 / 时长差 | 65 |
encoding | base64 / url / hex / hash / UUID | 46 |
json | JMESPath 子集查询 | 66 |
calculator | 安全数学表达式求值(无 eval) | 31 |
csv | RFC 4180 解析 / 查询 / 统计(严格引号) | 50 |
regex | 测试 / 提取 / 替换 / 静态解释(worker 硬超时) | 63 |
markdown | HTML↔Markdown / GFM 表格 / 目录生成(白名单安全) | 71 |
diff | 文本/JSON/CSV/Markdown 结构化比较与 unified diff(只读) | 124 |
stat | 描述统计 / 百分位数 / 频数分布 / 相关性(零依赖确定性) | 82 |
schema | JSON Schema 验证 / 路径 / 解释 / 安全 default(零网络零动态) | 125 |
| 合计 | 723 |
架构
dsh-toolkit/
├── src/index.ts # meta 包:相对路径动态导入 10 个子包 apply(),聚合注册
├── packages/dsh-tool-* # vendored 子包(pack artifact 快照,name 保持 @deepseek-ai/dsh-tool-*)
├── scripts/
│ ├── link-deps.sh # 构建期 junction(cordis → vendor/cordis,dsh-tools → packages/core/tools)
│ ├── build-all.sh # 一键构建 10 子包 + meta 包(tsc)
│ ├── test-all.sh # 一键跑 10 子包 vitest(合计用例数)
│ ├── install.sh # meta / 逐包两种挂载模式(含 dry-run)
│ ├── install-web.sh # 独立 bundle 批量安装 → web profile
│ ├── install-headless.sh # 独立 bundle 批量安装 → headless profile
│ └── install-all.sh # web + headless 都装
├── catalog.json # collection 清单(hub collection 分类识别依据)
└── tsconfig.base.json # 共享编译配置(固化踩坑经验)
与实施文档方案 A 的工程化适配:子包为私有 Git/collection 包,peer 名解析在 profile 内不可行, 故 meta 包采用相对路径动态导入(零解析魔法、打包自足);子包 runtime 依赖 (
@deepseek-ai/dsh-tools)在 npm 独立模式(默认)下不依赖 DSH monorepo,monorepo 模式经子包构建期 junction 解析。
安装
仓库位于 omdsh-dev/dsh-toolkit(public)。
独立 bundle 模型(推荐)
每个子包独立安装、启用、禁用、卸载:
# 安装单个工具到 web profile
dsh plugin --profile web add github:omdsh-dev/dsh-tool-csv
# 一次性任务(headless)profile
dsh plugin --profile headless add github:omdsh-dev/dsh-tool-diff
批量安装(collection 辅助脚本,幂等——重复执行不会重复添加):
./scripts/install-web.sh # 全部 10 工具 → web profile
./scripts/install-headless.sh # 全部 10 工具 → headless profile(dsh run 使用面)
./scripts/install-all.sh # 两个 profile 都装
验证与运行:
dsh --profile web --dump-config | grep tool-csv # 行存在即安装成功
dsh run "使用 csv 工具解析 'a,b\n1,2'" # headless 端到端
⚠️ web 与 headless 是不同 profile:web 安装不会自动覆盖 headless;
dsh run默认使用 headless。 Windows 路径使用正斜杠(C:/...)。
npm pack tarball 安装
本地构建后用 tarball 路径安装(不依赖 GitHub):
# tarball 方式(web 为例;headless 同)
npm pack
dsh plugin --profile web add <npm pack 产物 tarball 路径>
meta bundle 模型(可选)
需要一次原子挂载全部工具时,挂载根 meta 包:
dsh plugin --profile web add github:omdsh-dev/dsh-toolkit
dsh --profile web --dump-config | grep tool-kit
⚠️ 若 profile 已单独挂载过同名插件(tool-time/.../tool-diff/tool-stat/tool-schema),挂 meta 包会注册重名报错—— 此时先移除旧插件,或用独立 bundle 模型。meta apply 具备原子性(任一子插件失败时 逆序回滚已注册工具,不残留部分状态)。
手动安装与旧版本兼容
旧场景(monorepo 集成、不支持 Profile Bundle 的旧快照或插件开发调试环境——本地 junction/symlink、手动编辑 profile 层)。
构建与测试
npm 独立模式(默认,推荐):无需 DSH monorepo;npm install(devDependencies 自包含)后即可:
npm run build:all # 10 子包 + meta 包 tsc + 产物完整性验证(无 .ts 残留导入、10+1 个 lib/index.js)
bash scripts/test-all.sh # 10 子包 vitest 全量(723 用例);任一失败整体非零退出
npm pack # prepack 自包含(build:all),tarball 含 lib + 10 个子包
monorepo 模式(可选:源码贡献/旧 snapshot):显式提供 DSH monorepo 根:
export DSH_MONOREPO=<DSH 0.1.0-rc.8(npm)安装路径> # 或作为第一个参数
bash scripts/build-all.sh # link-deps + 10 子包 + meta 包 tsc + 产物完整性验证
bash scripts/test-all.sh
prepack已指向build:all(完整构建 10 子包 + meta),保证 pack artifact 含全部运行入口;根 Git 入口由当前src预构建并提交。 本仓库只在本地验证构建、测试与 pack artifact;不要将这些结果解读为 npm registry 发布或未实际执行的 consumer/profile 验证。
同步 vendored(子仓库有更新时)
把 packages/<name> 与源仓库重新同步(src/tests/package.json/tsconfig/cordis.patch.yml/LICENSE/README.md),并在 README 标注子包版本。
新增工具
见 docs/CONTRIBUTING.md:复制模板子包 → 实现 → 测试 → build-all 验证 → 更新 catalog.json。
许可
MIT
查看使用指南 →
该插件的安装步骤、关键要点、FAQ 与兼容性说明(基于已收录字段派生)。
收录徽章
[](https://deepseek-plugin.org/plugins/omdsh-dev/dsh-toolkit/packages/dsh-tool-diff)把这段 markdown 粘贴到你的 GitHub README,链接回本插件详情页。徽章只声明已被本站收录,不代表安全认证。