pi-openai-toolkit 0.11.1 → 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 +28 -0
- package/README.md +57 -23
- package/README_zh.md +57 -23
- package/package.json +126 -114
- package/src/config.ts +39 -69
- package/src/context-management/codex-provider.ts +261 -0
- package/src/context-management/history-notes.ts +325 -0
- package/src/context-management/messages.ts +106 -0
- package/src/context-management/namespace-tools.ts +426 -0
- package/src/context-management/tool-contract.ts +23 -0
- package/src/context-management/tools.ts +313 -0
- package/src/context-management/types.ts +160 -0
- package/src/context-management/window-budget.ts +83 -0
- package/src/context-management/window-manager.ts +427 -0
- package/src/context-management/window-request.ts +125 -0
- package/src/debug.ts +3 -3
- package/src/extension-runtime.ts +305 -18
- package/src/payload-rewrite.ts +40 -10
- package/src/remote-v2-client.ts +340 -99
- package/src/request-context-cache.ts +36 -3
- package/src/serializer.ts +4 -12
- package/src/types.ts +16 -19
- package/tsconfig.check.json +0 -1
- package/src/inline-compaction.ts +0 -1264
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 & 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 & Model-Reviewed Auto Mode</strong>
|
|
5
5
|
</p>
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
-
`pi-openai-toolkit` is an all-in-one OpenAI enhancement package for **Pi (>= 0.
|
|
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`):
|
|
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.
|
|
@@ -20,6 +20,8 @@
|
|
|
20
20
|
|
|
21
21
|
## Installation
|
|
22
22
|
|
|
23
|
+
Requires **Pi >= 0.85.1** and **Node.js >= 22.19.0**; older Pi versions are not supported. Pi supplies the GPT-6 Astra catalog and OpenAI API Key/Codex subscription login; Toolkit does not implement a separate login flow.
|
|
24
|
+
|
|
23
25
|
### Install the published package globally (recommended)
|
|
24
26
|
|
|
25
27
|
```bash
|
|
@@ -97,6 +99,8 @@ C:\Users\<user>\.pi\agent\extensions\pi-openai-toolkit\config.json
|
|
|
97
99
|
{
|
|
98
100
|
"compaction": {
|
|
99
101
|
"enabled": true,
|
|
102
|
+
"contextManagement": "off",
|
|
103
|
+
"codexGatewayModels": [],
|
|
100
104
|
"allowCompactionContinuityBreak": false,
|
|
101
105
|
"remoteCompactModel": "uwoacrimson/gpt-5.6-luna",
|
|
102
106
|
"nativeFallback": {
|
|
@@ -104,11 +108,6 @@ C:\Users\<user>\.pi\agent\extensions\pi-openai-toolkit\config.json
|
|
|
104
108
|
"model": null,
|
|
105
109
|
"thinkingLevel": "off"
|
|
106
110
|
},
|
|
107
|
-
"autoCompaction": {
|
|
108
|
-
"enabled": true,
|
|
109
|
-
"continuation": "inline",
|
|
110
|
-
"unsupportedFallback": "followUp"
|
|
111
|
-
},
|
|
112
111
|
"responsesApis": [
|
|
113
112
|
"openai-responses",
|
|
114
113
|
"openai-codex-responses"
|
|
@@ -134,7 +133,7 @@ C:\Users\<user>\.pi\agent\extensions\pi-openai-toolkit\config.json
|
|
|
134
133
|
"models": [
|
|
135
134
|
"uwoacrimson/gpt-5.6-luna"
|
|
136
135
|
],
|
|
137
|
-
"reviewerModel": "uwoacrimson/gpt-5.6-
|
|
136
|
+
"reviewerModel": "uwoacrimson/gpt-5.6-luna",
|
|
138
137
|
"gate": "side-effect",
|
|
139
138
|
"extraTools": [
|
|
140
139
|
"openai_generate_image"
|
|
@@ -168,22 +167,45 @@ C:\Users\<user>\.pi\agent\extensions\pi-openai-toolkit\config.json
|
|
|
168
167
|
|
|
169
168
|
#### `compaction`
|
|
170
169
|
|
|
171
|
-
- `enabled` (*boolean*, default: `true`): Enable or disable
|
|
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.
|
|
172
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).
|
|
173
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.
|
|
174
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.
|
|
175
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.
|
|
176
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"`).
|
|
177
|
-
- `
|
|
178
|
-
- `autoCompaction.continuation` (*`"inline" | "followUp" | "off"`*, default: `"inline"`): `inline` compacts inside the current official Pi 0.84.3 tool loop and refreshes the next provider context; `followUp` uses Pi's public hidden follow-up message path; `off` disables toolkit-triggered automatic compaction.
|
|
179
|
-
- `autoCompaction.unsupportedFallback` (*`"followUp" | "off"`*, default: `"followUp"`): Behavior when the guarded official-host inline adapter is unavailable. It does not change normal remote/native compaction fallback ordering.
|
|
180
|
-
- `autoCompaction.reserveTokens` (*non-negative integer*, optional): Override only the automatic trigger reserve. When omitted, the active Pi compaction setting is used. Pi's `keepRecentTokens` remains authoritative for compactability.
|
|
181
|
-
- `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"`.
|
|
182
179
|
- `notifyOnLoad` (*boolean*, default: `false`): Show a notification banner on Pi startup.
|
|
183
180
|
- `debug` (*boolean*, default: `false`): Output diagnostics and write execution artifacts to disk.
|
|
184
181
|
- `logProviderPayloads` / `logCompactResponses` (*boolean*, default: `false`): Write raw provider request payloads and compact SSE event bodies to artifacts.
|
|
185
|
-
- `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`.
|
|
186
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.
|
|
187
209
|
|
|
188
210
|
#### `webSearch`
|
|
189
211
|
|
|
@@ -226,6 +248,17 @@ Auto mode is opt-in through the empty-by-default `models` allowlist because it a
|
|
|
226
248
|
|
|
227
249
|
## Core Mechanics
|
|
228
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
|
+
|
|
229
262
|
### 1. Remote Compaction v2 Protocol
|
|
230
263
|
|
|
231
264
|
Instead of legacy JSON endpoints (`POST /responses/compact`), this toolkit implements the **`remote_compaction_v2`** protocol over standard streaming Responses:
|
|
@@ -254,14 +287,15 @@ Content-Type: application/json
|
|
|
254
287
|
2. Remote request attempted but failed on a model that *can* compact remotely → Pi's native `compact()` with `remoteCompactModel`, or the active model when no override is configured;
|
|
255
288
|
3. Model that cannot use remote v2 at all → Pi's native `compact()` with `compaction.nativeFallback.model`, or the active model when unset;
|
|
256
289
|
|
|
257
|
-
### 2.
|
|
290
|
+
### 2. Pi-Native Auto-Compaction and Continuation
|
|
258
291
|
|
|
259
|
-
|
|
292
|
+
**Pi 0.85.1+** owns automatic compaction. After tool results are appended and before the next assistant request, Pi checks its threshold, compacts eligible history and continues in the same run. Toolkit only supplies Remote v2 results and opaque replay through public hooks: no private host patches, extra compaction driver or hidden follow-up messages.
|
|
260
293
|
|
|
261
|
-
-
|
|
262
|
-
-
|
|
263
|
-
-
|
|
264
|
-
-
|
|
294
|
+
- Configure `compaction.enabled`, `compaction.reserveTokens` and `compaction.keepRecentTokens` in Pi's `~/.pi/agent/settings.json` or project `.pi/settings.json`.
|
|
295
|
+
- When Pi disables automatic compaction or has no eligible history, Toolkit does not start another driver. Manual `/compact` still uses the existing remote/native fallback chain.
|
|
296
|
+
- The retired Toolkit `compaction.autoCompaction` setting is ignored as an unknown field; your settings file is not rewritten.
|
|
297
|
+
- Remote v2 covers the complete compact input. A public `context` hook removes verified retained copies before encoding; persisted history is unchanged and new/transient messages survive.
|
|
298
|
+
- Cache parameters follow Pi's actual selection: applicable GPT-5.6+ long-cache requests retain `prompt_cache_options.ttl: "30m"`, while those models retain `mode: "explicit"` when caching is disabled. Toolkit does not force long caching on every request, and a different compactor only receives supported cache fields.
|
|
265
299
|
|
|
266
300
|
### 3. Model-Scoped Web Search
|
|
267
301
|
|
|
@@ -314,7 +348,7 @@ GPT-6 Astra is a Codex-backend (ChatGPT OAuth) model with two wire behaviors tha
|
|
|
314
348
|
- **Stable effort with `configuration_update`**: OpenAI prompt caching compares the request from the first byte, and the request-level `reasoning.effort` sits at the top - changing thinking level mid-conversation normally busts the whole cached prefix. Astra instead accepts a `configuration_update` input item that changes effort from that point onward while the request-level field stays put. This extension implements that for the active conversation: the first request pins the baseline effort, every later change is spliced into the transcript at the position it should take effect (before the user message it applies to, or after the latest tool result inside a tool loop), and the same item is replayed at that position on every following request. The request body keeps the baseline byte-stable, so the cache prefix survives level changes.
|
|
315
349
|
- **History-rewrite safety**: Each spliced item is anchored to a fingerprint of the transcript position it was inserted at. If a later request's history no longer matches - compaction, branch switch, `/clear`, anything rewrote the transcript - the baseline is discarded and the next request re-pins its own effort, rather than placing an update at a stale position.
|
|
316
350
|
- **Compaction isolation**: The compact endpoints reject histories containing `configuration_update` items. This is enforced in two places: the payload rewriter never splices items into a `compaction_trigger`-shaped request, and both compaction clients strip any such item defensively from replayed input, so an Astra session can still be compacted by this package.
|
|
317
|
-
- **Scope**: The rewrite applies only to models listed in `codexAstra.models` on either Responses wire family (Astra is the only SKU known to accept the item; anything else answers HTTP 400 on it - the allowlist is what encodes that knowledge for gateways that proxy it), only when the request actually carries a wire-level effort, and never to `off`/`none`. Everything runs inside a try/catch: any unexpected payload shape or planner failure leaves the request untouched. To avoid double-splicing when both this toolkit and a host that implements the same behavior (Oh My Pi itself) are active, enable this layer on only one side.
|
|
351
|
+
- **Scope**: The rewrite applies only to models listed in `codexAstra.models` on either Responses wire family (Astra is the only SKU known to accept the item; anything else answers HTTP 400 on it - the allowlist is what encodes that knowledge for gateways that proxy it), only when the request actually carries a wire-level effort, and never to `off`/`none`. Gateway pass-through was verified live: a `configuration_update` item placed before the user turn it applies to returned HTTP 200 with a completed response. Everything runs inside a try/catch: any unexpected payload shape or planner failure leaves the request untouched. To avoid double-splicing when both this toolkit and a host that implements the same behavior (Oh My Pi itself) are active, enable this layer on only one side.
|
|
318
352
|
|
|
319
353
|
Catalog note: Pi's bundled `openai-codex` model list does not include `gpt-6-astra` yet. Register it in `~/.pi/agent/models.json` under the built-in provider (custom models merge into the built-in list): `api: "openai-codex-responses"`, `baseUrl: "https://chatgpt.com/backend-api"`, `contextWindow: 272000`, `maxTokens: 128000`, and a `thinkingLevelMap` exposing `low` through `max`. Pi's Codex OAuth login supplies the token; this package reads it through Pi's `ModelRegistry` and never touches the credential store directly.
|
|
320
354
|
|
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
|
|
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">
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
-
`pi-openai-toolkit` 是专为 **Pi (>= 0.
|
|
13
|
+
`pi-openai-toolkit` 是专为 **Pi (>= 0.85.1)** 打造的 OpenAI 增强工具包,集成了五项针对 OpenAI Responses 协议的扩展:
|
|
14
14
|
|
|
15
|
-
1.
|
|
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 不必停下来等你确认也能继续推进。
|
|
@@ -20,6 +20,8 @@
|
|
|
20
20
|
|
|
21
21
|
## 安装使用
|
|
22
22
|
|
|
23
|
+
需要 **Pi >= 0.85.1** 与 **Node.js >= 22.19.0**;不再支持旧 Pi。GPT-6 Astra 的模型目录、OpenAI API Key 和 Codex 订阅登录由 Pi 提供,Toolkit 不重复实现登录流程。
|
|
24
|
+
|
|
23
25
|
### 全局安装已发布版本(推荐)
|
|
24
26
|
|
|
25
27
|
```bash
|
|
@@ -95,6 +97,8 @@ C:\Users\<user>\.pi\agent\extensions\pi-openai-toolkit\config.json
|
|
|
95
97
|
{
|
|
96
98
|
"compaction": {
|
|
97
99
|
"enabled": true,
|
|
100
|
+
"contextManagement": "off",
|
|
101
|
+
"codexGatewayModels": [],
|
|
98
102
|
"allowCompactionContinuityBreak": false,
|
|
99
103
|
"remoteCompactModel": "uwoacrimson/gpt-5.6-luna",
|
|
100
104
|
"nativeFallback": {
|
|
@@ -102,11 +106,6 @@ C:\Users\<user>\.pi\agent\extensions\pi-openai-toolkit\config.json
|
|
|
102
106
|
"model": null,
|
|
103
107
|
"thinkingLevel": "off"
|
|
104
108
|
},
|
|
105
|
-
"autoCompaction": {
|
|
106
|
-
"enabled": true,
|
|
107
|
-
"continuation": "inline",
|
|
108
|
-
"unsupportedFallback": "followUp"
|
|
109
|
-
},
|
|
110
109
|
"responsesApis": [
|
|
111
110
|
"openai-responses",
|
|
112
111
|
"openai-codex-responses"
|
|
@@ -132,7 +131,7 @@ C:\Users\<user>\.pi\agent\extensions\pi-openai-toolkit\config.json
|
|
|
132
131
|
"models": [
|
|
133
132
|
"uwoacrimson/gpt-5.6-luna"
|
|
134
133
|
],
|
|
135
|
-
"reviewerModel": "uwoacrimson/gpt-5.6-
|
|
134
|
+
"reviewerModel": "uwoacrimson/gpt-5.6-luna",
|
|
136
135
|
"gate": "side-effect",
|
|
137
136
|
"extraTools": [
|
|
138
137
|
"openai_generate_image"
|
|
@@ -166,22 +165,45 @@ C:\Users\<user>\.pi\agent\extensions\pi-openai-toolkit\config.json
|
|
|
166
165
|
|
|
167
166
|
#### `compaction`(压缩配置)
|
|
168
167
|
|
|
169
|
-
- `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。
|
|
170
171
|
- `allowCompactionContinuityBreak` (*boolean*, 默认 `false`): 若最近一次历史压缩由其他方式(如文本摘要)生成,设为 `true` 允许直接从当前有效文本上下文重建密文压缩链。
|
|
171
172
|
- `remoteCompactModel` (*string | null*, 默认 `null`): 仅用于 synthetic `remote_compaction_v2` 请求的模型,格式为 `"provider/model-id"`。Pi 不会切换当前会话模型,压缩完成后仍由原模型继续正常请求。覆盖模型必须与当前模型使用相同的实际生效 Base URL;Provider、Responses API 标识符和模型本身可以不同。为 `null` 时保持当前模型执行远端压缩的原有行为。
|
|
172
173
|
- `nativeFallback.enabled` (*boolean*, 默认 `true`): Toolkit 用显式摘要模型跑原生压缩的总开关。它不影响远端链路:`remote_compaction_v2` 照常被尝试,成功时照常生效。设为 `false` 只跳过失败后的那一步原生压缩,因此所有降级都直接交给 Pi 默认的当前模型压缩。
|
|
173
174
|
- `nativeFallback.model` (*string | null*, 默认 `null`): 摘要模型,格式为 `"provider/model-id"`(例如 `"openai/gpt-4o-mini"`),**仅**用于根本无法走远端 v2 的当前模型(非 Responses API,或 API 被 `responsesApis` 排除)。远端请求已经发出过的情境不会读这个字段;为 `null` 时由当前活动模型走 Pi 默认压缩路径。
|
|
174
175
|
- `nativeFallback.thinkingLevel` (*string*, 默认 `"off"`): 由本扩展指定模型时,传给 Pi 原生 `compact()` 的思考级别。
|
|
175
|
-
- `
|
|
176
|
-
- `autoCompaction.continuation` (*`"inline" | "followUp" | "off"`*, 默认 `"inline"`): `inline` 在官方 Pi 0.84.3 当前工具循环内完成压缩并刷新下一次 Provider 上下文;`followUp` 使用 Pi 公共的隐藏后续消息;`off` 关闭 Toolkit 触发的自动压缩。
|
|
177
|
-
- `autoCompaction.unsupportedFallback` (*`"followUp" | "off"`*, 默认 `"followUp"`): 官方 Host 私有 inline 适配器不可用时的处理方式,不改变原有远端/原生压缩降级顺序。
|
|
178
|
-
- `autoCompaction.reserveTokens` (*非负整数*, 可选): 仅覆盖自动触发阈值的保留 Token 数。未设置时使用当前 Pi 压缩配置;是否具有可压缩历史仍以 Pi 的 `keepRecentTokens` 为准。
|
|
179
|
-
- `responsesApis` (*string[]*): 允许尝试远端压缩的 API 标识符子集(从 `["openai-responses", "openai-codex-responses"]` 中选定)。
|
|
176
|
+
- `responsesApis` (*string[]*): 允许尝试远端压缩的 API 标识符子集(从 `["openai-responses", "openai-codex-responses"]` 中选定)。仅在 `contextManagement` 为 `"off"` 时影响压缩路径。
|
|
180
177
|
- `notifyOnLoad` (*boolean*, 默认 `false`): Pi 启动加载时是否弹出气泡提示。
|
|
181
178
|
- `debug` (*boolean*, 默认 `false`): 是否开启调试模式并记录诊断日志。
|
|
182
179
|
- `logProviderPayloads` / `logCompactResponses` (*boolean*, 默认 `false`): 是否在 Artifacts 中记录完整的 Provider 请求与 SSE 流事件体。
|
|
183
|
-
- `redactSensitiveData` (*boolean*, 默认 `true`): 对调试日志应用完整的敏感值脱敏。即使设为 `false`,Authorization 凭据、API Key/Token
|
|
180
|
+
- `redactSensitiveData` (*boolean*, 默认 `true`): 对调试日志应用完整的敏感值脱敏。即使设为 `false`,Authorization 凭据、API Key/Token、Codex account ID 以及 `encrypted_content` / `encrypted_output` 密文也始终会被替换为 `[REDACTED]`。
|
|
184
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 测试。
|
|
185
207
|
|
|
186
208
|
#### `webSearch`(联网搜索配置)
|
|
187
209
|
|
|
@@ -224,6 +246,17 @@ Auto 模式需要显式启用(`models` 默认为空),因为它相当于允
|
|
|
224
246
|
|
|
225
247
|
## 核心工作原理解析
|
|
226
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
|
+
|
|
227
260
|
### 1. Remote Compaction v2(远端密文压缩)
|
|
228
261
|
|
|
229
262
|
摒弃了老旧且不稳定的 `POST /responses/compact` JSON 端点,采用最新 **`remote_compaction_v2`** 标准流式协议:
|
|
@@ -252,14 +285,15 @@ Content-Type: application/json
|
|
|
252
285
|
2. 本可以远端压缩但网关报错或失败 → 用 `remoteCompactModel` 跑 Pi 原生 `compact()`,未配置覆盖模型则由当前活动模型执行;
|
|
253
286
|
3. 根本无法走远端的模型 → 用 `compaction.nativeFallback.model` 跑 Pi 原生 `compact()`,未配置则由当前活动模型执行;
|
|
254
287
|
|
|
255
|
-
### 2.
|
|
288
|
+
### 2. Pi 原生自动压缩与续跑
|
|
256
289
|
|
|
257
|
-
|
|
290
|
+
自动压缩完全由 **Pi 0.85.1+** 管理。Pi 在工具结果写入后、下一次 assistant 请求前检查上下文阈值,符合条件时在同一次运行中压缩并继续。Toolkit 只通过公共 Hook 提供 Remote v2 结果和密文回放,不安装私有补丁、不额外触发压缩,也不发送隐藏续跑消息。
|
|
258
291
|
|
|
259
|
-
-
|
|
260
|
-
-
|
|
261
|
-
-
|
|
262
|
-
-
|
|
292
|
+
- 在 Pi 的 `~/.pi/agent/settings.json` 或项目 `.pi/settings.json` 中配置 `compaction.enabled`、`compaction.reserveTokens` 和 `compaction.keepRecentTokens`。
|
|
293
|
+
- Pi 关闭自动压缩或没有可压缩历史时,Toolkit 不另开一套驱动;手动 `/compact` 仍使用原有远端/原生降级链路。
|
|
294
|
+
- Toolkit 配置中的旧 `compaction.autoCompaction` 已移除;旧键会按未知字段忽略,不会修改你的配置文件。
|
|
295
|
+
- Remote v2 已包含完整压缩输入。公共 `context` Hook 在编码前移除能确认已被 checkpoint 覆盖的近期消息副本;会话存档不变,压缩后的新消息和临时注入内容保留。
|
|
296
|
+
- 缓存参数遵循 Pi 的实际选择:适用的 GPT-5.6+ 长缓存保留 `prompt_cache_options.ttl: "30m"`,这些模型关闭缓存时保留 `mode: "explicit"`,不会对所有请求强制开启长缓存。不同压缩模型只接收其支持的参数。
|
|
263
297
|
|
|
264
298
|
### 3. 按模型启用的联网搜索
|
|
265
299
|
|
|
@@ -312,7 +346,7 @@ GPT-6 Astra 是 Codex 后端(ChatGPT OAuth)上的模型,有两个普通 Op
|
|
|
312
346
|
- **stable effort + `configuration_update`**:OpenAI 提示缓存从请求第一个字节开始比对,而请求级 `reasoning.effort` 就在头部——中途换思考档位通常会打爆整个缓存前缀。Astra 接受一种 `configuration_update` 输入项,从该项位置起改档位而不动请求级字段。本扩展把这套机制接到当前会话:首个请求钉住基线档位,之后的每次变更插入到它应生效的会话位置(作效于哪条用户消息就插在哪条之前,工具循环中途变更插在最近一条工具结果之后),后续请求在同一位置重放该项,请求体开头始终字节不变,缓存前缀存活。
|
|
313
347
|
- **历史重写安全**:每个插入项都锚定在它所在位置前一条内容的指纹上。后续请求的历史对不上(压缩、切分支、`/clear`,任何历史重写),基线直接作废,下一次请求用自己的档位重新钉基线,而不是把更新插到过期位置。
|
|
314
348
|
- **压缩隔离**:compact 端点拒绝含 `configuration_update` 的历史。两层防御:payload 改写器对带 `compaction_trigger` 的请求绝不插入;两个压缩客户端对回放输入里的该类项一律防御性剥离——所以 Astra 会话照常被本包压缩。
|
|
315
|
-
- **适用范围**:改写只作用于两种 Responses 线协议家族内 `codexAstra.models` 白名单中的模型(目前已知只有 astra 接受该 item,其他模型碰它就 400——网关代理同一模型时,白名单就是声明这件事的地方),且只改真正携带线上级 effort 的请求,`off`/`none`
|
|
349
|
+
- **适用范围**:改写只作用于两种 Responses 线协议家族内 `codexAstra.models` 白名单中的模型(目前已知只有 astra 接受该 item,其他模型碰它就 400——网关代理同一模型时,白名单就是声明这件事的地方),且只改真正携带线上级 effort 的请求,`off`/`none` 不动。网关透传已实测:插在生效用户消息之前的 `configuration_update` 返回 HTTP 200 且响应完整。整个钩子在 try/catch 里,任何意外形状或规划失败都原样放行请求。若 host 自身已实现同样行为(例如 Oh My Pi),两边只开一个,避免双重插入。
|
|
316
350
|
|
|
317
351
|
目录说明:Pi 内置的 `openai-codex` 模型列表还没有 `gpt-6-astra`,需要在 `~/.pi/agent/models.json` 内置 provider 下注册(自定义 models 会与内置列表合并):`api: "openai-codex-responses"`、`baseUrl: "https://chatgpt.com/backend-api"`、`contextWindow: 272000`、`maxTokens: 128000`,并用 `thinkingLevelMap` 声明 `low` 到 `max`。登录用 Pi 的 Codex OAuth 流程;本包通过 Pi 的 `ModelRegistry` 读凭据,不碰存储文件。
|
|
318
352
|
|