pi-edit-fuzzy
pi edit 容错修复钩子:edit 执行前修复 oldText 漂移(空白/缩进/转义/CJK 标点,两档 pass 链),失败后增强错误候选反馈;不替换原生 edit 工具。
Package details
Install pi-edit-fuzzy from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:pi-edit-fuzzy- Package
pi-edit-fuzzy- Version
0.1.0- Published
- Oct 31, 2026
- Downloads
- 373/mo · 373/wk
- Author
- jsonsong
- License
- MIT
- Types
- extension
- Size
- 58.7 KB
- Dependencies
- 0 dependencies · 1 peer
Pi manifest JSON
{
"extensions": [
"./index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-edit-fuzzy
pi 的 edit 工具容错修复扩展:不替换原生 edit,通过 tool_call / tool_result
两个事件钩子,在 edit 执行前修复模型漂移的 oldText(空白/缩进/转义/CJK 标点),
在 edit 失败后增强错误反馈(最近候选 + 相似度 + 行号),把「失败 → 盲重试」循环
压缩为「一次修复命中」。
安装
pi install ./packages/edit-fuzzy # 本地安装(仓库内路径)
pi install npm:pi-edit-fuzzy # 从 npm 安装
pi install npm:pi-edit-fuzzy@0.1.0 # 锁定版本
卸载 = 摘钩子,原生 edit 裸跑,无持久化状态、无文件残留(用户级配置文件除外)。
行为
edit 执行前(tool_call 修复)
- 原生优先:原生精确匹配 / fuzzy(NFKC、行尾空白、智能引号等)能命中的
oldText一律不干预,零开销直通 - 原生找不到时,按档位依次尝试修复 pass;修复 = 把
oldText改写为文件中的 真实文本(改写后必然被原生精确匹配,最终校验与落盘始终由原生完成) - 统一护栏:当前 pass 规则下完整
oldText有多个候选位置 → 不修,转为 歧义反馈;候选 span 远大于oldText(> 3×)→ 拒绝;任何钩子异常 → 静默 放行原生路径(fail-open)
edit 执行后(tool_result 增强)
- 失败(找不到文本):追加最近候选片段 + 文本相似度 + 行号
- 失败(多处命中):追加全部命中行号
- 本钩子判定的歧义:追加候选行号,提示补充上下文
- 成功且有修复:追加一行提示(注明 pass 与 edits 下标),让模型知晓并自我修正
两档修复链
| 档位 | pass | 说明 |
|---|---|---|
| 1(默认) | line-trimmed / whitespace / indentation / escape / boundary / cjk | 确定性变换:行尾空白、行内空格、缩进、字面转义、边界空行、CJK 标点(全量:。,、,《》【】 + NFKC 全角形式,一个 pass 处理完整集合) |
| 2 | 档 1 + block-anchor / context-aware / multi-occurrence / unicode-normalized | 追加启发式:首尾行锚 + 中段相似度、滑窗整体相似度、多候选评分差消歧(top ≥ 0.8 且领先次优 ≥ 0.15)、Unicode 标点归一化 |
档 2 多候选不再直接放弃:先由评分消歧,差值不足才报歧义。档位只影响匹配宽松 程度,统一护栏(候选唯一/偏大拒绝/原生最终校验)两档都在。
配置
启动时初始化一次(session 重启重读);/edit-fuzzy 可随时查看并重读。
用户级 ~/.pi/agent/pi-edit-fuzzy.json(不存在则首次启动自动创建默认值):
{
"level": 1,
"enabled": true,
"log": false
}
项目级 <项目>/.pi/agent/pi-edit-fuzzy.json(只读,字段级覆盖用户级):
{
"level": 2
}
level:1 或 2,缺省 1enabled:false= 钩子全部直通(等价禁用包但不摘载)log:true= 写内测日志~/.pi/agent/logs/edit-fuzzy.jsonl(每次 edit 调用一行,含 pass 触发、原生 edit 异常、钩子自身异常;写失败静默不反噬主流程)- 文件不存在 / JSON 非法 / 字段类型错 → 缺省值 + 一行警告,不阻断加载
命令
/edit-fuzzy # 查看当前配置并从磁盘重读(改文件后免重启)
/edit-fuzzy 1|2 # 切换档位(写入用户级文件并立即生效)
/edit-fuzzy on|off # 开关(写入用户级文件并立即生效)
/edit-fuzzy log # 切换内测日志(写入用户级文件并立即生效)
日志分析(内测):仓库内 packages/edit-fuzzy/test/log-analysis.test.ts 读取该
JSONL 打印 pass 命中率 / 修复有效性 / 漏检样本;pnpm vitest run packages/edit-fuzzy,
日志文件不存在时自动 skip。
限制
- 不做
replaceAll(需改工具 schema,钩子层无法实现) - 只修
oldText,不改写newText(含缩进容错场景:模型把 oldText/newText 缩进一起写少时,新代码可能少缩进,成功提示会提醒模型自查) - 接受极低概率的误匹配残余风险(唯一候选仍可能不符合模型意图);修复后的 diff 查看与验证是最终保障
- 超大文件 / 超长 oldText 会跳过评分类 pass(成本护栏),宁可让原生失败
与上游对比
- 与 pi-semantic-edit 的能力对比
台账见本包
DELTA.md(pass 设计移植自其思想,本包以事件钩子而非工具替换 的方式承接)
License
MIT