pi-openai-toolkit 0.12.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/NOTICE CHANGED
@@ -53,3 +53,31 @@ furnished to do so, subject to the following conditions:
53
53
 
54
54
  The above copyright notice and this permission notice shall be included in all
55
55
  copies or substantial portions of the Software.
56
+
57
+ The Remote Context management implementation in src/context-management/ was
58
+ adapted from @howaboua/pi-codex-conversion@3.0.29 at source commit
59
+ 7021ae48e8efe36a3becc5830d529696ff798e5e.
60
+
61
+ Upstream copyright and license notice:
62
+
63
+ MIT License
64
+
65
+ Copyright (c) 2026 Igor Warzocha
66
+
67
+ Permission is hereby granted, free of charge, to any person obtaining a copy
68
+ of this software and associated documentation files (the "Software"), to deal
69
+ in the Software without restriction, including without limitation the rights
70
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
71
+ copies of the Software, and to permit persons to whom the Software is
72
+ furnished to do so, subject to the following conditions:
73
+
74
+ The above copyright notice and this permission notice shall be included in all
75
+ copies or substantial portions of the Software.
76
+
77
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
78
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
79
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
80
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
81
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
82
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
83
+ SOFTWARE.
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # pi-openai-toolkit
2
2
 
3
3
  <p align="center">
4
- <strong>OpenAI-focused toolkit for <a href="https://github.com/earendil-works/pi">Pi</a>: Remote Compaction v2, Hosted Web Search, Native Image Generation &amp; Model-Reviewed Auto Mode</strong>
4
+ <strong>OpenAI-focused toolkit for <a href="https://github.com/earendil-works/pi">Pi</a>: Codex Remote Context Management, Remote Compaction v2, Hosted Web Search, Native Image Generation &amp; Model-Reviewed Auto Mode</strong>
5
5
  </p>
6
6
 
7
7
  <p align="center">
@@ -12,7 +12,7 @@
12
12
 
13
13
  `pi-openai-toolkit` is an all-in-one OpenAI enhancement package for **Pi (>= 0.85.1)**. It bundles five extensions designed for OpenAI Responses endpoints:
14
14
 
15
- 1. **Remote Responses Compaction v2** (`extensions/compaction.ts`): Server-side opaque context compaction using the `remote_compaction_v2` SSE streaming protocol. Preserves context fidelity without lossy text re-summarization.
15
+ 1. **Remote Responses Compaction v2 + Codex Remote Context Management** (`extensions/compaction.ts`): Two long-context strategies. Remote Context management (`compaction.contextManagement: "remote"`) ports Codex's native window system to Pi: a no-summary `new_context` rollover gated on a real notes checkpoint, cross-window `history` / `notes` tools with encrypted argument transport, `get_context_remaining` budgeting, and configurable context reminders — over native Codex OAuth or an allowlisted Codex-compatible gateway. When it is off, the toolkit falls back to server-side opaque `remote_compaction_v2` SSE compaction, which preserves context fidelity without lossy text re-summarization.
16
16
  2. **Model-Scoped Web Search** (`extensions/web-search.ts`): Toolkit-owned hosted Web Search for an exact `provider/model-id` allowlist configured with `webSearch.models`, across the supported `openai-responses` and `openai-codex-responses` APIs.
17
17
  3. **Native Image Generation** (`extensions/image-generation.ts`): A sequential local tool backed by the hosted Responses `image_generation` tool. It supports text-to-image and explicit local-reference edits while keeping binary image data out of session history.
18
18
  4. **Model-Reviewed Auto Mode** (`extensions/auto-mode.ts`): Pi does not prompt before running tools. Auto mode adds a gate on state-changing tool calls and lets a reviewer model you configure approve or deny each one, so the agent keeps working without interrupting you.
@@ -99,6 +99,8 @@ C:\Users\<user>\.pi\agent\extensions\pi-openai-toolkit\config.json
99
99
  {
100
100
  "compaction": {
101
101
  "enabled": true,
102
+ "contextManagement": "off",
103
+ "codexGatewayModels": [],
102
104
  "allowCompactionContinuityBreak": false,
103
105
  "remoteCompactModel": "uwoacrimson/gpt-5.6-luna",
104
106
  "nativeFallback": {
@@ -131,7 +133,7 @@ C:\Users\<user>\.pi\agent\extensions\pi-openai-toolkit\config.json
131
133
  "models": [
132
134
  "uwoacrimson/gpt-5.6-luna"
133
135
  ],
134
- "reviewerModel": "uwoacrimson/gpt-5.6-sol",
136
+ "reviewerModel": "uwoacrimson/gpt-5.6-luna",
135
137
  "gate": "side-effect",
136
138
  "extraTools": [
137
139
  "openai_generate_image"
@@ -165,18 +167,45 @@ C:\Users\<user>\.pi\agent\extensions\pi-openai-toolkit\config.json
165
167
 
166
168
  #### `compaction`
167
169
 
168
- - `enabled` (*boolean*, default: `true`): Enable or disable Remote Compaction.
170
+ - `enabled` (*boolean*, default: `true`): Enable or disable toolkit compaction hooks.
171
+ - `contextManagement` (*`"off" | "remote"`*, default: `"off"`): Opt into Codex Remote Context management. `"remote"` is active for the native `openai-codex` / `openai-codex-responses` route, or for an exact entry in `codexGatewayModels` whose model resolves to `uwoacrimson` / `openai-responses`. Native mode reuses Pi's existing Codex OAuth through `ModelRegistry`; gateway mode uses the configured data-plane API key and does not derive or forward a local Codex account ID. Remote windows use Codex history/notes, retain the full Pi JSONL session, and do not generate ordinary summaries. While active, this feature owns context rollover and disables this package's `remote_compaction_v2` request. Set it back to `"off"` or clear the allowlist to roll back to the existing compaction behavior. Remote backend failures are surfaced; they never silently fall back to Local context management.
172
+ - `codexGatewayModels` (*string[]*, default: `[]`): Exact `provider/model-id` entries allowed to use the NEWapi/CPA Codex gateway, for example `"uwoacrimson/gpt-5.6-luna"`. Entries are opt-in, trimmed, and matched exactly; the gateway sends the bare model ID in `X-Codex-Model` and keeps the configured `/v1` base URL. An empty list disables gateway Remote Context.
169
173
  - `allowCompactionContinuityBreak` (*boolean*, default: `false`): When `true`, allows restarting a fresh native opaque compaction chain from Pi's current session text if the latest compaction was made by another strategy (e.g. text summary).
170
174
  - `remoteCompactModel` (*string | null*, default: `null`): Model formatted as `provider/model-id` used only for the synthetic `remote_compaction_v2` request. Pi's active session model is not switched and resumes normal requests after compaction. The override must resolve to the same effective base URL as the active model; provider, Responses API identifier, and model may differ. `null` preserves the current same-model path.
171
175
  - `nativeFallback.enabled` (*boolean*, default: `true`): Master switch for toolkit-driven native compaction with an explicit summary model. It never touches the remote chain: `remote_compaction_v2` is still attempted and still wins when it succeeds. When `false`, only the post-failure native step is skipped, so every fallback falls straight through to Pi's own default compaction with the active model.
172
176
  - `nativeFallback.model` (*string | null*, default: `null`): Summary model formatted as `provider/model-id` (e.g. `"openai/gpt-4o-mini"`) used **only** when the active model cannot use remote v2 at all (non-Responses API, or an API excluded by `responsesApis`). It is never consulted once a remote request was attempted, and `null` means the active model runs Pi's default compaction path.
173
177
  - `nativeFallback.thinkingLevel` (*string*, default: `"off"`): Reasoning / thinking level passed to Pi's native `compact()` whenever this extension supplies the model (`"off"`, `"minimal"`, `"low"`, `"medium"`, `"high"`, `"xhigh"`, `"max"`).
174
- - `responsesApis` (*string[]*): Narrow the supported remote compaction API identifiers (subset of `["openai-responses", "openai-codex-responses"]`).
178
+ - `responsesApis` (*string[]*): Narrow the supported remote compaction API identifiers (subset of `["openai-responses", "openai-codex-responses"]`). This setting applies only when `contextManagement` is `"off"`.
175
179
  - `notifyOnLoad` (*boolean*, default: `false`): Show a notification banner on Pi startup.
176
180
  - `debug` (*boolean*, default: `false`): Output diagnostics and write execution artifacts to disk.
177
181
  - `logProviderPayloads` / `logCompactResponses` (*boolean*, default: `false`): Write raw provider request payloads and compact SSE event bodies to artifacts.
178
- - `redactSensitiveData` (*boolean*, default: `true`): Apply full sensitive-value redaction to debug artifacts. Authorization credentials, API keys/tokens, and opaque `encrypted_content` are always redacted even when this option is `false`.
182
+ - `redactSensitiveData` (*boolean*, default: `true`): Apply full sensitive-value redaction to debug artifacts. Authorization credentials, API keys/tokens, Codex account IDs, and opaque `encrypted_content` / `encrypted_output` are always redacted even when this option is `false`.
179
183
  - `artifactRoot` (*string*): Directory root for diagnostic artifacts. Relative paths resolve against the config directory.
184
+ - `contextReminderThresholdPercent` (*integer*, default: `5`, range `0`-`100`): Remote Context only. When tokens remaining in the current window drop below this percentage of the context window, the toolkit injects a checkpoint reminder once per window; at `0` reminders are disabled (the exhausted-window fallback still fires). Set it comfortably above Pi's native reserve band so the model gets a chance to roll the window over before the native threshold is reached.
185
+
186
+ ### Recommended Remote Context configuration
187
+
188
+ To run Codex Remote Context management on this gateway setup:
189
+
190
+ ```json
191
+ {
192
+ "compaction": {
193
+ "enabled": true,
194
+ "contextManagement": "remote",
195
+ "codexGatewayModels": ["uwoacrimson/gpt-6-astra"],
196
+ "contextReminderThresholdPercent": 10
197
+ }
198
+ }
199
+ ```
200
+
201
+ Two operational notes:
202
+
203
+ - **Disable Pi's native compaction for Remote-managed sessions.** While `contextManagement` is `"remote"` and the model is covered (native Codex, or listed in `codexGatewayModels`), the toolkit already cancels every Pi-native compaction attempt — threshold, manual `/compact`, and overflow — so no lossy summary can slip in behind its back. If you also want belt-and-braces at the host level, set `"compaction": { "enabled": false }` in Pi's `~/.pi/agent/settings.json`; models outside the Remote coverage still compact normally with Pi's own policy either way.
204
+ - **`new_context` cannot discard unsaved state silently.** The tool refuses to roll over unless the current window contains a *successful* `notes` `append_to_file` / `write_file` (read-only notes calls and failed writes do not count; the check is rebuilt from the session branch, so it survives restarts and resumes). `force: true` bypasses the gate for explicit user-authorized discards, and the toolkit's own exhausted-context fallback path bypasses it automatically.
205
+
206
+ #### Remote Context protocol notes
207
+
208
+ When `compaction.contextManagement` is `"remote"`, the toolkit activates `new_context`, `get_context_remaining`, `history`, and `notes` for the native Codex route or an exact allowlisted gateway model. History and notes use the alpha `alpha/history/v2/*` and `alpha/notes/v2/*` endpoints, including encrypted argument policy headers for search and note writes. `new_context` accepts an optional `force` flag; without a successful notes checkpoint in the current window it refuses unless `force` is set (see Recommended Remote Context configuration). Gateway requests carry the same bounded session ID, affinity scope, and bare model hint as live Responses requests; the gateway never receives local OAuth credentials or account cookies. The request carries the current window and turn metadata; timeout, abort, non-2xx, malformed JSON, authentication, and protocol failures are explicit tool errors. For covered models the toolkit also cancels Pi's native compaction while the Remote runtime is inactive, so no lossy summary is produced behind its back; fix the activation reason shown in the notification instead. The protocol is based on `@howaboua/pi-codex-conversion@3.0.29` source commit `7021ae48e8efe36a3becc5830d529696ff798e5e`; these alpha endpoints may change and the endpoint/header fixtures must be updated together.
180
209
 
181
210
  #### `webSearch`
182
211
 
@@ -219,6 +248,17 @@ Auto mode is opt-in through the empty-by-default `models` allowlist because it a
219
248
 
220
249
  ## Core Mechanics
221
250
 
251
+ ### 0. Codex Remote Context Management
252
+
253
+ When `compaction.contextManagement` is `"remote"` and the session's model is covered — native `openai-codex` / `openai-codex-responses`, or an exact `provider/model-id` entry in `codexGatewayModels` resolving to `uwoacrimson` / `openai-responses` — the toolkit replaces summarization-based compaction with Codex's native context-window lifecycle:
254
+
255
+ - **Window identity.** `session_start` initializes a context window (first / current / previous window id, window number) and persists each boundary as a `codex-context-window` custom message in the Pi session, replayed on resume and reconstructed after forks. Every live request carries the window and turn identity through `x-codex-window-id` / `x-codex-turn-metadata`.
256
+ - **No-summary rollover.** `new_context` installs a fresh window and trims the previous one from the model context; nothing is re-summarized, so no lossy text survives in place of the conversation. The old turns remain retrievable server-side through `history`.
257
+ - **Checkpoint gate.** A rollover requires a successful `notes` write inside the current window, verified against the persisted session branch; without it, `new_context` refuses and tells the model to checkpoint first. This is a hard guard against the failure mode where a notes backend is down and a rollover silently discards live working state. `force: true` and the exhausted-context fallback path are the only ways past the gate, and the fallback message instructs a single last notes write before rollover.
258
+ - **Cross-window memory.** `history` (`list_windows`, `list_items`, `read_item`, `search_contents`) and `notes` (`list_files_by_prefix`, `read_file`, `search_contents`, `append_to_file`, `write_file`) hit the alpha Codex backend endpoints with encrypted tool arguments and encrypted result handling; note paths resolve under the session agent (`/root/notes/...`). After a rollover, a server-side thread hint points the model at the notes that hold the live task state.
259
+ - **Budget.** `get_context_remaining` reports the remaining window budget; `contextReminderThresholdPercent` injects the checkpoint reminder once per window as remaining tokens fall below the configured percentage of the context window.
260
+ - **Ownership of compaction.** While configured for a covered model, the toolkit owns all compaction events: Pi-native compaction is cancelled even when the Remote runtime is inactive (the reason is surfaced as a notification, e.g. a tool-name conflict or OAuth resolution failure), and `remote_compaction_v2` is never sent. Set `contextManagement` back to `"off"` or clear the allowlist to restore the previous behavior.
261
+
222
262
  ### 1. Remote Compaction v2 Protocol
223
263
 
224
264
  Instead of legacy JSON endpoints (`POST /responses/compact`), this toolkit implements the **`remote_compaction_v2`** protocol over standard streaming Responses:
package/README_zh.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # pi-openai-toolkit
2
2
 
3
3
  <p align="center">
4
- <strong>专为 <a href="https://github.com/earendil-works/pi">Pi</a> 打造的 OpenAI 增强工具包:远端无损压缩 v2、原生托管联网搜索、图像生成与模型审批 Auto 模式</strong>
4
+ <strong>专为 <a href="https://github.com/earendil-works/pi">Pi</a> 打造的 OpenAI 增强工具包:Codex 远端上下文管理、远端无损压缩 v2、原生托管联网搜索、图像生成与模型审批 Auto 模式</strong>
5
5
  </p>
6
6
 
7
7
  <p align="center">
@@ -12,7 +12,7 @@
12
12
 
13
13
  `pi-openai-toolkit` 是专为 **Pi (>= 0.85.1)** 打造的 OpenAI 增强工具包,集成了五项针对 OpenAI Responses 协议的扩展:
14
14
 
15
- 1. **远端无损压缩 (Remote Compaction v2)** (`extensions/compaction.ts`): 基于 `remote_compaction_v2` SSE 流式协议实现的服务端密文无损会话压缩,彻底告别会话变长后丢失细节的文本二次摘要。
15
+ 1. **Codex 远端上下文管理 + 远端无损压缩 v2** (`extensions/compaction.ts`): 两套长上下文策略。远端上下文管理(`compaction.contextManagement: "remote"`)把 Codex 原生窗口体系移植到 Pi:无摘要 `new_context` 换窗(附真实 notes checkpoint 硬门禁)、跨窗口 `history` / `notes` 工具(加密参数传输)、`get_context_remaining` 预算查询与可配置上下文提醒——支持原生 Codex OAuth 或白名单 Codex 兼容 Gateway。关闭时则由 `remote_compaction_v2` SSE 协议提供服务端密文无损压缩,彻底告别会话变长后丢失细节的文本二次摘要。
16
16
  2. **按模型启用的联网搜索** (`extensions/web-search.ts`): 通过 `webSearch.models` 精确匹配 `provider/model-id`,由 Toolkit 为符合条件的 `openai-responses` 与 `openai-codex-responses` 会话提供并拥有原生联网搜索。
17
17
  3. **原生图像生成** (`extensions/image-generation.ts`): 注册由 Responses 托管 `image_generation` 工具驱动的本地顺序工具,支持文生图和显式本地参考图编辑,同时避免把图像二进制写入会话历史。
18
18
  4. **模型审批 Auto 模式** (`extensions/auto-mode.ts`): Pi 默认不会为工具调用弹出审批确认。Auto 模式为改变状态的工具调用加上一道审批门,由你指定的审批模型判定放行或拦截,让 Agent 不必停下来等你确认也能继续推进。
@@ -97,6 +97,8 @@ C:\Users\<user>\.pi\agent\extensions\pi-openai-toolkit\config.json
97
97
  {
98
98
  "compaction": {
99
99
  "enabled": true,
100
+ "contextManagement": "off",
101
+ "codexGatewayModels": [],
100
102
  "allowCompactionContinuityBreak": false,
101
103
  "remoteCompactModel": "uwoacrimson/gpt-5.6-luna",
102
104
  "nativeFallback": {
@@ -129,7 +131,7 @@ C:\Users\<user>\.pi\agent\extensions\pi-openai-toolkit\config.json
129
131
  "models": [
130
132
  "uwoacrimson/gpt-5.6-luna"
131
133
  ],
132
- "reviewerModel": "uwoacrimson/gpt-5.6-sol",
134
+ "reviewerModel": "uwoacrimson/gpt-5.6-luna",
133
135
  "gate": "side-effect",
134
136
  "extraTools": [
135
137
  "openai_generate_image"
@@ -163,18 +165,45 @@ C:\Users\<user>\.pi\agent\extensions\pi-openai-toolkit\config.json
163
165
 
164
166
  #### `compaction`(压缩配置)
165
167
 
166
- - `enabled` (*boolean*, 默认 `true`): 是否启用远端无损压缩。
168
+ - `enabled` (*boolean*, 默认 `true`): 是否启用 Toolkit 的压缩 Hook。
169
+ - `contextManagement` (*`"off" | "remote"`*,默认 `"off"`): 可选的 Codex Remote Context 管理。`"remote"` 可用于原生 `openai-codex` / `openai-codex-responses` 路线,或 `codexGatewayModels` 中精确白名单项对应的 `uwoacrimson` / `openai-responses` 模型。原生模式复用 Pi 已有的 Codex OAuth,通过 `ModelRegistry` 获取;Gateway 模式使用配置的数据面 API key,不推导也不转发本地 Codex account ID。Remote 窗口保留完整 Pi JSONL,不生成普通摘要,并使用 Codex history/notes。开启后由它独占上下文窗口切换,因此不会发送本包现有的 `remote_compaction_v2` 请求。设回 `"off"` 或清空白名单即可回滚到原有压缩行为;Remote 后端失败会明确报错,不会静默切换到 Local。
170
+ - `codexGatewayModels` (*string[]*,默认 `[]`): 允许使用 NEWapi/CPA Codex Gateway 的精确 `provider/model-id` 项,例如 `"uwoacrimson/gpt-5.6-luna"`。条目会去空格并精确匹配;转发时 `X-Codex-Model` 使用不带 provider 前缀的模型 ID,并保留配置中的 `/v1` Base URL。空数组表示关闭 Gateway Remote Context。
167
171
  - `allowCompactionContinuityBreak` (*boolean*, 默认 `false`): 若最近一次历史压缩由其他方式(如文本摘要)生成,设为 `true` 允许直接从当前有效文本上下文重建密文压缩链。
168
172
  - `remoteCompactModel` (*string | null*, 默认 `null`): 仅用于 synthetic `remote_compaction_v2` 请求的模型,格式为 `"provider/model-id"`。Pi 不会切换当前会话模型,压缩完成后仍由原模型继续正常请求。覆盖模型必须与当前模型使用相同的实际生效 Base URL;Provider、Responses API 标识符和模型本身可以不同。为 `null` 时保持当前模型执行远端压缩的原有行为。
169
173
  - `nativeFallback.enabled` (*boolean*, 默认 `true`): Toolkit 用显式摘要模型跑原生压缩的总开关。它不影响远端链路:`remote_compaction_v2` 照常被尝试,成功时照常生效。设为 `false` 只跳过失败后的那一步原生压缩,因此所有降级都直接交给 Pi 默认的当前模型压缩。
170
174
  - `nativeFallback.model` (*string | null*, 默认 `null`): 摘要模型,格式为 `"provider/model-id"`(例如 `"openai/gpt-4o-mini"`),**仅**用于根本无法走远端 v2 的当前模型(非 Responses API,或 API 被 `responsesApis` 排除)。远端请求已经发出过的情境不会读这个字段;为 `null` 时由当前活动模型走 Pi 默认压缩路径。
171
175
  - `nativeFallback.thinkingLevel` (*string*, 默认 `"off"`): 由本扩展指定模型时,传给 Pi 原生 `compact()` 的思考级别。
172
- - `responsesApis` (*string[]*): 允许尝试远端压缩的 API 标识符子集(从 `["openai-responses", "openai-codex-responses"]` 中选定)。
176
+ - `responsesApis` (*string[]*): 允许尝试远端压缩的 API 标识符子集(从 `["openai-responses", "openai-codex-responses"]` 中选定)。仅在 `contextManagement` 为 `"off"` 时影响压缩路径。
173
177
  - `notifyOnLoad` (*boolean*, 默认 `false`): Pi 启动加载时是否弹出气泡提示。
174
178
  - `debug` (*boolean*, 默认 `false`): 是否开启调试模式并记录诊断日志。
175
179
  - `logProviderPayloads` / `logCompactResponses` (*boolean*, 默认 `false`): 是否在 Artifacts 中记录完整的 Provider 请求与 SSE 流事件体。
176
- - `redactSensitiveData` (*boolean*, 默认 `true`): 对调试日志应用完整的敏感值脱敏。即使设为 `false`,Authorization 凭据、API Key/Token 和 `encrypted_content` 密文也始终会被替换为 `[REDACTED]`。
180
+ - `redactSensitiveData` (*boolean*, 默认 `true`): 对调试日志应用完整的敏感值脱敏。即使设为 `false`,Authorization 凭据、API Key/Token、Codex account ID 以及 `encrypted_content` / `encrypted_output` 密文也始终会被替换为 `[REDACTED]`。
177
181
  - `artifactRoot` (*string*): 诊断日志存储根目录,支持 `~/` 路径。
182
+ - `contextReminderThresholdPercent` (*integer*, 默认 `5`,范围 `0`-`100`): 仅用于 Remote Context。当前窗口剩余 token 低于上下文窗口该百分比时,Toolkit 每窗口注入一次 checkpoint 提醒;设为 `0` 关闭提醒(窗口耗尽兜底仍照旧生效)。建议设在明显高于 Pi 原生 reserve 余量的位置,让模型在撞上原生阈值前有机会主动换窗。
183
+
184
+ ### Remote Context 推荐配置
185
+
186
+ 在本网关环境下启用 Codex 远端上下文管理:
187
+
188
+ ```json
189
+ {
190
+ "compaction": {
191
+ "enabled": true,
192
+ "contextManagement": "remote",
193
+ "codexGatewayModels": ["uwoacrimson/gpt-6-astra"],
194
+ "contextReminderThresholdPercent": 10
195
+ }
196
+ }
197
+ ```
198
+
199
+ 两点运行提示:
200
+
201
+ - **Remote 覆盖的会话请确保 Pi 原生压缩不会插队。** 只要 `contextManagement` 为 `"remote"` 且模型在覆盖范围内(原生 Codex 或列入 `codexGatewayModels`),Toolkit 就会取消所有 Pi 原生压缩尝试——阈值触发、手动 `/compact`、溢出恢复全部拦下,不会有有损摘要背地里插入。如果想再加一道保险,可在 Pi 的 `~/.pi/agent/settings.json` 里设 `"compaction": { "enabled": false }`;覆盖范围外的模型无论如何都会正常走 Pi 自己的压缩。
202
+ - **`new_context` 不会静默丢弃未保存状态。** 当前窗口内没有*成功的* `notes` `append_to_file` / `write_file` 时,换窗会被拒绝(只读操作和失败的写入不算;检查从会话分支重建,重启/resume 后依然有效)。`force: true` 供用户明确授权丢弃时绕过门禁;Toolkit 自己的窗口耗尽兜底路径会自动绕过。
203
+
204
+ #### Remote Context 协议说明
205
+
206
+ 开启 `compaction.contextManagement: "remote"` 后,本包会在原生 Codex 路线或精确白名单 Gateway 模型上激活 `new_context`、`get_context_remaining`、`history` 和 `notes`。History/notes 使用 alpha `alpha/history/v2/*` 与 `alpha/notes/v2/*` 端点;搜索和笔记写入会携带加密参数策略 Header。`new_context` 支持可选 `force` 参数;当前窗口没有成功的 notes checkpoint 时,除非设置 `force`,否则拒绝换窗(见上方推荐配置)。Gateway 请求与实时 Responses 请求使用相同的有界 session ID、affinity scope 和不带 provider 前缀的模型提示;Gateway 不会收到本地 OAuth 凭据或 account cookie。请求带有窗口和 turn metadata;超时、取消、非 2xx、非法 JSON、认证和协议错误都会明确返回工具错误。对覆盖范围内的模型,即使 Remote 运行时未激活,Toolkit 也会取消 Pi 原生压缩,不会产生有损摘要;请按通知里的原因修复激活问题(如工具名冲突、OAuth 解析失败)。协议参考 `@howaboua/pi-codex-conversion@3.0.29` 的 source commit `7021ae48e8efe36a3becc5830d529696ff798e5e`;这些 alpha 端点变化时,需要同步更新端点、Header 和 fixture 测试。
178
207
 
179
208
  #### `webSearch`(联网搜索配置)
180
209
 
@@ -217,6 +246,17 @@ Auto 模式需要显式启用(`models` 默认为空),因为它相当于允
217
246
 
218
247
  ## 核心工作原理解析
219
248
 
249
+ ### 0. Codex 远端上下文管理(Remote Context Management)
250
+
251
+ 当 `compaction.contextManagement` 为 `"remote"` 且会话模型在覆盖范围内(原生 `openai-codex` / `openai-codex-responses`,或 `codexGatewayModels` 中精确匹配的 `uwoacrimson` / `openai-responses` 条目),Toolkit 会用 Codex 原生上下文窗口体系取代摘要式压缩:
252
+
253
+ - **窗口身份。** `session_start` 初始化上下文窗口(first / current / previous window id、窗口编号),每次换窗以 `codex-context-window` 自定义消息持久化到 Pi 会话,resume 可回放、fork 后重建;每次实时请求通过 `x-codex-window-id` / `x-codex-turn-metadata` 携带窗口与 turn 身份。
254
+ - **无摘要换窗。** `new_context` 安装新窗口并把旧窗口从模型上下文裁剪掉,不做任何再摘要,因此不会有有损文本取代对话;旧轮次仍可通过服务端 `history` 取回。
255
+ - **Checkpoint 硬门禁。** 换窗前必须存在当前窗口内成功的 `notes` 写入,校验基于持久化会话分支重建,重启/resume 后依然有效;不满足时 `new_context` 直接拒绝并提示先 checkpoint。这正是针对“notes 后端故障时换窗静默丢失工作状态”的硬拦截。`force: true` 与窗口耗尽兜底是仅有的两条绕过路径,兜底消息会要求先做最后一次 notes 写入再换窗。
256
+ - **跨窗口记忆。** `history`(`list_windows`、`list_items`、`read_item`、`search_contents`)与 `notes`(`list_files_by_prefix`、`read_file`、`search_contents`、`append_to_file`、`write_file`)调用 alpha Codex 后端端点,工具参数与结果均按加密协议处理;notes 路径解析到会话 agent 目录下(`/root/notes/...`)。换窗后服务端 thread hint 会指向持有当前任务状态的 notes。
257
+ - **预算。** `get_context_remaining` 报告当前窗口剩余预算;`contextReminderThresholdPercent` 控制剩余 token 低于窗口百分比时每窗口一次的 checkpoint 提醒。
258
+ - **压缩独占。** 对覆盖模型,Toolkit 拥有全部压缩事件:即使 Remote 运行时未激活也会取消 Pi 原生压缩(未激活原因以通知明确报出,如工具名冲突、OAuth 解析失败),`remote_compaction_v2` 不会发送。设回 `"off"` 或清空白名单即恢复原有行为。
259
+
220
260
  ### 1. Remote Compaction v2(远端密文压缩)
221
261
 
222
262
  摒弃了老旧且不稳定的 `POST /responses/compact` JSON 端点,采用最新 **`remote_compaction_v2`** 标准流式协议:
package/package.json CHANGED
@@ -1,116 +1,126 @@
1
- {
2
- "name": "pi-openai-toolkit",
3
- "version": "0.12.0",
4
- "private": false,
5
- "type": "module",
6
- "engines": {
7
- "node": ">=22.19.0"
8
- },
9
- "description": "OpenAI-focused Pi toolkit providing remote Responses compaction, native Web Search, native image generation, and model-reviewed auto mode.",
10
- "author": "awoaCrim and contributors",
11
- "license": "MIT",
12
- "repository": {
13
- "type": "git",
14
- "url": "git+https://github.com/awoaCrim/pi-openai-toolkit.git"
15
- },
16
- "bugs": {
17
- "url": "https://github.com/awoaCrim/pi-openai-toolkit/issues"
18
- },
19
- "homepage": "https://github.com/awoaCrim/pi-openai-toolkit#readme",
20
- "publishConfig": {
21
- "access": "public",
22
- "registry": "https://registry.npmjs.org/"
23
- },
24
- "keywords": [
25
- "pi-package",
26
- "pi-extension",
27
- "openai",
28
- "compaction",
29
- "web-search",
30
- "image-generation",
31
- "auto-mode",
32
- "codex",
33
- "responses"
34
- ],
35
- "pi": {
36
- "extensions": [
37
- "./extensions/compaction.ts",
38
- "./extensions/web-search.ts",
39
- "./extensions/image-generation.ts",
40
- "./extensions/auto-mode.ts",
41
- "./extensions/codex-astra.ts"
42
- ]
43
- },
44
- "files": [
45
- "extensions/compaction.ts",
46
- "extensions/web-search.ts",
47
- "extensions/image-generation.ts",
48
- "extensions/auto-mode.ts",
49
- "src/compact-client.ts",
50
- "src/config.ts",
51
- "src/debug.ts",
52
- "src/details-store.ts",
53
- "src/deferred-tool-carryover.ts",
54
- "src/extension-runtime.ts",
55
- "src/image-generation/artifacts.ts",
56
- "src/image-generation/client.ts",
57
- "src/image-generation/eligibility.ts",
58
- "src/image-generation/extension.ts",
59
- "src/image-generation/protocol.ts",
60
- "src/image-generation/references.ts",
61
- "src/image-generation/render.ts",
62
- "src/image-generation/service.ts",
63
- "src/image-generation/types.ts",
64
- "src/auto-mode/extension.ts",
65
- "src/auto-mode/policy.ts",
66
- "src/auto-mode/prompt.ts",
67
- "src/auto-mode/transcript.ts",
68
- "src/auto-mode/reviewer.ts",
69
- "src/auto-mode/classifier.ts",
70
- "src/auto-mode/types.ts",
71
- "extensions/codex-astra.ts",
72
- "src/codex-astra/effort-planner.ts",
73
- "src/codex-astra/extension.ts",
74
- "src/model-scope.ts",
75
- "src/native-fallback.ts",
76
- "src/payload-rewrite.ts",
77
- "src/provider-headers.ts",
78
- "src/responses-headers.ts",
79
- "src/remote-v2-client.ts",
80
- "src/request-context-cache.ts",
81
- "src/runtime.ts",
82
- "src/serializer.ts",
83
- "src/supported-environment.ts",
84
- "src/types.ts",
85
- "src/web-search/extension.ts",
86
- "src/web-search/payload.ts",
87
- "src/web-search/prompt.ts",
88
- "src/web-search/types.ts",
89
- "README.md",
90
- "README_zh.md",
91
- "LICENSE",
92
- "NOTICE",
93
- "tsconfig.check.json"
94
- ],
95
- "scripts": {
96
- "test": "bun test",
97
- "test:coverage": "bun test --coverage --coverage-reporter=text --coverage-reporter=lcov && node ./scripts/check-lcov.mjs ./coverage/lcov.info",
98
- "test:pi": "bun test ./test/pi-smoke.test.ts",
99
- "typecheck": "tsc -p tsconfig.check.json"
100
- },
101
- "peerDependencies": {
102
- "@earendil-works/pi-agent-core": ">=0.85.1",
103
- "@earendil-works/pi-ai": ">=0.85.1",
104
- "@earendil-works/pi-coding-agent": ">=0.85.1",
105
- "@earendil-works/pi-tui": ">=0.85.1"
106
- },
107
- "devDependencies": {
108
- "@earendil-works/pi-agent-core": "0.85.1",
109
- "@earendil-works/pi-ai": "0.85.1",
110
- "@earendil-works/pi-coding-agent": "0.85.1",
111
- "@earendil-works/pi-tui": "0.85.1",
112
- "@types/node": "24.12.4",
113
- "bun": "1.2.23",
114
- "typescript": "5.9.3"
115
- }
116
- }
1
+ {
2
+ "name": "pi-openai-toolkit",
3
+ "version": "0.13.0",
4
+ "private": false,
5
+ "type": "module",
6
+ "engines": {
7
+ "node": ">=22.19.0"
8
+ },
9
+ "description": "OpenAI-focused Pi toolkit providing remote Responses compaction, native Web Search, native image generation, and model-reviewed auto mode.",
10
+ "author": "awoaCrim and contributors",
11
+ "license": "MIT",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/awoaCrim/pi-openai-toolkit.git"
15
+ },
16
+ "bugs": {
17
+ "url": "https://github.com/awoaCrim/pi-openai-toolkit/issues"
18
+ },
19
+ "homepage": "https://github.com/awoaCrim/pi-openai-toolkit#readme",
20
+ "publishConfig": {
21
+ "access": "public",
22
+ "registry": "https://registry.npmjs.org/"
23
+ },
24
+ "keywords": [
25
+ "pi-package",
26
+ "pi-extension",
27
+ "openai",
28
+ "compaction",
29
+ "web-search",
30
+ "image-generation",
31
+ "auto-mode",
32
+ "codex",
33
+ "responses"
34
+ ],
35
+ "pi": {
36
+ "extensions": [
37
+ "./extensions/compaction.ts",
38
+ "./extensions/web-search.ts",
39
+ "./extensions/image-generation.ts",
40
+ "./extensions/auto-mode.ts",
41
+ "./extensions/codex-astra.ts"
42
+ ]
43
+ },
44
+ "files": [
45
+ "extensions/compaction.ts",
46
+ "extensions/web-search.ts",
47
+ "extensions/image-generation.ts",
48
+ "extensions/auto-mode.ts",
49
+ "src/compact-client.ts",
50
+ "src/config.ts",
51
+ "src/debug.ts",
52
+ "src/details-store.ts",
53
+ "src/deferred-tool-carryover.ts",
54
+ "src/extension-runtime.ts",
55
+ "src/context-management/types.ts",
56
+ "src/context-management/messages.ts",
57
+ "src/context-management/window-budget.ts",
58
+ "src/context-management/window-request.ts",
59
+ "src/context-management/window-manager.ts",
60
+ "src/context-management/codex-provider.ts",
61
+ "src/context-management/history-notes.ts",
62
+ "src/context-management/tools.ts",
63
+ "src/context-management/namespace-tools.ts",
64
+ "src/context-management/tool-contract.ts",
65
+ "src/image-generation/artifacts.ts",
66
+ "src/image-generation/client.ts",
67
+ "src/image-generation/eligibility.ts",
68
+ "src/image-generation/extension.ts",
69
+ "src/image-generation/protocol.ts",
70
+ "src/image-generation/references.ts",
71
+ "src/image-generation/render.ts",
72
+ "src/image-generation/service.ts",
73
+ "src/image-generation/types.ts",
74
+ "src/auto-mode/extension.ts",
75
+ "src/auto-mode/policy.ts",
76
+ "src/auto-mode/prompt.ts",
77
+ "src/auto-mode/transcript.ts",
78
+ "src/auto-mode/reviewer.ts",
79
+ "src/auto-mode/classifier.ts",
80
+ "src/auto-mode/types.ts",
81
+ "extensions/codex-astra.ts",
82
+ "src/codex-astra/effort-planner.ts",
83
+ "src/codex-astra/extension.ts",
84
+ "src/model-scope.ts",
85
+ "src/native-fallback.ts",
86
+ "src/payload-rewrite.ts",
87
+ "src/provider-headers.ts",
88
+ "src/responses-headers.ts",
89
+ "src/remote-v2-client.ts",
90
+ "src/request-context-cache.ts",
91
+ "src/runtime.ts",
92
+ "src/serializer.ts",
93
+ "src/supported-environment.ts",
94
+ "src/types.ts",
95
+ "src/web-search/extension.ts",
96
+ "src/web-search/payload.ts",
97
+ "src/web-search/prompt.ts",
98
+ "src/web-search/types.ts",
99
+ "README.md",
100
+ "README_zh.md",
101
+ "LICENSE",
102
+ "NOTICE",
103
+ "tsconfig.check.json"
104
+ ],
105
+ "scripts": {
106
+ "test": "bun test",
107
+ "test:coverage": "bun test --coverage --coverage-reporter=text --coverage-reporter=lcov && node ./scripts/check-lcov.mjs ./coverage/lcov.info",
108
+ "test:pi": "bun test ./test/pi-smoke.test.ts",
109
+ "typecheck": "tsc -p tsconfig.check.json"
110
+ },
111
+ "peerDependencies": {
112
+ "@earendil-works/pi-agent-core": ">=0.85.1",
113
+ "@earendil-works/pi-ai": ">=0.85.1",
114
+ "@earendil-works/pi-coding-agent": ">=0.85.1",
115
+ "@earendil-works/pi-tui": ">=0.85.1"
116
+ },
117
+ "devDependencies": {
118
+ "@earendil-works/pi-agent-core": "0.85.1",
119
+ "@earendil-works/pi-ai": "0.85.1",
120
+ "@earendil-works/pi-coding-agent": "0.85.1",
121
+ "@earendil-works/pi-tui": "0.85.1",
122
+ "@types/node": "24.12.4",
123
+ "bun": "1.2.23",
124
+ "typescript": "5.9.3"
125
+ }
126
+ }
package/src/config.ts CHANGED
@@ -30,6 +30,7 @@ import {
30
30
  type AutoModeGate,
31
31
  type CodexAstraConfig,
32
32
  type CompactionConfig,
33
+ type ContextManagementMode,
33
34
  type ImageGenerationConfig,
34
35
  type LoadedToolkitConfig,
35
36
  type NativeFallbackConfig,
@@ -43,10 +44,13 @@ export const CONFIG_PATH = path.join(CONFIG_DIR, "config.json");
43
44
  const TOP_LEVEL_FIELDS = new Set(["compaction", "webSearch", "imageGeneration", "autoMode", "codexAstra"]);
44
45
  const COMPACTION_FIELDS = new Set([
45
46
  "enabled",
47
+ "contextManagement",
48
+ "codexGatewayModels",
46
49
  "allowCompactionContinuityBreak",
47
50
  "remoteCompactModel",
48
51
  "nativeFallback",
49
52
  "responsesApis",
53
+ "contextReminderThresholdPercent",
50
54
  "notifyOnLoad",
51
55
  "debug",
52
56
  "logProviderPayloads",
@@ -131,6 +135,20 @@ function toBoolean(value: unknown, fieldPath: string, warnings: string[]): boole
131
135
  return undefined;
132
136
  }
133
137
 
138
+ function toContextManagementMode(
139
+ value: unknown,
140
+ fieldPath: string,
141
+ warnings: string[],
142
+ ): ContextManagementMode | undefined {
143
+ if (value === undefined) return undefined;
144
+ if (typeof value === "string") {
145
+ const normalized = value.trim();
146
+ if (normalized === "off" || normalized === "remote") return normalized;
147
+ }
148
+ warnings.push(`Ignoring ${fieldPath}: expected one of off, remote.`);
149
+ return undefined;
150
+ }
151
+
134
152
  function toModelSpec(value: unknown, fieldPath: string, warnings: string[]): string | null | undefined {
135
153
  if (value === undefined) return undefined;
136
154
  if (value === null) return null;
@@ -278,6 +296,17 @@ function applyCompactionConfig(
278
296
  warnUnknownFields(raw, COMPACTION_FIELDS, "compaction", warnings);
279
297
 
280
298
  resolved.enabled = toBoolean(raw.enabled, "compaction.enabled", warnings) ?? resolved.enabled;
299
+ resolved.contextManagement =
300
+ toContextManagementMode(raw.contextManagement, "compaction.contextManagement", warnings) ??
301
+ resolved.contextManagement;
302
+ const codexGatewayModels = toStringList(
303
+ raw.codexGatewayModels,
304
+ "compaction.codexGatewayModels",
305
+ warnings,
306
+ );
307
+ if (codexGatewayModels !== undefined) {
308
+ resolved.codexGatewayModels = codexGatewayModels;
309
+ }
281
310
  resolved.allowCompactionContinuityBreak =
282
311
  toBoolean(
283
312
  raw.allowCompactionContinuityBreak,
@@ -286,6 +315,16 @@ function applyCompactionConfig(
286
315
  ) ?? resolved.allowCompactionContinuityBreak;
287
316
  resolved.notifyOnLoad =
288
317
  toBoolean(raw.notifyOnLoad, "compaction.notifyOnLoad", warnings) ?? resolved.notifyOnLoad;
318
+ const reminderPercent = toBoundedInteger(
319
+ raw.contextReminderThresholdPercent,
320
+ "compaction.contextReminderThresholdPercent",
321
+ warnings,
322
+ 0,
323
+ 100,
324
+ );
325
+ if (reminderPercent !== undefined) {
326
+ resolved.contextReminderThresholdPercent = reminderPercent;
327
+ }
289
328
  resolved.debug = toBoolean(raw.debug, "compaction.debug", warnings) ?? resolved.debug;
290
329
  resolved.logProviderPayloads =
291
330
  toBoolean(raw.logProviderPayloads, "compaction.logProviderPayloads", warnings) ??