pi-openai-toolkit 0.13.1 → 0.14.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/README.md CHANGED
@@ -3,6 +3,8 @@
3
3
  [![npm version](https://img.shields.io/npm/v/pi-openai-toolkit.svg)](https://www.npmjs.com/package/pi-openai-toolkit)
4
4
  [![license: MIT](https://img.shields.io/npm/l/pi-openai-toolkit.svg)](./LICENSE)
5
5
 
6
+ [简体中文](./README.zh.md)
7
+
6
8
  OpenAI toolkit for Pi: Codex Remote Context windows, remote compaction v2, hosted Web Search, image gen, auto mode.
7
9
 
8
10
  `pi-openai-toolkit` bundles five Pi extensions for the OpenAI Responses wire family (`openai-responses` and `openai-codex-responses`):
@@ -11,7 +13,7 @@ OpenAI toolkit for Pi: Codex Remote Context windows, remote compaction v2, hoste
11
13
  2. **Web Search** (`extensions/web-search.ts`): hosted `web_search` injection for an exact `provider/model-id` allowlist, reusing the live model connection.
12
14
  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
15
  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`.
16
+ 5. **Codex Astra** (`extensions/codex-astra.ts`): Codex backend version-gate headers and cache-preserving `configuration_update` effort changes for `gpt-6-astra`. Activated silently by model id; no configuration section.
15
17
 
16
18
  The package is a Pi extension set, not an importable library: everything is configured through one JSON file and activated automatically inside Pi.
17
19
 
@@ -73,7 +75,7 @@ Do not run `pi-remote-compact`, `@lll9p/pi-better-compaction`, or a standalone `
73
75
 
74
76
  ## Usage
75
77
 
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.
78
+ All features are controlled by one configuration file, plus per-session commands. With no config file present, compaction runs with its defaults; Web Search, image generation, auto mode, and Remote Context stay opt-in. The Astra compatibility layer and gateway Remote Context are keyed off the built-in `gpt-6-astra` model id, not off any allowlist.
77
79
 
78
80
  Create `~/.pi/agent/extensions/pi-openai-toolkit/config.json` (Windows: `C:\Users\<user>\.pi\agent\extensions\pi-openai-toolkit\config.json`):
79
81
 
@@ -82,7 +84,6 @@ Create `~/.pi/agent/extensions/pi-openai-toolkit/config.json` (Windows: `C:\User
82
84
  "compaction": {
83
85
  "enabled": true,
84
86
  "contextManagement": "remote",
85
- "codexGatewayModels": ["uwoacrimson/gpt-6-astra"],
86
87
  "contextReminderThresholdPercent": 10,
87
88
  "allowCompactionContinuityBreak": false,
88
89
  "remoteCompactModel": "uwoacrimson/gpt-5.6-luna",
@@ -102,8 +103,7 @@ Create `~/.pi/agent/extensions/pi-openai-toolkit/config.json` (Windows: `C:\User
102
103
  "models": ["uwoacrimson/gpt-5.6-luna"],
103
104
  "reviewerModel": "uwoacrimson/gpt-5.6-luna",
104
105
  "gate": "side-effect"
105
- },
106
- "codexAstra": { "enabled": true, "models": ["uwoacrimson/gpt-6-astra"] }
106
+ }
107
107
  }
108
108
  ```
109
109
 
@@ -122,8 +122,7 @@ Every key is optional; unknown keys are ignored with a warning rather than writt
122
122
  | Key | Type / default | Meaning |
123
123
  | --- | --- | --- |
124
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. |
125
+ | `contextManagement` | `"off"` \| `"remote"`, `"off"` | Opt into Codex Remote Context management. Covered models are native Codex models plus `gpt-6-astra` on a Codex-compatible gateway (`openai-responses`); the match is built in, there is no allowlist. 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. |
127
126
  | `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
127
  | `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
128
  | `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. |
@@ -168,10 +167,7 @@ Every key is optional; unknown keys are ignored with a warning rather than writt
168
167
 
169
168
  #### `codexAstra`
170
169
 
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. |
170
+ Removed. The Astra compatibility layer (backend version-gate headers for all `openai-codex-responses` requests, plus the cache-preserving `configuration_update` effort rewrite) now activates silently for any model whose id is `gpt-6-astra` on a Responses-family API — no configuration needed, and old `codexAstra` sections in existing configs are ignored with an unknown-field warning. Only caveat left: do not run it together with another host that implements the same rewrite (e.g. Oh My Pi) to avoid double-splicing.
175
171
 
176
172
  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
173
 
@@ -179,7 +175,7 @@ Catalog note: Pi's bundled `openai-codex` list may not include `gpt-6-astra` yet
179
175
 
180
176
  #### Codex Remote Context management
181
177
 
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:
178
+ When `contextManagement` is `"remote"` and the session model is covered (native `openai-codex`, or `gpt-6-astra` on `openai-responses`; the model match is built in), the toolkit takes the session through the Codex window lifecycle:
183
179
 
184
180
  - **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
181
  - **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`.
package/README.zh.md CHANGED
@@ -13,18 +13,17 @@
13
13
  2. **联网搜索**(`extensions/web-search.ts`):为 `provider/model-id` 精确白名单注入托管 `web_search`,复用当前模型连接。
14
14
  3. **图像生成**(`extensions/image-generation.ts`):由托管 `image_generation` 工具驱动的本地 `openai_generate_image`,支持文生图与显式本地参考图编辑,图像字节不进会话历史。
15
15
  4. **Auto 模式**(`extensions/auto-mode.ts`):为改变状态的工具调用增设审批模型门禁,Agent 不必停下来等你确认。
16
- 5. **Codex Astra**(`extensions/codex-astra.ts`):为 `gpt-6-astra` 补发 Codex 后端版本门禁头,并用 `configuration_update` 会话项保住提示缓存。
16
+ 5. **Codex Astra**(`extensions/codex-astra.ts`):为 `gpt-6-astra` 补发 Codex 后端版本门禁头,并用 `configuration_update` 会话项保住提示缓存。按模型名静默启用,无配置段。
17
17
 
18
18
  本包是 Pi 扩展集而非可导入库:一切通过一个 JSON 配置文件驱动,在 Pi 内自动生效。
19
19
 
20
20
  ## 目录
21
-
21
+ - [安全](#安全)
22
22
  - [背景](#背景)
23
23
  - [安装](#安装)
24
24
  - [使用](#使用)
25
25
  - [配置](#配置)
26
26
  - [功能指南](#功能指南)
27
- - [安全](#安全)
28
27
  - [开发](#开发)
29
28
  - [API](#api)
30
29
  - [Remote Context 工具](#remote-context-工具)
@@ -33,6 +32,13 @@
33
32
  - [贡献](#贡献)
34
33
  - [许可证](#许可证)
35
34
 
35
+ ## 安全
36
+
37
+ - **覆盖模型不会有静默的有损摘要。** `contextManagement: "remote"` 覆盖某模型期间,Pi 原生压缩在阈值、手动 `/compact`、溢出全部路径上被取消,v2 也不发送。若想再加宿主级保险,在 Pi `settings.json` 设 `"compaction": { "enabled": false }`;覆盖范围外的模型照常走 Pi 自己的策略。
38
+ - **网关隔离。** 网关模式只转发配置的数据面 key;OAuth 令牌、account cookie、account ID 一律剥离;artifact 中凭据与不透明密文永远脱敏。
39
+ - **Checkpoint 门禁。** `new_context` 无法在没有本窗口成功 notes 写入、也没有用户显式 `force` 授权时丢弃未保存工作状态——Codex 官方实验特性上出现过的"后端故障 + 换窗丢状态"在此被硬拦。
40
+ - **计费与审批边界。** 图像生成显式开启且可能产生费用;审批请求禁用提示缓存、只授予只读工具,无 UI 会话 fail-closed。
41
+
36
42
  ## 背景
37
43
 
38
44
  Pi 内置压缩会把旧轮次摘要成文本,细节随之丢失;OpenAI Codex 后端其实提供两种无损机制,普通客户端拿不到:**`remote_compaction_v2` SSE 协议**(用加密密文项替换被摘要的前缀)与实验性**上下文窗口体系**(`new_context` / `history` / `notes`,完全不做摘要地换窗)。本工具包对着真实后端实现了两者,并已在 Codex OAuth 与 Codex 兼容网关中继(NEWapi + CLIProxyAPI)上端到端验证。
@@ -69,7 +75,7 @@ pi install git:github.com/awoaCrim/pi-openai-toolkit
69
75
 
70
76
  ## 使用
71
77
 
72
- 所有功能由一个配置文件加会话内命令控制。无配置文件时:压缩与 Astra 在符合条件的模型上启用,联网搜索、图像生成、Auto 模式、Remote Context 全部默认不启用。
78
+ 所有功能由一个配置文件加会话内命令控制。无配置文件时:压缩按默认值运行;联网搜索、图像生成、Auto 模式、Remote Context 均需显式开启。Astra 兼容层与网关 Remote Context 按内置的 `gpt-6-astra` 模型名匹配启用,不走任何白名单。
73
79
 
74
80
  创建 `~/.pi/agent/extensions/pi-openai-toolkit/config.json`(Windows:`C:\Users\<user>\.pi\agent\extensions\pi-openai-toolkit\config.json`):
75
81
 
@@ -78,7 +84,6 @@ pi install git:github.com/awoaCrim/pi-openai-toolkit
78
84
  "compaction": {
79
85
  "enabled": true,
80
86
  "contextManagement": "remote",
81
- "codexGatewayModels": ["uwoacrimson/gpt-6-astra"],
82
87
  "contextReminderThresholdPercent": 10,
83
88
  "allowCompactionContinuityBreak": false,
84
89
  "remoteCompactModel": "uwoacrimson/gpt-5.6-luna",
@@ -98,8 +103,7 @@ pi install git:github.com/awoaCrim/pi-openai-toolkit
98
103
  "models": ["uwoacrimson/gpt-5.6-luna"],
99
104
  "reviewerModel": "uwoacrimson/gpt-5.6-luna",
100
105
  "gate": "side-effect"
101
- },
102
- "codexAstra": { "enabled": true, "models": ["uwoacrimson/gpt-6-astra"] }
106
+ }
103
107
  }
104
108
  ```
105
109
 
@@ -118,8 +122,7 @@ pi --model uwoacrimson/gpt-6-astra "继续部署任务"
118
122
  | 键 | 类型 / 默认 | 说明 |
119
123
  | --- | --- | --- |
120
124
  | `enabled` | *boolean*, `true` | 压缩扩展 hook 总开关。 |
121
- | `contextManagement` | `"off"` \| `"remote"`, `"off"` | 为原生 Codex 模型及 `codexGatewayModels` 条目启用 Codex 远端上下文管理。覆盖模型由其独占:不发送 `remote_compaction_v2`,且取消 Pi 原生压缩(见[安全](#安全))。设回 `"off"` 即回滚。 |
122
- | `codexGatewayModels` | *string[]*, `[]` | 允许走 Codex 兼容网关跑 Remote Context 的精确 `provider/model-id`(如 `"uwoacrimson/gpt-5.6-luna"`,API 须为 `openai-responses`)。网关收到的是 `X-Codex-Model` 里的裸模型 ID,Base URL 保持配置的 `/v1`。 |
125
+ | `contextManagement` | `"off"` \| `"remote"`, `"off"` | 启用 Codex 远端上下文管理。覆盖模型为原生 Codex 模型,加上在 Codex 兼容网关(`openai-responses`)上的 `gpt-6-astra`;匹配规则内置,无白名单。覆盖模型由其独占:不发送 `remote_compaction_v2`,且取消 Pi 原生压缩(见[安全](#安全))。设回 `"off"` 即回滚。 |
123
126
  | `contextReminderThresholdPercent` | *integer* `0`-`100`, `5` | 仅 Remote Context:当前窗口剩余 token 低于窗口该百分比时,每窗口注入一次 checkpoint 提醒;`0` 关闭提醒(窗口耗尽兜底仍生效)。建议明显高于 Pi 原生 reserve 余量(默认 16384 token,约为 272k 窗口的 6%),让模型在撞阈值前有机会主动换窗。 |
124
127
  | `allowCompactionContinuityBreak` | *boolean*, `false` | v2 路径:最近一次压缩由其他方式(如文本摘要)生成时,允许从当前文本上下文重建密文链。 |
125
128
  | `remoteCompactModel` | *string \| null*, `null` | v2 路径:仅用于 synthetic `remote_compaction_v2` 请求的模型,会话模型不切换;必须与当前模型解析出相同生效 Base URL。 |
@@ -164,10 +167,7 @@ pi --model uwoacrimson/gpt-6-astra "继续部署任务"
164
167
 
165
168
  #### `codexAstra`
166
169
 
167
- | 键 | 类型 / 默认 | 说明 |
168
- | --- | --- | --- |
169
- | `enabled` | *boolean*, `true` | Astra 兼容层:后端版本门禁头 + 保缓存的档位改写(见下)。 |
170
- | `models` | *string[]*, `[]` | 接受 `configuration_update` 输入项的模型(目前仅 Astra 世代,如网关侧 `"uwoacrimson/gpt-6-astra"`);版本头则对所有 `openai-codex-responses` 请求生效,与本名单无关。宿主(如 Oh My Pi)已实现同款改写时只开一边,避免双重插入。 |
170
+ 已移除。Astra 兼容层(对所有 `openai-codex-responses` 请求的版本门禁头,以及保缓存的 `configuration_update` 档位改写)现按模型名 `gpt-6-astra` 静默启用(限 Responses 系 API),无需任何配置;旧配置里的 `codexAstra` 段会按未知字段告警并忽略。唯一保留的注意事项:宿主(如 Oh My Pi)已实现同款改写时只开一边,避免双重插入。
171
171
 
172
172
  模型目录说明:Pi 内置 `openai-codex` 列表可能还没有 `gpt-6-astra`。在 `~/.pi/agent/models.json` 的内置 provider 下登记(`api: "openai-codex-responses"`、`baseUrl: "https://chatgpt.com/backend-api"`、`contextWindow: 272000`、`maxTokens: 128000`、`thinkingLevelMap` `low`…`max`);令牌由 Pi 的 Codex OAuth 提供。
173
173
 
@@ -175,7 +175,7 @@ pi --model uwoacrimson/gpt-6-astra "继续部署任务"
175
175
 
176
176
  #### Codex 远端上下文管理
177
177
 
178
- `contextManagement` 为 `"remote"` 且会话模型被覆盖(原生 `openai-codex`,或 `codexGatewayModels` 中精确匹配且 API 为 `openai-responses` 的条目)时,会话进入 Codex 窗口生命周期:
178
+ `contextManagement` 为 `"remote"` 且会话模型被覆盖(原生 `openai-codex`,或 API 为 `openai-responses` 的 `gpt-6-astra`;模型匹配内置)时,会话进入 Codex 窗口生命周期:
179
179
 
180
180
  - **窗口身份。** `session_start` 初始化窗口(first/current/previous id、窗口编号),以 `codex-context-window` 自定义消息持久化进 Pi 会话;resume 回放、fork 后重建。实时请求携带 `x-codex-window-id` 与 `x-codex-turn-metadata`。
181
181
  - **无摘要换窗。** `new_context` 安装新窗口并把旧窗口从模型上下文裁剪,不做任何再摘要;旧轮次仍可通过服务端 `history` 取回。
@@ -195,13 +195,6 @@ pi --model uwoacrimson/gpt-6-astra "继续部署任务"
195
195
 
196
196
  会话内用 `pi --auto` 或 `/auto on` 启用(页脚显示状态;启用动作本身不发起任何请求)。被门禁的每个调用由 `reviewerModel` 审批:分开评估行为固有风险与对话授权程度,按固定表得出 `allow`/`deny`;审批模型可先跑只读工具取证;否决会把理由与禁止绕条款返回给请求模型;未完成的审批(超时/取消/报错)按故障上报,绝不伪装成安全结论。所有决策以非上下文会话条目持久化备审计。无 UI(`-p`/JSON)时无人可升级确认,审批不可用即拦截。
197
197
 
198
- ## 安全
199
-
200
- - **覆盖模型不会有静默的有损摘要。** `contextManagement: "remote"` 覆盖某模型期间,Pi 原生压缩在阈值、手动 `/compact`、溢出全部路径上被取消,v2 也不发送。若想再加宿主级保险,在 Pi `settings.json` 设 `"compaction": { "enabled": false }`;覆盖范围外的模型照常走 Pi 自己的策略。
201
- - **网关隔离。** 网关模式只转发配置的数据面 key;OAuth 令牌、account cookie、account ID 一律剥离;artifact 中凭据与不透明密文永远脱敏。
202
- - **Checkpoint 门禁。** `new_context` 无法在没有本窗口成功 notes 写入、也没有用户显式 `force` 授权时丢弃未保存工作状态——Codex 官方实验特性上出现过的"后端故障 + 换窗丢状态"在此被硬拦。
203
- - **计费与审批边界。** 图像生成显式开启且可能产生费用;审批请求禁用提示缓存、只授予只读工具,无 UI 会话 fail-closed。
204
-
205
198
  ## 开发
206
199
 
207
200
  ```bash
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-openai-toolkit",
3
- "version": "0.13.1",
3
+ "version": "0.14.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "engines": {
@@ -1,6 +1,5 @@
1
1
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
- import { loadToolkitConfig } from "../config";
3
- import { isExactModelAllowed } from "../model-scope";
2
+ import { ASTRA_MODEL_ID } from "../types";
4
3
  import { CODEX_CLIENT_VERSION } from "../responses-headers";
5
4
  import {
6
5
  getEffortControlState,
@@ -53,10 +52,7 @@ function getSessionId(ctx: { sessionManager: { getSessionId(): string } }): stri
53
52
  }
54
53
  }
55
54
 
56
- export function registerCodexAstraExtension(
57
- pi: ExtensionAPI,
58
- loadConfig: typeof loadToolkitConfig = loadToolkitConfig,
59
- ): void {
55
+ export function registerCodexAstraExtension(pi: ExtensionAPI): void {
60
56
  const states = new Map<string, EffortControlState>();
61
57
 
62
58
  // Switching or forking a session rebuilds the runtime and re-fires
@@ -67,18 +63,16 @@ export function registerCodexAstraExtension(
67
63
 
68
64
  pi.on("before_provider_request", (event, ctx) => {
69
65
  try {
70
- const { config } = loadConfig();
71
- const astra = config.codexAstra;
72
- if (!astra.enabled || astra.models.length === 0) return undefined;
73
-
66
+ // Silent activation by design: the Astra compatibility layer exists only
67
+ // to keep `gpt-6-astra` working through the Codex backend gate, so it
68
+ // keys off the bare model id instead of an operator allowlist.
74
69
  const model = ctx.model;
75
70
  // Both Responses wire families carry the same reasoning.effort prefix
76
- // problem, and upstream OMP plans on both providers; which models
77
- // accept the item is decided by the allowlist, not by API family.
71
+ // problem, and upstream OMP plans on both providers.
78
72
  if (!model || (model.api !== "openai-codex-responses" && model.api !== "openai-responses")) {
79
73
  return undefined;
80
74
  }
81
- if (!isExactModelAllowed(model, astra.models)) return undefined;
75
+ if (model.id !== ASTRA_MODEL_ID) return undefined;
82
76
 
83
77
  const payload = parseAstraPayload(event.payload);
84
78
  // The payload must belong to the model the eligibility check just