diff 与工具调用可视化 · 看见 agent 在干什么
agent 改一个文件、跑一条命令,你在 scrollback 里看到的那块彩色 diff、那个带计时的工具卡片,是怎么从 ACP 流式事件画出来的。这一章看 grok 的 diff 引擎、工具块类型、渐进式语法高亮,以及流式工具调用如何变成滚动区里的块。
diff 与工具调用可视化 · 看见 agent 在干什么
一个编码 agent 最重要的可视化,就是「它到底改了什么」。这一章看 grok 怎么把工具执行画成你屏幕上那块彩色 diff 和工具卡片。
diff 引擎:拆成独立 crate
算 diff 的纯逻辑已从 pager 里拆出来,成了独立的小 crate xai-grok-pager-diff(原先的 diff.rs 基本原样搬过去),构建 diff 不再牵动整个 pager。它基于 similar::TextDiff,把改动算成 DiffHunk(一串 DiffLine,各带旧/新行号 + ChangeTag)。extract_edit_hunks 从一个 ACP 工具调用里抽 hunk 有三种策略:① 从结构化的 SearchReplace 输出;② 从 ACP 的 Diff.meta;③ 从 old_text/new_text 直接对比(执行前的预览)。同一文件的多次编辑可由 stitch_overlapping_hunks 缝成连续 diff——行号对不上时宁可保留分开的 hunk,也不画出错的内容。
工具块:一个和类型对齐的 sum type
scrollback 里每个工具调用是一个 ToolCallBlock——Execute/Read/Edit/Search/Skill/… 共 13 个变体,大多包一个专属块结构(包括专门展示 send_subagent_message 的 SentMessage)。流式路径上,tool_call_to_block 按 ACP 的 tool_call.kind 分派到对应的块;另有 from_name 按工具名映射(bash→Execute、read_file→Read、apply_patch→Edit……),供通用构造器用。
一个体贴的细节是 VerbGroupKind 的时态感知:连续的同类工具行会折叠成一行标题,比如「Read 3 files」「Searched 4 patterns」——组里还有在跑的就用进行时(Reading、Searching),全部完成后用过去式(Read、Searched),名词还按数量变复数。小事,但让界面读起来像人话。
渐进式语法高亮
编辑块的高亮(edit.rs)有个漂亮的渐进设计 EditHighlightPhase:
HunkOnly:第一次绘制,只按 hunk 用 syntect 高亮(快,立即出画面);Pending→FileScoped:后台 worker 算出全文件作用域的高亮再回填——这样跨越多行的语法结构(一个字符串、一段注释)也能正确着色(删除行仍按 hunk 高亮;主题切换后对不上,就退回 hunk-only)。
超过 EDIT_HL_MAX_BYTES(2 MiB)/ 5 万行就停在 hunk-only,不硬扛。hunk 之间用「… N unchanged lines」占位;默认只显示新文件一列行号,也可以打开 GitHub 式的旧+新双列行号。
「先出个够用的、再后台升级成更好的」这个模式——先 hunk 高亮秒出、再全文件高亮回填——在交互式软件里很常见:先反馈,后精修。它让「大文件 diff 卡一下」变成「立刻有、随后更准」。
流式:ACP 事件 → 滚动区块
最动态的部分是 acp/tracker.rs 的 AcpUpdateTracker——把 ACP 的 SessionUpdate 事件转成 scrollback 变更。工具调用一到:若还在跑,就压一个运行中的块并记进 pending_tools(到达时已完成就直接定稿);ToolCallUpdate 把状态和输出增量灌进那个块(命令输出做增量 UTF-8 解码);Completed/Failed 时 tool_call_to_block 定稿成完整块,编辑块随后排上全文件高亮任务。编辑块还能合并(try_coalesce_edit):同一文件相邻、都已成功完成的多次编辑折叠成一块,并把全文件高亮任务重指到存活的那块——不过这是个灰度开关,默认关闭,要在 [ui] 里打开 collapsed_edit_blocks。
和《从 LLM 到 Coding Agent》对照
教学最小实现里,工具结果就是 print(result)。grok 的增量是把「agent 干活」做成实时、可读、可折叠的可视化:三策略抽 diff、时态感知的动词、渐进式高亮、流式块增量、编辑合并。这是「看得见 agent 在想什么、改什么」——交互式编码 agent 的体验核心。下一章看这一切怎么适配五花八门的终端。
上一篇:输入、slash 与补全 · 下一篇:主题与终端适配