# pi-background-compaction

在后台提前准备压缩结果，减少上下文压缩带来的等待，让编码任务更顺畅地推进。需要压缩时，Pi 可以复用准备好的结果，而不必从头开始。

[English](README.md) | 简体中文

后台准备和自动应用默认开启。即使检查点最终没有使用，准备过程也可能消耗服务商配额。它可以减少等待，但不保证每次压缩都更快或更便宜。

## 安装

本扩展需要配合兼容的压缩引擎使用，例如 [pi-codex-compact](https://github.com/AHGGG/pi-extensions/tree/main/packages/pi-codex-compact)。本扩展决定何时准备和应用检查点；引擎负责向服务商发送请求、校验检查点和执行恢复流程。

1. 安装或更新兼容的压缩引擎。按照 [pi-codex-compact 的安装说明](https://github.com/AHGGG/pi-extensions/tree/main/packages/pi-codex-compact)操作，并保持引擎扩展启用。
2. 安装本扩展：

   ```sh
   pi install git:github.com/AHGGG/pi-background-compaction@master
   ```

3. 重启 Pi。

请使用支持独立后台扩展的新版引擎，不要同时运行旧版内置的后台控制器。如果 Pi 提示未安装兼容引擎，请更新引擎并重启。本扩展无法单独准备检查点。

移除本扩展不会移除引擎的手动压缩或检查点重放功能。

## 手动启动后台准备

运行 `/background-compaction prepare`，或打开 `/background-compaction` → **Prepare now**。Pi 空闲时立即启动准备；模型/工具正在运行或有排队输入时，只排队一次，在下一个成功完成的模型/工具批次（`turn_end`）捕获完整历史并启动后台准备。两种方式都会跳过 token 和请求大小阈值，不等待提供商返回，主代理可继续工作。

**Background preparation** 必须为 On，操作不会更改已保存的设置。已有有效的 Preparing 或 Ready 结果时直接复用，不重复请求。只有新准备确实可以启动时，才清除本会话的失败暂停。重复操作不会增加排队任务。模型出错时，排队请求保留到后续成功批次；取消、导航、压缩、模型/思考级别或影响准备的设置变化会清除请求。如果在该边界无法捕获历史，请求会被消耗但不启动准备，可再次选择 Prepare 重试。压缩正在进行时仍需等结束后重试。

沿用现有重试次数和 **Apply when ready** 设置。空闲时准备完成本身不会强制应用；结果会在下一个正常安全边界自动应用，也可运行 `/compact` 应用。与 `/compact` 不同，`prepare` 不等待压缩完成，也不会立即修改会话历史。准备可能消耗提供商额度。

## 开始使用

安装后，后台准备、**Apply when ready（准备好后应用）**和进度提示默认开启。运行 `/background-compaction`，打开 **Settings（设置）**即可修改。

成功完成一轮后，以下任一条件达到即可开始后台准备：上下文使用率达到默认 70%，或兼容传输扩展报告完整请求达到默认 **13 MiB**。准备期间，你可以继续工作。

在 `/background-compaction` → Settings → **Full-request size threshold** 中修改大小阈值；对应 `asyncRequestSizeMiB`，范围为 1–32 的整数，1 MiB = 1,048,576 字节。需要更新 `pi-chatgpt-zstd` 到支持 `pi.request-context-size.v1:observed` 的版本。没有该信号时，原有 token 阈值仍正常工作。即使发送的是较小的增量，也统计完整序列化 WebSocket 请求的 UTF-8 字节，包括图片和工具输出。

这只是预防性触发器，不是服务端上限，也不会在发送前阻止请求。它沿用现有成功轮次结束边界；单个大批次仍可能在摘要准备前超限。不新增 1009 恢复、不删除图片、不切换传输、不修改现有请求大小限制。大小观察只用于当前轮次，在压缩、导航、模型/会话变化、取消或失败后失效。

准备好的检查点有两种使用方式：

- **关闭 Apply when ready：** 等到手动执行 `/compact` 或 Pi 自动触发压缩时再使用。
- **保持 Apply when ready 开启（默认）：** 校验通过后，扩展可以在当前模型/工具批次结束后，或下一个空闲输入边界应用检查点。

**Ready（就绪）**表示检查点已准备好，但尚未写入会话。会话、模型、服务商或相关设置的变化都可能使其失效。引擎会在应用前检查它是否仍然可用。使用当前版本引擎时，Text summary 在系统提示词、启用工具或思考级别变化后仍可使用；Provider checkpoint 保留更严格的检查。

## 选择输出格式

本扩展负责安排后台任务，压缩引擎决定准备哪种结果。更新 `pi-codex-compact` 后，打开 `/codex-compact` → **Settings**，将压缩模式设为 **Text summary（文本摘要）**或 **Provider checkpoint（服务商检查点）**：

- **Text summary：** 用普通模型请求总结已捕获的历史，并加入 scratchpad 指引。准备摘要时，主代理可以继续工作。
- **Provider checkpoint（默认）：** 请求服务商生成加密、不透明的检查点。

在 `/background-compaction` 中保持 **Apply when ready** 开启，两种结果都会在下一个安全边界自动应用。准备阶段不会替换当前历史；应用时只替换已总结的前缀，保留安全的近期原始消息，以及之后产生的新消息和工具结果。切换分支或不兼容的设置变化可能使结果失效，但正常追加消息不会。

切换格式时请保持核心引擎启用。已有的加密历史仍需通过兼容的服务商重放，才能转为文本摘要。文本摘要模式使用引擎已支持的 Responses 服务商，并不代表支持所有服务商 API。

应用任一种格式都会改变对话前缀，可能降低下一次请求的缓存复用。提前准备摘要不保证缓存命中或费用更低。无需增加另一套后台调度器，也无需新增本扩展的设置。

## 工作流程

使用默认设置时：

```mermaid
flowchart TD
    A[Pi 执行你的任务] --> B[一轮结束且上下文使用率达到 70%]
    B --> C[在后台准备文本摘要或服务商检查点]
    C -.-> D[Pi 可以继续工作]
    C --> E[压缩结果就绪]
    E --> F[在安全边界校验]
    F --> G[应用结果，保留新消息并继续]
```

安全边界是当前模型/工具批次结束后，或下一个空闲输入边界，不是正在进行的请求中途。如果正式压缩在准备完成前触发，它会等待兼容的后台任务。如果后台任务失败或其结果无法使用，引擎会转到前台执行压缩。

## 手动和自动压缩

如果兼容的检查点仍在准备中，不带自定义指令的 `/compact` 会像 Pi 自动压缩一样等待它完成。等待期间显示 **Preparing（准备中）**是正常的。如果准备或校验失败，引擎会改为在前台执行压缩。

- 按 Escape 取消等待。取消不会应用检查点，也不会发起替代请求。
- 向 `/compact` 传入自定义指令时，会替换尚未完成的后台任务，以确保使用新指令。
- 如果 Pi 在处理 `/compact` 之前取消了当前运行，已经随之取消的后台任务就无法复用。

模型请求失败不会取消仍然有效的后台准备，也不会在重试期间启动重复请求。开启 **Apply when ready** 时，在失败请求或重试期间准备就绪的结果会继续等待，不会修改历史。后续一轮成功完成后，如果检查点仍然有效，就可以应用。显式取消会阻止该检查点自动应用，但仍可手动执行 `/compact`。

## 命令

| 命令 | 作用 |
| --- | --- |
| `/background-compaction` | 在终端界面打开 Settings、Status 和 Help。 |
| `/background-compaction diagnostics` | 显示当前准备、上次停止的结果和当前会话中保留的上次失败报告。 |
| `/background-compaction resume` | 解除当前会话因失败而进入的暂停状态。下一轮结束后可以重新开始准备。 |
| `/compact` | 执行 Pi 的压缩，有兼容的后台任务时优先复用。 |

在支持 UI 的 RPC 模式下，`/background-compaction` 会显示设置文件路径，而不是打开菜单。print 和 JSON 模式不提供菜单。`resume` 命令不依赖菜单。

## 设置

设置保存在 Pi 的 agent 目录中的 `pi-background-compaction.json`，通常为 `~/.pi/agent/pi-background-compaction.json`。

| 设置 | 默认值 | 含义 |
| --- | --- | --- |
| `asyncEnabled` | `true` | 允许在后台准备检查点。 |
| `asyncAutoApply` | `true` | 检查点就绪后即可应用，不必等待常规压缩触发。需要先开启后台准备。 |
| `asyncThresholdPercent` | `70` | 允许开始准备时的上下文使用率百分比，必须是 1 到 99 的整数。 |
| `asyncRequestSizeMiB` | `13` | 兼容传输报告的完整请求大小阈值，1–32 MiB 的整数；与 token 阈值满足任一即可触发。 |
| `logCompaction` | `true` | 显示准备和应用检查点的提示。 |

菜单中的修改会立即保存并生效。Escape 只关闭菜单，不会撤销已保存的修改。如果直接编辑文件，请运行 `/reload` 重新加载。无效的设置文件会使后台准备关闭，且不会被覆盖；修复文件后再重新加载。

这些设置属于用户级别，不支持项目覆盖。服务商超时、重试、检查点保留和恢复选项由压缩引擎管理，不属于本扩展。

### 从内置控制器迁移

后台设置和恢复命令已从 `/codex-compact` 移到 `/background-compaction`。

如果新设置文件不存在，本扩展会从同目录的 `pi-codex-compact.json` 读取上面四项设置。Status 会标明正在使用旧设置。在新菜单中首次显式保存时，会将它们写入新文件，不修改旧文件，也不复制服务商凭据。

新文件存在后，以新文件为准。显式保存的值会被保留，包括 `false` 和旧阈值。两个文件中缺失的字段都使用上表的默认值；新文件缺失的字段不会回退到旧文件。保存新设置前，请保留旧设置。

## 失败处理和限制

准备请求失败后，当前会话会暂停后续后台准备。警告会显示耗时，以及引擎提供的可安全展示的失败原因；没有可用原因时会显示通用提示。手动 `/compact` 和 Pi 自动压缩仍然可用。

使用支持诊断的引擎时，状态栏会显示耗时和最近的流活动。长时间无活动的提示只是提醒，不会取消请求或缩短截止时间。后台失败警告本身会附上有长度限制的诊断报告，包含每次尝试的时间和流结束情况；即使关闭生命周期日志也会显示。因此只需复制这一条警告，不必再次复现。使用新版引擎时，不会另外重复输出准备失败报告；较旧但支持诊断的引擎可能仍会提前输出一份报告。扩展会在当前会话中保留上次失败报告，执行 `resume` 后仍可通过 Status 或 `/background-compaction diagnostics` 查看。报告不包含提示词、scratchpad 内容、凭据或检查点正文。引擎无法提供诊断时，同一条警告会明确说明。如果最终诊断快照无法读取，但仍有较早的快照，报告会明确标注为最近可用的诊断，而非最终诊断。

需要重试后台准备时，运行 `/background-compaction resume`。它只解除暂停，不会立即向服务商发送请求。

会话变化或检查点不再适用时，检查点也可能被丢弃。Status 会单独保留上次准备结果及安全原因，避免与当前准备混淆。诊断会区分当前报告和保留报告，并在引擎结束后保留真正的最终快照。预期的会话或任务归属变化以及主动取消不算服务商请求失败，也不会因此暂停后台准备。真正的准备或应用失败（包括结果超出可用预算）仍保留原有的失败暂停行为。自动应用不会为了替换无效检查点而悄悄发起新的服务商请求。

本扩展不增加服务商支持，也不配置凭据。请求沿用兼容引擎的服务商路由和认证。请只安装可信的扩展和引擎；数据处理方式、支持的服务商及恢复行为请参阅引擎文档。

## 开发

```sh
npm install
npm run check
npm test
```

使用本地兼容的 `pi-extensions` 仓库运行集成测试：

```sh
npm run test:integration -- /path/to/pi-extensions
```

在 Pi 中加载本地扩展：

```sh
pi -e ./src/index.ts
```

## 许可证

[MIT](LICENSE)。保留原始 Narumi 版权声明。

## 后台准备自动重试

`asyncRetryCount` 默认为 `1`：首次尝试失败后最多再重试一次，总共两次；可设为 0–5，0 表示关闭。首次等待 5 秒，随后 10 秒，更多重试最多等待 30 秒。所有尝试共用原始准备截止时间，不延长超时。手动 `/compact` 等待同一个准备任务。引擎原有的底层传输重试仍在每次尝试中生效，可能额外消耗配额。

仅重试引擎明确标记的暂时性准备失败；取消、过期状态、永久性或未分类错误不重试。重试耗尽后暂停后台准备。请同时更新引擎和 companion；旧引擎没有重试标记时保持单次尝试。完整文件名、检查点应用和前台恢复行为不受影响。
