pi-openai-toolkit 0.14.4 → 0.14.6

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.
Files changed (43) hide show
  1. package/README.md +119 -147
  2. package/README.zh.md +119 -151
  3. package/docs/internals.md +42 -21
  4. package/package.json +127 -127
  5. package/src/auto-mode/classifier.ts +165 -165
  6. package/src/auto-mode/policy.ts +146 -146
  7. package/src/auto-mode/prompt.ts +279 -279
  8. package/src/auto-mode/reviewer.ts +325 -325
  9. package/src/auto-mode/transcript.ts +133 -133
  10. package/src/auto-mode/types.ts +137 -137
  11. package/src/codex-astra/effort-planner.ts +175 -175
  12. package/src/codex-astra/extension.ts +122 -122
  13. package/src/config.ts +621 -592
  14. package/src/context-management/codex-provider.ts +260 -260
  15. package/src/context-management/history-notes.ts +357 -325
  16. package/src/context-management/messages.ts +112 -106
  17. package/src/context-management/namespace-tools.ts +426 -426
  18. package/src/context-management/tool-contract.ts +23 -23
  19. package/src/context-management/tools.ts +306 -311
  20. package/src/context-management/types.ts +168 -161
  21. package/src/context-management/window-budget.ts +83 -83
  22. package/src/context-management/window-manager.ts +60 -51
  23. package/src/context-management/window-request.ts +125 -125
  24. package/src/debug.ts +1 -1
  25. package/src/extension-runtime.ts +34 -9
  26. package/src/image-generation/artifacts.ts +237 -237
  27. package/src/image-generation/client.ts +248 -248
  28. package/src/image-generation/eligibility.ts +18 -18
  29. package/src/image-generation/extension.ts +19 -2
  30. package/src/image-generation/protocol.ts +473 -405
  31. package/src/image-generation/references.ts +194 -194
  32. package/src/image-generation/render.ts +252 -252
  33. package/src/image-generation/service.ts +249 -243
  34. package/src/image-generation/types.ts +189 -184
  35. package/src/model-scope.ts +17 -17
  36. package/src/provider-headers.ts +23 -23
  37. package/src/responses-headers.ts +173 -108
  38. package/src/runtime.ts +513 -477
  39. package/src/types.ts +11 -0
  40. package/src/web-search/extension.ts +80 -80
  41. package/src/web-search/payload.ts +96 -96
  42. package/src/web-search/prompt.ts +20 -20
  43. package/src/web-search/types.ts +45 -45
@@ -1,243 +1,249 @@
1
- import { getAgentDir, type ExtensionContext } from "@earendil-works/pi-coding-agent";
2
- import { loadToolkitConfig } from "../config";
3
- import { resolveResponsesEnvironment } from "../runtime";
4
- import {
5
- copyImageToExplicitPath,
6
- prepareExplicitOutputPath,
7
- saveCanonicalImage,
8
- } from "./artifacts";
9
- import { requestGeneratedImage } from "./client";
10
- import { isImageGenerationEnabledForModel } from "./eligibility";
11
- import {
12
- buildImageGenerationRequest,
13
- normalizeGenerateImageParams,
14
- } from "./protocol";
15
- import {
16
- clearPreparedReferences,
17
- prepareReferenceImages,
18
- } from "./references";
19
- import {
20
- IMAGE_GENERATION_CAPABLE_APIS,
21
- IMAGE_GENERATION_MIME_TYPE,
22
- IMAGE_GENERATION_MODEL,
23
- ImageGenerationError,
24
- sanitizeImageDiagnostic,
25
- type GenerateImageParams,
26
- type ImageGenerationExecutionResult,
27
- type ImageGenerationFailureCode,
28
- type ParsedGeneratedImage,
29
- } from "./types";
30
-
31
- export type ImageGenerationServiceDependencies = {
32
- loadConfig: typeof loadToolkitConfig;
33
- resolveRuntime: typeof resolveResponsesEnvironment;
34
- getAgentDir: typeof getAgentDir;
35
- prepareOutput: typeof prepareExplicitOutputPath;
36
- prepareReferences: typeof prepareReferenceImages;
37
- requestImage: typeof requestGeneratedImage;
38
- saveCanonical: typeof saveCanonicalImage;
39
- copyExplicit: typeof copyImageToExplicitPath;
40
- clearReferences: typeof clearPreparedReferences;
41
- };
42
-
43
- const DEFAULT_SERVICE_DEPS: ImageGenerationServiceDependencies = {
44
- loadConfig: loadToolkitConfig,
45
- resolveRuntime: resolveResponsesEnvironment,
46
- getAgentDir,
47
- prepareOutput: prepareExplicitOutputPath,
48
- prepareReferences: prepareReferenceImages,
49
- requestImage: requestGeneratedImage,
50
- saveCanonical: saveCanonicalImage,
51
- copyExplicit: copyImageToExplicitPath,
52
- clearReferences: clearPreparedReferences,
53
- };
54
-
55
- function runtimeFailure(
56
- reason: string,
57
- errorMessage?: string,
58
- ): ImageGenerationError {
59
- switch (reason) {
60
- case "disabled":
61
- return new ImageGenerationError("disabled", "Image generation is disabled.");
62
- case "unsupported-api":
63
- case "missing-model":
64
- return new ImageGenerationError(
65
- "unsupported-model",
66
- "Image generation is unavailable for the current model.",
67
- );
68
- case "missing-api-key":
69
- case "auth-resolution-failed":
70
- return new ImageGenerationError(
71
- "authentication",
72
- sanitizeImageDiagnostic(
73
- errorMessage,
74
- "Unable to resolve authentication for image generation with the current model.",
75
- ),
76
- );
77
- default:
78
- return new ImageGenerationError(
79
- "missing-runtime",
80
- "Unable to resolve the current model's Responses endpoint for image generation.",
81
- );
82
- }
83
- }
84
-
85
- function throwIfAborted(signal: AbortSignal | undefined): void {
86
- if (signal?.aborted) {
87
- throw new ImageGenerationError("aborted", "Image generation was cancelled.");
88
- }
89
- }
90
-
91
- function clientFailureCode(reason: string): ImageGenerationFailureCode {
92
- switch (reason) {
93
- case "aborted":
94
- case "timeout":
95
- case "authentication":
96
- case "rate-limit":
97
- case "request-rejected":
98
- case "backend-unavailable":
99
- case "network":
100
- case "oversized-response":
101
- case "malformed-response":
102
- case "no-image":
103
- return reason;
104
- default:
105
- return "network";
106
- }
107
- }
108
-
109
- function formatResultText(args: {
110
- artifactPath: string;
111
- outputPath?: string;
112
- warning?: string;
113
- edited: boolean;
114
- width: number;
115
- height: number;
116
- }): string {
117
- const lines = [
118
- `${args.edited ? "Edited" : "Generated"} PNG image (${args.width}x${args.height}).`,
119
- `Artifact: ${args.artifactPath}`,
120
- ];
121
- if (args.outputPath) lines.push(`Copied to: ${args.outputPath}`);
122
- if (args.warning) lines.push(`Warning: ${args.warning}`);
123
- return lines.join("\n");
124
- }
125
-
126
- export function createImageGenerationExecutor(
127
- deps: ImageGenerationServiceDependencies = DEFAULT_SERVICE_DEPS,
128
- ): (args: {
129
- params: GenerateImageParams;
130
- toolCallId: string;
131
- signal?: AbortSignal;
132
- ctx: ExtensionContext;
133
- }) => Promise<ImageGenerationExecutionResult> {
134
- return async (args) => {
135
- const params = normalizeGenerateImageParams(args.params);
136
- throwIfAborted(args.signal);
137
- const { config } = deps.loadConfig();
138
- if (!isImageGenerationEnabledForModel(args.ctx.model, config.imageGeneration)) {
139
- throw new ImageGenerationError(
140
- "unsupported-model",
141
- "Image generation is not enabled for the current provider/model-id.",
142
- );
143
- }
144
-
145
- const runtimeResolution = await deps.resolveRuntime(args.ctx, {
146
- enabled: config.imageGeneration.enabled,
147
- responsesApis: IMAGE_GENERATION_CAPABLE_APIS,
148
- });
149
- if (!runtimeResolution.ok) {
150
- throw runtimeFailure(runtimeResolution.reason, runtimeResolution.errorMessage);
151
- }
152
-
153
- const agentDir = deps.getAgentDir();
154
- const explicitOutput = await deps.prepareOutput({
155
- rawPath: params.outputPath,
156
- agentDir,
157
- ctx: args.ctx,
158
- signal: args.signal,
159
- });
160
-
161
- const references = await deps.prepareReferences({
162
- paths: params.referenceImagePaths,
163
- ctx: args.ctx,
164
- signal: args.signal,
165
- });
166
- let generated: ParsedGeneratedImage | undefined;
167
- try {
168
- throwIfAborted(args.signal);
169
- const body = buildImageGenerationRequest({
170
- routingModel: runtimeResolution.runtime.model,
171
- params,
172
- references,
173
- });
174
- const response = await deps.requestImage({
175
- runtime: runtimeResolution.runtime,
176
- body,
177
- signal: args.signal,
178
- });
179
- if (!response.ok) {
180
- throw new ImageGenerationError(
181
- clientFailureCode(response.reason),
182
- response.errorMessage,
183
- );
184
- }
185
- generated = response.image;
186
-
187
- const artifactPath = await deps.saveCanonical({
188
- bytes: generated.bytes,
189
- agentDir,
190
- sessionId: args.ctx.sessionManager.getSessionId(),
191
- imageCallId: generated.imageCallId || args.toolCallId,
192
- });
193
-
194
- let outputPath: string | undefined;
195
- let warning: string | undefined;
196
- if (explicitOutput) {
197
- try {
198
- await deps.copyExplicit({ bytes: generated.bytes, plan: explicitOutput });
199
- outputPath = explicitOutput.path;
200
- } catch (error) {
201
- warning = sanitizeImageDiagnostic(
202
- error instanceof Error ? error.message : error,
203
- `The generated image was saved to the canonical artifact, but copying to ${explicitOutput.path} failed.`,
204
- );
205
- }
206
- }
207
-
208
- const edited = references.length > 0;
209
- const details = {
210
- artifactPath,
211
- ...(outputPath ? { outputPath } : {}),
212
- routingModel: `${runtimeResolution.runtime.provider}/${runtimeResolution.runtime.model}`,
213
- imageModel: IMAGE_GENERATION_MODEL,
214
- imageCallId: generated.imageCallId,
215
- ...(generated.responseId ? { responseId: generated.responseId } : {}),
216
- mimeType: IMAGE_GENERATION_MIME_TYPE,
217
- byteCount: generated.bytes.length,
218
- width: generated.width,
219
- height: generated.height,
220
- edited,
221
- referenceCount: references.length,
222
- ...(generated.revisedPrompt ? { revisedPrompt: generated.revisedPrompt } : {}),
223
- ...(warning ? { warning } : {}),
224
- };
225
- return {
226
- details,
227
- text: formatResultText({
228
- artifactPath,
229
- outputPath,
230
- warning,
231
- edited,
232
- width: generated.width,
233
- height: generated.height,
234
- }),
235
- };
236
- } finally {
237
- deps.clearReferences(references);
238
- generated?.bytes.fill(0);
239
- }
240
- };
241
- }
242
-
243
- export const executeImageGeneration = createImageGenerationExecutor();
1
+ import { getAgentDir, type ExtensionContext } from "@earendil-works/pi-coding-agent";
2
+ import { loadToolkitConfig } from "../config";
3
+ import { resolveResponsesEnvironment } from "../runtime";
4
+ import {
5
+ copyImageToExplicitPath,
6
+ prepareExplicitOutputPath,
7
+ saveCanonicalImage,
8
+ } from "./artifacts";
9
+ import { requestGeneratedImage } from "./client";
10
+ import { isImageGenerationEnabledForModel } from "./eligibility";
11
+ import {
12
+ buildImageGenerationRequest,
13
+ normalizeGenerateImageParams,
14
+ selectImageGenerationModel,
15
+ } from "./protocol";
16
+ import {
17
+ clearPreparedReferences,
18
+ prepareReferenceImages,
19
+ } from "./references";
20
+ import {
21
+ IMAGE_GENERATION_CAPABLE_APIS,
22
+ IMAGE_GENERATION_MIME_TYPE,
23
+ ImageGenerationError,
24
+ sanitizeImageDiagnostic,
25
+ type GenerateImageParams,
26
+ type ImageGenerationExecutionResult,
27
+ type ImageGenerationFailureCode,
28
+ type ParsedGeneratedImage,
29
+ } from "./types";
30
+
31
+ export type ImageGenerationServiceDependencies = {
32
+ loadConfig: typeof loadToolkitConfig;
33
+ resolveRuntime: typeof resolveResponsesEnvironment;
34
+ getAgentDir: typeof getAgentDir;
35
+ prepareOutput: typeof prepareExplicitOutputPath;
36
+ prepareReferences: typeof prepareReferenceImages;
37
+ requestImage: typeof requestGeneratedImage;
38
+ saveCanonical: typeof saveCanonicalImage;
39
+ copyExplicit: typeof copyImageToExplicitPath;
40
+ clearReferences: typeof clearPreparedReferences;
41
+ };
42
+
43
+ const DEFAULT_SERVICE_DEPS: ImageGenerationServiceDependencies = {
44
+ loadConfig: loadToolkitConfig,
45
+ resolveRuntime: resolveResponsesEnvironment,
46
+ getAgentDir,
47
+ prepareOutput: prepareExplicitOutputPath,
48
+ prepareReferences: prepareReferenceImages,
49
+ requestImage: requestGeneratedImage,
50
+ saveCanonical: saveCanonicalImage,
51
+ copyExplicit: copyImageToExplicitPath,
52
+ clearReferences: clearPreparedReferences,
53
+ };
54
+
55
+ function runtimeFailure(
56
+ reason: string,
57
+ errorMessage?: string,
58
+ ): ImageGenerationError {
59
+ switch (reason) {
60
+ case "disabled":
61
+ return new ImageGenerationError("disabled", "Image generation is disabled.");
62
+ case "unsupported-api":
63
+ case "missing-model":
64
+ return new ImageGenerationError(
65
+ "unsupported-model",
66
+ "Image generation is unavailable for the current model.",
67
+ );
68
+ case "missing-api-key":
69
+ case "auth-resolution-failed":
70
+ return new ImageGenerationError(
71
+ "authentication",
72
+ sanitizeImageDiagnostic(
73
+ errorMessage,
74
+ "Unable to resolve authentication for image generation with the current model.",
75
+ ),
76
+ );
77
+ default:
78
+ return new ImageGenerationError(
79
+ "missing-runtime",
80
+ "Unable to resolve the current model's Responses endpoint for image generation.",
81
+ );
82
+ }
83
+ }
84
+
85
+ function throwIfAborted(signal: AbortSignal | undefined): void {
86
+ if (signal?.aborted) {
87
+ throw new ImageGenerationError("aborted", "Image generation was cancelled.");
88
+ }
89
+ }
90
+
91
+ function clientFailureCode(reason: string): ImageGenerationFailureCode {
92
+ switch (reason) {
93
+ case "aborted":
94
+ case "timeout":
95
+ case "authentication":
96
+ case "rate-limit":
97
+ case "request-rejected":
98
+ case "backend-unavailable":
99
+ case "network":
100
+ case "oversized-response":
101
+ case "malformed-response":
102
+ case "no-image":
103
+ return reason;
104
+ default:
105
+ return "network";
106
+ }
107
+ }
108
+
109
+ function formatResultText(args: {
110
+ artifactPath: string;
111
+ outputPath?: string;
112
+ warning?: string;
113
+ edited: boolean;
114
+ width: number;
115
+ height: number;
116
+ }): string {
117
+ const lines = [
118
+ `${args.edited ? "Edited" : "Generated"} PNG image (${args.width}x${args.height}).`,
119
+ `Artifact: ${args.artifactPath}`,
120
+ ];
121
+ if (args.outputPath) lines.push(`Copied to: ${args.outputPath}`);
122
+ if (args.warning) lines.push(`Warning: ${args.warning}`);
123
+ return lines.join("\n");
124
+ }
125
+
126
+ export function createImageGenerationExecutor(
127
+ deps: ImageGenerationServiceDependencies = DEFAULT_SERVICE_DEPS,
128
+ ): (args: {
129
+ params: GenerateImageParams;
130
+ toolCallId: string;
131
+ signal?: AbortSignal;
132
+ ctx: ExtensionContext;
133
+ }) => Promise<ImageGenerationExecutionResult> {
134
+ return async (args) => {
135
+ const params = normalizeGenerateImageParams(args.params);
136
+ throwIfAborted(args.signal);
137
+ const { config } = deps.loadConfig();
138
+ if (!isImageGenerationEnabledForModel(args.ctx.model, config.imageGeneration)) {
139
+ throw new ImageGenerationError(
140
+ "unsupported-model",
141
+ "Image generation is not enabled for the current provider/model-id.",
142
+ );
143
+ }
144
+
145
+ const imageModel = selectImageGenerationModel({
146
+ requestedModel: params.model,
147
+ configuredModels: config.imageGeneration.models,
148
+ });
149
+
150
+ const runtimeResolution = await deps.resolveRuntime(args.ctx, {
151
+ enabled: config.imageGeneration.enabled,
152
+ responsesApis: IMAGE_GENERATION_CAPABLE_APIS,
153
+ });
154
+ if (!runtimeResolution.ok) {
155
+ throw runtimeFailure(runtimeResolution.reason, runtimeResolution.errorMessage);
156
+ }
157
+
158
+ const agentDir = deps.getAgentDir();
159
+ const explicitOutput = await deps.prepareOutput({
160
+ rawPath: params.outputPath,
161
+ agentDir,
162
+ ctx: args.ctx,
163
+ signal: args.signal,
164
+ });
165
+
166
+ const references = await deps.prepareReferences({
167
+ paths: params.referenceImagePaths,
168
+ ctx: args.ctx,
169
+ signal: args.signal,
170
+ });
171
+ let generated: ParsedGeneratedImage | undefined;
172
+ try {
173
+ throwIfAborted(args.signal);
174
+ const body = buildImageGenerationRequest({
175
+ routingModel: runtimeResolution.runtime.model,
176
+ imageModel,
177
+ params,
178
+ references,
179
+ });
180
+ const response = await deps.requestImage({
181
+ runtime: runtimeResolution.runtime,
182
+ body,
183
+ signal: args.signal,
184
+ });
185
+ if (!response.ok) {
186
+ throw new ImageGenerationError(
187
+ clientFailureCode(response.reason),
188
+ response.errorMessage,
189
+ );
190
+ }
191
+ generated = response.image;
192
+
193
+ const artifactPath = await deps.saveCanonical({
194
+ bytes: generated.bytes,
195
+ agentDir,
196
+ sessionId: args.ctx.sessionManager.getSessionId(),
197
+ imageCallId: generated.imageCallId || args.toolCallId,
198
+ });
199
+
200
+ let outputPath: string | undefined;
201
+ let warning: string | undefined;
202
+ if (explicitOutput) {
203
+ try {
204
+ await deps.copyExplicit({ bytes: generated.bytes, plan: explicitOutput });
205
+ outputPath = explicitOutput.path;
206
+ } catch (error) {
207
+ warning = sanitizeImageDiagnostic(
208
+ error instanceof Error ? error.message : error,
209
+ `The generated image was saved to the canonical artifact, but copying to ${explicitOutput.path} failed.`,
210
+ );
211
+ }
212
+ }
213
+
214
+ const edited = references.length > 0;
215
+ const details = {
216
+ artifactPath,
217
+ ...(outputPath ? { outputPath } : {}),
218
+ routingModel: `${runtimeResolution.runtime.provider}/${runtimeResolution.runtime.model}`,
219
+ imageModel,
220
+ imageCallId: generated.imageCallId,
221
+ ...(generated.responseId ? { responseId: generated.responseId } : {}),
222
+ mimeType: IMAGE_GENERATION_MIME_TYPE,
223
+ byteCount: generated.bytes.length,
224
+ width: generated.width,
225
+ height: generated.height,
226
+ edited,
227
+ referenceCount: references.length,
228
+ ...(generated.revisedPrompt ? { revisedPrompt: generated.revisedPrompt } : {}),
229
+ ...(warning ? { warning } : {}),
230
+ };
231
+ return {
232
+ details,
233
+ text: formatResultText({
234
+ artifactPath,
235
+ outputPath,
236
+ warning,
237
+ edited,
238
+ width: generated.width,
239
+ height: generated.height,
240
+ }),
241
+ };
242
+ } finally {
243
+ deps.clearReferences(references);
244
+ generated?.bytes.fill(0);
245
+ }
246
+ };
247
+ }
248
+
249
+ export const executeImageGeneration = createImageGenerationExecutor();