pi-remote-compaction
v0.1.3
Published
Remote GPT compaction, proactive triggering, and compact TUI transcript retention for Pi
Maintainers
Readme
Pi 远端与预阈值上下文压缩
这是一个面向 Pi 0.82+ 的上下文压缩包,适用于 gpt-* 模型。它的单一包入口会注册两个相互配合的功能:
src/remote-compaction.ts:为 OpenAI Responses API 提供远端不透明压缩,并提供安全的 Chat Completions 兼容路径。src/preemptive-compaction.ts:根据配置,在 Pi 原生阈值耗尽前请求压缩。
二者由包根目录的 index.ts 统一注册,因此 Pi 会将该包作为一个扩展加载。
两个扩展职责分离:
preemptive-compaction 决定何时请求压缩
remote-compaction 决定符合条件的 GPT 模型如何压缩二者不会彼此替代。触发扩展使用 Pi 正常的 ctx.compact() 流程;远端压缩、Observational Memory 以及其他 session_before_compact 钩子仍保留各自的压缩结果和回退行为。Pi 0.82 对多个未取消的钩子结果按加载顺序处理,最后一个已定义结果生效,因此除非明确需要这种顺序,否则不建议同时启用多个竞争性的压缩结果提供者。
模型路由
remote-compaction.ts 不会硬编码 provider 名称或静态模型列表。它仅处理 ID 匹配 gpt-* 的模型:
| 当前模型 API | 行为 |
| --- | --- |
| openai-responses | 使用高保真的 /responses/compact 不透明压缩;保存并回放标准加密 compaction_summary 项。 |
| openai-completions | 兼容路径:先验证 /responses/compact,再通过第二次 /chat/completions 请求生成 Pi 所需的续接文本摘要。两次请求报告的用量和按配置模型估算的成本会合并写入压缩条目。 |
| 其他 API 或非 gpt-* 模型 | 不执行操作;Pi 及其他已安装的压缩钩子继续按原方式工作。 |
如果远端处理失败,钩子会显示脱敏的中英双语警告并返回 undefined,从而保留用户当前配置的 Pi/扩展回退链。
安装
安全提示: Pi 扩展拥有与 Pi 进程相同的系统访问权限。安装第三方包前请先检查源代码。
推荐从 npm 安装:
pi install npm:pi-remote-compaction更新或移除 npm 安装:
pi update npm:pi-remote-compaction
pi remove npm:pi-remote-compaction如需把安装记录写入项目的 .pi/settings.json,请添加 -l:
pi install -l npm:pi-remote-compaction项目级安装可使用 pi update npm:pi-remote-compaction 更新,或使用 pi remove -l npm:pi-remote-compaction 移除。
如果需要为开发或调试安装仓库中的特定修订版,仍可使用 Git 来源:
# GitHub
pi install git:github.com/aloneio/pi-remote-compaction
# GitLab
pi install git:gitlab.com/aloneio/pi-remote-compaction首次安装后请重启 Pi。
如果修改了源码 checkout 中的包代码,请执行 /reload 或重启 Pi。设置会在每个已完成回合边界重新读取,但重启是同时应用包代码和配置变更最稳妥的方式。
如果从旧的独立扩展文件升级,请先从用户或项目扩展目录中删除
remote-compaction.ts和preemptive-compaction.ts,再安装本包。Pi 会分别加载独立扩展和包扩展,保留两份会重复注册钩子。
预阈值触发
Pi 的原生自动压缩在助手回合结束后按以下条件判断:
contextTokens > contextWindow - reserveTokens例如上下文窗口为 272,000 tokens、Pi 使用默认 reserveTokens: 16,384 时,原生阈值约为 255,616 tokens。
如果没有其他适用的用户阈值,preemptive-compaction.ts 默认在当前模型上下文窗口的 85% 触发。对于 272,000 tokens:
231,200 tokens扩展会在每个完成的 turn_end 边界检查,而不是等整个任务完全停止。在 Pi 中,该事件只会在当前批次所有工具调用都产生最终结果后触发。达到阈值后,扩展请求 Pi 的常规压缩操作。
压缩成功后,只有正常完成且包含工具调用的回合才可能提交隐藏续接消息,并且提交前必须确认没有更新的排队输入。真实用户输入始终优先。错误、已中止、因长度停止、无工具调用或所有工具均终止任务的回合不会自动续接。扩展不会有意重跑刚刚完成的工具调用。agent_settled 仅用于恢复会话以及用量/重试边缘情况。
Pi 0.82 不会在 turn_end 暴露内部 shouldCompact() 判断;原生自动压缩会在 agent_end 之后或下一条用户输入前检查。因此本包只在已完成回合边界复现阈值计算,并不实现另一套摘要器。真正的压缩仍由 Pi 的 ctx.compact() 流程完成;之后 session_before_compact 会让 remote-compaction.ts、Observational Memory 或其他钩子选择具体压缩方式,返回 undefined 则保留 Pi 内置回退。仅判断是否需要压缩不会增加模型调用。
设置 usePiNativeThreshold: true 可复现 Pi 的有效原生 reserve 阈值,包括未显式配置时的默认 reserveTokens: 16,384;不设置或设为 false 则保留本包默认的 85%。
Pi 0.82 的公共扩展 API 无法在正在执行的命令中间安全压缩,因为 ctx.compact() 会中止当前 agent 操作。因此这里的“立即”是指当前命令/工具批次结束后的第一个安全边界,而不是命令执行中途。
扩展会在每个边界读取:
~/.pi/agent/settings.json
<当前工作目录>/.pi/settings.json可信项目设置覆盖全局设置。显式的预阈值配置优先于 Observational Memory。扩展会观察已开始的压缩并协作式抑制第二次请求;Pi 0.82 没有公开的跨扩展原子压缩锁,因此这是一项尽力协调规则,而不是排他所有权保证。
触发提示只描述触发行为。完成提示会报告正常钩子链最终选择的压缩方法,以及自动续接是否已提交,或是否因新的/排队中的用户输入而放弃。取消或失败的请求会锁定当前分支叶节点,避免同一分支立即重复失败;分支继续产生新条目后会重新启用检查。
TUI 渲染记录保留
每次成功压缩后,本包只清理旧的 TUI 渲染组件,并保留最新压缩结果和少量最近尾部。它不会修改 session JSONL、生成的压缩摘要或 LLM 上下文。该功能默认启用。只有实际删除了至少一个渲染组件时才会强制重绘;强制重绘可能清除终端 scrollback。
{
"preemptive-compaction": {
"enabled": true,
"thresholdRatio": 0.85,
"usePiNativeThreshold": false,
"clearRenderedContextAfterCompaction": true,
"renderedContextKeepRecentItems": 24
}
}设置 clearRenderedContextAfterCompaction: false 可保留完整 TUI transcript。renderedContextKeepRecentItems 默认为 24;设为 0 时只保留最新的已渲染压缩结果。RPC、JSON、print 模式、session 历史、/tree、导出内容以及未来 LLM 请求均不受影响。
完整的阈值解析顺序、覆盖示例、安全上限以及关闭自动压缩时的行为,请参阅英文技术文档:Preemptive Compaction。
高保真不透明模式
该模式需要同时满足:
- 模型 ID 匹配
gpt-*。 - 该模型在
~/.pi/agent/models.json中配置为api: "openai-responses"。 - 上游支持
POST /responses/compact,并返回:object: "response.compaction";- 加密的
compaction_summaryoutput 项。
模型级 API 覆盖示例:
{
"id": "gpt-example",
"api": "openai-responses"
}Provider 名称不影响路由。仍使用 openai-completions 的模型会走兼容文本摘要路径,无法回放不透明 Responses 项。
扩展会把标准不透明 output 保存到 Pi 压缩条目的 details 中,并在后续每次 Responses 请求前,把自身的 checkpoint 文本占位符替换为该 output。不透明状态同时绑定精确模型 ID 和 /responses/compact endpoint;切换模型或 endpoint 后不会回放。
连续的不透明压缩会携带前一次不透明 checkpoint。如果紧邻的上一次压缩来自其他机制,则下一次不透明请求会明确包含该文本摘要,不会跨过它搜索更旧、已经过时的不透明 checkpoint。
openai-completions 兼容路径会把序列化片段发送到同一配置 endpoint 系列两次:先发送到 /responses/compact 验证兼容性,再发送到 /chat/completions 生成 Pi 可消费的续接摘要。请按此保护配置的 endpoint。当两个响应都报告 usage 时,本包会记录合并 token 数和按配置模型估算的成本。
不透明 compact output 属于敏感会话状态,会保存在 Pi 正常的 session JSONL 文件中。请像保护普通对话历史一样保护 session 文件。
诊断命令
/remote-compact-probe该命令会为当前 gpt-* 模型探测 /responses/compact,并且只把脱敏后的响应结构写入会话。它不会改变压缩状态。探测成功本身并不能证明后续续接和回放一定正确。
可移植性
Pi 0.82 没有公开导出内部 Responses 消息转换器。本扩展会相对于当前 Pi 可执行文件解析它。对于非标准或打包后的布局,可提供绝对路径:
export PI_REMOTE_COMPACTION_CONVERTER_PATH=/path/to/@earendil-works/pi-ai/dist/api/openai-responses-shared.js如果无法解析转换器,不透明模式会安全回退到当前配置的压缩链。
验证
在更改 Pi 版本、provider、模型 API 设置或扩展后,可以运行:
PI_OFFLINE=1 pi --mode rpc --no-session <<'EOF'
{"id":1,"type":"get_commands"}
EOF如需验证不透明模式,请在隔离的真实会话中:
- 创建足够上下文,使
/compact可以工作。 - 在旧上下文中加入唯一标记。
- 执行
/compact。 - 确认压缩条目包含:
fromHook: true;details.kind: "openai-opaque-compaction-v2";- 含
compaction_summary的details.output。
- 在同一会话中询问该标记。
- 重启并恢复会话,再次询问该标记,以验证持久化回放。
对于不支持远端 compact 的通道,请确认 Pi 能通过现有回退链完成压缩、显示中英双语回退提示,并且不记录扩展错误。
