Cell - Ta Changes
Ta 自带的 pi 包(默认开启,可在 Web 客户端的 设置 → 扩展 关闭):每轮回复改动了哪些文件。回复结束后,输入框上方固定显示一个胶囊按钮"N 个文件已更改 +增 −删"(对话里最近一轮改动了文件的回复,撤销后消失),点开是在它上方弹出的改动文件列表(文件名、所在目录、增删行数,Ta 新建的文件标"新建"),点文件在右侧工作台以差异视图打开(改动前后对比,只读);列表底部"撤销本轮改动"把这些文件恢复成这轮回复之前的样子,Ta 新建的文件会被删除。
由三部分组成,都不改 Ta 的核心:
- pi 扩展(
pi.extensions,web-src/extension.ts→extension/index.mjs):edit、write工具(包括 codemode 脚本里的嵌套调用)第一次在本轮写某个文件之前,读下文件当时的内容;回复结束(agent_settled,中途停止也算)时比较每个文件的前后内容,发一条不在对话里显示的ta-changes自定义消息(display: false),details里是改动的文件、增删行数和前后内容的哈希。这条消息只给人看:扩展在context事件里把它从发给模型的上下文中去掉。文件经TA_HOST_EVENT应答里的files(会话执行环境里的文件)读写,所以ssh://远程目录同样适用。 - 服务端(
pi.host,web-src/host.ts→host/index.mjs):按内容哈希保存改动前后的文件内容(<agentDir>/changes/<前两位>/<哈希>,相同内容只存一份,30 天没有再用到的在 ta serve 启动时清理);给页面取对话当前分支上最近的一次改动(latest)、读内容(read)和撤销(revert)。撤销交给该会话的 pi 扩展执行,已撤销的改动记在包数据的reverted键里,所有浏览器看到的都一样。 - Web 扩展(
pi.web,web-src/index.tsx→web/index.js):用ui.setWidget(默认位置aboveEditor)把胶囊和列表放在输入框上方:切到一个对话时向服务端要最近的一次改动,之后随message_end事件更新;撤销说明用registerMessageRenderer画成对话里的一行;差异视图用pi.ui.DiffEditor。
撤销
- 只在 Ta 没有在这个对话里工作时才能撤销;对话需要在 Ta 服务里开着(页面上正显示的对话都是开着的)。
- 文件在这轮之后又被改过(用户手改、之后的回复或别的程序)时先询问:确认后才覆盖,之后的修改会丢失。已经是这轮之前样子的文件跳过。
- 撤销后,对话里加一行"已撤销 N 个文件的改动",这条消息会进入模型的上下文,告诉 Ta 这些文件已恢复,改之前要重新读。
限制
- 记录
edit、write工具写的文件,以及选了别的 coding agent(CodeBuddy Code、Claude Code、Codex,见 ta-agents)时它用自己的编辑工具写的文件:ta-agents 一知道某次调用要改哪个文件(多在执行之前),就经pi.events发TA_FILE_WRITE_EVENT,带上 Agent 给出的改动前文本(ACP 的 diff)时以它为准,否则这时读下文件。bash等命令改动的文件不在列表里,也不会被撤销。 - 增删行数照
git diff --stat的算法;二进制文件不计行数、不显示差异,但能撤销。超过 4 MB 的文件只计数,不保存内容,不能撤销。 - 只在 Ta 服务(ta serve)里工作;单独运行
ta(终端)时不记录。