系统提示词封面(新增能力):
- extensions/system-prompt-cover.ts:读取 ~/.pi/agent/SYSTEM_COVER.md,
在 before_agent_start 返回 { systemPrompt },用文本拼接替换 Pi 默认
系统提示词的开头,同时保留 tools / rules / docs / skills /
project_context / cwd 全部分区及其原始顺序。
- 必须走 forceSystemPrompt 投影路径。customPrompt 选项会连带抑制
tools / rules / docs 三个分区,而回填只能追加到末尾,无法恢复原顺序;
且 forceSystemPrompt 优先级更高,二者同时存在时 customPrompt 会被
静默忽略,因此 handler 不得写 customPrompt。
- 分割边界要求独占一行的裸标签:<project_instructions path="..."> 嵌套在
<project_context> 内,只有裸标签才是分区边界。
- 注册在 tool-routing 之前,否则提示词已被压平,改 systemPromptOptions
不再影响本轮请求。
- scripts/deploy-system-prompt-cover.mjs:同目录临时文件 + rename 原子
覆盖,不保留备份;install.sh 从脚本目录、update.sh 从升级后组合包
定位 helper,禁止回退到可能陈旧的脚本目录。
- 封面缺失、不可读或空白时静默 no-op,Pi 行为保持不变;封面每轮重新
读取,修改后在下一轮生效,不影响已结束的历史对话。
pi-compaction 投影修正:
- 仅在「摘要 + Source 行」严格短于原文时才替换工具结果。此前命中即
无条件替换,小结果反而被包壳放大;未替换的结果完整保留原始 content
parts(含非文本部分)。
- deterministic.maxStubTokens 由 256 提升到 1024。
pi-tool-search 常驻工具:
- alwaysEnabled 增加 context_tree_query:恢复被投影的工具证据不应依赖
一次 tool_search 激活,常驻同时保持请求前缀稳定。
- BUNDLE_TOOL_SEARCH_DEFAULTS_VERSION 由 3 提升到 4;
scripts/migrate-tool-search-settings.mjs 新增 version-3 快照常量,
使其与 version-2 一样可被完整精确匹配并迁移。
- 权限策略为 context_tree_query 显式 allow:它只读扩展自己的 segment
索引、不触碰工作区,常驻后不应每轮触发 AutoReview 往返。该种子仅在
全新安装时部署,已存在的用户 policy.jsonc 不会被覆盖。
文档与测试同步:
- AGENTS.md:新增 system-prompt-cover 开发约定,修正加载顺序、
bundleDefaultsVersion、可迁移旧快照集合与常驻工具范围的描述。
- pi-tool-search 的 README / CHANGELOG 同步 version 4 与新增常驻工具。
- tests/system-prompt-cover.test.ts:覆盖顺序保持、尾部逐字节不变、
嵌套 project_instructions 不误判、部署幂等与覆盖、缺源时非零退出。
- 修正 pi-tool-search/test/config.test.ts 与
tests/tool-search-settings-migration.test.ts 中写死的 version 3 与
工具列表断言。
- update-git-clean-recovery / tool-search-settings-migration 的 mock
组合包补拷 scripts/,与真实发布包结构一致,避免 helper 定位失败。
测试:根 61/61、pi-compaction 36/36 + tsc、pi-tool-search 16/16 + tsc、
pi-permission-system 2577/2577;sh -n 与 git diff --check 通过。
pi-compaction
High-performance unified context projection and compaction for Pi.
Responsibilities
- incrementally index completed tool calls;
- replace large tool results with deterministic bounded evidence stubs;
- pass small tool results through unchanged whenever a stub would not be shorter;
- refine large stubs with non-blocking semantic summaries;
- expose one effective context projection to normal provider requests and Codex/SubAPI native compaction;
- cancel Pi's raw threshold compaction until the effective lower-bound reaches the configured threshold;
- retain original tool evidence through
context_tree_query; - publish read-only effective metrics for the footer and context observer.
Context Mode remains responsible for preventing large external data from entering the session. RTK remains responsible for ordinary tool-output cleanup.
Configuration
Set piCompaction in the Pi agent settings.json:
{
"piCompaction": {
"enabled": true,
"softRatio": 0.72,
"hardRatio": 0.9,
"targetRatio": 0.55,
"deterministic": {
"enabled": true,
"maxStubTokens": 256
},
"semantic": {
"enabled": true,
"model": "default",
"thinking": "low",
"concurrency": 1,
"minInputChars": 4000,
"maxInputChars": 24000,
"maxRetries": 2
},
"native": {
"enabled": true
}
}
}
The extension never writes settings. Invalid or missing fields are normalized in memory.
Native providers
Native compaction is enabled by piCompaction.native.enabled and uses the model selected in the session when compaction starts. It does not select a separate summarization model.
| Provider | API | Native transport |
|---|---|---|
openai-codex |
openai-codex-responses |
Existing Codex Responses endpoint and JWT/account-ID authentication |
sub-api |
openai-responses |
Public Responses endpoint and resolved gateway headers or API key |
For SubAPI, keep the existing models.json API as openai-responses. The adapter requires an explicit HTTP(S) baseUrl: for example, https://gateway.example/v1 becomes https://gateway.example/v1/responses; an existing /responses suffix is not duplicated. It preserves configured headers and merges the native compaction beta feature, without decoding the API key or adding a ChatGPT account ID. No gateway hostname or credentials are bundled.
SubAPI preserves a non-empty explicit Authorization header (case-insensitively) ahead of the API key. Without it, a non-blank API key supplies Bearer authentication; if no key is available, a non-empty cf-aig-authorization header also supports proxy-managed authentication. Header-only credentials do not create a dummy Bearer token. Missing or blank credentials fail before any network request and return control to Pi. Official Codex still requires its API key/JWT even when explicit authentication headers are present.
Both transports send the current projection as ResponseItems, append compaction_trigger, and parse the SSE compaction item. SubAPI must support Sub2API native remote compaction v2 on its public Responses endpoint. This is not a client for the separate /v1/responses/compact endpoint; supporting only that endpoint or ordinary Responses chat is insufficient.
Request interception also restores SubAPI native checkpoints into subsequent Responses input. Checkpoints retain a bounded portable summary for switching models/providers, and their version 1 format is unchanged. Native authentication, transport or response failures return control to Pi's normal compaction fallback. Other provider/API pairs and native.enabled: false retain the existing portable-summary path. Setting native.enabled to false does not discard an already-created native checkpoint.
The gateway must have a compatible deployed version, model and available upstream account. Offline tests cover the protocol and lifecycle; they do not establish live gateway availability. No settings migration, provider rename or Pi core modification is required.
Session format
The only custom entry type is pi-compaction, version 1. Segment summary entries contain hashes, summaries, and source references; they never duplicate complete raw tool output. Native checkpoints use Pi compaction-entry details with the same kind/version.
Projection replaces a tool result only when the resulting summary plus its Source: recovery line is strictly shorter than the original text content. Small tool results are therefore passed through byte-for-byte and keep their original content parts, including any non-text parts. Because a stub is only larger than the text it would replace when the original is short, this comparison is the sole gate; no separate size option exists. Every indexed result remains recoverable through context_tree_query whether or not the message was replaced.
This implementation intentionally does not read legacy context-prune-* or openai-codex-native-compaction entries. Start a new session after switching to this extension.
Interfaces
context_tree_query: recover original bounded tool evidence by source key or tool call ID./compaction-status: show raw/effective tokens, reclaimed tokens, confidence, segments, and pending semantic jobs.
Performance model
The first session hydration scans the branch once. Appended turns use delta projection and immutable cached snapshots. The context hook performs no model call and no session write. Semantic summaries run in a bounded background worker and become visible only at later safe event boundaries.