pai-acp
v0.1.22
Published
Active Context Pruning (ACP) extension for Pi — model-driven context compression that keeps conversations flowing.
Maintainers
Readme
为什么选择 ACP
当对话变长,模型的上下文会耗尽。多数工具采用硬截断 —— 静默丢弃早期消息。ACP 把 compress 工具交给模型:由 LLM 决定何时压缩、压缩什么,将内容压缩成高保真摘要,在回收上下文空间的同时保留关键细节(文件路径、决策、错误字符串)。
与 Pi 内置的自动压缩(把所有内容替换成单个摘要)不同,ACP:
- 保留结构 — 压缩的范围变成带标签的块,可后续解压
- 多级压缩 — 摘要可被进一步蒸馏(T1 → T2 → T3),随会话增长保持有界
- 可搜索 —
search_context无需解压即可搜索已压缩块内的信息 - 有选择性 — 受保护的工具、用户消息、近期工作集永不被压缩
这使得:
- 一个会话即可支撑海量工作。 根据三级压缩架构的模拟测试(见 opencode-acp),单会话累计可处理约 100 亿至 600 亿 token —— 同时对遥远的关键信息(路径、决策、签名)保持长久记忆。用户可以在同一个会话里连续工作几个月,而无需因为上下文膨胀而开新会话丢上下文。
- 上下文长期保持精简。 实际运行中上下文通常稳定在 15 万 token 以下(opencode-acp 实测维持在 20 万以下),相比传统压缩方案动辄撑到 100 万上下文,单会话累计可节省近 5 倍的 token 费用。
安装
pi install npm:pai-acp完成。扩展在下次 Pi 启动时自动加载。无需配置 —— 它会自动读取模型的上下文窗口。
建议先卸载
pi-subagents(可选,推荐)。 pai-acp 自带acp_delegate子代理工具(见下文),以极低的上下文成本(~600 tok vs ~7K tok/轮)替代 pi-subagents。如果你已安装 pi-subagents,卸载它以避免重复的委派工具:pi remove npm:pi-subagents
工作原理
ACP 拦截 Pi 的 context 事件(每次 LLM 调用前触发),运行一个 8 阶段管线:
assign refs → sync blocks → prune → filter → hide calls → recommend → nudge → emergency truncate每条消息获得一个不可见的 <acp> 引用标签(m00001、m00002、...),对模型可见但用户不可见。模型用这些引用来指定压缩范围。
Pi 内置的自动压缩会被取消 —— ACP 是唯一的上下文管理者。
模型工具
| 工具 | 作用 |
|------|------|
| compress | 用详细摘要替换连续的消息范围 |
| decompress | 恢复之前压缩的块内容 |
| search_context | 按关键词搜索已压缩块摘要(及可见消息) |
| acp_status | 显示上下文用量、已压缩块、可压缩范围 |
| acp_delegate | 为某个任务派生一个干净上下文的子代理(审查 / 调研 / 实现 / 规划 / 建议) |
| acp_delegate_wait | 阻塞等待委派任务完成(返回结果,否则超时) |
| acp_delegate_cancel | 按 runId 取消正在运行的委派任务 |
acp_delegate — 干净上下文委派
把一个自包含的任务交给一个运行在干净上下文中的新 pi 进程。五个内置角色,各自有定制的工具白名单和系统提示:
| 角色 | 工具 | 适用场景 |
|------|------|----------|
| reviewer | read, bash | 只读代码审查(bug、风险、file:line) |
| researcher | read, bash | 只读代码库调研 |
| worker | read, edit, write, bash | 修改代码 |
| planner | read, bash | 分析 + 提出分步计划 |
| oracle | read, bash | 回答问题 / 建议 |
委派的完整结果保存到文件(/tmp/acp-delegate/<runId>.out);工具结果和注入通知只携带任务标题 + 文件路径(无预览)— 需要细节时用 read 读取。这让父上下文保持精简。
- 交互(TUI)与 RPC 模式:
async:true(默认)在后台运行子进程;完成时一条简短通知注入到聊天框。 - Print / JSON 模式(
pi -p、SDK):async:true自动降级为同步 — 结果在同一轮作为工具结果返回(父进程一轮后即退出,后台注入会丢失)。
在交互 TUI 中,异步运行还会在编辑器下方显示一个实时状态 widget(角色、已运行秒数、任务预览),让你随时知道什么在跑、跑了多久。RPC/print/JSON 模式自动禁用。
/acp 命令
为用户提供丰富的状态显示:
╭─────────────────────────────────────────────╮
│ ACP Context Analysis │
╰─────────────────────────────────────────────╯
[email protected]
Context: 12% (120K / 1.0M)
Growth: +15K since last nudge
Token Breakdown:
System ░░░░░░░░░░░░░░░░░░░░ 2% 2.1K
Tool ████████████░░░░░░░░ 58% 69.6K
Summaries ████░░░░░░░░░░░░░░░░ 20% 24.0K
Code ██░░░░░░░░░░░░░░░░░░ 10% 12.0K
Text █░░░░░░░░░░░░░░░░░░░ 5% 6.0K
Blocks: 3 active (3.7K summary, 15.2K original compressed)
b1 (T1) 3.7K→599 age=5m "API exploration"
b2 (T1) 8.2K→2.1K age=2m "Debug session"
b3 (T2) 3.3K→1.0K age=1m "Architecture review"配置
pai-acp 开箱即用,无需任何配置。可以在 JSON 配置文件中设置三个可选 key。
配置文件
创建 ~/.pi/acp.json(全局)和/或 <项目>/.pi/acp.json(项目级,覆盖全局):
{
"debug": false,
"autoUpdate": true,
"modelContextLimit": 200000,
"delegate": true
}| Key | 默认值 | 说明 |
|-----|--------|------|
| debug | false | 将诊断事件写入 ~/.pi/acp-debug.log。也可用环境变量 ACP_DEBUG=1 启用。 |
| autoUpdate | true | Pi 启动时检查 npm 是否有更新版本并自动安装(限频:每 3 分钟最多一次检查)。禁用以避免所有启动时的网络请求。 |
| modelContextLimit | (自动) | 覆盖上下文上限(token 数)。默认为模型的 contextWindow。 |
| delegate | true | 启用 acp_delegate 工具(delegate/wait/cancel)及其系统提示词段落。设为 false 则不注册这些工具(例如你用了别的子代理扩展,或跑 headless 场景异步注入没有意义)。 |
只有这四个 key 会被
acp.json读取。 其他调优参数(preserveRecentMessages、protectedTools、nudge 阈值)是代码级的,不向用户开放。
环境变量
| 变量 | 作用 |
|------|------|
| ACP_AUTO_UPDATE | 设为 0 / false / no / off(不区分大小写)以禁用自动更新,覆盖配置值。 |
| ACP_MODEL_CONTEXT_LIMIT | 覆盖上下文上限。优先级高于配置值。 |
| ACP_DEBUG | 设为 1 或 true 启用 debug 日志。 |
压缩策略
模型接收(在其系统提示中)关于何时压缩、逐字保留什么(路径、签名、错误、决策、用户意图)、丢弃什么(冗长日志、重复内容、已消费的探索)的详细指导。这段指导每轮都注入,确保它始终在模型的注意力范围内。
哪些内容会被保护
ACP 保护三类内容不被压缩:
- 永久保护的工具 —
compress调用被硬保护(它们是承载关键元数据的;压缩它们会破坏 decompress 和"摘要是历史"的契约)。 - 软近期区 — 最后 N 条消息(默认 5)和最后约 5K token 被软保护,让模型保留工作集。来自
decompress、search_context、read、bash的工具结果被排除出此区:它们体量大、消费后就该能压缩,所以不该占用保护预算。 - 最后一条用户消息 — 始终保护(用户意图必须存活)。
基于 acp-kernel
压缩引擎是 acp-kernel — 平台无关、MIT 许可的库,有 208 个测试。它被内联打包进 dist/index.js,因此零运行时依赖。
许可证
MIT.
