pi-openai-toolkit 0.13.0 → 0.13.1
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/README.md +250 -379
- package/README.zh.md +253 -0
- package/package.json +3 -3
- package/README_zh.md +0 -377
package/README.md
CHANGED
|
@@ -1,379 +1,250 @@
|
|
|
1
|
-
# pi-openai-toolkit
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
`
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
pi
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
{
|
|
100
|
-
"
|
|
101
|
-
"enabled": true,
|
|
102
|
-
"
|
|
103
|
-
"
|
|
104
|
-
"
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
- `
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
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
|
-
|
|
262
|
-
### 1. Remote Compaction v2 Protocol
|
|
263
|
-
|
|
264
|
-
Instead of legacy JSON endpoints (`POST /responses/compact`), this toolkit implements the **`remote_compaction_v2`** protocol over standard streaming Responses:
|
|
265
|
-
|
|
266
|
-
```http
|
|
267
|
-
POST /responses
|
|
268
|
-
Content-Type: application/json
|
|
269
|
-
|
|
270
|
-
{
|
|
271
|
-
"model": "...",
|
|
272
|
-
"input": [
|
|
273
|
-
...currentResponsesInput,
|
|
274
|
-
{ "type": "compaction_trigger" }
|
|
275
|
-
],
|
|
276
|
-
"stream": true,
|
|
277
|
-
"store": false
|
|
278
|
-
}
|
|
279
|
-
```
|
|
280
|
-
|
|
281
|
-
- **Validation Criteria**: Must return a valid SSE stream with `response.completed` (status `completed`) containing exactly one output item of `type: "compaction"` with non-empty `encrypted_content`.
|
|
282
|
-
- **Remote Model Override**: `compaction.remoteCompactModel` can assign a same-gateway Responses model as the checkpoint producer while the active model remains the consumer. Its registered model metadata, authentication, headers, and effective base URL are used only for the synthetic compact request. Existing and recursive checkpoints remain replayable by the active model.
|
|
283
|
-
- **Zero Loss Replay**: The opaque encrypted item is stored in `CompactionEntry.details.compactedWindow`. On subsequent requests, it is transparently prepended after fresh preamble instructions alongside live turns, eliminating lossy text re-summaries.
|
|
284
|
-
- **Fail-Closed Replay Guard**: Replay anchors on the Pi-authored compaction summary item by content and replaces it with the opaque compacted window; the post-compaction context is preserved verbatim, so transient messages injected by other extensions no longer block replay. If the summary anchor cannot be found, the toolkit aborts the provider request, shows an error notification, and always writes a content-free `*-replay-failure.json` artifact even when `logProviderPayloads` is disabled. The sentinel-only payload is never sent to the model.
|
|
285
|
-
- **Graceful Multi-Tier Fallback**:
|
|
286
|
-
1. Compatible Responses endpoints → Remote v2 Opaque Compaction.
|
|
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;
|
|
288
|
-
3. Model that cannot use remote v2 at all → Pi's native `compact()` with `compaction.nativeFallback.model`, or the active model when unset;
|
|
289
|
-
|
|
290
|
-
### 2. Pi-Native Auto-Compaction and Continuation
|
|
291
|
-
|
|
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.
|
|
293
|
-
|
|
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.
|
|
299
|
-
|
|
300
|
-
### 3. Model-Scoped Web Search
|
|
301
|
-
|
|
302
|
-
For allowlisted models using `openai-responses` or `openai-codex-responses`, the extension hooks into `before_provider_request` and `before_agent_start`:
|
|
303
|
-
|
|
304
|
-
- Injects `{ "type": "web_search" }` tool definition into the payload.
|
|
305
|
-
- Appends `web_search_call.action.sources` to the Responses `include` array.
|
|
306
|
-
- Appends concise search prompting to the system instructions.
|
|
307
|
-
- **Zero-Latency**: Uses Pi's existing connection, auth headers, and base URL without standalone HTTP overhead.
|
|
308
|
-
- **Toolkit Ownership**: For an eligible model, the outgoing payload removes the local function tool named `web_search` so native search is the only search path. Switching to an ineligible model restores that local tool's previous active state.
|
|
309
|
-
|
|
310
|
-
### 4. Native Image Generation and Editing
|
|
311
|
-
|
|
312
|
-
When `imageGeneration.enabled` is `true` and the active model speaks a Responses API, Pi exposes the sequential `openai_generate_image` tool:
|
|
313
|
-
|
|
314
|
-
- **Isolated request**: Sends one non-streaming, `store: false` Responses request containing only the image prompt and explicitly approved references. It does not forward recent conversation history and does not automatically retry after dispatch, avoiding accidental duplicate charges.
|
|
315
|
-
- **Generation and editing**: Supports text-to-image or editing with 1-5 explicitly supplied local PNG, JPEG, or WebP reference paths. Reference upload always requires interactive confirmation; headless sessions reject reference uploads.
|
|
316
|
-
- **Same route, fixed image model**: Reuses the current model's effective base URL, authentication, and provider headers, but requests the hosted `gpt-image-2` tool. It does not use a separate Codex OAuth flow or switch the active Pi model.
|
|
317
|
-
- **PNG artifacts**: Validates the returned PNG and saves it under `<Pi agent dir>/generated-images/<session-id>/<image-call-id>.png`. Existing files are never overwritten.
|
|
318
|
-
- **Safe optional copy**: A relative output path is allowed only in a trusted project. Paths outside both the trusted project and Pi agent directory require interactive confirmation. Output is PNG-only and existing destinations are rejected.
|
|
319
|
-
- **Compact session data**: Tool results contain paths and bounded metadata, never image base64. The Pi TUI preview reads the canonical artifact from disk when image display is supported; deleting the artifact removes the preview. Explicit reference path strings remain part of the tool-call arguments, but reference bytes do not.
|
|
320
|
-
- **Headless behavior**: Text-to-image with the default artifact path remains available without a UI. Reference uploads and external output paths that require approval are rejected in headless sessions.
|
|
321
|
-
- **Billing and verification boundary**: The configured gateway/provider remains the billing authority; the tool does not synthesize Pi usage or cost metadata. Deterministic tests and smoke checks never dispatch image generation, and no live paid probe runs without separate explicit approval.
|
|
322
|
-
|
|
323
|
-
### 5. Model-Reviewed Auto Mode
|
|
324
|
-
|
|
325
|
-
Pi does not prompt before running `bash`, `write`, or `edit`; the only built-in trust prompt concerns project-local settings. This extension adds the approval gate and lets a reviewer model operate it, mirroring Codex's `approval_policy` plus `approvals_reviewer` pairing.
|
|
326
|
-
|
|
327
|
-
- **Engagement is non-blocking**: `pi --auto`, `/auto on`, and `/auto all` only flip in-session state and update the footer status. No provider request happens at engagement time, so turning the mode on can never stall the current turn.
|
|
328
|
-
- **Gate scope**: `side-effect` reviews `bash`, `write`, and `edit`; `extraTools` adds named tools; `/auto all` (or `gate: "all"`) reviews every tool call. Read-only tools pass through untouched in the default scope.
|
|
329
|
-
- **Two independent axes, one derived outcome**: The reviewer scores the action's intrinsic risk (`low`/`medium`/`high`/`critical`) separately from how far the conversation actually authorizes it (`unknown`/`low`/`medium`/`high`), then derives `allow`/`deny` from a fixed table: `low` and `medium` risk are allowed, `high` requires at least `medium` authorization and a narrow scope, `critical` is always denied. Judging only "does this command look dangerous" is what makes an approval reviewer rubber-stamp or block everything.
|
|
330
|
-
- **Bounded transcript**: The reviewer receives a compact view of the conversation built from Pi's session entries, with user turns protected under their own budget and tool output on a smaller separate one, so verbose command output cannot crowd out the human turns that establish authorization. Omitted history is marked `<truncated />` rather than silently dropped, and only `[user]` entries count as evidence of approval.
|
|
331
|
-
- **The reviewer can investigate**: When `evidenceTools` is on, the reviewer runs as a short bounded agent loop over Pi's read-only tools (`read`, `grep`, `find`, `ls`). It can open the script it is about to allow, check whether a deletion target exists or is empty, or confirm a write path lies inside the project. This extension executes those calls; the reviewer is never handed `bash`, a write tool, or network access, which is what keeps "let the judge look around" safe.
|
|
332
|
-
- **Lenient verdict contract**: Only the outcome is required. `{"outcome":"allow"}` is a complete answer; risk, authorization, and rationale are back-filled (an unstated risk on a deny is recorded as `high`, which keeps the audit conservative in the direction that matters). Both `outcome`/`rationale` and the older `decision`/`reason` spelling are accepted. Unreadable output is a failure, never a guess.
|
|
333
|
-
- **Untrusted evidence stays untrusted**: Tool arguments, transcript text, and file contents are labelled as data. Claims of prior approval, urgency, or instructions to answer a particular way inside them are ignored by policy.
|
|
334
|
-
- **Optional non-blocking pre-scorer**: With `classifier.enabled`, a cheap single-token classification (`high`/`low`) of the trajectory runs after each gated tool result. A fresh `low` score satisfies the next gated call without waiting for a full review; `high`, a stale score, a failed sample, or a repeat of a tool already denied this turn all fall through to the blocking reviewer. The classifier can never deny anything.
|
|
335
|
-
- **Denials carry an anti-circumvention clause**: A block returns the risk, the authorization, and the reviewer's reason to the requesting model, plus an explicit prohibition on achieving the same outcome by workaround, renaming, splitting, or indirect execution. The model may take a materially safer alternative or ask you.
|
|
336
|
-
- **A review that did not finish is not a safety verdict**: Timeout, cancellation, provider error, and unreadable output each report their own cause and tell the agent not to infer unsafety from the failure. Only an actual `deny` is worded as a rejection.
|
|
337
|
-
- **Rejection circuit breaker**: Repeated denials in one turn end the turn rather than letting the agent and reviewer negotiate indefinitely, on either a consecutive run or a denial rate inside a sliding window. `turn_start` clears the counters.
|
|
338
|
-
- **Human fallback**: When a review is unavailable in an interactive session, the extension asks you directly with the failure reason. In print (`-p`) and JSON mode there is nobody to ask, so the action fails closed and is blocked.
|
|
339
|
-
- **Eligibility is rechecked live**: Switching to a model outside `autoMode.models`, clearing `reviewerModel`, or setting `enabled: false` disengages immediately. Returning to an allowlisted model does not re-engage automatically; you must ask again with `/auto on`.
|
|
340
|
-
- **Bounded audit trail**: Every decision is persisted as a custom session entry (`pi-openai-toolkit.auto-mode-decision.v1`) containing the tool name, call id, decision, bounded rationale, reviewer model, risk level, user authorization, investigation rounds used, and decision source (`reviewer`, `classifier`, `human`, `policy`, or `circuit-breaker`). Custom entries never enter LLM context, and tool arguments are not recorded.
|
|
341
|
-
- **Cost boundary**: Each gated call costs at least one reviewer completion, and enabling `evidenceTools` lets that review expand into up to `maxEvidenceRounds` extra completions. The pre-scorer adds one small completion per gated tool result when enabled. Reviewer completions run with prompt caching disabled, and the reviewer can execute nothing beyond the read-only tools listed above.
|
|
342
|
-
|
|
343
|
-
### 6. Codex GPT-6 Astra Compatibility
|
|
344
|
-
|
|
345
|
-
GPT-6 Astra is a Codex-backend (ChatGPT OAuth) model with two wire behaviors that a plain OpenAI client does not get for free. This layer covers both, adapted from Oh My Pi 18.1.8 (MIT).
|
|
346
|
-
|
|
347
|
-
- **Backend version gate**: The Codex backend admits or hides model SKUs by the `version` header, and `gpt-6-astra` requires at least `0.153.0`. The extension sets that pin on every live `openai-codex-responses` request via `before_provider_headers` (only when the host has not set one), and the package's own synthetic requests - remote compaction v2, native compact v1, hosted image generation - carry the same pin from the shared header builder. The pinned value tracks the upstream `CODEX_CLIENT_VERSION`; when OpenAI raises the gate, that constant is what changes.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
352
|
-
|
|
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.
|
|
354
|
-
|
|
355
|
-
---
|
|
356
|
-
|
|
357
|
-
## Development & Testing
|
|
358
|
-
|
|
359
|
-
```bash
|
|
360
|
-
# Typecheck TypeScript definitions
|
|
361
|
-
npm run typecheck
|
|
362
|
-
|
|
363
|
-
# Run full test suite with Bun
|
|
364
|
-
bun test
|
|
365
|
-
|
|
366
|
-
# Run Pi integration smoke tests
|
|
367
|
-
npm run test:pi
|
|
368
|
-
|
|
369
|
-
# Dry-run package archive
|
|
370
|
-
npm pack --dry-run
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
---
|
|
374
|
-
|
|
375
|
-
## License & Acknowledgments
|
|
376
|
-
|
|
377
|
-
- Licensed under the **MIT License**. See [LICENSE](./LICENSE) for details.
|
|
378
|
-
- Native Web Search behavior was adapted from [`code-yeongyu/pi-openai-web-search`](https://github.com/code-yeongyu/pi-openai-web-search) (commit `39643380682f02f306b0de2673ff136c45ccc2a2`). See [NOTICE](./NOTICE).
|
|
379
|
-
- [LINUX DO](https://linux.do/) community.
|
|
1
|
+
# pi-openai-toolkit
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/pi-openai-toolkit)
|
|
4
|
+
[](./LICENSE)
|
|
5
|
+
|
|
6
|
+
OpenAI toolkit for Pi: Codex Remote Context windows, remote compaction v2, hosted Web Search, image gen, auto mode.
|
|
7
|
+
|
|
8
|
+
`pi-openai-toolkit` bundles five Pi extensions for the OpenAI Responses wire family (`openai-responses` and `openai-codex-responses`):
|
|
9
|
+
|
|
10
|
+
1. **Compaction & Remote Context** (`extensions/compaction.ts`): two long-context strategies. [Codex Remote Context management](#codex-remote-context-management) ports Codex's native window lifecycle to Pi — no-summary `new_context` rollover with a hard notes-checkpoint gate, cross-window `history` / `notes` tools with encrypted argument transport, and budgeted checkpoint reminders. With it off, the extension runs **Remote Compaction v2**: server-side opaque encrypted compaction that never re-summarizes your conversation into lossy text.
|
|
11
|
+
2. **Web Search** (`extensions/web-search.ts`): hosted `web_search` injection for an exact `provider/model-id` allowlist, reusing the live model connection.
|
|
12
|
+
3. **Image Generation** (`extensions/image-generation.ts`): a local `openai_generate_image` tool backed by the hosted `image_generation` tool, for text-to-image and explicit local-reference edits without putting image bytes into session history.
|
|
13
|
+
4. **Auto Mode** (`extensions/auto-mode.ts`): a reviewer-model approval gate on state-changing tool calls so the agent keeps working without interrupting you.
|
|
14
|
+
5. **Codex Astra** (`extensions/codex-astra.ts`): Codex backend version-gate headers and cache-preserving `configuration_update` effort changes for `gpt-6-astra`.
|
|
15
|
+
|
|
16
|
+
The package is a Pi extension set, not an importable library: everything is configured through one JSON file and activated automatically inside Pi.
|
|
17
|
+
|
|
18
|
+
## Table of Contents
|
|
19
|
+
- [Security](#security)
|
|
20
|
+
- [Background](#background)
|
|
21
|
+
- [Install](#install)
|
|
22
|
+
- [Usage](#usage)
|
|
23
|
+
- [Configuration](#configuration)
|
|
24
|
+
- [Feature guides](#feature-guides)
|
|
25
|
+
- [Development](#development)
|
|
26
|
+
- [API](#api)
|
|
27
|
+
- [Remote Context tools](#remote-context-tools)
|
|
28
|
+
- [HTTP protocol reference](#http-protocol-reference)
|
|
29
|
+
- [Maintainers](#maintainers)
|
|
30
|
+
- [Contributing](#contributing)
|
|
31
|
+
- [License](#license)
|
|
32
|
+
|
|
33
|
+
## Security
|
|
34
|
+
|
|
35
|
+
- **No silent lossy summaries on covered models.** While `contextManagement: "remote"` covers a model, Pi-native compaction is cancelled on every path (threshold, manual `/compact`, overflow) even if the remote runtime is inactive, and v2 is never sent. If you additionally want host-level belt-and-braces, set `"compaction": { "enabled": false }` in Pi's `settings.json`; uncovered models keep Pi's normal policy either way.
|
|
36
|
+
- **Gateway isolation.** Gateway-mode Remote Context forwards only the configured data-plane key; OAuth tokens, account cookies, and account ids are stripped, and artifacts always redact credentials, account ids, and opaque encrypted payloads.
|
|
37
|
+
- **Checkpoint gate.** `new_context` cannot discard unsaved working state without either a successful notes write in the window or an explicit `force` the user authorized — the failure mode reported against Codex's own experimental rollout is blocked here.
|
|
38
|
+
- **Billing and review boundaries.** Image generation is opt-in and may incur charges; auto mode reviews run with caching disabled, grant the reviewer read-only tools only, and fail closed in headless sessions.
|
|
39
|
+
|
|
40
|
+
## Background
|
|
41
|
+
|
|
42
|
+
Pi's built-in compaction summarizes old turns into text, which loses detail; the OpenAI Codex backend instead offers two lossless mechanisms that plain clients do not get for free: the `remote_compaction_v2` SSE protocol (an encrypted opaque checkpoint replaces the summarized prefix) and the experimental **context-window system** (`new_context`, `history`, `notes`) that rolls the window over without any summary at all. This toolkit implements both against the live backends, verified end to end on Codex OAuth and on a Codex-compatible gateway relay (NEWapi + CLIProxyAPI).
|
|
43
|
+
|
|
44
|
+
Provenance: the Remote Context protocol was reverse-engineered from `@howaboua/pi-codex-conversion@3.0.29` (source commit `7021ae48e8efe36a3becc5830d529696ff798e5e`); the Astra compatibility layer is adapted from Oh My Pi 18.1.8 (MIT); Web Search behavior was adapted from [`pi-openai-web-search`](https://github.com/code-yeongyu/pi-openai-web-search) (commit `3964338`). Attribution details are in [NOTICE](./NOTICE). The alpha `history`/`notes` endpoints may change upstream without notice; endpoint and header fixtures in this repository must be updated together with them.
|
|
45
|
+
|
|
46
|
+
Requires **Pi >= 0.85.1** and **Node.js >= 22.19.0**. Pi supplies the model catalog and Codex/API-key login; this toolkit never implements its own login flow and never touches the credential store directly.
|
|
47
|
+
|
|
48
|
+
## Install
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pi install npm:pi-openai-toolkit
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
This registers the package in Pi's global settings; verify with `pi list`. For a single project instead:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pi install npm:pi-openai-toolkit --local
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
From git (development or pinned builds):
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pi install git:github.com/awoaCrim/pi-openai-toolkit
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Updating
|
|
67
|
+
|
|
68
|
+
`pi update --extensions` updates Pi packages including this toolkit. Published versions are on [npm](https://www.npmjs.com/package/pi-openai-toolkit).
|
|
69
|
+
|
|
70
|
+
### Conflict warning
|
|
71
|
+
|
|
72
|
+
Do not run `pi-remote-compact`, `@lll9p/pi-better-compaction`, or a standalone `pi-openai-web-search` alongside this toolkit: duplicate hooks cause race conditions and duplicated system prompts.
|
|
73
|
+
|
|
74
|
+
## Usage
|
|
75
|
+
|
|
76
|
+
All features are controlled by one configuration file, plus per-session commands. With no config file present, compaction and Astra are enabled on eligible models while Web Search, image generation, auto mode, and Remote Context stay opt-in.
|
|
77
|
+
|
|
78
|
+
Create `~/.pi/agent/extensions/pi-openai-toolkit/config.json` (Windows: `C:\Users\<user>\.pi\agent\extensions\pi-openai-toolkit\config.json`):
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"compaction": {
|
|
83
|
+
"enabled": true,
|
|
84
|
+
"contextManagement": "remote",
|
|
85
|
+
"codexGatewayModels": ["uwoacrimson/gpt-6-astra"],
|
|
86
|
+
"contextReminderThresholdPercent": 10,
|
|
87
|
+
"allowCompactionContinuityBreak": false,
|
|
88
|
+
"remoteCompactModel": "uwoacrimson/gpt-5.6-luna",
|
|
89
|
+
"nativeFallback": { "enabled": true, "model": null, "thinkingLevel": "off" },
|
|
90
|
+
"responsesApis": ["openai-responses", "openai-codex-responses"],
|
|
91
|
+
"notifyOnLoad": false,
|
|
92
|
+
"debug": false,
|
|
93
|
+
"logProviderPayloads": false,
|
|
94
|
+
"logCompactResponses": false,
|
|
95
|
+
"redactSensitiveData": true,
|
|
96
|
+
"artifactRoot": "~/.pi/agent/artifacts/pi-openai-toolkit/compaction"
|
|
97
|
+
},
|
|
98
|
+
"webSearch": { "enabled": true, "models": ["uwoacrimson/gpt-5.6-luna"] },
|
|
99
|
+
"imageGeneration": { "enabled": false },
|
|
100
|
+
"autoMode": {
|
|
101
|
+
"enabled": true,
|
|
102
|
+
"models": ["uwoacrimson/gpt-5.6-luna"],
|
|
103
|
+
"reviewerModel": "uwoacrimson/gpt-5.6-luna",
|
|
104
|
+
"gate": "side-effect"
|
|
105
|
+
},
|
|
106
|
+
"codexAstra": { "enabled": true, "models": ["uwoacrimson/gpt-6-astra"] }
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Then start Pi as usual; the toolkit loads automatically and hooks every session:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
pi --model uwoacrimson/gpt-6-astra "resume the deploy task"
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Configuration
|
|
117
|
+
|
|
118
|
+
Every key is optional; unknown keys are ignored with a warning rather than written back to your file. `models`-style keys are exact `provider/model-id` allowlists — trimming only, no globbing — so each feature is off until you list a model for it.
|
|
119
|
+
|
|
120
|
+
#### `compaction`
|
|
121
|
+
|
|
122
|
+
| Key | Type / default | Meaning |
|
|
123
|
+
| --- | --- | --- |
|
|
124
|
+
| `enabled` | *boolean*, `true` | Master switch for the compaction extension's hooks. |
|
|
125
|
+
| `contextManagement` | `"off"` \| `"remote"`, `"off"` | Opt into Codex Remote Context management for native Codex models and `codexGatewayModels` entries. While it owns a covered model, `remote_compaction_v2` is never sent and Pi-native compaction is cancelled (see [Security](#security)). Set back to `"off"` to roll back. |
|
|
126
|
+
| `codexGatewayModels` | *string[]*, `[]` | Exact `provider/model-id` entries allowed to run Remote Context through a Codex-compatible gateway (e.g. `"uwoacrimson/gpt-5.6-luna"` on `openai-responses`). The gateway receives the bare model id in `X-Codex-Model` and keeps the configured `/v1` base URL. |
|
|
127
|
+
| `contextReminderThresholdPercent` | *integer* `0`-`100`, `5` | Remote Context: inject the once-per-window checkpoint reminder when remaining tokens fall below this percentage of the context window. `0` disables reminders; the exhausted-window fallback still fires. Set it comfortably above Pi's native reserve band (default 16384 tokens ≈ 6% of a 272k window) so the model can roll over before the native threshold. |
|
|
128
|
+
| `allowCompactionContinuityBreak` | *boolean*, `false` | v2 path: restart a fresh opaque chain from current session text when the latest compaction was made by another strategy (e.g. a text summary). |
|
|
129
|
+
| `remoteCompactModel` | *string \| null*, `null` | v2 path: `provider/model-id` used only for the synthetic `remote_compaction_v2` request; the session model never switches. Must resolve to the same effective base URL as the active model. |
|
|
130
|
+
| `nativeFallback.enabled` | *boolean*, `true` | Toolkit-driven native compaction with an explicit summary model when the remote request was attempted and failed. Never touches a successful remote chain. |
|
|
131
|
+
| `nativeFallback.model` | *string \| null*, `null` | Summary model for models that cannot use v2 at all (non-Responses API, or excluded via `responsesApis`). `null` keeps the active model. |
|
|
132
|
+
| `nativeFallback.thinkingLevel` | *string*, `"off"` | Thinking level passed to Pi's `compact()` when this extension supplies the model (`off`, `minimal`, `low`, `medium`, `high`, `xhigh`, `max`). |
|
|
133
|
+
| `responsesApis` | *string[]*, both APIs | Narrow which Responses API identifiers may use remote compaction. Applies only when `contextManagement` is `"off"`. |
|
|
134
|
+
| `notifyOnLoad` | *boolean*, `false` | Startup notification banner. |
|
|
135
|
+
| `debug` | *boolean*, `false` | Write lifecycle and compaction artifacts under `artifactRoot`, including the Remote Context activation reason per `session_start`. |
|
|
136
|
+
| `logProviderPayloads` / `logCompactResponses` | *boolean*, `false` | Additionally write raw provider request payloads and compact SSE bodies to artifacts. Keep off unless inspecting a specific request. |
|
|
137
|
+
| `redactSensitiveData` | *boolean*, `true` | Full artifact redaction. Authorization credentials, API keys/tokens, Codex account ids, and opaque `encrypted_content` / `encrypted_output` are always redacted even when this is `false`. |
|
|
138
|
+
| `artifactRoot` | *string*, `~/.pi/agent/artifacts/pi-openai-toolkit/compaction` | Artifact directory root; relative paths resolve against the config directory. |
|
|
139
|
+
|
|
140
|
+
#### `webSearch`
|
|
141
|
+
|
|
142
|
+
| Key | Type / default | Meaning |
|
|
143
|
+
| --- | --- | --- |
|
|
144
|
+
| `enabled` | *boolean*, `true` | Master switch. |
|
|
145
|
+
| `models` | *string[]*, `[]` | Exact allowlist of `provider/model-id` sessions that receive hosted `web_search` injection on `openai-responses` / `openai-codex-responses`. For a listed model the local `web_search` function tool is removed from the payload so native search is the only path; switching away restores it. |
|
|
146
|
+
|
|
147
|
+
#### `imageGeneration`
|
|
148
|
+
|
|
149
|
+
| Key | Type / default | Meaning |
|
|
150
|
+
| --- | --- | --- |
|
|
151
|
+
| `enabled` | *boolean*, `false` | Single opt-in switch for the `openai_generate_image` tool. Off by default because every successful request may incur a charge. No model allowlist: the hosted tool is a capability of the Responses API, so it is exposed to every active model on a Responses wire and hidden elsewhere. |
|
|
152
|
+
|
|
153
|
+
#### `autoMode`
|
|
154
|
+
|
|
155
|
+
| Key | Type / default | Meaning |
|
|
156
|
+
| --- | --- | --- |
|
|
157
|
+
| `enabled` | *boolean*, `true` | Master switch; the mode still cannot engage until a model is allowlisted and `reviewerModel` is set. |
|
|
158
|
+
| `models` | *string[]*, `[]` | Allowlist of active session models permitted to run in auto mode. |
|
|
159
|
+
| `reviewerModel` | *string \| null*, `null` | Approving model (`provider/model-id`, resolved through Pi's registry). Used only for one-off reviews; never becomes the conversation model. |
|
|
160
|
+
| `gate` | `"side-effect"` \| `"all"`, `"side-effect"` | Which tool calls are reviewed. `/auto all` flips the session scope to everything. |
|
|
161
|
+
| `extraTools` | *string[]*, `[]` | Additional reviewed names on top of the side-effect set (`bash`, `write`, `edit`). |
|
|
162
|
+
| `timeoutMs` | *integer* 1000-120000, `30000` | Reviewer deadline across all rounds. Expiry is never approval. |
|
|
163
|
+
| `transcript` | *boolean*, `true` | Give the reviewer a bounded view of the conversation so it can judge authorization, not just intrinsic risk. |
|
|
164
|
+
| `evidenceTools` | *boolean*, `true` | Let the reviewer run Pi's read-only tools (`read`, `grep`, `find`, `ls`) to establish facts. It never receives `bash`, write tools, or network access. |
|
|
165
|
+
| `maxEvidenceRounds` | *integer* 0-8, `3` | Investigation rounds before the reviewer must answer; `0` is a single completion. |
|
|
166
|
+
| `classifier.*` | see code comments | Optional non-blocking low-risk pre-scorer (`enabled` `false`, `model`, `timeoutMs` `15000`, `maxLag` `2`). Can only fast-path ordinary calls, never deny. |
|
|
167
|
+
| `circuitBreaker.*` | — | Denials that end the turn instead of letting agent and reviewer negotiate forever (`consecutiveDenials` `3`, `recentDenials` `10` within `windowSize` `50`; `0` disables). |
|
|
168
|
+
|
|
169
|
+
#### `codexAstra`
|
|
170
|
+
|
|
171
|
+
| Key | Type / default | Meaning |
|
|
172
|
+
| --- | --- | --- |
|
|
173
|
+
| `enabled` | *boolean*, `true` | Astra compatibility layer: backend version-gate header plus the cache-preserving effort rewrite below. |
|
|
174
|
+
| `models` | *string[]*, `[]` | Models that accept the `configuration_update` input item (today only Astra-era models, e.g. `"uwoacrimson/gpt-6-astra"` on a gateway). The version header applies to all `openai-codex-responses` requests regardless of this list. Never enable this layer on a host that already implements the same rewrite (e.g. Oh My Pi) to avoid double-splicing. |
|
|
175
|
+
|
|
176
|
+
Catalog note: Pi's bundled `openai-codex` list may not include `gpt-6-astra` yet. Register it in `~/.pi/agent/models.json` under the built-in provider (`api: "openai-codex-responses"`, `baseUrl: "https://chatgpt.com/backend-api"`, `contextWindow: 272000`, `maxTokens: 128000`, `thinkingLevelMap` `low`…`max`); Pi's Codex OAuth supplies the token.
|
|
177
|
+
|
|
178
|
+
### Feature guides
|
|
179
|
+
|
|
180
|
+
#### Codex Remote Context management
|
|
181
|
+
|
|
182
|
+
When `contextManagement` is `"remote"` and the session model is covered (native `openai-codex`, or an exact `codexGatewayModels` entry on `openai-responses`), the toolkit takes the session through the Codex window lifecycle:
|
|
183
|
+
|
|
184
|
+
- **Window identity.** `session_start` initializes a window (first/current/previous ids, window number) persisted as a `codex-context-window` custom message in the Pi session; boundaries replay on resume and rebuild after forks. Live requests carry `x-codex-window-id` and `x-codex-turn-metadata`.
|
|
185
|
+
- **No-summary rollover.** `new_context` installs a fresh window and trims the previous one from model context. Nothing is re-summarized; old turns stay retrievable server-side through `history`.
|
|
186
|
+
- **Checkpoint gate.** A rollover requires a *successful* `notes` `append_to_file` / `write_file` inside the current window, verified against the persisted session branch (so it survives restarts). Without it, `new_context` refuses; `force: true` is the explicit user-authorized escape, and the toolkit's exhausted-context fallback bypasses the gate automatically after instructing one final notes write.
|
|
187
|
+
- **Budget.** `get_context_remaining` reports the live window budget; `contextReminderThresholdPercent` controls the once-per-window checkpoint reminder.
|
|
188
|
+
- **Ownership.** For covered models the toolkit owns every compaction event: `remote_compaction_v2` is not sent, and Pi-native compaction is cancelled on all paths — including while the remote runtime is temporarily inactive, so no lossy summary can slip in behind its back. The inactive reason is surfaced as a notification (and in the `session_start` lifecycle artifact when `debug` is on); fix that cause rather than expecting compaction.
|
|
189
|
+
|
|
190
|
+
The native route reuses Pi's Codex OAuth through `ModelRegistry`; gateway route requests use the configured data-plane API key only — local OAuth credentials, account cookies, and account ids are never forwarded to a gateway.
|
|
191
|
+
|
|
192
|
+
**Verifying activation.** After `/reload` or a new session, the session should contain a `codex-context-window` boundary message and `new_context` / `get_context_remaining` / `history` / `notes` tools. With `debug: true`, each `session_start` writes a lifecycle artifact under `artifactRoot` whose `activation` field records `active` and, when inactive, the exact reason (e.g. `tool-name-conflict`, `missing-api-key`, `auth-resolution-failed`).
|
|
193
|
+
|
|
194
|
+
#### Remote Compaction v2
|
|
195
|
+
|
|
196
|
+
With `contextManagement` off, eligible Responses sessions compact through `remote_compaction_v2`: a `compaction_trigger` item appended to the live streaming request yields one output item of `type: "compaction"` with non-empty `encrypted_content`, stored in `CompactionEntry.details.compactedWindow`. On later requests the opaque checkpoint is replayed ahead of live turns — zero-loss, no text summary. Replay fails closed: if the summary anchor cannot be located, the request is aborted with a notification and a content-free failure artifact; the sentinel-only payload is never sent. Fallback tiers: a failed remote attempt may use Pi's native compaction (`remoteCompactModel`/active model); models that cannot use v2 at all use `nativeFallback`. Pi 0.85.1+ owns automatic compaction driving; the toolkit never starts its own driver.
|
|
197
|
+
|
|
198
|
+
#### Auto Mode
|
|
199
|
+
|
|
200
|
+
Engage per session with `pi --auto` or `/auto on` (footer shows state; engaging never stalls the current turn). Each gated call is reviewed by `reviewerModel`, which scores intrinsic risk and conversation authorization separately and derives `allow`/`deny` from a fixed table; it may investigate with read-only tools first; denials return the reason plus an anti-workaround clause; unfinished reviews are reported as failures, never safety verdicts. Every decision is persisted as a non-context session entry for audit. In headless (`-p`/JSON) sessions there is nobody to escalate to, so unavailable reviews block.
|
|
201
|
+
|
|
202
|
+
## Development
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
npm run typecheck # tsc project check
|
|
206
|
+
bun test # full unit suite
|
|
207
|
+
npm run test:pi # Pi integration smoke tests
|
|
208
|
+
npm pack --dry-run # inspect the published archive
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
The Remote Context protocol fixtures (`src/context-management/`) must be updated together with any upstream alpha endpoint change.
|
|
212
|
+
|
|
213
|
+
## API
|
|
214
|
+
|
|
215
|
+
### Remote Context tools
|
|
216
|
+
|
|
217
|
+
The four tools the extension registers when Remote Context is active:
|
|
218
|
+
|
|
219
|
+
| Tool | Parameters | Result / errors |
|
|
220
|
+
| --- | --- | --- |
|
|
221
|
+
| `new_context` | `{ force?: boolean }` | Rolls to the next window without summarizing. Refuses unless a successful notes checkpoint exists in the current window (`force` overrides). Reports "already scheduled" if a rollover is pending. |
|
|
222
|
+
| `get_context_remaining` | none | Remaining tokens and window identity for the current budget; `unknown` when no usage source exists yet. |
|
|
223
|
+
| `history` | `{ action: "list_windows" \| "list_items" \| "read_item" \| "search_contents", ... }` | Reads prior windows. Pass returned `item_id` / window ids **unchanged**. Search text is sent under the encrypted-argument policy. |
|
|
224
|
+
| `notes` | `{ action: "list_files_by_prefix" \| "read_file" \| "search_contents" \| "append_to_file" \| "write_file", path, text, ... }` | Cross-window working memory. Paths resolve under the session agent (e.g. `/root/notes/<file>` or a relative note path); an invalid path is rejected by the backend. Successful append/write is what satisfies the `new_context` gate. |
|
|
225
|
+
|
|
226
|
+
All four throw explicit tool errors on timeout, abort, non-2xx, malformed JSON, authentication, or protocol failures — they never silently degrade.
|
|
227
|
+
|
|
228
|
+
### HTTP protocol reference
|
|
229
|
+
|
|
230
|
+
Internal alpha endpoints, adapted from `@howaboua/pi-codex-conversion` (see [Background](#background)):
|
|
231
|
+
|
|
232
|
+
```text
|
|
233
|
+
POST {base}/alpha/history/v2/list_windows | list_items | read_item | search_contents
|
|
234
|
+
POST {base}/alpha/notes/v2/list_files_by_prefix | read_file | search_contents | append_to_file | write_file
|
|
235
|
+
GET {base}/alpha/notes/v2/thread_hint
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Native route uses `{base} = <backend-api>/codex` with `Authorization: Bearer <oauth token>`, `ChatGPT-Account-ID`, and Codex CLI headers. Gateway route uses the configured `/v1` base with the data-plane API key, `originator: codex_cli_rs`, `X-Codex-Affinity-Scope`, and `X-Codex-Model` carrying the bare model id — never local credentials. Both set `Session-Id` / `X-Client-Request-Id` to the bounded Pi session id, `x-openai-tool-output-truncation-policy`, and `x-openai-encrypted-tool-arguments` for endpoints with encrypted parameters; encrypted results come back as `encrypted_output` and are re-encoded into later requests. These are alpha contracts: the upstream backend may change them at any time.
|
|
239
|
+
|
|
240
|
+
## Maintainers
|
|
241
|
+
|
|
242
|
+
[awoaCrim](https://github.com/awoaCrim)
|
|
243
|
+
|
|
244
|
+
## Contributing
|
|
245
|
+
|
|
246
|
+
Issues and pull requests are welcome at the [issue tracker](https://github.com/awoaCrim/pi-openai-toolkit/issues). For behavior-changing work, open an issue first so protocol assumptions (especially alpha `history`/`notes` contracts) can be discussed. Run `bun test` and `npm run typecheck` before submitting; new wire-protocol behavior needs fixture-based tests.
|
|
247
|
+
|
|
248
|
+
## License
|
|
249
|
+
|
|
250
|
+
MIT © awoaCrim and contributors. See [LICENSE](./LICENSE) and the third-party attribution in [NOTICE](./NOTICE).
|