wj-pi-auto-compact

Automatic context compaction extension for Pi

Packages

Package details

extension

Install wj-pi-auto-compact from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:wj-pi-auto-compact
Package
wj-pi-auto-compact
Version
1.0.4
Published
Aug 30, 2026
Downloads
780/mo · 22/wk
Author
bxqyher
License
MIT
Types
extension
Size
53.4 KB
Dependencies
1 dependency · 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

wj-pi-auto-compact

wj-pi-auto-compact 是一个面向 Pi 的上下文自动压缩扩展。当当前模型的上下文使用率达到指定百分比后,扩展会在合适的生命周期节点调用 Pi 公共扩展 API 触发压缩;如果逻辑任务仍在执行,压缩成功后会尝试继续该任务。

扩展可以独立运行,不依赖、导入或探测任何子代理扩展。其他有状态扩展可以按需接入通用协调协议,在压缩前后暂停并恢复自己的会话状态。

功能

  • 按百分比触发:基于 ctx.getContextUsage().percent 判断,默认阈值为 90%
  • 区分任务状态:最终答复结束后只执行空闲压缩;工具任务尚未完成时,压缩成功后尝试继续同一逻辑任务。
  • 避免重复压缩:识别 Pi 已经发起的 thresholdoverflow 原生压缩,不再重复调用 ctx.compact()
  • 保守处理并发事件:外部手动压缩、来源不明确的压缩记录和 Already compacted 错误不会被误判为本次压缩成功。
  • 扩展间协调屏障:通过 Pi EventBus 提供 discoverpreparecomplete 三阶段协调协议。
  • 严格配置校验:拒绝非法 UTF-8、非法 JSON、未知字段、错误类型和越界阈值。
  • 运行时兼容门禁:Pi 版本不满足要求时不注册压缩处理器,并在宿主支持 extension UI 时显示一次警告。
  • 适配多种运行模式:TUI、RPC、JSON 和 print 模式下均执行相同的压缩逻辑。

本扩展不会注册命令、工具、快捷键、widget 或设置界面。安装并启用后,正常使用 Pi 即可。

运行要求

项目 最低要求
Node.js 22.19.0
Pi >=0.84.1,包名为 @earendil-works/pi-coding-agent;已验证至 0.84.2
Git 从 Git 仓库安装时需要

扩展从 Pi 公开导出的 VERSION 获取实际版本,并使用严格的 SemVer 规则检查 >=0.84.1。该范围按 semver 默认规则排除预发布版本,例如 0.84.1-beta.1 不会通过检查。

Pi 扩展以当前用户权限运行,可以访问本机文件和进程。安装任何第三方扩展前都应先检查其源码。

安装

用户级安装

对当前用户的所有 Pi 项目启用:

pi install npm:wj-pi-auto-compact

Pi 会克隆仓库、安装生产依赖,并把包写入用户级设置。

项目级安装

只为当前项目启用:

pi install npm:wj-pi-auto-compact -l

项目级安装会写入当前项目的 .pi/settings.json。其他使用者信任该项目后,Pi 会自动安装缺失的包。

临时试用

只在本次 Pi 进程中加载,不修改持久设置:

pi -e npm:wj-pi-auto-compact

固定到标签或提交的包不会被 pi update --extensions 自动移动到其他版本。

管理安装

# 查看已安装的 Pi 包
pi list

# 更新本扩展
pi update --extension npm:wj-pi-auto-compact

# 删除用户级安装
pi remove npm:wj-pi-auto-compact

# 删除当前项目的安装
pi remove npm:wj-pi-auto-compact -l

使用方法

安装完成后启动 Pi,不需要执行额外命令:

pi

默认情况下,扩展会在某个 turn 结束且上下文使用率达到或超过 90% 时记录一次阈值命中,并根据任务状态选择处理方式:

场景 行为
助手已经给出最终答复 等待真实的 agent_settled,压缩成功后保持会话空闲,不创建新 turn
助手刚完成工具调用,且 Pi 随后开始了真实的新 turn 建立协调屏障并中断当前 run;Pi 静止后执行压缩,成功时尝试注入一次用户可见的 continuation
工具调用后没有出现后继 turn_start 按已结束任务处理,只压缩,不猜测任务需要继续
使用率低于阈值,或 Pi 无法提供百分比 不触发压缩,也不自行估算 token 百分比

TUI 或支持 extension UI 的 RPC 宿主会在开始自动压缩时显示一次信息通知,其中包含触发时的上下文使用率、配置阈值、已用 token、上下文窗口 token 和阈值对应的 token 数。示例:

Context usage is 95% (95,000 / 100,000 tokens). Auto-compaction threshold is 90% (90,000 tokens). Preparing to compact.

JSON、print 或其他 ctx.hasUI === false 的宿主不会增加替代文本输出。

配置

配置文件固定为:

<用户主目录>/.pi/agent/wj-pi-auto-compact.json

这是用户级配置,目前不支持项目级配置、环境变量或命令行覆盖。文件不存在时直接使用默认值,无需手动创建。

完整配置示例:

{
  "enabled": true,
  "maxContextPercent": 90,
  "customInstructions": "请优先保留当前任务目标、已完成的修改、未解决的问题、关键文件路径和下一步计划。"
}
字段 类型 默认值 说明
enabled boolean true 是否启用本扩展的自动触发逻辑
maxContextPercent number 90 触发阈值,必须是有限数值,且 0 < value <= 100;允许小数
customInstructions string 未配置 传给 Pi 原生压缩的补充指令;空字符串或全空白字符串不产生附加指令

三个字段都可以省略,省略时使用对应默认值。例如 {} 等价于不配置自定义指令的默认配置。

配置校验

配置必须满足以下条件:

  • 文件内容是有效 UTF-8。
  • 根值是 JSON 对象,不能是数组、字符串或 null
  • 只能包含 enabledmaxContextPercentcustomInstructions
  • 每个字段的类型和值域必须正确。

customInstructions 会透传给 Pi 的 ctx.compact({ customInstructions }),作为摘要时的补充指令;Pi 仍然使用自己的默认摘要提示词,不会被本字段完全替换。该配置只影响本扩展触发的自动压缩,不影响 Pi 原生的 threshold/overflow 自动压缩。

配置文件存在但校验失败时,扩展会禁用当前扩展实例,而不是带着部分配置继续运行。宿主支持 extension UI 时会显示一次具体原因。修正配置后,在 Pi 中执行 /reload 或重新启动 Pi;配置只在扩展加载时读取,不会在每个 turn 中重复读取。

运行机制

一次典型事务的流程如下:

turn_end 检查使用率
  -> 根据任务状态等待 agent_end 或后继 turn_start
  -> discover / prepare 协调参与者
  -> 等待 agent_settled
  -> 复用 Pi 原生压缩,或调用 ctx.compact()
  -> complete 协调参与者
  -> 必要时发送用户可见的 continuation

空闲压缩

最终答复结束后达到阈值时,扩展会等待 Pi 的真实 agent_settled 再触发压缩。成功后不会发送 continuation,也不会创建额外的模型轮次。

工具任务续跑

扩展不会仅凭助手消息中存在 toolCall 就认定任务尚未结束。只有成功的工具 turn 后又观察到真实的 turn_start,才会建立协调屏障并调用 ctx.abort() 中断当前 run。

压缩和协调都成功后,扩展通过 pi.sendMessage() 发送一次对用户和模型均可见的 continuation:

[wj-pi-auto-compact/v1]
Auto-compaction completed. Continue the interrupted task from the compacted context.

该消息使用 display: truetriggerTurn: true,并通过 details.coordinationRequestId 关联本次协调事务。它继续的是同一逻辑任务,但 Pi 会创建一个新的物理 turn。

扩展会在 5 秒内等待该消息对应的真实 message_start。超时只表示“启动未确认”,不会证明消息没有入队,也不会反向发送错误补偿;迟到的 message_start 仍可完成本地匹配。只有 sendMessage() 同步抛错时,扩展才能确定 continuation 未提交。

与 Pi 原生压缩的关系

本扩展不会关闭或替换 Pi 自带的 threshold/overflow 自动压缩。两者的配置彼此独立:

  • maxContextPercent 控制本扩展何时准备压缩。
  • customInstructions 只用于本扩展最终调用 ctx.compact() 的自动压缩请求;缺失或为空时使用 Pi 默认摘要指令。
  • Pi 的 reserveTokenskeepRecentTokens 等设置仍控制 Pi 自身的压缩策略和摘要内容。
  • 当前事务中观察到同一 branch 上明确的 thresholdoverflow session_compact 后,本扩展认为原生压缩已经完成,不再调用 ctx.compact()
  • overflow 事件带有 willRetry: true 时,Pi 已承诺原生重试,本扩展不会再发送 continuation。
  • Pi 已尝试原生压缩但失败或取消时,本扩展不会额外包一层重试。
  • 用户或其他扩展触发的 manual compaction 不会被当成本事务的成功证据。

压缩摘要、进度指示、取消处理、重试次数和退避逻辑均复用 Pi 的原生实现。

协调协议

扩展通过 Pi EventBus 公开协议 wj-pi-auto-compact/coordination/v1,供其他有状态扩展在压缩前后建立屏障。独立运行时不需要任何参与者。

阶段 请求事件 响应事件 用途
发现 .../discover .../discovered 查找当前 session 中需要屏障的参与者
准备 .../prepare .../prepared 要求固定参与者暂停或保存状态
完成 .../complete .../completed 通知压缩结果并释放屏障

事件完整前缀为 wj-pi-auto-compact/coordination/v1/。协议只传递协议版本、请求 ID、不透明的参与者 ID、屏障标记、业务确认和压缩结果,不传递其他扩展的任务身份或运行时领域数据。

关键语义:

  • 每个事务都会重新发现参与者,session_start 的预发现结果只用于预热。
  • 发现窗口为 100 毫秒;prepare 和 complete 的业务确认期限分别为 12 秒。
  • 只有 requiresBarrier: true 的参与者会进入本次固定成员集合。
  • EventBus 的底层投递成功不能代替 preparedcompleted 业务确认。
  • prepare 被拒绝、超时或状态不确定时,会向全部目标发送幂等的 not_started 以释放潜在屏障。
  • complete 采用全体确认语义;任一固定参与者未确认时,不会发送 continuation,并向全体成员补发 not_started
  • succeeded 只表示压缩已经成功,不保证 continuation 已经交付或模型最终执行成功。

协议类型、解析规则和常量见 src/coordination-protocol.ts,客户端事务实现见 src/coordination-client.ts

许可证

本项目使用 MIT License,Copyright (c) 2026 WJ。

已知限制

这些限制来自 Pi 当前公开扩展 API,扩展只能保守处理,无法完全消除:

  • manual session_before_compactsession_compact 没有请求 ID。本扩展只能结合当前 branch、非 manual 原因和本次 ctx.compact() 的专属回调判断归属。
  • ctx.compact() 没有公开取消句柄或 Promise。正常 session 中,本扩展会持续等待本次调用的 onCompleteonError;session shutdown/reload 只能停止本地等待并释放协调事务,不能保证底层摘要工作已经停止。
  • pi.sendMessage() 的公开返回类型是 void,没有投递回调或撤销 API。匹配的 message_start 只能证明 Pi 已经开始处理,不能保证后续 provider 请求或模型 turn 最终成功。