@oai404iao/pi-codex-runtime 0.1.0-alpha.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/LICENSE +28 -0
- package/LICENSES/Apache-2.0.txt +201 -0
- package/LICENSES/OpenAI-Codex-NOTICE.txt +6 -0
- package/README.md +26 -0
- package/THIRD_PARTY_NOTICES.md +19 -0
- package/config.schema.json +174 -0
- package/models.schema.json +217 -0
- package/package.json +68 -0
- package/provenance/openai-codex-eb9dceba-reserved-tools.json +140 -0
- package/src/activation.ts +56 -0
- package/src/broker.ts +133 -0
- package/src/capabilities.ts +146 -0
- package/src/codex-http.ts +133 -0
- package/src/codex-identity-extension.ts +341 -0
- package/src/codex-request-profile.ts +45 -0
- package/src/codex-reserved-tools.ts +33 -0
- package/src/codex-wire-identity.ts +596 -0
- package/src/extension/provider-presentation.ts +11 -0
- package/src/glyphs.ts +70 -0
- package/src/index.ts +4 -0
- package/src/model-catalog/catalog.ts +636 -0
- package/src/model-catalog/default-models.json +252 -0
- package/src/model-catalog/runtime.ts +113 -0
- package/src/model-catalog/types.ts +95 -0
- package/src/provider-headers.ts +54 -0
- package/src/providers/openai-codex/stream-effects.ts +21 -0
- package/src/providers/openai-codex/types.ts +155 -0
- package/src/providers/responses/citations.ts +105 -0
- package/src/providers/responses/history.ts +144 -0
- package/src/providers/responses/items.ts +87 -0
- package/src/providers/responses/markdown.ts +92 -0
- package/src/providers/responses/messages.ts +169 -0
- package/src/providers/responses/signatures.ts +102 -0
- package/src/providers/responses/stream-state.ts +99 -0
- package/src/providers/responses/stream.ts +386 -0
- package/src/providers/responses/text-renderer.ts +147 -0
- package/src/providers/responses/text.ts +32 -0
- package/src/providers/responses/tool-identity.ts +25 -0
- package/src/providers/responses/tools.ts +14 -0
- package/src/providers/responses/types.ts +113 -0
- package/src/providers/responses/usage.ts +53 -0
- package/src/reserved-tools/image-generation.ts +53 -0
- package/src/reserved-tools/types.ts +32 -0
- package/src/reserved-tools/web-search.ts +269 -0
- package/src/session-claims.ts +19 -0
- package/src/settings.ts +247 -0
- package/src/subagent-inline.ts +8 -0
- package/src/tool-activation.ts +89 -0
- package/src/utils/theme.ts +7 -0
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"models": [
|
|
4
|
+
{
|
|
5
|
+
"id": "openai/gpt-5.6-sol",
|
|
6
|
+
"enabled": true,
|
|
7
|
+
"responses": {
|
|
8
|
+
"providerShim": true,
|
|
9
|
+
"endpoint": "openai",
|
|
10
|
+
"mode": "lite",
|
|
11
|
+
"systemPromptPlacement": "developer",
|
|
12
|
+
"transport": "auto",
|
|
13
|
+
"websocketPrewarm": true
|
|
14
|
+
},
|
|
15
|
+
"tools": {
|
|
16
|
+
"parallelCalls": false,
|
|
17
|
+
"applyPatch": "custom",
|
|
18
|
+
"webSearch": {
|
|
19
|
+
"implementation": "standalone",
|
|
20
|
+
"contentTypes": ["text", "image"]
|
|
21
|
+
},
|
|
22
|
+
"imageGeneration": "standalone",
|
|
23
|
+
"viewImage": false
|
|
24
|
+
},
|
|
25
|
+
"compaction": "responses",
|
|
26
|
+
"fast": {
|
|
27
|
+
"serviceTier": "priority",
|
|
28
|
+
"costMultiplier": 2
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"id": "openai/gpt-5.6-terra",
|
|
33
|
+
"extends": "openai/gpt-5.6-sol"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"id": "openai/gpt-5.6-luna",
|
|
37
|
+
"extends": "openai/gpt-5.6-sol"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"id": "openai/gpt-5.5",
|
|
41
|
+
"enabled": true,
|
|
42
|
+
"responses": {
|
|
43
|
+
"providerShim": true,
|
|
44
|
+
"endpoint": "openai",
|
|
45
|
+
"mode": "standard",
|
|
46
|
+
"systemPromptPlacement": "instructions",
|
|
47
|
+
"transport": "auto",
|
|
48
|
+
"websocketPrewarm": true
|
|
49
|
+
},
|
|
50
|
+
"tools": {
|
|
51
|
+
"parallelCalls": true,
|
|
52
|
+
"applyPatch": "custom",
|
|
53
|
+
"webSearch": {
|
|
54
|
+
"implementation": "hosted",
|
|
55
|
+
"contentTypes": ["text", "image"]
|
|
56
|
+
},
|
|
57
|
+
"imageGeneration": "standalone",
|
|
58
|
+
"viewImage": false
|
|
59
|
+
},
|
|
60
|
+
"compaction": "responses",
|
|
61
|
+
"fast": {
|
|
62
|
+
"serviceTier": "priority",
|
|
63
|
+
"costMultiplier": 2.5
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"id": "openai/gpt-5.4",
|
|
68
|
+
"extends": "openai/gpt-5.5",
|
|
69
|
+
"fast": {
|
|
70
|
+
"serviceTier": "priority",
|
|
71
|
+
"costMultiplier": 2
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"id": "openai/gpt-5.4-mini",
|
|
76
|
+
"extends": "openai/gpt-5.4",
|
|
77
|
+
"fast": false
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"id": "openai/gpt-5.2",
|
|
81
|
+
"extends": "openai/gpt-5.4-mini",
|
|
82
|
+
"tools": {
|
|
83
|
+
"webSearch": {
|
|
84
|
+
"implementation": "hosted",
|
|
85
|
+
"contentTypes": ["text"]
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"id": "openai/codex-auto-review",
|
|
91
|
+
"extends": "openai/gpt-5.4-mini"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"id": "openai/gpt-5",
|
|
95
|
+
"extends": "openai/gpt-5.2",
|
|
96
|
+
"fast": {
|
|
97
|
+
"serviceTier": "priority",
|
|
98
|
+
"costMultiplier": 2
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"id": "openai/gpt-5-mini",
|
|
103
|
+
"extends": "openai/gpt-5",
|
|
104
|
+
"fast": false
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"id": "openai/gpt-5.1",
|
|
108
|
+
"extends": "openai/gpt-5"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"id": "openai/gpt-5.1-codex",
|
|
112
|
+
"extends": "openai/gpt-5.1"
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"id": "openai/gpt-5.3-codex",
|
|
116
|
+
"extends": "openai/gpt-5.4-mini"
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"id": "openai/gpt-4.1",
|
|
120
|
+
"enabled": true,
|
|
121
|
+
"responses": {
|
|
122
|
+
"providerShim": true,
|
|
123
|
+
"endpoint": "openai",
|
|
124
|
+
"mode": "standard",
|
|
125
|
+
"systemPromptPlacement": "instructions",
|
|
126
|
+
"transport": "sse",
|
|
127
|
+
"websocketPrewarm": false
|
|
128
|
+
},
|
|
129
|
+
"tools": {
|
|
130
|
+
"parallelCalls": true,
|
|
131
|
+
"applyPatch": false,
|
|
132
|
+
"webSearch": false,
|
|
133
|
+
"imageGeneration": "hosted",
|
|
134
|
+
"viewImage": false
|
|
135
|
+
},
|
|
136
|
+
"compaction": "pi",
|
|
137
|
+
"fast": false
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"id": "openai/o4-mini",
|
|
141
|
+
"extends": "openai/gpt-4.1",
|
|
142
|
+
"tools": {
|
|
143
|
+
"imageGeneration": false
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
"id": "openai-codex/gpt-5.6-sol",
|
|
148
|
+
"extends": "openai/gpt-5.6-sol",
|
|
149
|
+
"responses": {
|
|
150
|
+
"endpoint": "codex"
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
"id": "openai-codex/gpt-5.6-terra",
|
|
155
|
+
"extends": "openai/gpt-5.6-terra",
|
|
156
|
+
"responses": {
|
|
157
|
+
"endpoint": "codex"
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"id": "openai-codex/gpt-5.6-luna",
|
|
162
|
+
"extends": "openai/gpt-5.6-luna",
|
|
163
|
+
"responses": {
|
|
164
|
+
"endpoint": "codex"
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"id": "openai-codex/gpt-5.5",
|
|
169
|
+
"extends": "openai/gpt-5.5",
|
|
170
|
+
"responses": {
|
|
171
|
+
"endpoint": "codex"
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
"id": "openai-codex/gpt-5.4",
|
|
176
|
+
"extends": "openai/gpt-5.4",
|
|
177
|
+
"responses": {
|
|
178
|
+
"endpoint": "codex"
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"id": "openai-codex/gpt-5.4-mini",
|
|
183
|
+
"extends": "openai/gpt-5.4-mini",
|
|
184
|
+
"responses": {
|
|
185
|
+
"endpoint": "codex"
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
"id": "openai-codex/gpt-5.2",
|
|
190
|
+
"extends": "openai/gpt-5.2",
|
|
191
|
+
"responses": {
|
|
192
|
+
"endpoint": "codex"
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
"id": "openai-codex/codex-auto-review",
|
|
197
|
+
"extends": "openai/codex-auto-review",
|
|
198
|
+
"responses": {
|
|
199
|
+
"endpoint": "codex"
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
"id": "openai-codex/gpt-5",
|
|
204
|
+
"extends": "openai/gpt-5",
|
|
205
|
+
"responses": {
|
|
206
|
+
"endpoint": "codex"
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
"id": "openai-codex/gpt-5-mini",
|
|
211
|
+
"extends": "openai/gpt-5-mini",
|
|
212
|
+
"responses": {
|
|
213
|
+
"endpoint": "codex"
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
"id": "openai-codex/gpt-5.1",
|
|
218
|
+
"extends": "openai/gpt-5.1",
|
|
219
|
+
"responses": {
|
|
220
|
+
"endpoint": "codex"
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
"id": "openai-codex/gpt-5.1-codex",
|
|
225
|
+
"extends": "openai/gpt-5.1-codex",
|
|
226
|
+
"responses": {
|
|
227
|
+
"endpoint": "codex"
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
"id": "openai-codex/gpt-5.3-codex",
|
|
232
|
+
"extends": "openai/gpt-5.3-codex",
|
|
233
|
+
"responses": {
|
|
234
|
+
"endpoint": "codex"
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
"id": "openai-codex/gpt-4.1",
|
|
239
|
+
"extends": "openai/gpt-4.1",
|
|
240
|
+
"responses": {
|
|
241
|
+
"endpoint": "codex"
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
"id": "openai-codex/o4-mini",
|
|
246
|
+
"extends": "openai/o4-mini",
|
|
247
|
+
"responses": {
|
|
248
|
+
"endpoint": "codex"
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
]
|
|
252
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type { CodexRequestProfileOverride } from "../codex-request-profile.js";
|
|
2
|
+
import {
|
|
3
|
+
loadSettings,
|
|
4
|
+
type CodexMinimalToolsSettings,
|
|
5
|
+
} from "../settings.js";
|
|
6
|
+
import { resolveModelProfile } from "./catalog.js";
|
|
7
|
+
import type {
|
|
8
|
+
ModelIdentityLike,
|
|
9
|
+
ResolvedModelProfile,
|
|
10
|
+
ResponsesEndpoint,
|
|
11
|
+
} from "./types.js";
|
|
12
|
+
|
|
13
|
+
export interface ResolvedCodexModelSettings extends CodexMinimalToolsSettings {
|
|
14
|
+
modelProfile?: ResolvedModelProfile;
|
|
15
|
+
modelProfileHash?: string;
|
|
16
|
+
providerShimActive?: boolean;
|
|
17
|
+
webSearchImplementation?: "hosted" | "standalone";
|
|
18
|
+
imageGenerationImplementation?: "hosted" | "standalone";
|
|
19
|
+
fastServiceTier?: string;
|
|
20
|
+
fastCostMultiplier?: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function endpointUsesApiKey(endpoint: ResponsesEndpoint, model: ModelIdentityLike | undefined): boolean {
|
|
24
|
+
if (endpoint === "openai") return true;
|
|
25
|
+
if (endpoint === "codex") return false;
|
|
26
|
+
return model?.provider !== "openai-codex";
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function supportsCodexResponsesApi(model: ModelIdentityLike | undefined): boolean {
|
|
30
|
+
if (model?.api === "openai-responses" || model?.api === "openai-codex-responses") return true;
|
|
31
|
+
if (model?.api) return false;
|
|
32
|
+
return model?.provider === "openai" || model?.provider === "openai-codex";
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function loadModelSettings(
|
|
36
|
+
model: ModelIdentityLike | undefined,
|
|
37
|
+
cwd?: string,
|
|
38
|
+
baseSettings = loadSettings(cwd),
|
|
39
|
+
): ResolvedCodexModelSettings {
|
|
40
|
+
const modelProfile = resolveModelProfile(model, { settings: baseSettings });
|
|
41
|
+
if (!modelProfile || !modelProfile.effective.enabled) {
|
|
42
|
+
return {
|
|
43
|
+
...baseSettings,
|
|
44
|
+
providerShimActive: false,
|
|
45
|
+
nativeProviderTools: false,
|
|
46
|
+
openaiTransport: "sse",
|
|
47
|
+
openaiWebSocketPrewarm: false,
|
|
48
|
+
compactionMode: "pi",
|
|
49
|
+
requestProfile: {
|
|
50
|
+
responsesMode: "standard",
|
|
51
|
+
reasoningSummary: "auto",
|
|
52
|
+
systemPromptPlacement: "instructions",
|
|
53
|
+
patchTransport: "function",
|
|
54
|
+
supportsHostedTools: false,
|
|
55
|
+
supportsParallelTools: true,
|
|
56
|
+
},
|
|
57
|
+
apiKeyMode: model?.provider !== "openai-codex",
|
|
58
|
+
imageGeneration: false,
|
|
59
|
+
webSearchEnabled: false,
|
|
60
|
+
viewImage: false,
|
|
61
|
+
applyPatchEnabled: false,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const effective = modelProfile.effective;
|
|
66
|
+
const packageEnabled = baseSettings.enabled;
|
|
67
|
+
const providerShimActive = packageEnabled
|
|
68
|
+
&& effective.responses.providerShim
|
|
69
|
+
&& supportsCodexResponsesApi(model);
|
|
70
|
+
const configuredWebSearchImplementation = effective.tools.webSearch
|
|
71
|
+
? effective.tools.webSearch.implementation
|
|
72
|
+
: undefined;
|
|
73
|
+
const configuredImageGenerationImplementation = effective.tools.imageGeneration || undefined;
|
|
74
|
+
const webSearchImplementation = !packageEnabled
|
|
75
|
+
|| (configuredWebSearchImplementation === "hosted" && !providerShimActive)
|
|
76
|
+
? undefined
|
|
77
|
+
: configuredWebSearchImplementation;
|
|
78
|
+
const imageGenerationImplementation = !packageEnabled
|
|
79
|
+
|| (configuredImageGenerationImplementation === "hosted" && !providerShimActive)
|
|
80
|
+
? undefined
|
|
81
|
+
: configuredImageGenerationImplementation;
|
|
82
|
+
const supportsHostedTools = webSearchImplementation === "hosted"
|
|
83
|
+
|| imageGenerationImplementation === "hosted";
|
|
84
|
+
const usesProviderToolRewrite = Boolean(webSearchImplementation || imageGenerationImplementation);
|
|
85
|
+
const requestProfile: CodexRequestProfileOverride = {
|
|
86
|
+
responsesMode: effective.responses.mode,
|
|
87
|
+
reasoningSummary: effective.responses.reasoningSummary,
|
|
88
|
+
systemPromptPlacement: effective.responses.systemPromptPlacement,
|
|
89
|
+
patchTransport: effective.tools.applyPatch === "custom" ? "custom" : "function",
|
|
90
|
+
supportsHostedTools,
|
|
91
|
+
supportsParallelTools: effective.tools.parallelCalls,
|
|
92
|
+
};
|
|
93
|
+
return {
|
|
94
|
+
...baseSettings,
|
|
95
|
+
providerShimActive,
|
|
96
|
+
nativeProviderTools: providerShimActive && usesProviderToolRewrite,
|
|
97
|
+
openaiTransport: effective.responses.transport,
|
|
98
|
+
openaiWebSocketPrewarm: effective.responses.websocketPrewarm,
|
|
99
|
+
compactionMode: providerShimActive ? effective.compaction : "pi",
|
|
100
|
+
requestProfile,
|
|
101
|
+
apiKeyMode: endpointUsesApiKey(effective.responses.endpoint, model),
|
|
102
|
+
imageGeneration: imageGenerationImplementation !== undefined,
|
|
103
|
+
webSearchEnabled: webSearchImplementation !== undefined,
|
|
104
|
+
viewImage: packageEnabled && effective.tools.viewImage,
|
|
105
|
+
applyPatchEnabled: packageEnabled && effective.tools.applyPatch !== false,
|
|
106
|
+
modelProfile,
|
|
107
|
+
modelProfileHash: modelProfile.profileHash,
|
|
108
|
+
webSearchImplementation,
|
|
109
|
+
imageGenerationImplementation,
|
|
110
|
+
fastServiceTier: providerShimActive && effective.fast ? effective.fast.serviceTier : undefined,
|
|
111
|
+
fastCostMultiplier: providerShimActive && effective.fast ? effective.fast.costMultiplier : undefined,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
export type ResponsesEndpoint = "auto" | "openai" | "codex";
|
|
2
|
+
export type ResponsesMode = "standard" | "lite";
|
|
3
|
+
export type ReasoningSummary = "auto" | "concise" | "detailed" | "none";
|
|
4
|
+
export type ResponsesTransport = "sse" | "websocket" | "websocket-cached" | "auto";
|
|
5
|
+
export type SystemPromptPlacement = "instructions" | "developer";
|
|
6
|
+
export type PatchTransport = "function" | "custom";
|
|
7
|
+
export type WebSearchContentType = "text" | "image";
|
|
8
|
+
export type NativeCompactionMode = "pi" | "responses" | "responses-compact";
|
|
9
|
+
|
|
10
|
+
export interface ModelIdentityLike {
|
|
11
|
+
provider?: string;
|
|
12
|
+
id?: string;
|
|
13
|
+
name?: string;
|
|
14
|
+
api?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface ResponsesProfilePatch {
|
|
18
|
+
providerShim?: boolean;
|
|
19
|
+
endpoint?: ResponsesEndpoint;
|
|
20
|
+
mode?: ResponsesMode;
|
|
21
|
+
reasoningSummary?: ReasoningSummary;
|
|
22
|
+
systemPromptPlacement?: SystemPromptPlacement;
|
|
23
|
+
transport?: ResponsesTransport;
|
|
24
|
+
websocketPrewarm?: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface WebSearchProfile {
|
|
28
|
+
implementation: "hosted" | "standalone";
|
|
29
|
+
contentTypes?: WebSearchContentType[];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface ModelToolsProfilePatch {
|
|
33
|
+
parallelCalls?: boolean;
|
|
34
|
+
applyPatch?: false | PatchTransport;
|
|
35
|
+
webSearch?: false | WebSearchProfile;
|
|
36
|
+
imageGeneration?: false | "hosted" | "standalone";
|
|
37
|
+
viewImage?: boolean;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface FastModeProfile {
|
|
41
|
+
serviceTier: string;
|
|
42
|
+
costMultiplier?: number;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface ModelProfilePatch {
|
|
46
|
+
id: string;
|
|
47
|
+
extends?: string;
|
|
48
|
+
enabled?: boolean;
|
|
49
|
+
responses?: ResponsesProfilePatch;
|
|
50
|
+
tools?: ModelToolsProfilePatch;
|
|
51
|
+
compaction?: NativeCompactionMode;
|
|
52
|
+
fast?: false | FastModeProfile;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface ModelCatalogFile {
|
|
56
|
+
$schema?: string;
|
|
57
|
+
version: 1;
|
|
58
|
+
models: ModelProfilePatch[];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface EffectiveResponsesProfile {
|
|
62
|
+
providerShim: boolean;
|
|
63
|
+
endpoint: ResponsesEndpoint;
|
|
64
|
+
mode: ResponsesMode;
|
|
65
|
+
reasoningSummary: ReasoningSummary;
|
|
66
|
+
systemPromptPlacement: SystemPromptPlacement;
|
|
67
|
+
transport: ResponsesTransport;
|
|
68
|
+
websocketPrewarm: boolean;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface EffectiveModelToolsProfile {
|
|
72
|
+
parallelCalls: boolean;
|
|
73
|
+
applyPatch: false | PatchTransport;
|
|
74
|
+
webSearch: false | WebSearchProfile;
|
|
75
|
+
imageGeneration: false | "hosted" | "standalone";
|
|
76
|
+
viewImage: boolean;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface EffectiveModelProfile {
|
|
80
|
+
enabled: boolean;
|
|
81
|
+
responses: EffectiveResponsesProfile;
|
|
82
|
+
tools: EffectiveModelToolsProfile;
|
|
83
|
+
compaction: NativeCompactionMode;
|
|
84
|
+
fast: false | FastModeProfile;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export type ModelProfileSource = "bundled" | "user" | "legacy";
|
|
88
|
+
|
|
89
|
+
export interface ResolvedModelProfile {
|
|
90
|
+
id: string;
|
|
91
|
+
sources: ModelProfileSource[];
|
|
92
|
+
profileHash: string;
|
|
93
|
+
effective: EffectiveModelProfile;
|
|
94
|
+
diagnostics: string[];
|
|
95
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { ProviderHeaders } from "@earendil-works/pi-ai";
|
|
2
|
+
|
|
3
|
+
const suppressedHeaders = new WeakMap<Headers, Set<string>>();
|
|
4
|
+
|
|
5
|
+
function normalizedName(name: string): string {
|
|
6
|
+
return name.trim().toLowerCase();
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function providerHeaderDirective(
|
|
10
|
+
headers: ProviderHeaders | undefined,
|
|
11
|
+
name: string,
|
|
12
|
+
): string | null | undefined {
|
|
13
|
+
const target = normalizedName(name);
|
|
14
|
+
let directive: string | null | undefined;
|
|
15
|
+
for (const [candidate, value] of Object.entries(headers ?? {})) {
|
|
16
|
+
if (normalizedName(candidate) === target) directive = value;
|
|
17
|
+
}
|
|
18
|
+
return directive;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function mergeProviderHeaders(...layers: Array<ProviderHeaders | undefined>): Headers {
|
|
22
|
+
const headers = new Headers();
|
|
23
|
+
const suppressed = new Set<string>();
|
|
24
|
+
for (const layer of layers) {
|
|
25
|
+
for (const [name, value] of Object.entries(layer ?? {})) {
|
|
26
|
+
const normalized = normalizedName(name);
|
|
27
|
+
if (value === null) {
|
|
28
|
+
headers.delete(name);
|
|
29
|
+
suppressed.add(normalized);
|
|
30
|
+
} else {
|
|
31
|
+
headers.set(name, value);
|
|
32
|
+
suppressed.delete(normalized);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
suppressedHeaders.set(headers, suppressed);
|
|
37
|
+
return headers;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function isProviderHeaderSuppressed(headers: Headers, name: string): boolean {
|
|
41
|
+
return suppressedHeaders.get(headers)?.has(normalizedName(name)) ?? false;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function setProviderDefaultHeader(headers: Headers, name: string, value: string): boolean {
|
|
45
|
+
if (isProviderHeaderSuppressed(headers, name) || headers.has(name)) return false;
|
|
46
|
+
headers.set(name, value);
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function setProviderGeneratedHeader(headers: Headers, name: string, value: string): boolean {
|
|
51
|
+
if (isProviderHeaderSuppressed(headers, name)) return false;
|
|
52
|
+
headers.set(name, value);
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { AssistantMessage, AssistantMessageEventStream } from "@earendil-works/pi-ai/compat";
|
|
2
|
+
import type { StreamEventShape } from "./types.js";
|
|
3
|
+
|
|
4
|
+
export interface ProviderEventContext {
|
|
5
|
+
cwd: string;
|
|
6
|
+
requestPrompt?: string;
|
|
7
|
+
signal?: AbortSignal;
|
|
8
|
+
output: AssistantMessage;
|
|
9
|
+
stream: AssistantMessageEventStream;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A fresh observer is created for each response attempt. Events are normalized
|
|
14
|
+
* and continuation items captured before observation; observation is awaited
|
|
15
|
+
* before replay parsing. Observers must not mutate wire items or consume events.
|
|
16
|
+
* Optional effects own their failure policy; uncaught errors fail the stream.
|
|
17
|
+
*/
|
|
18
|
+
export interface ProviderStreamEffects {
|
|
19
|
+
createEventObserver?: (context: ProviderEventContext) =>
|
|
20
|
+
(event: StreamEventShape) => void | Promise<void>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { type SimpleStreamOptions } from "@earendil-works/pi-ai/compat";
|
|
2
|
+
import { type ResponseCreateParamsStreaming } from "openai/resources/responses/responses.js";
|
|
3
|
+
import { type CodexRequestIdentity } from "../../codex-wire-identity.js";
|
|
4
|
+
|
|
5
|
+
export interface WebSocketLike {
|
|
6
|
+
readyState?: number;
|
|
7
|
+
bufferedAmount?: number;
|
|
8
|
+
send(data: string, callback?: (error?: Error) => void): void;
|
|
9
|
+
close(code?: number, reason?: string): void;
|
|
10
|
+
addEventListener(type: string, listener: (event: unknown) => void): void;
|
|
11
|
+
removeEventListener(type: string, listener: (event: unknown) => void): void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface SessionWebSocketCacheEntry {
|
|
15
|
+
socket: WebSocketLike;
|
|
16
|
+
busy: boolean;
|
|
17
|
+
waiters: WebSocketAcquireWaiter[];
|
|
18
|
+
idleTimer?: ReturnType<typeof setTimeout>;
|
|
19
|
+
continuation?: CachedWebSocketContinuationState;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface WebSocketAcquireWaiter {
|
|
23
|
+
resolve: (acquired: AcquiredWebSocket) => void;
|
|
24
|
+
reject: (error: Error) => void;
|
|
25
|
+
signal?: AbortSignal;
|
|
26
|
+
onAbort?: () => void;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface AcquiredWebSocket {
|
|
30
|
+
socket: WebSocketLike;
|
|
31
|
+
entry?: SessionWebSocketCacheEntry;
|
|
32
|
+
reused: boolean;
|
|
33
|
+
release: (options?: { keep?: boolean }) => void;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface CachedWebSocketContinuationState {
|
|
37
|
+
lastRequestBody: ResponsesBody;
|
|
38
|
+
lastResponseId: string;
|
|
39
|
+
lastResponseItems: unknown[];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface WebSocketPrewarmRequest {
|
|
43
|
+
url: string;
|
|
44
|
+
headers: Headers;
|
|
45
|
+
cacheKey: string;
|
|
46
|
+
body: ResponsesBody;
|
|
47
|
+
requestMetadata: WebSocketRequestMetadata;
|
|
48
|
+
signal?: AbortSignal;
|
|
49
|
+
connectTimeoutMs?: number;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface WebSocketRequestMetadata {
|
|
53
|
+
/** Legacy Pi session lookup key used by exported test helpers. */
|
|
54
|
+
sessionId?: string;
|
|
55
|
+
threadId?: string;
|
|
56
|
+
turnId: string;
|
|
57
|
+
requestKind?: "turn" | "compaction" | "prewarm";
|
|
58
|
+
identity?: CodexRequestIdentity;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export type NativeToolOwnership = (name: "web_search" | "image_generation") => boolean;
|
|
62
|
+
|
|
63
|
+
export interface OpenAIResponsesProviderController {
|
|
64
|
+
ownsNativeTool?: NativeToolOwnership;
|
|
65
|
+
getCurrentTurnId(sessionId: string | undefined): string | undefined;
|
|
66
|
+
getRequestIdentity?(
|
|
67
|
+
sessionId: string | undefined,
|
|
68
|
+
requestKind?: CodexRequestIdentity["requestKind"],
|
|
69
|
+
): CodexRequestIdentity | undefined;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface ResponsesBody {
|
|
73
|
+
model: string;
|
|
74
|
+
store: boolean;
|
|
75
|
+
stream: boolean;
|
|
76
|
+
instructions?: string;
|
|
77
|
+
previous_response_id?: string;
|
|
78
|
+
input: unknown[];
|
|
79
|
+
text: { verbosity: string };
|
|
80
|
+
include: string[];
|
|
81
|
+
prompt_cache_key?: string;
|
|
82
|
+
tool_choice: "auto";
|
|
83
|
+
parallel_tool_calls: boolean;
|
|
84
|
+
temperature?: number;
|
|
85
|
+
service_tier?: string;
|
|
86
|
+
generate?: boolean;
|
|
87
|
+
tools?: unknown[];
|
|
88
|
+
reasoning?: {
|
|
89
|
+
effort?: string;
|
|
90
|
+
summary?: string;
|
|
91
|
+
context?: "all_turns";
|
|
92
|
+
};
|
|
93
|
+
client_metadata?: Record<string, string>;
|
|
94
|
+
[key: string]: unknown;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
interface ResponseEnvelope {
|
|
98
|
+
id?: string;
|
|
99
|
+
status?: string;
|
|
100
|
+
usage?: {
|
|
101
|
+
input_tokens?: number;
|
|
102
|
+
output_tokens?: number;
|
|
103
|
+
total_tokens?: number;
|
|
104
|
+
input_tokens_details?: { cached_tokens?: number };
|
|
105
|
+
};
|
|
106
|
+
service_tier?: string;
|
|
107
|
+
error?: { message?: string };
|
|
108
|
+
[key: string]: unknown;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export type ServiceTier = ResponseCreateParamsStreaming["service_tier"];
|
|
112
|
+
|
|
113
|
+
export type ProviderTransport = NonNullable<SimpleStreamOptions["transport"]>;
|
|
114
|
+
|
|
115
|
+
export interface NodeWebSocketModule {
|
|
116
|
+
WebSocket: new (url: string, options?: Record<string, unknown>) => {
|
|
117
|
+
readyState: number;
|
|
118
|
+
bufferedAmount: number;
|
|
119
|
+
send(data: string, callback?: (error?: Error) => void): void;
|
|
120
|
+
close(code?: number, reason?: string): void;
|
|
121
|
+
terminate?(): void;
|
|
122
|
+
on(type: string, listener: (...args: any[]) => void): void;
|
|
123
|
+
off(type: string, listener: (...args: any[]) => void): void;
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export interface StreamEventShape {
|
|
128
|
+
type?: string;
|
|
129
|
+
status?: number;
|
|
130
|
+
status_code?: number;
|
|
131
|
+
sequence_number?: number;
|
|
132
|
+
error?: {
|
|
133
|
+
type?: string;
|
|
134
|
+
message?: string;
|
|
135
|
+
code?: string;
|
|
136
|
+
plan_type?: string;
|
|
137
|
+
resets_at?: number;
|
|
138
|
+
[key: string]: unknown;
|
|
139
|
+
};
|
|
140
|
+
response?: ResponseEnvelope;
|
|
141
|
+
item_id?: string;
|
|
142
|
+
output_index?: number;
|
|
143
|
+
item?: {
|
|
144
|
+
id?: string;
|
|
145
|
+
type?: string;
|
|
146
|
+
result?: string | null;
|
|
147
|
+
output_format?: string;
|
|
148
|
+
revised_prompt?: string;
|
|
149
|
+
status?: string;
|
|
150
|
+
[key: string]: unknown;
|
|
151
|
+
};
|
|
152
|
+
code?: string;
|
|
153
|
+
message?: string;
|
|
154
|
+
[key: string]: unknown;
|
|
155
|
+
}
|