pi-openai-toolkit 0.14.2 → 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 +239 -246
- package/README.zh.md +243 -246
- 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/context-management/window-manager.ts +479 -421
- package/src/extension-runtime.ts +9 -5
- package/src/types.ts +7 -0
- package/src/web-search/prompt.ts +1 -1
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) {
|
|
@@ -3,16 +3,15 @@ import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
|
3
3
|
import { mergeProviderHeaders } from "../provider-headers";
|
|
4
4
|
import { CODEX_CLIENT_VERSION } from "../responses-headers";
|
|
5
5
|
import { normalizeBaseUrl } from "../runtime";
|
|
6
|
+
import { isExactModelAllowed } from "../model-scope";
|
|
6
7
|
import {
|
|
7
8
|
isNonEmptyString,
|
|
8
9
|
type CodexContextProvider,
|
|
9
10
|
type CodexContextProviderResolution,
|
|
10
11
|
} from "./types";
|
|
11
|
-
import { ASTRA_MODEL_ID } from "../types";
|
|
12
12
|
|
|
13
13
|
const CODEX_PROVIDER = "openai-codex";
|
|
14
14
|
const CODEX_API = "openai-codex-responses";
|
|
15
|
-
const GATEWAY_PROVIDER = "uwoacrimson";
|
|
16
15
|
const GATEWAY_API = "openai-responses";
|
|
17
16
|
const CODEX_TOOL_ORIGINATOR = "codex_cli_rs";
|
|
18
17
|
const CODEX_GATEWAY_ORIGINATOR = "codex_cli_rs";
|
|
@@ -32,12 +31,14 @@ export function isNativeCodexModel(
|
|
|
32
31
|
|
|
33
32
|
export function isCodexGatewayModel(
|
|
34
33
|
model: ExtensionContext["model"] | undefined,
|
|
34
|
+
gatewayModels: readonly string[] = [],
|
|
35
35
|
): boolean {
|
|
36
|
-
//
|
|
37
|
-
// (
|
|
38
|
-
//
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
// Gateway coverage is an operator allowlist of exact "provider/model" keys
|
|
37
|
+
// (compaction.gatewayContextModels). The backend relay must actually pass
|
|
38
|
+
// hosted window markers through; models outside the list stay on remote
|
|
39
|
+
// compaction v2.
|
|
40
|
+
if (!model || model.api !== GATEWAY_API) return false;
|
|
41
|
+
return isExactModelAllowed(model, gatewayModels);
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
export function normalizeCodexBackendBaseUrl(baseUrl: string | undefined | null): string | undefined {
|
|
@@ -172,6 +173,7 @@ export function codexContextProviderHeaders(
|
|
|
172
173
|
export async function resolveCodexContextProvider(
|
|
173
174
|
ctx: ExtensionContext,
|
|
174
175
|
modelOverride: ExtensionContext["model"] = ctx.model,
|
|
176
|
+
gatewayModels: readonly string[] = [],
|
|
175
177
|
): Promise<CodexContextProviderResolution> {
|
|
176
178
|
const model = modelOverride;
|
|
177
179
|
const descriptor = {
|
|
@@ -183,13 +185,9 @@ export async function resolveCodexContextProvider(
|
|
|
183
185
|
if (!model) return { ok: false, reason: "unsupported-model" };
|
|
184
186
|
|
|
185
187
|
const isNative = isNativeCodexModel(model);
|
|
186
|
-
const isGateway = isCodexGatewayModel(model);
|
|
188
|
+
const isGateway = isCodexGatewayModel(model, gatewayModels);
|
|
187
189
|
if (!isNative && !isGateway) {
|
|
188
|
-
return {
|
|
189
|
-
ok: false,
|
|
190
|
-
reason: model.provider === GATEWAY_PROVIDER ? "unsupported-model" : "unsupported-model",
|
|
191
|
-
...descriptor,
|
|
192
|
-
};
|
|
190
|
+
return { ok: false, reason: "unsupported-model", ...descriptor };
|
|
193
191
|
}
|
|
194
192
|
if (!isNative && model.api !== GATEWAY_API) {
|
|
195
193
|
return { ok: false, reason: "unsupported-api", ...descriptor };
|
|
@@ -217,7 +215,7 @@ export async function resolveCodexContextProvider(
|
|
|
217
215
|
provider: {
|
|
218
216
|
kind: "codex-gateway",
|
|
219
217
|
route: "codex-gateway",
|
|
220
|
-
provider:
|
|
218
|
+
provider: model.provider,
|
|
221
219
|
api: GATEWAY_API,
|
|
222
220
|
model: model.id,
|
|
223
221
|
baseUrl: rawBaseUrl,
|
|
@@ -78,11 +78,12 @@ export async function callHistoryNotesBackend(
|
|
|
78
78
|
mode: "tokens",
|
|
79
79
|
limit: TOOL_OUTPUT_TOKEN_LIMIT,
|
|
80
80
|
},
|
|
81
|
+
gatewayModels: readonly string[] = [],
|
|
81
82
|
): Promise<HistoryNotesResult> {
|
|
82
83
|
const timeoutSignal = AbortSignal.timeout(BACKEND_TIMEOUT_MS);
|
|
83
84
|
if (signal?.aborted) return { ok: false, reason: "aborted" };
|
|
84
85
|
const requestSignal = signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal;
|
|
85
|
-
const providerResult = await resolveProviderWithDeadline(ctx, requestSignal, timeoutSignal);
|
|
86
|
+
const providerResult = await resolveProviderWithDeadline(ctx, requestSignal, timeoutSignal, gatewayModels);
|
|
86
87
|
if (providerResult === "aborted") return { ok: false, reason: "aborted" };
|
|
87
88
|
if (providerResult === "timeout") return { ok: false, reason: "backend-timeout" };
|
|
88
89
|
const provider = providerResult;
|
|
@@ -134,6 +135,7 @@ async function resolveProviderWithDeadline(
|
|
|
134
135
|
ctx: ExtensionContext,
|
|
135
136
|
requestSignal: AbortSignal,
|
|
136
137
|
timeoutSignal: AbortSignal,
|
|
138
|
+
gatewayModels: readonly string[] = [],
|
|
137
139
|
): Promise<Awaited<ReturnType<typeof resolveCodexContextProvider>> | "aborted" | "timeout"> {
|
|
138
140
|
if (requestSignal.aborted) return timeoutSignal.aborted ? "timeout" : "aborted";
|
|
139
141
|
return new Promise((resolve) => {
|
|
@@ -146,7 +148,7 @@ async function resolveProviderWithDeadline(
|
|
|
146
148
|
};
|
|
147
149
|
const onAbort = () => finish(timeoutSignal.aborted ? "timeout" : "aborted");
|
|
148
150
|
requestSignal.addEventListener("abort", onAbort, { once: true });
|
|
149
|
-
resolveCodexContextProvider(ctx, ctx.model).then(
|
|
151
|
+
resolveCodexContextProvider(ctx, ctx.model, gatewayModels).then(
|
|
150
152
|
(value) => finish(value),
|
|
151
153
|
() => finish({ ok: false, reason: "auth-resolution-failed" }),
|
|
152
154
|
);
|
|
@@ -156,6 +158,7 @@ async function resolveProviderWithDeadline(
|
|
|
156
158
|
export async function loadHistoryNotesThreadHint(
|
|
157
159
|
ctx: ExtensionContext,
|
|
158
160
|
signal?: AbortSignal,
|
|
161
|
+
gatewayModels: readonly string[] = [],
|
|
159
162
|
): Promise<string | undefined> {
|
|
160
163
|
const result = await callHistoryNotesBackend(
|
|
161
164
|
THREAD_HINT_ENDPOINT,
|
|
@@ -163,6 +166,7 @@ export async function loadHistoryNotesThreadHint(
|
|
|
163
166
|
ctx,
|
|
164
167
|
signal,
|
|
165
168
|
{ mode: "bytes", limit: THREAD_HINT_MAX_BYTES },
|
|
169
|
+
gatewayModels,
|
|
166
170
|
);
|
|
167
171
|
if (!result.ok) {
|
|
168
172
|
if (result.reason === "aborted") throw new Error("Remote context hint request was aborted");
|
|
@@ -178,6 +182,7 @@ export async function executeHistoryNotesTool(
|
|
|
178
182
|
params: Record<string, unknown>,
|
|
179
183
|
ctx: ExtensionContext,
|
|
180
184
|
signal?: AbortSignal,
|
|
185
|
+
gatewayModels: readonly string[] = [],
|
|
181
186
|
): Promise<AgentToolResult<CodexHistoryNotesDetails>> {
|
|
182
187
|
const endpoint = namespace === "history"
|
|
183
188
|
? HISTORY_ENDPOINTS[action as HistoryAction]
|
|
@@ -190,6 +195,7 @@ export async function executeHistoryNotesTool(
|
|
|
190
195
|
ctx,
|
|
191
196
|
signal,
|
|
192
197
|
undefined,
|
|
198
|
+
gatewayModels,
|
|
193
199
|
);
|
|
194
200
|
if (!result.ok) throw new Error(formatHistoryNotesFailure(result.reason, result.status));
|
|
195
201
|
const modelResult = { ...result.value };
|
|
@@ -85,6 +85,7 @@ export function createContextManagementTools(
|
|
|
85
85
|
pi: ExtensionAPI,
|
|
86
86
|
manager: CodexContextWindowManager,
|
|
87
87
|
isActive: (ctx: ExtensionContext) => Promise<boolean> | boolean,
|
|
88
|
+
getGatewayModels: () => readonly string[] = () => [],
|
|
88
89
|
): ContextManagementTools {
|
|
89
90
|
const assertActive = async (ctx: ExtensionContext): Promise<void> => {
|
|
90
91
|
if (!(await isActive(ctx))) throw new Error("remote-context-inactive");
|
|
@@ -142,7 +143,7 @@ export function createContextManagementTools(
|
|
|
142
143
|
],
|
|
143
144
|
execute: async (_id, params, _signal, _update, ctx) => {
|
|
144
145
|
await assertActive(ctx);
|
|
145
|
-
return executeHistoryNotesTool("history", params.action, params as Record<string, unknown>, ctx, _signal);
|
|
146
|
+
return executeHistoryNotesTool("history", params.action, params as Record<string, unknown>, ctx, _signal, getGatewayModels());
|
|
146
147
|
},
|
|
147
148
|
};
|
|
148
149
|
const notes: ToolDefinition<typeof NOTES_PARAMETERS, CodexHistoryNotesDetails> = {
|
|
@@ -161,7 +162,7 @@ export function createContextManagementTools(
|
|
|
161
162
|
executionMode: "sequential",
|
|
162
163
|
execute: async (_id, params, _signal, _update, ctx) => {
|
|
163
164
|
await assertActive(ctx);
|
|
164
|
-
return executeHistoryNotesTool("notes", params.action, params as Record<string, unknown>, ctx, _signal);
|
|
165
|
+
return executeHistoryNotesTool("notes", params.action, params as Record<string, unknown>, ctx, _signal, getGatewayModels());
|
|
165
166
|
},
|
|
166
167
|
};
|
|
167
168
|
return { newContext, getContextRemaining, history, notes };
|
|
@@ -293,9 +294,10 @@ export function registerContextManagementTools(
|
|
|
293
294
|
pi: ExtensionAPI,
|
|
294
295
|
manager: CodexContextWindowManager,
|
|
295
296
|
isActive: (ctx: ExtensionContext) => Promise<boolean> | boolean,
|
|
297
|
+
getGatewayModels?: () => readonly string[],
|
|
296
298
|
): ContextManagementToolController {
|
|
297
299
|
const controller = new ContextManagementToolController(pi);
|
|
298
|
-
controller.register(createContextManagementTools(pi, manager, isActive));
|
|
300
|
+
controller.register(createContextManagementTools(pi, manager, isActive, getGatewayModels));
|
|
299
301
|
return controller;
|
|
300
302
|
}
|
|
301
303
|
|
|
@@ -67,7 +67,8 @@ export type NativeCodexContextProvider = {
|
|
|
67
67
|
export type GatewayCodexContextProvider = {
|
|
68
68
|
kind: "codex-gateway";
|
|
69
69
|
route: "codex-gateway";
|
|
70
|
-
provider
|
|
70
|
+
/** Operator-defined provider name; matched via compaction.gatewayContextModels. */
|
|
71
|
+
provider: string;
|
|
71
72
|
api: "openai-responses";
|
|
72
73
|
model: string;
|
|
73
74
|
baseUrl: string;
|