为什么你的Diff还这么吵?Whiteboard语义Diff查看器:Rust AST差异与WASM插件原理
【免费下载链接】whiteboardopen-source canvas for thoughtful software design项目地址: https://gitcode.com/gh_mirrors/whiteboard36/whiteboard
你的每次提交都在刷屏?成百上千行的红绿交错里,真正重要的改动可能只有二十行。Whiteboard 是一款开源的"深思熟虑的软件设计画布"(open-source canvas for thoughtful software design),它内置了一个用Rust 编写的语义 Diff 查看器:不再按行比对,而是基于 AST(抽象语法树)理解代码结构,把测试、文档、样板改动折叠起来,把大段新增函数概括成伪代码。更妙的是,这套行为完全可以通过WASM 插件系统自定义——本文带你读懂它的原理与上手方法。
一、先认识 Whiteboard:人机共用的设计画布
Whiteboard 是一个桌面应用,让你和 Claude Code、Codex 等编码智能体在同一个工作区里协作设计软件。智能体通过 SDK 在应用内的画布上"画图"——时序图、实体关系图、软件拓扑图——描述它的工作成果。
它的核心理念在 README.md 中写得很清楚:
Diagrams that lead to code:点击画布上的任何可视化元素,可以直接跳转到底层代码。
而解决"Diff 太吵"这一痛点的答案,就在 README.md 的Semantic diff viewer一节:
原始 diff 视图往往噪音很大,所以我们用 Rust 写了一个语义的、AST 感知的 diff 查看器,让你只看与自身相关的代码改动。
二、为什么传统行级 Diff 如此"吵闹"
传统git diff的工作方式很简单:逐行对比文本。这带来三个经典问题:
| 问题 | 具体表现 | 后果 |
|---|---|---|
| 噪音淹没信号 | 一次重命名/格式化波及几百行 | 真正的逻辑改动被淹没 |
| 改动被拆碎 | 同一函数的修改散落在文件各处 | 无法判断"改了什么语义" |
| 无关内容刷屏 | 单测、注释、文档全量高亮 | 评审注意力被稀释 |
评审一个分支时,你最关心的其实只有一句话:"这次改动的行为是什么?"行级 diff 回答不了这个问题,而 AST 语义 diff 可以——它先"读懂"代码结构,再比较结构节点(函数、类型、语句块),而不是字符。
三、原理拆解:Rust 编写的 diffr 引擎
3.1 独立的 Rust 二进制diffr
Whiteboard 没有把语义 diff 塞进前端,而是让一个名为diffr的Rust 可执行文件独立负责全部解析工作。桌面端只是以子进程方式启动它,这一点在 structural-diff.ts 中一目了然:
- 优先使用随应用打包的
bin/diffr(Windows 为diffr.exe) - 也支持通过环境变量
REVIEW_DIFFR_BINARY指向自定义构建 - 启动失败时会给出清晰的诊断信息,而不是静默降级
3.2 NDJSON 流式协议:大仓库也能渐进出结果
diffr与桌面端之间通过NDJSON(每行一个 JSON 事件)通信,核心逻辑见 structural-diff.ts:
--repo <路径> --format ndjson --stream-annotations base head -- file1 file2 ...事件流按序包含四类:
start—— 本次比较涉及哪些文件file—— 某个文件的结构化 diff 结果(边算边发)annotations—— 注释/摘要等增强信息complete—— 收尾,汇报失败数与是否中止
前端对每一行做严格校验(协议解码见 structural-diff.ts),单条记录超过 64 MiB 或出现乱序事件都会直接抛错,保证"宁可报错,不渲染脏数据"。
3.3 并发复用:同一比较只算一次
多个视图(覆盖率统计、编辑器渲染)可能同时订阅同一个比较。structural-comparisons.ts 中的StructuralComparisons用"引用计数 + 事件重放"的方式让所有消费者共享一次计算,并最多保留两个空闲比较结果,兼顾内存与响应速度。
3.4 合理的默认行为
Whiteboard 为语义 diff 内置了一组"降噪默认值":
- 📐大型新增函数 → 概括为伪代码,一眼看懂意图,无需逐行阅读
- 🧪单元测试与文档改动 → 折叠/隐藏,评审时默认不出现在视野中
- 🔍 所有行为均可通过插件与配置重新定义
四、WASM 插件系统:让 Diff 按你的习惯"消音"
4.1 插件配置:一份 TOML 说了算
diffr的可定制性来自它内建的WASM 插件系统。应用会把设置写入标准的 TOML 配置文件(写入逻辑见 diffr-config.ts):
plugins.order = ["bundled.summarize"] plugins.bundled.summarize.enabled = true这意味着插件以 WASM 模块形式加载进diffr,在 AST 处理管线中执行——既保证了跨平台一致行为,又让扩展逻辑与宿主隔离、沙箱化运行。
4.2 内置的summarize插件:AI 伪代码摘要
最典型的内置插件是bundled.summarize:当一段新增代码大到人类难以速读时,插件调用你配置的模型服务,把它压缩成一段伪代码摘要。
在 diffr-config.ts 中可以看到,桌面端会读取diffr提供的配置 schema,动态生成设置页里的:
- provider(模型服务商)与默认模型
- endpoint / API key(也支持从环境变量读取密钥)
- system_prompt(摘要提示词,留空则用内置默认)
- tests(是否对测试代码同样摘要)
而 diffr-config.ts 的保存流程还做了两个工程细节:更换服务商时先清空旧密钥再写入新地址,避免密钥错配到别的供应商;每次写入后主动失效缓存的比较结果,保证新配置立即生效。
4.3 应用内的可视化配置
这些能力在设置页有完整 UI,对应 diffr-config-section.tsx。配置完成后,桌面端还会提供一个"摘要测试":用一份样例 Rust 文件跑一次真实摘要,确认密钥、模型与网络都正常(实现见 diffr-config.ts)。
五、新手上手指南:3 步用上语义 Diff
- 下载并打开 Whiteboard—— 支持 macOS / Windows / Linux,MIT 协议开源,直接运行在你本地的代码检出上;
- 连接你的智能体—— 在欢迎页选择 Claude Code、Codex 等;
- 让智能体评审你的分支—— 例如:"请对比我当前分支与最新的 main,把结果在 Whiteboard 中打开"。
打开结果后,你看到的就是经过 AST 语义过滤的 diff:大函数是摘要,测试是折叠的,而真正的逻辑改动被清晰地呈现出来。
六、源码导读:去哪里看更清楚
想深入原理?按这条路线读源码最顺:
| 想了解的 | 入口文件 |
|---|---|
| 整体理念与默认行为 | README.md |
启动diffr与流式事件循环 | structural-diff.ts |
| 比较结果的并发复用 | structural-comparisons.ts |
| 插件配置与 AI 摘要设置 | diffr-config.ts |
| 流协议的校验解码 | structural-diff.ts |
| 桌面端设置页 UI | diffr-config-section.tsx |
七、总结:把"看 Diff"变成"读意图"
Whiteboard 的语义 Diff 查看器给出了一套值得借鉴的组合拳:
- ⚙️Rust + AST:独立高性能引擎,按语法结构而非文本行比较
- 📡NDJSON 流式协议:大仓库渐进渲染,协议严格校验
- 🧩WASM 插件系统:摘要、折叠、降噪策略全部可插拔、可配置
- 🤖AI 伪代码摘要:大函数压缩成意图,测试文档默认隐身
当 AI 智能体生成代码的体量越来越大,"行级 diff"只会越来越吵。用结构理解改动、用插件定义降噪规则——这正是 Whiteboard 想让你获得的评审体验。
【免费下载链接】whiteboardopen-source canvas for thoughtful software design项目地址: https://gitcode.com/gh_mirrors/whiteboard36/whiteboard
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考