Skip to content

fix(agent-runtime): feed pi's file-op collector the names it reads - #862

Merged
vastsa merged 2 commits into
mainfrom
fix/pi-file-op-tool-names
Sep 22, 2026
Merged

vastsa merged 2 commits into
mainfrom
fix/pi-file-op-tool-names

Conversation

@vastsa

@vastsa vastsa commented Sep 22, 2026

Copy link
Copy Markdown
Owner

摘要

修 #827 排查时发现的一条缺陷:压缩检查点的文件清单永远为空。修法是在把条目交给 pi 的准备阶段时,把 pi 只认的三个工具名(read / write / edit)转成小写。不 closes 任何 issue。

根因

检查点的 readFiles / modifiedFiles,以及摘要追加的 <read-files> 段,都由 pi 自己的 extractFileOpsFromMessage 产出。它 switch (block.name) 只匹配小写 read / write / edit——即 pi 自己工具的名字;PI-Desktop 注册的是 Read / Write / Edit,于是每次收集都匹配不到任何东西,检查点始终报出空文件清单。

已核实(@earendil-works/pi-coding-agent@0.86.1 的 dist/core/compaction/utils.js,其调用点在 compaction.js 与 branch-summarization.js):整个 pi 包中 "Read" 出现 0 次。

改法(最小改动,只动边界一侧)

新增 packages/agent-runtime/src/pi-file-ops.ts:

  • PI_FILE_OP_TOOL_NAMES = { Read: "read", Write: "write", Edit: "edit" }
  • withPiFileOpToolNames(entries):把交给 pi prepareCompaction 的条目复制一份并改写这三个名字的拼写。

在 runtime.ts::prepareCompactionInput 里接上:prepareCompaction(withPiFileOpToolNames(entries), …)。

三条性质:

  1. 存储字节不变:只返回副本,transcript / 检查点 / 重建上下文都保留我们的拼写。
  2. 常见路径零成本:历史里没有这类调用时,原样返回入参数组(toBe 级别有测试钉住)。
  3. 只转这三个:pi 的收集器不读其它名字,因此 Grep、Glob、Bash、插件与 MCP 名字保持我们注册的拼写,被摘要的文本只在 pi 真正消费该名字的地方变化。

验证

packages/agent-runtime/src/pi-file-ops.test.ts(7 条,全部通过):

  • 适配器本身:三个名字被改写、其它名字与其它消息类型不受影响、不修改入参、返回原数组的零成本路径、能吞下没有 message 的条目与没有 content 的消息;
  • 用真实 pi 的 prepareCompaction 对照:同一段历史,接适配器时 fileOps.read = ["src/a.txt"]、edited = ["src/a.ts"];不接适配器时三个集合都为空(正是这条缺陷的回归锁);
  • 被摘要的工具调用名变为 read / edit,确认改变只发生在拼写层面。

全量:packages/agent-runtime 957 passed(60 文件);pnpm docs:check 通过(508 页,en/zh 双语镜像齐备)。

文档

  • docs/spec/03-runtime/02-agent-runtime.md §5.1(上下文检查点保护)+ zh 镜像:说明文件清单来自 pi 的收集器、以及边界转换;
  • decisions-log D618(en + zh)。

说明

没有采用"把整个工具命名空间改成 pi 的小写拼写"的方案:那是跨 Rust/TS/UI/文档/历史数据的契约级改动,与本次缺陷的规模不匹配;本 PR 是能让收集生效的最小改动。

A checkpoint's readFiles/modifiedFiles, and the <read-files> section a summary
appends, are produced by pi's own extractFileOpsFromMessage, which switches on
the lowercase names read/write/edit — the names pi's tools carry. PI-Desktop
registers Read/Write/Edit, so the collector matched nothing and every checkpoint
reported an empty file list (issue #827 read a compaction report that showed it).

The conversion stays on our side of the boundary: withPiFileOpToolNames copies
the entries handed to pi's prepareCompaction with exactly those three names
respawned, so no stored byte changes and the common path allocates nothing. It
is the smallest change that makes the collection work; the alternative — moving
the whole tool namespace to pi's spelling — is a much larger contract change.

Only those three names are converted, because pi's collector reads nothing else:
Grep, Glob, Bash, plugin and MCP names keep the spelling we register.
Copilot AI lite review requested due to automatic review settings September 22, 2026 08:14

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

…p fixture

The build typechecks the tests too: Entry is a union, so the fixture entries
need an intermediate cast, and prepareCompaction answers a discriminated Result
that has to be narrowed before value is read.
@vastsa
vastsa merged commit 13e9c68 into main Sep 22, 2026
5 checks passed
@vastsa
vastsa deleted the fix/pi-file-op-tool-names branch September 24, 2026 01:54

This branch was previously deployed

1 inactive deployment
Preview — 35c35429 Deployed Sep 22, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants