pi-openai-toolkit 0.14.3 → 0.14.4
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 +150 -162
- package/README.zh.md +156 -164
- package/docs/internals.md +73 -0
- package/extensions/auto-mode.ts +1 -1
- package/extensions/codex-astra.ts +1 -1
- package/extensions/compaction.ts +1 -1
- package/extensions/image-generation.ts +1 -1
- package/extensions/web-search.ts +1 -1
- package/package.json +2 -1
- package/src/config.ts +10 -0
- package/src/context-management/codex-provider.ts +12 -14
- package/src/context-management/history-notes.ts +8 -2
- package/src/context-management/tools.ts +5 -3
- package/src/context-management/types.ts +2 -1
- package/src/extension-runtime.ts +9 -5
- package/src/types.ts +7 -0
- package/src/web-search/prompt.ts +1 -1
package/README.zh.md
CHANGED
|
@@ -2,51 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/pi-openai-toolkit)
|
|
4
4
|
[](./LICENSE)
|
|
5
|
-
|
|
6
|
-
面向 Pi 的 OpenAI 工具包:Codex 远端上下文窗口、远端无损压缩 v2、托管联网搜索、图像生成与 Auto 模式。
|
|
7
|
-
|
|
8
5
|
[English](./README.md)
|
|
9
6
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
1. **压缩与远端上下文管理**(`extensions/compaction.ts`):两套长上下文策略。[Codex 远端上下文管理](#codex-远端上下文管理)把 Codex 原生窗口体系移植到 Pi——无摘要 `new_context` 换窗(附成功的 notes checkpoint 硬门禁)、跨窗口 `history` / `notes` 工具(加密参数传输)、按预算触发的 checkpoint 提醒。关闭它时,本扩展走 **Remote Compaction v2**:服务端密文压缩,绝不做有损文本重摘要。
|
|
13
|
-
2. **联网搜索**(`extensions/web-search.ts`):为 `provider/model-id` 精确白名单注入托管 `web_search`,复用当前模型连接。
|
|
14
|
-
3. **图像生成**(`extensions/image-generation.ts`):由托管 `image_generation` 工具驱动的本地 `openai_generate_image`,支持文生图与显式本地参考图编辑,图像字节不进会话历史。
|
|
15
|
-
4. **Auto 模式**(`extensions/auto-mode.ts`):为改变状态的工具调用增设审批模型门禁,Agent 不必停下来等你确认。
|
|
16
|
-
5. **Codex Astra**(`extensions/codex-astra.ts`):为 `gpt-6-astra` 补发 Codex 后端版本门禁头,并用 `configuration_update` 会话项保住提示缓存。按模型名静默启用,无配置段。
|
|
17
|
-
|
|
18
|
-
本包是 Pi 扩展集而非可导入库:一切通过一个 JSON 配置文件驱动,在 Pi 内自动生效。
|
|
19
|
-
|
|
20
|
-
## 目录
|
|
21
|
-
- [安全](#安全)
|
|
22
|
-
- [背景](#背景)
|
|
23
|
-
- [安装](#安装)
|
|
24
|
-
- [使用](#使用)
|
|
25
|
-
- [配置](#配置)
|
|
26
|
-
- [功能指南](#功能指南)
|
|
27
|
-
- [开发](#开发)
|
|
28
|
-
- [API](#api)
|
|
29
|
-
- [Remote Context 工具](#remote-context-工具)
|
|
30
|
-
- [HTTP 协议参考](#http-协议参考)
|
|
31
|
-
- [维护者](#维护者)
|
|
32
|
-
- [贡献](#贡献)
|
|
33
|
-
- [许可证](#许可证)
|
|
34
|
-
- [致谢](#致谢)
|
|
35
|
-
|
|
36
|
-
## 安全
|
|
37
|
-
|
|
38
|
-
- **覆盖模型不会有静默的有损摘要。** `contextManagement: "remote"` 覆盖某模型期间,Pi 原生压缩在阈值、手动 `/compact`、溢出全部路径上被取消,v2 也不发送。若想再加宿主级保险,在 Pi `settings.json` 设 `"compaction": { "enabled": false }`;覆盖范围外的模型照常走 Pi 自己的策略。
|
|
39
|
-
- **网关隔离。** 网关模式只转发配置的数据面 key;OAuth 令牌、account cookie、account ID 一律剥离;artifact 中凭据与不透明密文永远脱敏。
|
|
40
|
-
- **Checkpoint 门禁。** `new_context` 无法在没有本窗口成功 notes 写入、也没有用户显式 `force` 授权时丢弃未保存工作状态——Codex 官方实验特性上出现过的"后端故障 + 换窗丢状态"在此被硬拦。
|
|
41
|
-
- **计费与审批边界。** 图像生成显式开启且可能产生费用;审批请求禁用提示缓存、只授予只读工具,无 UI 会话 fail-closed。
|
|
7
|
+
面向 Pi 的 OpenAI 工具包:无损长会话上下文管理、托管联网搜索、图像生成与带审批门禁的 Auto 模式。
|
|
42
8
|
|
|
43
|
-
|
|
9
|
+
Pi 内置压缩把较早的轮次摘要为文本,细节永久丢失。OpenAI Codex 后端用一整套通用客户端从未获得的机制解决这个问题:上下文窗口体系(`new_context`、`history`、`notes`)、加密无损压缩、托管工具。本包通过对接真实后端协议,把这些 Codex 能力移植进 Pi;Auto 模式则是本包自有功能。需要说明:覆盖模型会话中出现的窗口工具是 Codex 的机制、由本包接通,并非 Pi 或本包独立发明的能力。
|
|
44
10
|
|
|
45
|
-
|
|
11
|
+
## 特性
|
|
46
12
|
|
|
47
|
-
|
|
13
|
+
- **上下文窗口**(Codex 机制移植)- `new_context` 切换新窗口,全程不重摘要
|
|
14
|
+
- **跨窗口回读** - `history` 搜索、阅读更早窗口的原始内容
|
|
15
|
+
- **工作记忆笔记** - `notes` 持久化存档,作为每次换窗的门禁
|
|
16
|
+
- **加密压缩 v2** - OpenAI 后端压缩能力,为 Responses 模型接通
|
|
17
|
+
- **托管联网搜索** - OpenAI Responses 原生 `web_search`,对列入的模型替换 Pi 本地工具
|
|
18
|
+
- **图像生成** - 托管 `image_generation`(gpt-image-2)的 Pi 封装,图像字节不入会话历史
|
|
19
|
+
- **Auto 模式** - 本包自有功能:副作用工具调用的审查模型门禁
|
|
20
|
+
- **安全承诺** - 覆盖模型上杜绝有损摘要,凭据不出本机
|
|
48
21
|
|
|
49
|
-
|
|
22
|
+
需要 Pi >= 0.85.1、Node.js >= 22.19.0。本包不注册任何 provider 或模型,全部经由 Pi 已有的目录、登录与会话存储工作。不要与 `pi-remote-compact`、`@lll9p/pi-better-compaction` 或独立的 `pi-openai-web-search` 同时运行:重复 hook 会导致竞态。
|
|
50
23
|
|
|
51
24
|
## 安装
|
|
52
25
|
|
|
@@ -54,198 +27,217 @@ Pi 内置压缩会把旧轮次摘要成文本,细节随之丢失;OpenAI Code
|
|
|
54
27
|
pi install npm:pi-openai-toolkit
|
|
55
28
|
```
|
|
56
29
|
|
|
57
|
-
|
|
30
|
+
仅安装到当前项目:
|
|
58
31
|
|
|
59
32
|
```bash
|
|
60
33
|
pi install npm:pi-openai-toolkit --local
|
|
61
34
|
```
|
|
62
35
|
|
|
63
|
-
从 git
|
|
36
|
+
从 git 安装(开发或锁定构建):
|
|
64
37
|
|
|
65
38
|
```bash
|
|
66
39
|
pi install git:github.com/awoaCrim/pi-openai-toolkit
|
|
67
40
|
```
|
|
68
41
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
`pi update --extensions` 会连同本工具包一起更新 Pi 包。已发布版本见 [npm](https://www.npmjs.com/package/pi-openai-toolkit)。
|
|
72
|
-
|
|
73
|
-
### 冲突警告
|
|
74
|
-
|
|
75
|
-
不要将 `pi-remote-compact`、`@lll9p/pi-better-compaction` 或独立的 `pi-openai-web-search` 与本包同时运行:重复 hook 会造成竞态和系统提示词重复。
|
|
42
|
+
后续用 `pi update --extensions` 更新。
|
|
76
43
|
|
|
77
|
-
##
|
|
44
|
+
## 快速开始
|
|
78
45
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
创建 `~/.pi/agent/extensions/pi-openai-toolkit/config.json`(Windows:`C:\Users\<user>\.pi\agent\extensions\pi-openai-toolkit\config.json`):
|
|
46
|
+
**1.** 创建 `~/.pi/agent/extensions/pi-openai-toolkit/config.json`(Windows:`C:\Users\<user>\.pi\agent\extensions\pi-openai-toolkit\config.json`):
|
|
82
47
|
|
|
83
48
|
```json
|
|
84
49
|
{
|
|
85
50
|
"compaction": {
|
|
86
|
-
"enabled": true,
|
|
87
51
|
"contextManagement": "remote",
|
|
88
|
-
"contextReminderThresholdPercent": 10
|
|
89
|
-
"allowCompactionContinuityBreak": false,
|
|
90
|
-
"remoteCompactModel": "uwoacrimson/gpt-5.6-luna",
|
|
91
|
-
"nativeFallback": { "enabled": true, "model": null, "thinkingLevel": "off" },
|
|
92
|
-
"responsesApis": ["openai-responses", "openai-codex-responses"],
|
|
93
|
-
"notifyOnLoad": false,
|
|
94
|
-
"debug": false,
|
|
95
|
-
"logProviderPayloads": false,
|
|
96
|
-
"logCompactResponses": false,
|
|
97
|
-
"redactSensitiveData": true,
|
|
98
|
-
"artifactRoot": "~/.pi/agent/artifacts/pi-openai-toolkit/compaction"
|
|
99
|
-
},
|
|
100
|
-
"webSearch": { "enabled": true, "models": ["uwoacrimson/gpt-5.6-luna"] },
|
|
101
|
-
"imageGeneration": { "enabled": false },
|
|
102
|
-
"autoMode": {
|
|
103
|
-
"enabled": true,
|
|
104
|
-
"models": ["uwoacrimson/gpt-5.6-luna"],
|
|
105
|
-
"reviewerModel": "uwoacrimson/gpt-5.6-luna",
|
|
106
|
-
"gate": "side-effect"
|
|
52
|
+
"contextReminderThresholdPercent": 10
|
|
107
53
|
}
|
|
108
54
|
}
|
|
109
55
|
```
|
|
110
56
|
|
|
111
|
-
|
|
57
|
+
**2.** 在覆盖的模型上启动 Pi:Pi 内置 Codex provider(`openai-codex`)上的任意会话,或已列入 `gatewayContextModels` 的网关模型:
|
|
112
58
|
|
|
113
59
|
```bash
|
|
114
|
-
pi --model uwoacrimson/gpt-6-astra
|
|
60
|
+
pi --model uwoacrimson/gpt-6-astra
|
|
115
61
|
```
|
|
116
62
|
|
|
117
|
-
|
|
63
|
+
**3.** 确认生效:会话内出现四个 Codex 上下文工具(`new_context`、`get_context_remaining`、`history`、`notes`)。
|
|
118
64
|
|
|
119
|
-
|
|
65
|
+
窗口余量低于提醒阈值时,模型收到一次提醒:存档笔记并换窗。更早的内容始终可通过 `history` 搜索。没有配置文件时,Pi 按默认策略运行,所有可选功能保持关闭。
|
|
120
66
|
|
|
121
|
-
|
|
67
|
+
网关覆盖是一份显式白名单:`compaction.gatewayContextModels` 逐条列出 `provider/model` 精确键,模型须走 `openai-responses` 线路,且你的网关确实透传 Codex 窗口标记。若 Pi 中尚未配置该网关,在 `~/.pi/agent/models.json` 添加:
|
|
122
68
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
| `enabled` | *boolean*, `true` | 总开关。 |
|
|
145
|
-
| `models` | *string[]*, `[]` | 接收托管 `web_search` 注入的精确白名单(限 Responses 系 API)。名单内模型的上行载荷会移除本地 `web_search` 函数工具,原生搜索成为唯一路径;切到名单外模型即恢复。 |
|
|
69
|
+
```json
|
|
70
|
+
{
|
|
71
|
+
"providers": {
|
|
72
|
+
"uwoacrimson": {
|
|
73
|
+
"baseUrl": "https://<your-gateway>/v1",
|
|
74
|
+
"apiKeyRef": "uwoacrimson",
|
|
75
|
+
"api": "openai",
|
|
76
|
+
"models": [{
|
|
77
|
+
"id": "gpt-6-astra",
|
|
78
|
+
"name": "GPT-6 Astra",
|
|
79
|
+
"api": "openai-responses",
|
|
80
|
+
"reasoning": true,
|
|
81
|
+
"input": ["text"],
|
|
82
|
+
"contextWindow": 272000,
|
|
83
|
+
"maxTokens": 16384,
|
|
84
|
+
"compat": {"thinkingLevelMap": {"off": 0, "minimal": 0.1, "low": 0.2, "medium": 0.5, "high": 1, "xhigh": 2, "max": 2}}
|
|
85
|
+
}]
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
146
90
|
|
|
147
|
-
|
|
91
|
+
## 用法
|
|
148
92
|
|
|
149
|
-
|
|
150
|
-
| --- | --- | --- |
|
|
151
|
-
| `enabled` | *boolean*, `false` | `openai_generate_image` 的唯一开关。默认关闭,因为每次成功请求都可能产生费用。无模型白名单:托管图像工具是 Responses API 能力,对所有 Responses 系模型暴露、其余隐藏。 |
|
|
93
|
+
### Codex Remote Context
|
|
152
94
|
|
|
153
|
-
|
|
95
|
+
这是 Codex 自身的上下文窗口机制,由本包为 Pi 实现。覆盖模型的会话按 Codex 客户端的方式运行:模型在上下文窗口中工作,用 `notes` 存档状态,在窗口装满前调用 `new_context`。不发生任何摘要,更早窗口通过 `history` 完整可读。本窗口没有成功笔记存档时换窗会被拒绝;resume 与 fork 后规则不变。提醒与窗口耗尽消息只向模型建议,换窗始终由模型自己调用 `new_context` 完成。
|
|
154
96
|
|
|
155
|
-
|
|
156
|
-
| --- | --- | --- |
|
|
157
|
-
| `enabled` | *boolean*, `true` | 总开关;未列入白名单或未设 `reviewerModel` 前依然无法启用。 |
|
|
158
|
-
| `models` | *string[]*, `[]` | 允许进入 auto 模式的当前会话模型白名单。 |
|
|
159
|
-
| `reviewerModel` | *string \| null*, `null` | 审批模型(`provider/model-id`,经 Pi 注册表解析)。只用于单次审批请求,绝不成为会话模型。 |
|
|
160
|
-
| `gate` | `"side-effect"` \| `"all"`, `"side-effect"` | 审批范围;`/auto all` 把当次会话扩到全部工具。 |
|
|
161
|
-
| `extraTools` | *string[]*, `[]` | 在副作用集(`bash`、`write`、`edit`)之外追加审批的工具名。 |
|
|
162
|
-
| `timeoutMs` | *integer* 1000-120000, `30000` | 审批模型全部轮次的总时限;超时绝不视为通过。 |
|
|
163
|
-
| `transcript` | *boolean*, `true` | 给审批模型有界的会话视图,使其能判断"用户是否授权"而非只看命令危险度。 |
|
|
164
|
-
| `evidenceTools` | *boolean*, `true` | 允许审批模型先用 Pi 只读工具(`read`/`grep`/`find`/`ls`)查证;它永远拿不到 `bash`、写工具或网络。 |
|
|
165
|
-
| `maxEvidenceRounds` | *integer* 0-8, `3` | 调查轮数上限;`0` 为单次补全。 |
|
|
166
|
-
| `classifier.*` | 见码内说明 | 可选非阻塞低风险预打分(`enabled` `false`、`model`、`timeoutMs` `15000`、`maxLag` `2`),只能给普通调用开快车道,绝不否决。 |
|
|
167
|
-
| `circuitBreaker.*` | — | 否决熔断(连续 `consecutiveDenials` `3` 或窗口 `windowSize` `50` 内 `recentDenials` `10` 结束回合;`0` 关闭)。 |
|
|
97
|
+
覆盖模型的压缩路径由本包独占:Pi 原生压缩全部取消,有损摘要无法进入会话。Remote Context 无法激活时,以通知报告确切原因。
|
|
168
98
|
|
|
169
|
-
|
|
99
|
+
生命周期机制与协议契约:[docs/internals.md](docs/internals.md#rollover-lifecycle)。
|
|
170
100
|
|
|
171
|
-
|
|
101
|
+
### Remote Compaction v2
|
|
172
102
|
|
|
173
|
-
|
|
103
|
+
适用于其他 Responses 模型:压缩触发时,本包请求 OpenAI 后端的压缩能力为旧前缀生成加密检查点,而非由文本摘要顶替;检查点由服务端计算,客户端只负责存储与回放。后续请求将其回放到较近轮次之前。远端尝试失败时回退到 Pi 原生压缩(`nativeFallback`)。线路契约:[docs/internals.md](docs/internals.md#remote-compaction-v2-wire-contract)。
|
|
174
104
|
|
|
175
|
-
###
|
|
105
|
+
### 联网搜索
|
|
176
106
|
|
|
177
|
-
|
|
107
|
+
```json
|
|
108
|
+
{
|
|
109
|
+
"webSearch": { "enabled": true, "models": ["uwoacrimson/gpt-5.6-luna"] }
|
|
110
|
+
}
|
|
111
|
+
```
|
|
178
112
|
|
|
179
|
-
|
|
113
|
+
列入的模型获得 OpenAI 托管 `web_search`,其本地 `web_search` 工具从载荷移除。复用当前模型连接,无需额外 key。
|
|
180
114
|
|
|
181
|
-
|
|
182
|
-
- **无摘要换窗。** `new_context` 安装新窗口并把旧窗口从模型上下文裁剪,不做任何再摘要;旧轮次仍可通过服务端 `history` 取回。
|
|
183
|
-
- **Checkpoint 门禁。** 换窗前必须存在当前窗口内*成功的* `notes` `append_to_file` / `write_file`,校验基于持久化会话分支重建(重启后依然有效);不满足时 `new_context` 拒绝。`force: true` 是用户明确授权丢弃的唯一逃生口;Toolkit 自己的窗口耗尽兜底会在要求最后一次 notes 写入后自动绕过门禁。
|
|
184
|
-
- **预算。** `get_context_remaining` 报告实时窗口预算;`contextReminderThresholdPercent` 控制每窗口一次的 checkpoint 提醒。
|
|
185
|
-
- **压缩独占。** 覆盖模型的全部压缩事件由本包接管:不发送 v2;即使 Remote 运行时暂时未激活也取消 Pi 原生压缩(阈值、手动 `/compact`、溢出三条路径全拦),不会有有损摘要背地里插入。未激活原因以通知呈现(`debug` 开启时同时写入 `session_start` lifecycle artifact 的 `activation` 字段),请修复该原因而非期待压缩。
|
|
115
|
+
### 图像生成
|
|
186
116
|
|
|
187
|
-
|
|
117
|
+
```json
|
|
118
|
+
{
|
|
119
|
+
"imageGeneration": { "enabled": true }
|
|
120
|
+
}
|
|
121
|
+
```
|
|
188
122
|
|
|
189
|
-
|
|
123
|
+
为所有 Responses 协议会话添加 `openai_generate_image`,封装 OpenAI 托管 `image_generation` 工具(`gpt-image-2`):文生图,以及显式传入本地参考文件的编辑。图像字节以 artifact 存储而非进入会话历史。每次成功请求都可能产生费用,默认关闭。
|
|
190
124
|
|
|
191
|
-
|
|
125
|
+
### Auto 模式
|
|
192
126
|
|
|
193
|
-
|
|
127
|
+
```json
|
|
128
|
+
{
|
|
129
|
+
"autoMode": {
|
|
130
|
+
"enabled": true,
|
|
131
|
+
"models": ["uwoacrimson/gpt-5.6-luna"],
|
|
132
|
+
"reviewerModel": "uwoacrimson/gpt-5.6-luna"
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
```
|
|
194
136
|
|
|
195
|
-
|
|
137
|
+
会话内用 `/auto on` 启用。副作用工具调用由 `reviewerModel` 批准(固有风险 + 对话授权),不再阻塞等用户。审查员仅有只读工具,超时不视为批准,无头会话一律阻断而非猜测。每条决定落盘可审计。
|
|
196
138
|
|
|
197
|
-
|
|
139
|
+
## 配置
|
|
198
140
|
|
|
199
|
-
|
|
141
|
+
配置文件唯一:`~/.pi/agent/extensions/pi-openai-toolkit/config.json`。所有键可选,未知键告警忽略。`models` 键是精确 `provider/model-id` 白名单(不支持通配),列入前功能保持关闭。
|
|
200
142
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
bun test # 全量单元测试
|
|
204
|
-
npm run test:pi # Pi 集成冒烟测试
|
|
205
|
-
npm pack --dry-run # 检查发布包内容
|
|
206
|
-
```
|
|
143
|
+
<details>
|
|
144
|
+
<summary><b>完整选项参考</b>(compaction、webSearch、imageGeneration、autoMode)</summary>
|
|
207
145
|
|
|
208
|
-
|
|
146
|
+
### `compaction`
|
|
147
|
+
|
|
148
|
+
| 键 | 类型 / 默认值 | 含义 |
|
|
149
|
+
| --- | --- | --- |
|
|
150
|
+
| `enabled` | *boolean*, `true` | 压缩扩展总开关。 |
|
|
151
|
+
| `contextManagement` | `"off"` \| `"remote"`, `"off"` | 为覆盖模型开启 Codex Remote Context:`openai-codex-responses` API 上的任意 `openai-codex` 会话,加上下列白名单中的网关模型。 |
|
|
152
|
+
| `gatewayContextModels` | *string[]*, `[]` | 允许经 `openai-responses` 网关线路使用 Codex Remote Context 的 `provider/model` 精确键。覆盖范围由使用者配置;原生 Codex 路线不看此列表。 |
|
|
153
|
+
| `contextReminderThresholdPercent` | *integer* `0`-`100`, `5` | 当剩余量低于可用预算(上下文窗口减去固定 16384 token 输出预留)的该百分比时,注入每窗口一次的 checkpoint 提醒。`0` 会连同窗口耗尽兜底一起关闭(当前实现如此),请保持大于 0。该阈值度量本包自己的预算,与 Pi 原生预留为固定数值配合,并非运行时动态联动。 |
|
|
154
|
+
| `allowCompactionContinuityBreak` | *boolean*, `false` | v2:最近一次压缩来自其他策略(如安装前的文本摘要)时,重建全新密文链。 |
|
|
155
|
+
| `remoteCompactModel` | *string \| null*, `null` | v2:仅用于服务端压缩请求的模型,会话模型不切换。必须与当前模型同 base URL。 |
|
|
156
|
+
| `nativeFallback.enabled` | *boolean*, `true` | 仅在远端压缩确实失败后回退到原生压缩。 |
|
|
157
|
+
| `nativeFallback.model` | *string \| null*, `null` | 完全无法使用 v2 的模型的摘要模型。`null` 沿用当前模型。 |
|
|
158
|
+
| `nativeFallback.thinkingLevel` | *string*, `"off"` | 回退摘要的 thinking level(`off`...`max`)。 |
|
|
159
|
+
| `responsesApis` | *string[]*, 两个 API | 允许使用 v2 压缩的 Responses API 标识。v2 只作用于未被 Remote Context 覆盖的模型。 |
|
|
160
|
+
| `notifyOnLoad` | *boolean*, `false` | 启动横幅。 |
|
|
161
|
+
| `debug` | *boolean*, `false` | 向 `artifactRoot` 写生命周期与压缩 artifact,含每次 `session_start` 的激活原因。 |
|
|
162
|
+
| `logProviderPayloads` / `logCompactResponses` | *boolean*, `false` | 额外写原始载荷与 SSE 响应体,排查特定请求时再开。 |
|
|
163
|
+
| `redactSensitiveData` | *boolean*, `true` | artifact 脱敏;凭据、account ID、密文永远脱敏。 |
|
|
164
|
+
| `artifactRoot` | *string*, `~/.pi/agent/artifacts/pi-openai-toolkit/compaction` | artifact 根目录;相对路径按配置目录解析。 |
|
|
165
|
+
|
|
166
|
+
### `webSearch`
|
|
167
|
+
|
|
168
|
+
| 键 | 类型 / 默认值 | 含义 |
|
|
169
|
+
| --- | --- | --- |
|
|
170
|
+
| `enabled` | *boolean*, `true` | 总开关。 |
|
|
171
|
+
| `models` | *string[]*, `[]` | 接收 OpenAI 托管 `web_search` 的会话:本地 `web_search` 工具被移除,原生 Responses API 工具被注入。 |
|
|
209
172
|
|
|
210
|
-
|
|
173
|
+
### `imageGeneration`
|
|
211
174
|
|
|
212
|
-
|
|
175
|
+
| 键 | 类型 / 默认值 | 含义 |
|
|
176
|
+
| --- | --- | --- |
|
|
177
|
+
| `enabled` | *boolean*, `false` | 向所有 Responses 协议会话开放 `openai_generate_image`。有意不设模型白名单。 |
|
|
213
178
|
|
|
214
|
-
|
|
179
|
+
### `autoMode`
|
|
215
180
|
|
|
216
|
-
|
|
|
181
|
+
| 键 | 类型 / 默认值 | 含义 |
|
|
217
182
|
| --- | --- | --- |
|
|
218
|
-
| `
|
|
219
|
-
| `
|
|
220
|
-
| `
|
|
221
|
-
| `
|
|
183
|
+
| `enabled` | *boolean*, `true` | 总开关;启用模式仍需列入模型并设置 `reviewerModel`。 |
|
|
184
|
+
| `models` | *string[]*, `[]` | 允许运行 Auto 模式的会话模型。 |
|
|
185
|
+
| `reviewerModel` | *string \| null*, `null` | 一次性审查的审批模型,绝不成为对话模型。 |
|
|
186
|
+
| `gate` | `"side-effect"` \| `"all"`, `"side-effect"` | 审查范围;`/auto all` 按会话切换。 |
|
|
187
|
+
| `extraTools` | *string[]*, `[]` | 在 `bash`、`write`、`edit` 之外追加审查的工具。 |
|
|
188
|
+
| `timeoutMs` | *integer* 1000-120000, `30000` | 审查总时限。超时不视为批准。 |
|
|
189
|
+
| `transcript` | *boolean*, `true` | 提供有界对话视图,供审查员判断授权情况。 |
|
|
190
|
+
| `evidenceTools` | *boolean*, `true` | 审查员可用 `read`、`grep`、`find`、`ls`;永远没有 `bash`、写工具与网络。 |
|
|
191
|
+
| `maxEvidenceRounds` | *integer* 0-8, `3` | 出结论前的调查轮数;`0` 为单次补全。 |
|
|
192
|
+
| `classifier.*` | *object* | 可选非阻塞低风险预打分器,只放行、不否决。 |
|
|
193
|
+
| `circuitBreaker.*` | *object* | 连续否决结束回合(`consecutiveDenials` `3`,或 `windowSize` `50` 内 `recentDenials` `10`;`0` 关闭)。 |
|
|
222
194
|
|
|
223
|
-
|
|
195
|
+
### `codexAstra`
|
|
224
196
|
|
|
225
|
-
|
|
197
|
+
已移除的配置段。Astra 兼容层对所有 Responses 系 API 的 `gpt-6-astra` 会话静默启用;旧 `codexAstra` 配置按未知字段告警忽略。若其他宿主(如 Oh My Pi)实现了同款改写,只启用一边。
|
|
226
198
|
|
|
227
|
-
|
|
199
|
+
</details>
|
|
228
200
|
|
|
229
|
-
|
|
230
|
-
POST {base}/alpha/history/v2/list_windows | list_items | read_item | search_contents
|
|
231
|
-
POST {base}/alpha/notes/v2/list_files_by_prefix | read_file | search_contents | append_to_file | write_file
|
|
232
|
-
GET {base}/alpha/notes/v2/thread_hint
|
|
233
|
-
```
|
|
201
|
+
## 安全
|
|
234
202
|
|
|
235
|
-
|
|
203
|
+
- 覆盖模型被 Remote Context 接管期间,Pi 原生压缩全部路径(阈值、手动 `/compact`、溢出)取消,无法产生有损摘要。
|
|
204
|
+
- 网关模式只转发配置的数据面 API key。OAuth token、account cookie、account ID 绝不发给网关,artifact 中永远脱敏。
|
|
205
|
+
- `new_context` 无法丢弃未保存状态:必须有本窗口成功的 notes 存档,或用户显式 `force`。
|
|
206
|
+
- 图像生成(计费)与 Auto 模式均需显式开启;无人可批准的场景下 Auto 模式阻断。
|
|
236
207
|
|
|
237
|
-
|
|
208
|
+
需要宿主层保险时,在 Pi 的 `settings.json` 设置 `"compaction": { "enabled": false }`。
|
|
238
209
|
|
|
239
|
-
|
|
210
|
+
## 开发
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
npm run typecheck # tsc 项目检查
|
|
214
|
+
bun test # 单元测试
|
|
215
|
+
npm run test:pi # Pi 集成冒烟测试
|
|
216
|
+
npm pack --dry-run # 检查发布包内容
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## 文档
|
|
220
|
+
|
|
221
|
+
- [docs/internals.md](docs/internals.md) - 协议端点、换窗生命周期、v2 线路契约、artifact、来源归属
|
|
222
|
+
- [README.md](README.md) - 英文原版(canonical)
|
|
223
|
+
- [NOTICE](./NOTICE) - 第三方归属
|
|
240
224
|
|
|
241
225
|
## 贡献
|
|
242
226
|
|
|
243
|
-
欢迎在 [issue 区](https://github.com/awoaCrim/pi-openai-toolkit/issues)提问和提交 PR
|
|
227
|
+
欢迎在 [issue 区](https://github.com/awoaCrim/pi-openai-toolkit/issues)提问和提交 PR。行为变更前先开 issue 讨论协议假设;提交前运行 `bun test` 与 `npm run typecheck`,线路变更需要 fixture 测试。
|
|
228
|
+
|
|
229
|
+
## 维护者
|
|
230
|
+
|
|
231
|
+
[awoaCrim](https://github.com/awoaCrim)
|
|
244
232
|
|
|
245
233
|
## 许可证
|
|
246
234
|
|
|
247
|
-
MIT © awoaCrim and contributors。见 [LICENSE](./LICENSE)
|
|
235
|
+
MIT © awoaCrim and contributors。见 [LICENSE](./LICENSE) 与 [NOTICE](./NOTICE)。
|
|
248
236
|
|
|
249
237
|
## 致谢
|
|
250
238
|
|
|
251
239
|
感谢 [Linux.do](https://linux.do/) 社区的支持与讨论。
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
*本文译自 [README.md](README.md)。若两版内容冲突,以英文版为准。*
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Toolkit Internals
|
|
2
|
+
|
|
3
|
+
Developer-facing reference for [pi-openai-toolkit](../README.md). This is the protocol and implementation detail that the README deliberately keeps out of the user's way. If you are only installing the toolkit, you never need this page; if you are changing wire behavior, fixtures, or the compaction strategy code, start here.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Remote Context protocol](#remote-context-protocol)
|
|
8
|
+
- [Rollover lifecycle](#rollover-lifecycle)
|
|
9
|
+
- [Remote Compaction v2 wire contract](#remote-compaction-v2-wire-contract)
|
|
10
|
+
- [Artifacts and debugging](#artifacts-and-debugging)
|
|
11
|
+
- [Provenance](#provenance)
|
|
12
|
+
|
|
13
|
+
## Remote Context protocol
|
|
14
|
+
|
|
15
|
+
Internal alpha endpoints, adapted from `@howaboua/pi-codex-conversion`:
|
|
16
|
+
|
|
17
|
+
```text
|
|
18
|
+
POST {base}/alpha/history/v2/list_windows | list_items | read_item | search_contents
|
|
19
|
+
POST {base}/alpha/notes/v2/list_files_by_prefix | read_file | search_contents | append_to_file | write_file
|
|
20
|
+
GET {base}/alpha/notes/v2/thread_hint
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
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.
|
|
24
|
+
|
|
25
|
+
Search text and note bodies are sent under the encrypted-argument policy. Live model requests carry `x-codex-window-id` and `x-codex-turn-metadata` request headers derived from the active window identity.
|
|
26
|
+
|
|
27
|
+
Coverage is never inferred from model names. A native session is `provider: "openai-codex"` on api `openai-codex-responses` (any model id). A gateway session must be on api `openai-responses` and carry an exact `provider/model` key listed in `compaction.gatewayContextModels`; the list ships empty and there is no built-in gateway SKU ([src/context-management/codex-provider.ts](../src/context-management/codex-provider.ts)). Unlisted gateway models, listed or not, keep running remote compaction v2 when Remote Context declines them. The toolkit registers no provider or model with Pi; it resolves credentials and base URLs through Pi's `ModelRegistry`.
|
|
28
|
+
|
|
29
|
+
## Rollover lifecycle
|
|
30
|
+
|
|
31
|
+
The `new_context` happy path, end to end:
|
|
32
|
+
|
|
33
|
+
```mermaid
|
|
34
|
+
sequenceDiagram
|
|
35
|
+
participant Model
|
|
36
|
+
participant Toolkit
|
|
37
|
+
participant Pi
|
|
38
|
+
participant Backend
|
|
39
|
+
Model->>Toolkit: notes append_to_file (checkpoint)
|
|
40
|
+
Toolkit->>Backend: alpha notes request (encrypted args)
|
|
41
|
+
Backend-->>Toolkit: encrypted_output
|
|
42
|
+
Model->>Toolkit: new_context
|
|
43
|
+
Toolkit->>Toolkit: verify successful notes write in this window
|
|
44
|
+
Toolkit-->>Pi: window marker appended, previous window trim scheduled
|
|
45
|
+
Model->>Backend: next request with the new x-codex-window-id
|
|
46
|
+
Pi->>Toolkit: session_before_compact
|
|
47
|
+
Toolkit-->>Pi: no-summary boundary consuming the scheduled trim
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
State invariants the lifecycle code must keep honest:
|
|
51
|
+
|
|
52
|
+
- The checkpoint gate verifies a *successful* `notes` `append_to_file` / `write_file` against the persisted session branch after the latest window boundary, so it survives restarts and forks.
|
|
53
|
+
- Budget checks are skipped until the current window has produced its own assistant usage; acting on the previous window's usage anchor burns the once-per-window reminder on a false alarm.
|
|
54
|
+
- The scheduled trim is consumed exactly once, synchronously, by the first compaction attempt whose boundary window id matches. Every other compaction path (threshold without a scheduled rollover, manual `/compact`, overflow) is cancelled.
|
|
55
|
+
- A window boundary is persisted as a `codex-context-window` custom message; `session_start` replays boundaries from the branch and rebuilds identity after forks.
|
|
56
|
+
|
|
57
|
+
## Remote Compaction v2 wire contract
|
|
58
|
+
|
|
59
|
+
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. A v2 response with a missing or empty checkpoint is never stored, and the `nativeFallback` tier is skipped: Pi's own threshold drives the next attempt, which may use `remoteCompactModel` when configured. `remoteCompactModel` must resolve to the same effective base URL as the active model.
|
|
60
|
+
|
|
61
|
+
## Artifacts and debugging
|
|
62
|
+
|
|
63
|
+
With `debug: true` the toolkit writes lifecycle and compaction artifacts under `artifactRoot` (default `~/.pi/agent/artifacts/pi-openai-toolkit/compaction`):
|
|
64
|
+
|
|
65
|
+
- each `session_start` writes a lifecycle artifact whose `activation` field records `active`, or the exact inactive reason (`tool-name-conflict`, `missing-api-key`, `auth-resolution-failed`, `model-not-covered`, ...);
|
|
66
|
+
- `logProviderPayloads` additionally writes raw provider request payloads, `logCompactResponses` the compact SSE bodies; keep both off unless inspecting a specific request;
|
|
67
|
+
- artifacts always redact Authorization credentials, API keys/tokens, Codex account ids, and opaque `encrypted_content` / `encrypted_output`, even with `redactSensitiveData: false`.
|
|
68
|
+
|
|
69
|
+
## Provenance
|
|
70
|
+
|
|
71
|
+
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).
|
|
72
|
+
|
|
73
|
+
Protocol fixtures live in [src/context-management/](../src/context-management/) and must be updated together with any upstream alpha endpoint change; fixture-based tests are required for new wire behavior.
|
package/extensions/auto-mode.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { default } from "../src/auto-mode/extension.ts";
|
|
1
|
+
export { default } from "../src/auto-mode/extension.ts";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { default } from "../src/codex-astra/extension.ts";
|
|
1
|
+
export { default } from "../src/codex-astra/extension.ts";
|
package/extensions/compaction.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { default } from "../src/extension-runtime.ts";
|
|
1
|
+
export { default } from "../src/extension-runtime.ts";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { default } from "../src/image-generation/extension.ts";
|
|
1
|
+
export { default } from "../src/image-generation/extension.ts";
|
package/extensions/web-search.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { default } from "../src/web-search/extension.ts";
|
|
1
|
+
export { default } from "../src/web-search/extension.ts";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-openai-toolkit",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.4",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -96,6 +96,7 @@
|
|
|
96
96
|
"src/web-search/payload.ts",
|
|
97
97
|
"src/web-search/prompt.ts",
|
|
98
98
|
"src/web-search/types.ts",
|
|
99
|
+
"docs/internals.md",
|
|
99
100
|
"README.md",
|
|
100
101
|
"README.zh.md",
|
|
101
102
|
"LICENSE",
|
package/src/config.ts
CHANGED
|
@@ -47,6 +47,7 @@ const COMPACTION_FIELDS = new Set([
|
|
|
47
47
|
"remoteCompactModel",
|
|
48
48
|
"nativeFallback",
|
|
49
49
|
"responsesApis",
|
|
50
|
+
"gatewayContextModels",
|
|
50
51
|
"contextReminderThresholdPercent",
|
|
51
52
|
"notifyOnLoad",
|
|
52
53
|
"debug",
|
|
@@ -347,6 +348,15 @@ function applyCompactionConfig(
|
|
|
347
348
|
resolved.responsesApis = apis;
|
|
348
349
|
}
|
|
349
350
|
|
|
351
|
+
const gatewayContextModels = toStringList(
|
|
352
|
+
raw.gatewayContextModels,
|
|
353
|
+
"compaction.gatewayContextModels",
|
|
354
|
+
warnings,
|
|
355
|
+
);
|
|
356
|
+
if (gatewayContextModels !== undefined) {
|
|
357
|
+
resolved.gatewayContextModels = gatewayContextModels;
|
|
358
|
+
}
|
|
359
|
+
|
|
350
360
|
if (typeof raw.artifactRoot === "string" && raw.artifactRoot.trim().length > 0) {
|
|
351
361
|
resolved.artifactRoot = raw.artifactRoot.trim();
|
|
352
362
|
} else if (raw.artifactRoot !== undefined) {
|