[控场AI]
· 7 分钟阅读· 3,615 字

AIClaw多文件审阅升级:停靠标签页保持阅读位置

AIClaw多文件审阅升级:停靠标签页保持阅读位置

AIClaw 通过停靠式多文件标签与独立阅读状态,让审阅切换不丢失上下文。

AIClaw 在 v3.7.11 引入停靠式阅读区域与多文件标签页,v3.7.12 补充每个文件独立的阅读状态,旨在解决多文件审阅中切换标签丢失上下文的问题。应用把阅读器放在聊天窗口旁,普通窗口会自动扩展最多 640 像素并在关闭后恢复,最大化与全屏则跳过调整。每个打开的文件拥有自己的视图、diff 布局与滚动位置,缓存复用不触发磁盘刷新,需重读要用 Refresh、对比变更记录要用 Compare。针对后台读取完成的竞态,状态仓库用请求标识符校验标签与会话归属,避免抢走用户当前选中的标签。冒烟测试覆盖了标签复用、位置恢复、迟到结果忽略等场景,但套件总数并不等于标签专项测试数,也不证明各平台原生窗口行为。

多文件审阅的痛点:标签切换丢失上下文

审查一个 AI Agent 的工作产物,往往需要在多个文件之间来回跳转:一份 Markdown 说明、一段 SQL 查询,以及连接两者的变更记录。如果每次切换都丢失阅读位置、或者替换掉你正在核对的对话,预览功能的价值就大打折扣。

AIClaw 在 v3.7.11 版本中引入了停靠式阅读区域,支持多文件标签页;随后的 v3.7.12 补充了每个文件的独立阅读状态。相关变更已于 10 月 13 日发布,最新公开版本 v3.7.14 仍保留这套实现。早在预览与变更记录分离的文章中,作者已解释过两种视图各自的定位。本篇聚焦于另一个工程问题:如何在多文件之间移动时,让审阅过程保持可用。

在对话旁边开辟阅读空间

应用程序布局把阅读器放在聊天窗口旁边。App.vue 的布局设计让聊天始终挂载,而阅读区域独立展示当前选中的文件。

对于普通窗口,Electron 宿主进程会尝试增加最多 640 像素的宽度,上限受当前显示器可用区域约束。它会记住原始的水平位置和宽度,在阅读区关闭时恢复——同样受可用显示区域限制。

最大化与全屏窗口会跳过这次自动调整。小屏幕上每个面板的空间依然有限:停靠并不会凭空创造屏幕容量。它的真正价值在于,当空间允许时,让对话与文件同时可见。

Electron 是一个用 Web 技术(HTML/CSS/JavaScript)构建跨平台桌面应用的框架,其架构分为主进程与渲染进程两层。主进程运行在 Node.js 环境中,拥有操作系统级能力,负责创建窗口、管理菜单、访问文件系统以及控制窗口尺寸与位置;渲染进程则相当于一个浏览器页面,负责界面渲染。两者通过 IPC(进程间通信)交换消息。文中提到的宿主进程代码指向主进程入口,因此它才有权限调整窗口宽度、记录原始位置并在关闭阅读区后恢复。这种职责划分也解释了为什么窗口尺寸调整发生在主进程,而阅读状态则保存在渲染进程的状态仓库中。

每个打开的文件都有自己的位置

预览状态仓库维护一个文件预览数组和一个独立的活跃选中项。打开当前会话中已存在的文件时,会复用其标签页和缓存内容;不同文件则分配新标签页。

标签栏支持鼠标选择,也支持键盘操作:左右方向键、Home 和 End。关闭活跃标签页会选中相邻标签;关闭非活跃标签不会影响当前选中项;关闭最后一个标签则收起整个阅读器。

缓存复用带来一个实际后果:再次打开同一文件并不是从磁盘刷新。需要重读文件时,请使用 Refresh;Compare 则在所属会话中查找该文件最新的变更记录。这两个操作彼此独立——切换标签并不会把一个历史快照变成磁盘上的当前文件。

视图与滚动位置绑定存储

阅读器组件把当前视图、diff 布局和滚动位置一并存入文件的预览状态。

位置键是分开的:源码、渲染后的 Markdown、变更前后的快照,以及每种 diff 布局各自独立。这一点很关键——渲染后 Markdown 中的位置无法可靠映射回源码位置,统一 diff 与并排 diff 的几何结构也完全不同。

设想一个典型工作流:在渲染模式下读到报告的中段,切到 SQL 文件查看统一对比模式,再返回报告时仍停留在渲染位置。切回 SQL 时,之前选择的对比布局同样保留。水平和垂直位置都会被记录。

这些状态属于内存中打开的阅读标签页。关闭标签即移除状态;切换会话或离开聊天视图会清空阅读区域。它不承诺重启应用后恢复打开的文件,也不应把刷新文件理解为内容变化后仍保留精确的语义位置。

统一 diff(unified diff)与并排 diff(side-by-side diff)是两种常见的差异展示格式。统一 diff 将删除行与新增行放在同一列,用前缀标记区分,行数紧凑、适合窄面板;并排 diff 则把旧版本与新版本分列左右,便于逐行对照,但需要更宽的显示空间。两者对同一处变更所对应的行号、行高与滚动偏移完全不同,因此无法共用同一个滚动位置。文中强调每种 diff 布局独立存储位置键,正是为了避免在切换布局时把位置错误地映射到另一套几何结构上,导致阅读跳位。

后台读取不应抢走你的下一个标签

多标签引入了一个单预览无法清晰表达的竞态条件。假设文件 A 仍在加载,此时你选中了已加载完成的文件 B。A 的最终结果应该更新 A,而不应把选中项从 B 抢回来。

状态仓库为每次读取分配一个请求标识符。读取完成时,它检查对应标签是否仍然存在、会话是否仍然匹配,然后更新标签而不无条件激活它。读取期间被关闭的标签,其结果会被忽略;来自此前会话的结果,不会在新对话中重新打开那个会话的阅读器。

这些检查保护的是响应与目标标签之间的关联,但它们并不会取消底层读取,也不构成独立的文件系统权限机制。

竞态条件(race condition)指多个异步操作的完成顺序不确定,从而导致结果依赖于时序的缺陷。在多标签场景中,用户先触发文件 A 的读取、随后切到已加载完毕的文件 B,如果 A 的读取结果回调不加判断地设置当前选中项,就会把视图从 B 强行拉回 A——这就是典型的竞态。文中用请求标识符(request identifier)为每次读取打上唯一标记,完成时先校验该标签是否仍存在、会话是否仍然匹配,再决定是否更新。这一模式把"响应归属哪个请求"显式化,是前端异步状态管理中处理迟到响应的常用手段。

测试覆盖与边界

公开的桌面冒烟测试使用真实的 Vue/preload 接口配合 fixture 宿主响应,覆盖了以下场景:标签复用不触发额外读取、恢复源码与渲染滚动位置、保留统一 diff、键盘切换、后台完成不改变选中项,以及忽略已关闭标签的迟到结果。

v3.7.11 的发布说明记录了 104 项工作界面检查及模拟窗口边界用例;v3.7.12 记录最终总计 133 项工作界面检查。这些是套件总数,而非标签页专项测试的数量。它们并不能证明每个操作系统、每种显示器排布下的原生窗口行为。作者表示,本文基于对标记版本实现与测试定义的检视,并未重新运行这些套件。

冒烟测试(smoke test)是一种覆盖范围较宽但深度较浅的测试,用来快速确认系统的主要功能路径能否跑通,而不是穷尽所有边界与组合。它通常作为构建或发布前的第一道闸门,失败即意味着存在明显问题。文中的桌面冒烟测试使用真实的 Vue 与 preload 接口,配合 fixture 宿主响应来模拟窗口环境,从而在不启动完整 Electron 宿主的情况下验证标签交互。需要注意,冒烟测试通过只说明核心路径可用,并不能替代针对每个操作系统、每种显示器排布的原生窗口行为验证。

这次变更的意义

真正有用的改变是审阅过程中的连续性:每个打开的文件保留自己的视图与位置,异步工作只更新它所属的文件,而不替你决定接下来该读什么。

对于需要频繁在文档、SQL 与变更记录之间交叉核对的开发者来说,这种连续性减少了重复定位的成本。它没有解决屏幕空间不足的物理限制,也没有承诺跨重启的状态持久化,但在多文件审阅这个具体场景里,把"不丢失上下文"做到了实现层面的闭环。

rss source: How AIClaw Keeps Multi-File Reviews in Place with Docked Tabs

#AIClaw#多文件审阅#停靠标签页#Electron 应用#阅读状态#Agent 工作流#代码审阅工具
分享:

相关推荐