pi-openai-toolkit 0.19.0 → 0.20.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.zh.md CHANGED
@@ -1,242 +1,156 @@
1
- # pi-openai-toolkit
2
-
3
- 为 Pi 添加 Codex 上下文窗口、Responses 压缩、托管工具和工具调用审查。
4
-
5
- [![npm 版本](https://img.shields.io/npm/v/pi-openai-toolkit.svg)](https://www.npmjs.com/package/pi-openai-toolkit)
6
- [![许可证:MIT](https://img.shields.io/npm/l/pi-openai-toolkit.svg)](LICENSE)
7
-
8
- [英文版](README.md)
9
-
10
- ## 功能
11
-
12
- | 功能 | 用途 |
13
- | --- | --- |
14
- | Codex 远程上下文 | 通过适配的 Codex 协议切换窗口,用 `history` 找回较早的工作内容。 |
15
- | 远程压缩 v2 | 使用加密的服务端检查点继续 Responses 会话。 |
16
- | 联网搜索 | 按模型选择本地 `pi-web-access`、Responses `web_search` 或实验性的 CPA `web_run`。 |
17
- | 图像生成 | 通过独立的 Images API 请求生成或编辑栅格图片。 |
18
- | 工具调用审查 | 通过 Toolkit 审批门禁,让审查模型判断指定调用是否可以执行。 |
19
-
20
- 本包沿用 Pi 已有的模型、认证和会话,不新增提供商或模型。
21
-
22
- ## 安装
23
-
24
- 需要 Pi 0.87.0+ 和 Node.js 22.19.0+。
25
-
26
- ```bash
27
- pi install npm:pi-openai-toolkit
28
- ```
29
-
30
- 加上 `--local` 可安装到当前项目。无论安装位置如何,Toolkit 都使用全局配置:
31
-
32
- `~/.pi/agent/extensions/pi-openai-toolkit/config.json`
33
-
34
- 文件不存在时,创建文件及所需目录。将下方 Toolkit 示例合并到已有的**配置格式 v2** 文件,不要覆盖其他设置。无版本号的旧配置请先运行 `/toolkit-config migration-preview`,详见[迁移指南](docs/configuration.md#legacy-compatibility-and-migration)。
35
-
36
- 默认情况下,符合条件的模型启用远程压缩 v2;远程上下文窗口、生图和自动模式关闭,搜索不由 Toolkit 管理。使用相关功能仍需后端支持。
37
-
38
- ## 快速开始:启用远程上下文
39
-
40
- 如果只需要搜索、生图或工具调用审查,可跳到[常见用法](#常见用法)。
41
-
42
- ### 使用 Pi 内置的 Codex 提供商
43
-
44
- 先登录 Pi 的 `openai-codex` 提供商,再添加以下 Toolkit 配置:
45
-
46
- ```json
47
- {
48
- "schemaVersion": 2,
49
- "defaults": {
50
- "context": { "mode": "remote-windows" }
51
- }
52
- }
53
- ```
54
-
55
- 使用 Codex 模型目录中的实际模型 ID 启动 Pi:
56
-
57
- ```bash
58
- pi --model openai-codex/<model-id>
59
- ```
60
-
61
- 检查是否出现 `new_context`、`get_context_remaining`、`history` 和 `notes`。工具出现表示已激活,不代表后端兼容性已经验证。较早窗口可通过 `history` 检索,不会加载到每次请求中。
62
-
63
- ### 使用兼容网关
64
-
65
- 网关必须支持 `openai-responses` 和 Codex 远程上下文协议,仅支持普通对话还不够。
66
-
67
- 如果模型已在 `~/.pi/agent/models.json` 注册,可跳过注册示例。
68
-
69
- <details>
70
- <summary>在 Pi 中注册网关模型</summary>
71
-
72
- 将以下内容合并到 Pi 的模型文件。按实际情况替换提供商名称、URL、密钥变量、模型 ID 和限制值;其中的数字仅为示例。
73
-
74
- ```json
75
- {
76
- "providers": {
77
- "my-gateway": {
78
- "baseUrl": "https://your-gateway.example/v1",
79
- "api": "openai-responses",
80
- "apiKey": "$MY_GATEWAY_KEY",
81
- "models": [{
82
- "id": "gpt-5.6-luna",
83
- "name": "GPT-5.6 Luna",
84
- "reasoning": true,
85
- "input": ["text"],
86
- "contextWindow": 272000,
87
- "maxTokens": 128000
88
- }]
89
- }
90
- }
91
- }
92
- ```
93
-
94
- PowerShell 中设置密钥:
95
-
96
- ```powershell
97
- $env:MY_GATEWAY_KEY = "replace-with-your-gateway-key"
98
- ```
99
-
100
- 或使用 POSIX shell:
101
-
102
- ```bash
103
- export MY_GATEWAY_KEY="replace-with-your-gateway-key"
104
- ```
105
-
106
- 在同一个终端中启动 Pi。
107
-
108
- </details>
109
-
110
- 在 Toolkit 配置中填写已注册的精确 `提供商/模型 ID`:
111
-
112
- ```json
113
- {
114
- "schemaVersion": 2,
115
- "models": {
116
- "my-gateway/gpt-5.6-luna": {
117
- "context": { "mode": "remote-windows" },
118
- "compatibility": { "transport": "codex-gateway" }
119
- }
120
- }
121
- }
122
- ```
123
-
124
- ```bash
125
- pi --model my-gateway/gpt-5.6-luna
126
- ```
127
-
128
- 检查是否出现上面列出的上下文工具。如果没有,使用 `/toolkit-config`,并检查通知、模型键、API、认证和 URL。
129
-
130
- ## 常见用法
131
-
132
- ### 用 `/compact` 保存工作并切换窗口
133
-
134
- 远程上下文已激活时,运行 `/compact` 可将工作状态保存到 notes,再进入新窗口,不生成会话摘要。命令后可以附加要求。
135
-
136
- 如需独立的检查点模型,在 `defaults` 或精确模型覆盖下设置 `context.remoteCompaction.model`。目标模型须在同一后端及账号下支持远程上下文;不设置则使用当前模型。Toolkit 会在继续工作前恢复原模型和思考等级。详见[上下文配置与要求](docs/configuration.md#context)。
137
-
138
- ### 使用服务端压缩
139
-
140
- 将 `context.mode` 设为 `"remote-compaction"`(默认值),使用加密的 Responses 检查点;设为 `"pi"` 则由 Pi 管理上下文。高级输入和回退选项见[配置参考](docs/configuration.md#context)。
141
-
142
- ### 选择联网搜索路由
143
-
144
- 设置默认路由,并按模型覆盖:
145
-
146
- ```json
147
- {
148
- "schemaVersion": 2,
149
- "defaults": {
150
- "webSearch": { "route": "local" }
151
- },
152
- "models": {
153
- "my-gateway/gpt-5.6-luna": {
154
- "webSearch": { "route": "hosted" }
155
- }
156
- }
157
- }
158
- ```
159
-
160
- | 路由 | 行为 |
161
- | --- | --- |
162
- | `unmanaged` | 由 Pi 和其他扩展管理搜索。 |
163
- | `local` | 保留现有本地 `pi-web-access` 工具。 |
164
- | `hosted` | 使用带来源标注的 Responses `web_search`。 |
165
- | `standalone-alpha` | 在支持 `/alpha/search` 的 CPA/Codex 网关上使用实验性的 `web_run`。 |
166
-
167
- Toolkit 不会在路由之间自动回退。后端要求见[搜索配置](docs/configuration.md#web-search)。
168
-
169
- ### 生成图片
170
-
171
- 需要符合条件的 Responses-capable 会话,并可能产生服务商费用。Pi 工具会向当前服务商发送独立的 Images API 请求(`/images/generations` 或 `/images/edits`;Codex 使用 `/codex/images/...`),不会把生图 tool 加入普通对话请求。选择服务商支持的生图模型后启用:
172
-
173
- ```json
174
- {
175
- "schemaVersion": 2,
176
- "defaults": {
177
- "imageGeneration": {
178
- "enabled": true,
179
- "defaultModel": "grok-imagine-image-2.0",
180
- "allowedModels": ["grok-imagine-image-2.0"]
181
- }
182
- }
183
- }
184
- ```
185
-
186
- 让 Pi 通过 `openai_generate_image` 生成图片,或编辑明确提供的本地参考图。选中的生图模型会写入独立请求;当前对话模型仍只负责路由和认证。PNG、JPEG 和 WebP 响应会按实际格式校验并保存。工具的可选 `model` 必须精确匹配 `allowedModels`,也可以使用 `batchSize`(1-10)并发生成多个独立变体。批量调用会保存 canonical artifacts,不能同时指定单文件 `outputPath`;`quality` 为 `auto` 时会省略该字段,让兼容网关使用自己的默认值。生图设置全局生效。详见[生图配置](docs/configuration.md#images)。
187
-
188
- ### 启用工具调用自动审查
189
-
190
- 为模型开放自动模式,并选择审查模型:
191
-
192
- ```json
193
- {
194
- "schemaVersion": 2,
195
- "models": {
196
- "my-gateway/gpt-5.6-luna": {
197
- "autoMode": {
198
- "available": true,
199
- "reviewerModel": "my-gateway/gpt-5.6-luna"
200
- }
201
- }
202
- }
203
- }
204
- ```
205
-
206
- 使用 `/auto on` 或 `--auto` 开启,`/auto off` 关闭。默认审查 `bash`、`write`、`edit` 和额外配置的工具;`gate: "all"` 审查所有调用。审查超时不会自动放行。详见[自动模式配置](docs/configuration.md#auto-mode)。
207
-
208
- ## 常用配置
209
-
210
- `defaults` 设置通用值,`models["provider/model-id"]` 按精确模型覆盖。Toolkit 只读取全局配置文件。
211
-
212
- | 命令 | 用途 |
213
- | --- | --- |
214
- | `/toolkit-config` | 查看生效设置及其来源。 |
215
- | `/toolkit-config validate` | 检查配置错误。 |
216
- | `/toolkit-config migration-preview` | 预览旧格式到 v2 的迁移,不写入文件。 |
217
-
218
- 这些命令需要 Pi 交互界面。完整说明见[配置参考](docs/configuration.md)、[编辑器 schema](config.schema.json)和[实现细节](docs/internals.md)。
219
-
220
- ## 开发
221
-
222
- 在仓库根目录安装依赖后运行:
223
-
224
- ```bash
225
- npm run typecheck
226
- ```
227
-
228
- ```bash
229
- bun test
230
- ```
231
-
232
- ```bash
233
- npm run test:pi
234
- ```
235
-
236
- ```bash
237
- npm pack --dry-run
238
- ```
239
-
240
- ## 许可证
241
-
242
- MIT © awoaCrim 与贡献者。见 [LICENSE](LICENSE) 和 [NOTICE](NOTICE)。
1
+ # pi-openai-toolkit
2
+
3
+ 为 Pi 添加远程上下文窗口、Responses 压缩、联网搜索、图像生成和工具调用审查。沿用 Pi 的模型、端点、认证和会话配置,不另行注册提供商或模型。
4
+
5
+ [![npm 版本](https://img.shields.io/npm/v/pi-openai-toolkit.svg)](https://www.npmjs.com/package/pi-openai-toolkit)
6
+ [![MIT](https://img.shields.io/npm/l/pi-openai-toolkit.svg)](LICENSE)
7
+
8
+ [English](README.md)
9
+
10
+ ## 安装与快速开始
11
+
12
+ 需要 Node.js **22.19.0+**、Pi **0.87.0+**。当前开发依赖锁定 Pi **0.99.1**;后端功能是否可用,还取决于所选模型、接口和账号权限。
13
+
14
+ ```bash
15
+ pi install npm:pi-openai-toolkit
16
+ ```
17
+
18
+ 在 Pi 中配置好模型和凭据后,照常启动。没有 Toolkit 配置文件时,符合条件的模型默认使用远程压缩;搜索由 Pi 和其他扩展管理,生图和 Auto Mode 默认关闭。
19
+
20
+ Toolkit 只读取一个全局配置文件,即使扩展安装在项目内也一样:
21
+
22
+ ```text
23
+ ~/.pi/agent/extensions/pi-openai-toolkit/config.json
24
+ ```
25
+
26
+ 新建配置时,按需创建父目录,使用 v2 格式:
27
+
28
+ ```json
29
+ {
30
+ "schemaVersion": 2,
31
+ "defaults": {
32
+ "context": { "mode": "remote-compaction" }
33
+ }
34
+ }
35
+ ```
36
+
37
+ 在 Pi 中检查配置:
38
+
39
+ - `/toolkit-config`:查看当前生效值及其来源
40
+ - `/toolkit-config validate`:检查配置错误
41
+ - `/toolkit-config migration-preview`:预览旧格式迁移,不写入文件
42
+
43
+ 配置按“内置默认值 → `defaults` → `models["provider/model-id"]`”覆盖。模型键精确匹配、区分大小写,不支持通配符或项目级配置。以下示例按需合并到现有文件,不要覆盖其他设置;没有 `schemaVersion` 的旧配置先看[迁移说明](docs/configuration.md#legacy-compatibility-and-migration)。
44
+
45
+ ## 上下文管理
46
+
47
+ 通过 `defaults.context.mode` 或单个模型的 `context.mode` 选择:
48
+
49
+ - `remote-compaction`:默认模式,使用服务端返回的加密检查点继续会话
50
+ - `remote-windows`:使用 Codex 远程上下文窗口,通过 `history` 检索较早内容、`notes` 保存交接信息
51
+ - `pi`:交给 Pi 管理上下文
52
+
53
+ **远程压缩**支持的 API 类型是 `openai-responses`、`openai-codex-responses` 和 `azure-openai-responses`,但后端仍须支持对应的检查点协议。可用 `context.remoteCompaction.model` 指定独立的压缩模型;远程压缩要求它与当前模型使用相同的有效 base URL。原生摘要回退有独立配置,并非所有失败都会回退;空检查点、来源不匹配或被修改的已封存历史会阻止存储或重放。详见[上下文配置](docs/configuration.md#context)和[检查点规则](docs/internals.md#remote-compaction-v2-wire-contract)。
54
+
55
+ **远程窗口**需要原生 `openai-codex` 提供商的 `openai-codex-responses` API,或支持相应协议的 `openai-responses` 网关。网关必须在精确模型下设置 `compatibility.transport: "codex-gateway"`;这一设置不会让普通兼容端点自动获得该能力。
56
+
57
+ 将上例的 `mode` 改为 `remote-windows` 后,符合条件的会话会提供 `new_context`、`get_context_remaining`、`history` 和 `notes`。手动 `/compact [instructions]` 会发起检查点交接:先成功写入 notes,再切换窗口。不具备窗口能力的模型仍走压缩流程;窗口激活失败不会静默改用摘要。
58
+
59
+ 远程窗口依赖 alpha 接口,上游可能随时调整。切换模型前也要留意旧窗口历史仍未清理的情况,详见[窗口生命周期](docs/internals.md#rollover-lifecycle)。
60
+
61
+ ## 搜索、生图与工具审查
62
+
63
+ ### 联网搜索
64
+
65
+ 在 `defaults.webSearch.route` 或精确模型的 `webSearch.route` 中选择:
66
+
67
+ - `unmanaged`:默认值,不接管搜索;这不等于禁止联网
68
+ - `local`:保留已有本地搜索工具(如 `pi-web-access`),不会安装或启用原本未启用的工具
69
+ - `hosted`:使用 Responses `web_search` 并返回来源标注,停用冲突的本地搜索工具
70
+ - `standalone-alpha`:实验性 `web_run`,通过独立的 `/alpha/search` 请求执行搜索、打开页面等操作
71
+
72
+ `hosted` 支持上述三类 Responses API,仍需后端和账号支持搜索。`standalone-alpha` 仅支持已验证的 OpenAI/Codex 路由,网关还须提供对应端点及能力。选定路由不可用、缺少认证或发生工具冲突时,不会自动换到另一条路由。完整操作列表见[搜索配置](docs/configuration.md#web-search)。
73
+
74
+ ### 图像生成
75
+
76
+ 生图配置只放在全局 `defaults.imageGeneration`。将示例中的 `image-model-id` 替换为后端实际支持的图片模型 ID:
77
+
78
+ ```json
79
+ {
80
+ "schemaVersion": 2,
81
+ "defaults": {
82
+ "imageGeneration": {
83
+ "enabled": true,
84
+ "defaultModel": "image-model-id",
85
+ "allowedModels": ["image-model-id"]
86
+ }
87
+ }
88
+ }
89
+ ```
90
+
91
+ 启用后,符合条件的会话提供 `openai_generate_image`,支持生成、参考图编辑和批量生成。当前会话模型负责路由和认证,图片模型通过独立 Images API 调用,不会替换对话模型。默认图片模型为 `grok-imagine-image-2.0`,不代表你的后端一定支持它;`defaultModel` 必须包含在 `allowedModels` 中。
92
+
93
+ 目前要求 `openai-responses` 或 `openai-codex-responses` 路由,以及可用的 Images API。返回结果须为 base64 编码的 PNG、JPEG 或 WebP。`batchSize` 为 1–10,每张图是一次独立请求,可能单独计费;部分失败会保留已保存的图片。编辑会向提供商发送参考图,请确认这些图片可以上传。详见[生图配置](docs/configuration.md#images)。
94
+
95
+ ### Responses WebSocket 传输
96
+
97
+ Toolkit 的 WebSocket adapter 默认关闭。对使用 Pi `openai-responses` API 的 GPT 模型,可通过全局配置开启:
98
+
99
+ ```json
100
+ {
101
+ "schemaVersion": 2,
102
+ "defaults": {
103
+ "responsesWebSocket": { "enabled": true }
104
+ }
105
+ }
106
+ ```
107
+
108
+ 它沿用当前模型的 provider、base URL、凭据、headers 和 model ID,不注册新的 provider。Pi 的 `transport: "auto"` 会先尝试 WebSocket,并在开始流式输出前回退到 SSE;`transport: "sse"` 保持原有 HTTP/SSE 路径。修改 Toolkit 配置后请重启或 reload Pi。详见[WebSocket 配置](docs/configuration.md#responses-websocket-transport)。
109
+
110
+ ### Auto Mode
111
+
112
+ Auto Mode 在工具执行前进行模型审查。先允许使用并指定 Pi 中已注册、可认证的审查模型,再手动开启:
113
+
114
+ ```json
115
+ {
116
+ "schemaVersion": 2,
117
+ "defaults": {
118
+ "autoMode": {
119
+ "available": true,
120
+ "reviewerModel": "provider/reviewer-model-id"
121
+ }
122
+ }
123
+ }
124
+ ```
125
+
126
+ 将 `provider/reviewer-model-id` 替换为实际模型。用 `/auto on` 或启动参数 `--auto` 开启,`/auto off` 关闭;只设置 `available: true` 不会自动开启。
127
+
128
+ 默认 `gate: "side-effect"` 审查 `bash`、`write`、`edit` 和 `extraTools` 中的工具,`gate: "all"` 审查所有工具。支持只读取证、拒绝次数熔断和可选的后台分类器预评分;开启分类器后,部分调用可依据预评分放行。
129
+
130
+ 审查超时或不可用不算批准:交互模式会请求用户确认,无界面模式会阻止调用。它不是沙箱,也不保证每次判断正确;选择不符合条件的模型会关闭 Auto Mode。完整配置见[Auto Mode](docs/configuration.md#auto-mode)。
131
+
132
+ ## 兼容性与排查
133
+
134
+ - 提供商、端点和凭据仍由 Pi 管理,不写进 Toolkit 配置。Azure 的部署映射、`api-version` 和认证说明见[提供商配置](docs/configuration.md#provider-specific-responses-endpoints)
135
+ - `pi-virtual` 使用 Pi 解析出的实际提供商和模型检查能力,不按虚拟模型名称推断支持情况
136
+ - 压缩和重放时遵守 Pi 模型元数据中的 `inputLimits.images` 缩放与数量限制,不修改持久化会话或原始请求对象
137
+ - 无效配置会阻止依赖它的操作。先运行 `/toolkit-config validate`,再检查模型、认证和后端能力;配置校验通过不等于端点可用
138
+ - 请求与压缩响应记录默认关闭。排查时才开启 `diagnostics.captureRequests` / `captureResponses`,分享日志前检查是否包含对话内容
139
+
140
+ 完整字段和默认值见[配置参考](docs/configuration.md)与 [JSON Schema](config.schema.json)。协议、检查点和调试细节见[内部实现](docs/internals.md)。
141
+
142
+ ## 开发
143
+
144
+ 在仓库根目录运行:
145
+
146
+ ```bash
147
+ npm ci
148
+ npm run typecheck
149
+ npm test
150
+ npm run test:pi
151
+ npm pack --dry-run
152
+ ```
153
+
154
+ 测试使用 Bun,已列入开发依赖。修改 README 的 JSON 示例时,同步更新中英文版本,文档测试会检查两者一致。
155
+
156
+ MIT © awoaCrim 与贡献者。许可证见 [LICENSE](LICENSE),第三方来源与致谢见 [NOTICE](NOTICE)。
@@ -184,6 +184,16 @@
184
184
  }
185
185
  }
186
186
  },
187
+ "responsesWebSocket": {
188
+ "type": "object",
189
+ "additionalProperties": false,
190
+ "properties": {
191
+ "enabled": {
192
+ "type": "boolean",
193
+ "default": false
194
+ }
195
+ }
196
+ },
187
197
  "autoMode": {
188
198
  "type": "object",
189
199
  "additionalProperties": false,
@@ -295,6 +305,9 @@
295
305
  "imageGeneration": {
296
306
  "$ref": "#/$defs/imageGeneration"
297
307
  },
308
+ "responsesWebSocket": {
309
+ "$ref": "#/$defs/responsesWebSocket"
310
+ },
298
311
  "autoMode": {
299
312
  "$ref": "#/$defs/autoMode"
300
313
  }
@@ -21,6 +21,7 @@ Create the file and parent directory if absent. This example states the shipped
21
21
  "defaultModel": "grok-imagine-image-2.0",
22
22
  "allowedModels": ["grok-imagine-image-2.0"]
23
23
  },
24
+ "responsesWebSocket": { "enabled": false },
24
25
  "autoMode": { "available": false }
25
26
  },
26
27
  "models": {},
@@ -85,6 +86,100 @@ This selects an existing Toolkit protocol profile, independently of context mode
85
86
 
86
87
  ---
87
88
 
89
+ ### Responses WebSocket transport
90
+
91
+ The Responses WebSocket extension is disabled by default. Enable it globally with `defaults.responsesWebSocket.enabled: true`; it is intentionally not a model-scoped override. Restart or reload Pi after changing this setting. An invalid or legacy configuration keeps the feature disabled.
92
+
93
+ The extension is an API-adapter override, not a provider registration. It applies to GPT model IDs whose Pi API is `openai-responses`, regardless of provider name. The active model's `baseUrl`, `apiKey`, configured headers, session id, and payload remain the source of truth.
94
+
95
+ The extension honors Pi's global `transport` setting:
96
+
97
+ | Pi `transport` | Behavior |
98
+ | --- | --- |
99
+ | `auto` | Try `wss://.../responses?model=...` first; fall back to the original SSE adapter only before a stream starts. |
100
+ | `websocket` | Require the WebSocket path; do not fall back to SSE. |
101
+ | `websocket-cached` | Use the WebSocket path with the same strict behavior. |
102
+ | `sse` | Bypass the extension and use the original HTTP/SSE adapter. |
103
+
104
+ The endpoint is derived from the model's base URL by appending `/responses` when needed and switching `https:`/`http:` to `wss:`/`ws:`. The first frame is a standard `response.create` object and incoming frames are passed through Pi's existing Responses event normalizer. The upstream must support the standard Responses WebSocket contract; this does not rewrite a server that only exposes Codex's `/codex/responses` path or Codex-only authentication.
105
+
106
+ This feature does not write Pi settings, model files, auth files, or global extensions. To keep the Toolkit adapter disabled, set `defaults.responsesWebSocket.enabled` to `false` or omit it. Once enabled, Pi's global `transport: "sse"` still bypasses the WebSocket path for a request.
107
+
108
+ ---
109
+
110
+ ### Provider-specific Responses endpoints
111
+
112
+ Toolkit consumes provider registration, endpoint, model, credential, and provider-scoped environment values from Pi. Keep those details in Pi's model and authentication stores; Toolkit configuration selects the feature policy and exact model overrides. Pi's complete `auth.env` object is preserved through Toolkit authentication and request setup, including compaction, replay, fallback, and hosted-tool boundaries.
113
+
114
+ #### Azure OpenAI Responses
115
+
116
+ Pi's `azure-openai-responses` API uses Azure's Responses endpoint. Toolkit uses Pi's resolved provider authentication and environment values for the base URL, deployment mapping, and `api-version`. Azure Responses requests use the `api-key` header and do not forward an inherited bearer `Authorization` header.
117
+
118
+ Set the API key and either a resource name or a full base URL before starting Pi. `AZURE_OPENAI_API_VERSION` defaults to `v1`, and `AZURE_OPENAI_DEPLOYMENT_NAME_MAP` maps the model ID selected in Pi to an Azure deployment name.
119
+
120
+ PowerShell:
121
+
122
+ ```powershell
123
+ $env:AZURE_OPENAI_API_KEY = "replace-with-your-azure-key"
124
+ $env:AZURE_OPENAI_RESOURCE_NAME = "replace-with-your-resource"
125
+ $env:AZURE_OPENAI_API_VERSION = "2025-01-01"
126
+ $env:AZURE_OPENAI_DEPLOYMENT_NAME_MAP = "model-id=replace-with-deployment"
127
+ ```
128
+
129
+ POSIX shell:
130
+
131
+ ```bash
132
+ export AZURE_OPENAI_API_KEY="replace-with-your-azure-key"
133
+ export AZURE_OPENAI_RESOURCE_NAME="replace-with-your-resource"
134
+ export AZURE_OPENAI_API_VERSION="2025-01-01"
135
+ export AZURE_OPENAI_DEPLOYMENT_NAME_MAP="model-id=replace-with-deployment"
136
+ ```
137
+
138
+ Use `AZURE_OPENAI_BASE_URL` instead of `AZURE_OPENAI_RESOURCE_NAME` when the full resource URL is already known, for example `https://your-resource.openai.azure.com`. Toolkit normalizes the resource root to `/openai/v1` and appends `api-version` to both the Responses and compact URLs.
139
+
140
+ Provider-scoped values can also be stored in Pi's `~/.pi/agent/auth.json`:
141
+
142
+ ```json
143
+ {
144
+ "azure-openai-responses": {
145
+ "type": "api_key",
146
+ "key": "$AZURE_OPENAI_API_KEY",
147
+ "env": {
148
+ "AZURE_OPENAI_RESOURCE_NAME": "replace-with-your-resource",
149
+ "AZURE_OPENAI_API_VERSION": "2025-01-01",
150
+ "AZURE_OPENAI_DEPLOYMENT_NAME_MAP": "model-id=replace-with-deployment"
151
+ }
152
+ }
153
+ }
154
+ ```
155
+
156
+ Pi resolves the credential and complete `env` object for each request; provider-scoped values take priority over the process environment. Keep `auth.json` private. The selected Pi model ID may differ from the Azure deployment name when the mapping is configured.
157
+
158
+ Enable the Azure Responses API in the Toolkit policy and start Pi with the registered model ID:
159
+
160
+ ```json
161
+ {
162
+ "schemaVersion": 2,
163
+ "defaults": {
164
+ "context": {
165
+ "mode": "remote-compaction",
166
+ "remoteCompaction": {
167
+ "apis": ["azure-openai-responses"]
168
+ }
169
+ },
170
+ "webSearch": { "route": "hosted" }
171
+ }
172
+ }
173
+ ```
174
+
175
+ ```bash
176
+ pi --model azure-openai-responses/<model-id>
177
+ ```
178
+
179
+ The exact model must still be registered in Pi's model catalog and authenticated through Pi. Keep provider registration and credentials in Pi's own configuration.
180
+
181
+ ---
182
+
88
183
  ### Web Search
89
184
 
90
185
  `defaults.webSearch.route` and `models[exact].webSearch.route` accept:
@@ -106,6 +201,39 @@ Image settings are global-only under `defaults.imageGeneration`. `enabled` defau
106
201
 
107
202
  These are bare output-model IDs, not active-session model keys. Each normalized ID must contain 1-256 characters. The allowed list must remain nonempty after normalization and contain the explicit default. A caller's one-call `model` must be a member; policy and membership are checked before auth, local-reference preparation/upload, and paid dispatch. The active session remains the routing/auth model, while the selected image model is sent in a separate Images API request. Generation uses `/images/generations`; edits use `/images/edits` (Codex uses the corresponding `/codex/images/...` paths). The wrapper never injects a Responses `image_generation` tool. Responses are accepted only when they contain one validated PNG, JPEG, or WebP `data[].b64_json` image; the canonical artifact uses the detected format extension. A literal `quality: "auto"` is omitted from the wire request for compatibility gateways that reject it. `batchSize` is a tool argument from 1-10; each item is an independent `n: 1` request, partial success preserves saved artifacts, and batch calls cannot use a single-file `outputPath`. Config does not grant permission to upload arbitrary local files or imply that a provider supports a particular image model.
108
203
 
204
+ Image input limits are declared in Pi's model metadata, not in Toolkit policy. For example:
205
+
206
+ ```json
207
+ {
208
+ "providers": {
209
+ "my-gateway": {
210
+ "baseUrl": "https://your-gateway.example/v1",
211
+ "api": "openai-responses",
212
+ "apiKey": "$MY_GATEWAY_KEY",
213
+ "models": [{
214
+ "id": "vision-model",
215
+ "name": "Vision Model",
216
+ "input": ["text", "image"],
217
+ "inputLimits": {
218
+ "images": {
219
+ "resize": {
220
+ "maxWidth": 1568,
221
+ "maxHeight": 1568,
222
+ "maxBytes": 524288,
223
+ "jpegQuality": 80
224
+ },
225
+ "maxPerMessage": 4,
226
+ "maxPerRequest": 8
227
+ }
228
+ }
229
+ }]
230
+ }
231
+ }
232
+ }
233
+ ```
234
+
235
+ At the compaction and replay boundary, Toolkit applies the declared resize profile before dispatch, counts images per message and request, and fails closed when a limit cannot be satisfied. It creates new input values without mutating the persisted session or original provider payload.
236
+
109
237
  ---
110
238
 
111
239
  ### Auto Mode
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-openai-toolkit",
3
- "version": "0.19.0",
3
+ "version": "0.20.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "engines": {
@@ -38,7 +38,8 @@
38
38
  "./src/web-search/extension.ts",
39
39
  "./src/image-generation/extension.ts",
40
40
  "./src/auto-mode/extension.ts",
41
- "./src/codex-astra/extension.ts"
41
+ "./src/codex-astra/extension.ts",
42
+ "./src/responses-websocket/extension.ts"
42
43
  ]
43
44
  },
44
45
  "files": [
@@ -89,6 +90,8 @@
89
90
  "src/auto-mode/types.ts",
90
91
  "src/codex-astra/effort-planner.ts",
91
92
  "src/codex-astra/extension.ts",
93
+ "src/responses-websocket/extension.ts",
94
+ "src/responses-websocket/transport.ts",
92
95
  "src/model-scope.ts",
93
96
  "src/native-fallback.ts",
94
97
  "src/payload-rewrite.ts",
@@ -8,7 +8,7 @@ import {
8
8
  type RemoteV2ContextSource,
9
9
  } from "../types";
10
10
 
11
- export type ConfigFeature = "context" | "webSearch" | "imageGeneration" | "autoMode" | "compatibility" | "diagnostics";
11
+ export type ConfigFeature = "context" | "webSearch" | "imageGeneration" | "autoMode" | "compatibility" | "responsesWebSocket" | "diagnostics";
12
12
  export type SearchRoute = "unmanaged" | "local" | "hosted" | "standalone-alpha";
13
13
  export type DiagnosticsConfig = {
14
14
  level: "error" | "warn" | "info" | "debug";
@@ -42,6 +42,7 @@ export type EffectiveToolkitPolicy = {
42
42
  context: ContextPolicy;
43
43
  webSearch: { route: SearchRoute };
44
44
  imageGeneration: { enabled: boolean; defaultModel: string; allowedModels: string[] };
45
+ responsesWebSocket: { enabled: boolean };
45
46
  autoMode: AutoModePolicy;
46
47
  compatibility: { transport: "standard" | "codex-gateway" };
47
48
  diagnostics: DiagnosticsConfig;
@@ -74,7 +75,7 @@ export type ConfigDocumentSnapshot = {
74
75
  issues: ConfigIssue[];
75
76
  };
76
77
  export const CONFIG_FEATURES: readonly ConfigFeature[] = [
77
- "context", "webSearch", "imageGeneration", "autoMode", "compatibility", "diagnostics",
78
+ "context", "webSearch", "imageGeneration", "autoMode", "compatibility", "responsesWebSocket", "diagnostics",
78
79
  ];
79
80
 
80
81
  /** Independent per-operation defaults, preserving the existing shipped policy. */
@@ -103,6 +104,7 @@ export function createPolicyDefaults(): EffectiveToolkitPolicy {
103
104
  defaultModel: DEFAULT_IMAGE_GENERATION_MODEL,
104
105
  allowedModels: [DEFAULT_IMAGE_GENERATION_MODEL],
105
106
  },
107
+ responsesWebSocket: { enabled: false },
106
108
  autoMode: {
107
109
  ...autoOptions,
108
110
  available: false,