@code-yeongyu/senpi 2026.9.8 → 2026.9.9-2

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 (185) hide show
  1. package/CHANGELOG.md +43 -3
  2. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  3. package/dist/core/agent-session-runtime.js +2 -0
  4. package/dist/core/agent-session-runtime.js.map +1 -1
  5. package/dist/core/agent-session.d.ts +8 -1
  6. package/dist/core/agent-session.d.ts.map +1 -1
  7. package/dist/core/agent-session.js +33 -0
  8. package/dist/core/agent-session.js.map +1 -1
  9. package/dist/core/compaction/compaction-execution.d.ts.map +1 -1
  10. package/dist/core/compaction/compaction-execution.js +5 -5
  11. package/dist/core/compaction/compaction-execution.js.map +1 -1
  12. package/dist/core/compaction/compaction-settings.d.ts +2 -0
  13. package/dist/core/compaction/compaction-settings.d.ts.map +1 -1
  14. package/dist/core/compaction/compaction-settings.js.map +1 -1
  15. package/dist/core/compaction/compaction.d.ts +3 -3
  16. package/dist/core/compaction/compaction.d.ts.map +1 -1
  17. package/dist/core/compaction/compaction.js +12 -7
  18. package/dist/core/compaction/compaction.js.map +1 -1
  19. package/dist/core/compaction/stream-watchdog.d.ts +29 -0
  20. package/dist/core/compaction/stream-watchdog.d.ts.map +1 -1
  21. package/dist/core/compaction/stream-watchdog.js +35 -0
  22. package/dist/core/compaction/stream-watchdog.js.map +1 -1
  23. package/dist/core/compaction-settings-access.d.ts +6 -0
  24. package/dist/core/compaction-settings-access.d.ts.map +1 -1
  25. package/dist/core/compaction-settings-access.js.map +1 -1
  26. package/dist/core/compaction-settings-resolver.d.ts +2 -0
  27. package/dist/core/compaction-settings-resolver.d.ts.map +1 -1
  28. package/dist/core/compaction-settings-resolver.js +5 -0
  29. package/dist/core/compaction-settings-resolver.js.map +1 -1
  30. package/dist/core/extensions/builtin/claude-sdk-oauth/session-stream.d.ts.map +1 -1
  31. package/dist/core/extensions/builtin/claude-sdk-oauth/session-stream.js +4 -1
  32. package/dist/core/extensions/builtin/claude-sdk-oauth/session-stream.js.map +1 -1
  33. package/dist/core/extensions/builtin/compaction/model-usability-budget.d.ts +1 -1
  34. package/dist/core/extensions/builtin/compaction/model-usability-budget.d.ts.map +1 -1
  35. package/dist/core/extensions/builtin/compaction/model-usability-budget.js +23 -3
  36. package/dist/core/extensions/builtin/compaction/model-usability-budget.js.map +1 -1
  37. package/dist/core/extensions/builtin/compaction/resume-admission.d.ts +7 -0
  38. package/dist/core/extensions/builtin/compaction/resume-admission.d.ts.map +1 -0
  39. package/dist/core/extensions/builtin/compaction/resume-admission.js +7 -0
  40. package/dist/core/extensions/builtin/compaction/resume-admission.js.map +1 -0
  41. package/dist/core/extensions/builtin/compaction/speculative-summary.d.ts +2 -0
  42. package/dist/core/extensions/builtin/compaction/speculative-summary.d.ts.map +1 -1
  43. package/dist/core/extensions/builtin/compaction/speculative-summary.js +5 -2
  44. package/dist/core/extensions/builtin/compaction/speculative-summary.js.map +1 -1
  45. package/dist/core/extensions/builtin/compaction/speculative.d.ts.map +1 -1
  46. package/dist/core/extensions/builtin/compaction/speculative.js +9 -3
  47. package/dist/core/extensions/builtin/compaction/speculative.js.map +1 -1
  48. package/dist/core/extensions/builtin/compaction/summarization-retry.d.ts +10 -4
  49. package/dist/core/extensions/builtin/compaction/summarization-retry.d.ts.map +1 -1
  50. package/dist/core/extensions/builtin/compaction/summarization-retry.js +14 -5
  51. package/dist/core/extensions/builtin/compaction/summarization-retry.js.map +1 -1
  52. package/dist/core/extensions/builtin/imagegen/params.d.ts +36 -0
  53. package/dist/core/extensions/builtin/imagegen/params.d.ts.map +1 -0
  54. package/dist/core/extensions/builtin/imagegen/params.js +55 -0
  55. package/dist/core/extensions/builtin/imagegen/params.js.map +1 -0
  56. package/dist/core/extensions/builtin/imagegen/reference-images.d.ts +11 -0
  57. package/dist/core/extensions/builtin/imagegen/reference-images.d.ts.map +1 -0
  58. package/dist/core/extensions/builtin/imagegen/reference-images.js +55 -0
  59. package/dist/core/extensions/builtin/imagegen/reference-images.js.map +1 -0
  60. package/dist/core/extensions/builtin/imagegen/skill/SKILL.md +47 -4
  61. package/dist/core/extensions/builtin/imagegen/tool.d.ts +10 -19
  62. package/dist/core/extensions/builtin/imagegen/tool.d.ts.map +1 -1
  63. package/dist/core/extensions/builtin/imagegen/tool.js +21 -45
  64. package/dist/core/extensions/builtin/imagegen/tool.js.map +1 -1
  65. package/dist/core/extensions/loader.d.ts +2 -1
  66. package/dist/core/extensions/loader.d.ts.map +1 -1
  67. package/dist/core/extensions/loader.js +17 -8
  68. package/dist/core/extensions/loader.js.map +1 -1
  69. package/dist/core/extensions/types.d.ts +5 -0
  70. package/dist/core/extensions/types.d.ts.map +1 -1
  71. package/dist/core/extensions/types.js.map +1 -1
  72. package/dist/core/resource-loader.d.ts +2 -0
  73. package/dist/core/resource-loader.d.ts.map +1 -1
  74. package/dist/core/resource-loader.js +11 -7
  75. package/dist/core/resource-loader.js.map +1 -1
  76. package/dist/core/sdk.d.ts.map +1 -1
  77. package/dist/core/sdk.js +13 -1
  78. package/dist/core/sdk.js.map +1 -1
  79. package/dist/core/session-manager.d.ts.map +1 -1
  80. package/dist/core/session-manager.js +11 -1
  81. package/dist/core/session-manager.js.map +1 -1
  82. package/dist/core/session-write-reservation.d.ts +4 -0
  83. package/dist/core/session-write-reservation.d.ts.map +1 -0
  84. package/dist/core/session-write-reservation.js +12 -0
  85. package/dist/core/session-write-reservation.js.map +1 -0
  86. package/dist/core/tools/read-classifiers.d.ts +17 -0
  87. package/dist/core/tools/read-classifiers.d.ts.map +1 -0
  88. package/dist/core/tools/read-classifiers.js +26 -0
  89. package/dist/core/tools/read-classifiers.js.map +1 -0
  90. package/dist/core/tools/read.d.ts +5 -1
  91. package/dist/core/tools/read.d.ts.map +1 -1
  92. package/dist/core/tools/read.js +21 -1
  93. package/dist/core/tools/read.js.map +1 -1
  94. package/dist/index.d.ts +1 -0
  95. package/dist/index.d.ts.map +1 -1
  96. package/dist/index.js +1 -0
  97. package/dist/index.js.map +1 -1
  98. package/dist/main.d.ts +14 -0
  99. package/dist/main.d.ts.map +1 -1
  100. package/dist/main.js +166 -147
  101. package/dist/main.js.map +1 -1
  102. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  103. package/dist/modes/interactive/interactive-mode.js +3 -0
  104. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  105. package/dist/modes/rpc/connection-handler.d.ts +2 -0
  106. package/dist/modes/rpc/connection-handler.d.ts.map +1 -1
  107. package/dist/modes/rpc/connection-handler.js +1 -1
  108. package/dist/modes/rpc/connection-handler.js.map +1 -1
  109. package/dist/modes/rpc/multi-session-host.d.ts +2 -0
  110. package/dist/modes/rpc/multi-session-host.d.ts.map +1 -1
  111. package/dist/modes/rpc/multi-session-host.js +18 -8
  112. package/dist/modes/rpc/multi-session-host.js.map +1 -1
  113. package/dist/modes/rpc/session-binding.d.ts.map +1 -1
  114. package/dist/modes/rpc/session-binding.js +3 -0
  115. package/dist/modes/rpc/session-binding.js.map +1 -1
  116. package/dist/modes/rpc/session-command-router.d.ts +1 -1
  117. package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
  118. package/dist/modes/rpc/session-command-router.js +57 -25
  119. package/dist/modes/rpc/session-command-router.js.map +1 -1
  120. package/dist/modes/rpc/session-event-writer.d.ts +23 -1
  121. package/dist/modes/rpc/session-event-writer.d.ts.map +1 -1
  122. package/dist/modes/rpc/session-event-writer.js +108 -1
  123. package/dist/modes/rpc/session-event-writer.js.map +1 -1
  124. package/dist/modes/rpc/session-registry.d.ts +4 -2
  125. package/dist/modes/rpc/session-registry.d.ts.map +1 -1
  126. package/dist/modes/rpc/session-registry.js +1 -1
  127. package/dist/modes/rpc/session-registry.js.map +1 -1
  128. package/dist/modes/rpc/session-worker-client.d.ts +47 -0
  129. package/dist/modes/rpc/session-worker-client.d.ts.map +1 -0
  130. package/dist/modes/rpc/session-worker-client.js +226 -0
  131. package/dist/modes/rpc/session-worker-client.js.map +1 -0
  132. package/dist/modes/rpc/session-worker-protocol.d.ts +103 -0
  133. package/dist/modes/rpc/session-worker-protocol.d.ts.map +1 -0
  134. package/dist/modes/rpc/session-worker-protocol.js +12 -0
  135. package/dist/modes/rpc/session-worker-protocol.js.map +1 -0
  136. package/dist/modes/rpc/session-worker-requests.d.ts +24 -0
  137. package/dist/modes/rpc/session-worker-requests.d.ts.map +1 -0
  138. package/dist/modes/rpc/session-worker-requests.js +71 -0
  139. package/dist/modes/rpc/session-worker-requests.js.map +1 -0
  140. package/dist/modes/rpc/session-worker.d.ts +2 -0
  141. package/dist/modes/rpc/session-worker.d.ts.map +1 -0
  142. package/dist/modes/rpc/session-worker.js +229 -0
  143. package/dist/modes/rpc/session-worker.js.map +1 -0
  144. package/dist/modes/rpc/worker-session-registry.d.ts +37 -0
  145. package/dist/modes/rpc/worker-session-registry.d.ts.map +1 -0
  146. package/dist/modes/rpc/worker-session-registry.js +207 -0
  147. package/dist/modes/rpc/worker-session-registry.js.map +1 -0
  148. package/docs/rpc.md +70 -9
  149. package/docs/settings.md +1 -0
  150. package/docs/skills.md +1 -1
  151. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +24 -0
  152. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  153. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  154. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js +23 -5
  155. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js.map +1 -1
  156. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images-edit.d.ts +4 -0
  157. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images-edit.d.ts.map +1 -0
  158. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images-edit.js +11 -0
  159. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images-edit.js.map +1 -0
  160. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images-params.d.ts +25 -0
  161. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images-params.d.ts.map +1 -0
  162. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images-params.js +58 -0
  163. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images-params.js.map +1 -0
  164. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.d.ts +3 -6
  165. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.d.ts.map +1 -1
  166. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.js +15 -33
  167. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.js.map +1 -1
  168. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts +61 -1
  169. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts.map +1 -1
  170. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js +61 -1
  171. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js.map +1 -1
  172. package/node_modules/@earendil-works/pi-ai/dist/images.d.ts +1 -0
  173. package/node_modules/@earendil-works/pi-ai/dist/images.d.ts.map +1 -1
  174. package/node_modules/@earendil-works/pi-ai/dist/images.js +1 -0
  175. package/node_modules/@earendil-works/pi-ai/dist/images.js.map +1 -1
  176. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  177. package/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -1
  178. package/node_modules/@earendil-works/pi-ai/dist/providers/data/nvidia.json +1 -1
  179. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  180. package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
  181. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  182. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  183. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  184. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  185. package/package.json +7 -7
@@ -0,0 +1,4 @@
1
+ import type { ImageContent } from "../types.ts";
2
+ import type { OpenAIImageParams } from "./openai-images-params.ts";
3
+ export declare function buildEditParams(params: OpenAIImageParams, images: ImageContent[]): Promise<OpenAIImageParams>;
4
+ //# sourceMappingURL=openai-images-edit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-images-edit.d.ts","sourceRoot":"","sources":["../../src/api/openai-images-edit.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAEnE,wBAAsB,eAAe,CAAC,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC,CASnH"}
@@ -0,0 +1,11 @@
1
+ import { toFile } from "openai";
2
+ export async function buildEditParams(params, images) {
3
+ if (images.length > 16)
4
+ throw new Error("OpenAI image edits accept at most 16 reference images");
5
+ const image = await Promise.all(images.map(({ data, mimeType }, i) => {
6
+ const ext = mimeType.split("/")[1];
7
+ return toFile(Buffer.from(data, "base64"), `reference-${i}.${ext}`, { type: mimeType });
8
+ }));
9
+ return { ...params, image };
10
+ }
11
+ //# sourceMappingURL=openai-images-edit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-images-edit.js","sourceRoot":"","sources":["../../src/api/openai-images-edit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIhC,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAyB,EAAE,MAAsB;IACtF,IAAI,MAAM,CAAC,MAAM,GAAG,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;IACjG,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,GAAG,CAC9B,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC,EAAE,EAAE;QACpC,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACnC,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,aAAa,CAAC,IAAI,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IACzF,CAAC,CAAC,CACF,CAAC;IACF,OAAO,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC;AAC7B,CAAC","sourcesContent":["import { toFile } from \"openai\";\nimport type { ImageContent } from \"../types.ts\";\nimport type { OpenAIImageParams } from \"./openai-images-params.ts\";\n\nexport async function buildEditParams(params: OpenAIImageParams, images: ImageContent[]): Promise<OpenAIImageParams> {\n\tif (images.length > 16) throw new Error(\"OpenAI image edits accept at most 16 reference images\");\n\tconst image = await Promise.all(\n\t\timages.map(({ data, mimeType }, i) => {\n\t\t\tconst ext = mimeType.split(\"/\")[1];\n\t\t\treturn toFile(Buffer.from(data, \"base64\"), `reference-${i}.${ext}`, { type: mimeType });\n\t\t}),\n\t);\n\treturn { ...params, image };\n}\n"]}
@@ -0,0 +1,25 @@
1
+ import type { Uploadable } from "openai";
2
+ import type { ImageGenerateParamsNonStreaming } from "openai/resources/images.js";
3
+ import type { ImagesContext, ImagesModel, ImagesOptions } from "../types.ts";
4
+ export type OpenAIImageQuality = "auto" | "low" | "medium" | "high" | "xhigh" | "max";
5
+ export type OpenAIImageSize = "auto" | "1024x1024" | "1536x1024" | "1024x1536" | `${number}x${number}`;
6
+ export interface OpenAIImagesOptions extends ImagesOptions {
7
+ size?: OpenAIImageSize;
8
+ quality?: OpenAIImageQuality;
9
+ n?: number;
10
+ }
11
+ export type OpenAIImageParams = Omit<ImageGenerateParamsNonStreaming, "size" | "quality"> & {
12
+ size?: OpenAIImageSize;
13
+ quality?: OpenAIImageQuality;
14
+ image?: Uploadable[];
15
+ };
16
+ export declare function parseOpenAIImageSize(size: string): {
17
+ ok: true;
18
+ size: string;
19
+ } | {
20
+ ok: false;
21
+ error: string;
22
+ };
23
+ export declare function buildParams(model: ImagesModel<"openai-images">, context: ImagesContext, options?: OpenAIImagesOptions): OpenAIImageParams;
24
+ export declare function isImageParams(value: unknown): value is OpenAIImageParams;
25
+ //# sourceMappingURL=openai-images-params.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-images-params.d.ts","sourceRoot":"","sources":["../../src/api/openai-images-params.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,4BAA4B,CAAC;AAClF,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAK7E,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;AACtF,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,GAAG,GAAG,MAAM,IAAI,MAAM,EAAE,CAAC;AAEvG,MAAM,WAAW,mBAAoB,SAAQ,aAAa;IACzD,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,CAAC,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,+BAA+B,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG;IAC3F,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;CACrB,CAAC;AAEF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAqB5G;AAED,wBAAgB,WAAW,CAC1B,KAAK,EAAE,WAAW,CAAC,eAAe,CAAC,EACnC,OAAO,EAAE,aAAa,EACtB,OAAO,CAAC,EAAE,mBAAmB,GAC3B,iBAAiB,CAwBnB;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,iBAAiB,CAExE"}
@@ -0,0 +1,58 @@
1
+ import { sanitizeSurrogates } from "../utils/sanitize-unicode.js";
2
+ const MAX_PROMPT_CHARS = 32_000;
3
+ export function parseOpenAIImageSize(size) {
4
+ if (["auto", "1024x1024", "1536x1024", "1024x1536"].includes(size))
5
+ return { ok: true, size };
6
+ const match = /^\d+x\d+$/.exec(size);
7
+ if (!match || match[0] !== size) {
8
+ return { ok: false, error: "OpenAI image size must be auto or WIDTHxHEIGHT with integer dimensions" };
9
+ }
10
+ const [width, height] = size.split("x").map(Number);
11
+ if (width > 3840 || height > 3840) {
12
+ return { ok: false, error: "OpenAI image size edges must be at most 3840 pixels" };
13
+ }
14
+ if (width % 16 !== 0 || height % 16 !== 0) {
15
+ return { ok: false, error: "OpenAI image size width and height must be divisible by 16" };
16
+ }
17
+ if (width > height * 3 || height > width * 3) {
18
+ return { ok: false, error: "OpenAI image size aspect ratio must be between 1:3 and 3:1 inclusive" };
19
+ }
20
+ const pixels = width * height;
21
+ if (pixels < 655360 || pixels > 8294400) {
22
+ return { ok: false, error: "OpenAI image size must contain between 655360 and 8294400 pixels inclusive" };
23
+ }
24
+ return { ok: true, size };
25
+ }
26
+ export function buildParams(model, context, options) {
27
+ const promptParts = [];
28
+ for (const item of context.input) {
29
+ if (item.type !== "text")
30
+ continue;
31
+ const text = sanitizeSurrogates(item.text);
32
+ if (text.trim())
33
+ promptParts.push(text);
34
+ }
35
+ const prompt = promptParts.join("\n\n");
36
+ if (!prompt.trim())
37
+ throw new Error("Image generation requires a non-empty text prompt");
38
+ if (prompt.length > MAX_PROMPT_CHARS) {
39
+ throw new Error(`Image generation prompt exceeds ${MAX_PROMPT_CHARS} characters`);
40
+ }
41
+ const size = options?.size ?? "auto";
42
+ const parsedSize = parseOpenAIImageSize(size);
43
+ if (!parsedSize.ok)
44
+ throw new Error(parsedSize.error);
45
+ return {
46
+ model: model.id,
47
+ prompt,
48
+ size,
49
+ quality: options?.quality ?? "auto",
50
+ n: options?.n ?? 1,
51
+ output_format: "png",
52
+ stream: false,
53
+ };
54
+ }
55
+ export function isImageParams(value) {
56
+ return typeof value === "object" && value !== null && "prompt" in value && typeof value.prompt === "string";
57
+ }
58
+ //# sourceMappingURL=openai-images-params.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-images-params.js","sourceRoot":"","sources":["../../src/api/openai-images-params.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Uploadable } from \"openai\";\nimport type { ImageGenerateParamsNonStreaming } from \"openai/resources/images.js\";\nimport type { ImagesContext, ImagesModel, ImagesOptions } from \"../types.ts\";\nimport { sanitizeSurrogates } from \"../utils/sanitize-unicode.ts\";\n\nconst MAX_PROMPT_CHARS = 32_000;\n\nexport type OpenAIImageQuality = \"auto\" | \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"max\";\nexport type OpenAIImageSize = \"auto\" | \"1024x1024\" | \"1536x1024\" | \"1024x1536\" | `${number}x${number}`;\n\nexport interface OpenAIImagesOptions extends ImagesOptions {\n\tsize?: OpenAIImageSize;\n\tquality?: OpenAIImageQuality;\n\tn?: number;\n}\n\nexport type OpenAIImageParams = Omit<ImageGenerateParamsNonStreaming, \"size\" | \"quality\"> & {\n\tsize?: OpenAIImageSize;\n\tquality?: OpenAIImageQuality;\n\timage?: Uploadable[];\n};\n\nexport function parseOpenAIImageSize(size: string): { ok: true; size: string } | { ok: false; error: string } {\n\tif ([\"auto\", \"1024x1024\", \"1536x1024\", \"1024x1536\"].includes(size)) return { ok: true, size };\n\tconst match = /^\\d+x\\d+$/.exec(size);\n\tif (!match || match[0] !== size) {\n\t\treturn { ok: false, error: \"OpenAI image size must be auto or WIDTHxHEIGHT with integer dimensions\" };\n\t}\n\tconst [width, height] = size.split(\"x\").map(Number);\n\tif (width > 3840 || height > 3840) {\n\t\treturn { ok: false, error: \"OpenAI image size edges must be at most 3840 pixels\" };\n\t}\n\tif (width % 16 !== 0 || height % 16 !== 0) {\n\t\treturn { ok: false, error: \"OpenAI image size width and height must be divisible by 16\" };\n\t}\n\tif (width > height * 3 || height > width * 3) {\n\t\treturn { ok: false, error: \"OpenAI image size aspect ratio must be between 1:3 and 3:1 inclusive\" };\n\t}\n\tconst pixels = width * height;\n\tif (pixels < 655360 || pixels > 8294400) {\n\t\treturn { ok: false, error: \"OpenAI image size must contain between 655360 and 8294400 pixels inclusive\" };\n\t}\n\treturn { ok: true, size };\n}\n\nexport function buildParams(\n\tmodel: ImagesModel<\"openai-images\">,\n\tcontext: ImagesContext,\n\toptions?: OpenAIImagesOptions,\n): OpenAIImageParams {\n\tconst promptParts: string[] = [];\n\tfor (const item of context.input) {\n\t\tif (item.type !== \"text\") continue;\n\t\tconst text = sanitizeSurrogates(item.text);\n\t\tif (text.trim()) promptParts.push(text);\n\t}\n\tconst prompt = promptParts.join(\"\\n\\n\");\n\tif (!prompt.trim()) throw new Error(\"Image generation requires a non-empty text prompt\");\n\tif (prompt.length > MAX_PROMPT_CHARS) {\n\t\tthrow new Error(`Image generation prompt exceeds ${MAX_PROMPT_CHARS} characters`);\n\t}\n\tconst size = options?.size ?? \"auto\";\n\tconst parsedSize = parseOpenAIImageSize(size);\n\tif (!parsedSize.ok) throw new Error(parsedSize.error);\n\treturn {\n\t\tmodel: model.id,\n\t\tprompt,\n\t\tsize,\n\t\tquality: options?.quality ?? \"auto\",\n\t\tn: options?.n ?? 1,\n\t\toutput_format: \"png\",\n\t\tstream: false,\n\t};\n}\n\nexport function isImageParams(value: unknown): value is OpenAIImageParams {\n\treturn typeof value === \"object\" && value !== null && \"prompt\" in value && typeof value.prompt === \"string\";\n}\n"]}
@@ -1,8 +1,5 @@
1
- import type { ImagesFunction, ImagesOptions } from "../types.ts";
2
- export interface OpenAIImagesOptions extends ImagesOptions {
3
- size?: "auto" | "1024x1024" | "1024x1536" | "1536x1024";
4
- quality?: "auto" | "low" | "medium" | "high";
5
- n?: number;
6
- }
1
+ import type { ImagesFunction } from "../types.ts";
2
+ import { type OpenAIImagesOptions } from "./openai-images-params.ts";
3
+ export { type OpenAIImageQuality, type OpenAIImageSize, type OpenAIImagesOptions, parseOpenAIImageSize, } from "./openai-images-params.ts";
7
4
  export declare const generateImages: ImagesFunction<"openai-images", OpenAIImagesOptions>;
8
5
  //# sourceMappingURL=openai-images.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"openai-images.d.ts","sourceRoot":"","sources":["../../src/api/openai-images.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAIX,cAAc,EAEd,aAAa,EAGb,MAAM,aAAa,CAAC;AAgBrB,MAAM,WAAW,mBAAoB,SAAQ,aAAa;IACzD,IAAI,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,CAAC;IACxD,OAAO,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC7C,CAAC,CAAC,EAAE,MAAM,CAAC;CACX;AAED,eAAO,MAAM,cAAc,EAAE,cAAc,CAAC,eAAe,EAAE,mBAAmB,CA+D/E,CAAC"}
1
+ {"version":3,"file":"openai-images.d.ts","sourceRoot":"","sources":["../../src/api/openai-images.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAIX,cAAc,EAId,MAAM,aAAa,CAAC;AAMrB,OAAO,EAA8B,KAAK,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAEjG,OAAO,EACN,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,oBAAoB,GACpB,MAAM,2BAA2B,CAAC;AAUnC,eAAO,MAAM,cAAc,EAAE,cAAc,CAAC,eAAe,EAAE,mBAAmB,CA0E/E,CAAC"}
@@ -2,9 +2,10 @@ import OpenAI from "openai";
2
2
  import { formatProviderError, normalizeProviderError } from "../utils/error-body.js";
3
3
  import { headersToRecord } from "../utils/headers.js";
4
4
  import { retryProviderRequest } from "../utils/provider-retry.js";
5
- import { sanitizeSurrogates } from "../utils/sanitize-unicode.js";
6
5
  import { resolveOpenAIClientAuth } from "./openai-client-auth.js";
7
- const MAX_PROMPT_CHARS = 32_000;
6
+ import { buildEditParams } from "./openai-images-edit.js";
7
+ import { buildParams, isImageParams } from "./openai-images-params.js";
8
+ export { parseOpenAIImageSize, } from "./openai-images-params.js";
8
9
  const MAX_IMAGE_BYTES = 24 * 1024 * 1024;
9
10
  const ENDPOINT_SUFFIXES = ["/chat/completions", "/responses", "/models"];
10
11
  const PNG_MAGIC = [0x89, 0x50, 0x4e, 0x47];
@@ -21,9 +22,13 @@ export const generateImages = async (model, context, options) => {
21
22
  };
22
23
  try {
23
24
  let params = buildParams(model, context, options);
25
+ const images = context.input.filter((item) => item.type === "image");
26
+ const method = images.length > 0 ? "edit" : "generate";
27
+ if (method === "edit")
28
+ params = await buildEditParams(params, images);
24
29
  const nextParams = await options?.onPayload?.(params, model);
25
30
  if (nextParams !== undefined) {
26
- if (!isGenerateParams(nextParams))
31
+ if (!isImageParams(nextParams))
27
32
  throw new Error("onPayload returned an invalid image generation payload");
28
33
  params = nextParams;
29
34
  }
@@ -41,7 +46,13 @@ export const generateImages = async (model, context, options) => {
41
46
  ...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),
42
47
  maxRetries: 0,
43
48
  };
44
- const { data: response, response: rawResponse } = await retryProviderRequest(() => client.images.generate(params, requestOptions).withResponse(), {
49
+ const { data: response, response: rawResponse } = await retryProviderRequest(() => {
50
+ // openai SDK pinned at 6.26.0 predates gpt-image-2.5 quality tiers
51
+ const sdkParams = params;
52
+ return (method === "edit"
53
+ ? client.images.edit(sdkParams, requestOptions)
54
+ : client.images.generate(sdkParams, requestOptions)).withResponse();
55
+ }, {
45
56
  maxRetries: options?.maxRetries,
46
57
  maxRetryDelayMs: options?.maxRetryDelayMs,
47
58
  signal: options?.signal,
@@ -66,35 +77,6 @@ export const generateImages = async (model, context, options) => {
66
77
  return output;
67
78
  }
68
79
  };
69
- function buildParams(model, context, options) {
70
- const promptParts = [];
71
- for (const item of context.input) {
72
- if (item.type === "image") {
73
- throw new Error("generations does not accept image input; use the images edit endpoint");
74
- }
75
- const text = sanitizeSurrogates(item.text);
76
- if (text.trim())
77
- promptParts.push(text);
78
- }
79
- const prompt = promptParts.join("\n\n");
80
- if (!prompt.trim())
81
- throw new Error("Image generation requires a non-empty text prompt");
82
- if (prompt.length > MAX_PROMPT_CHARS) {
83
- throw new Error(`Image generation prompt exceeds ${MAX_PROMPT_CHARS} characters`);
84
- }
85
- return {
86
- model: model.id,
87
- prompt,
88
- size: options?.size ?? "auto",
89
- quality: options?.quality ?? "auto",
90
- n: options?.n ?? 1,
91
- output_format: "png",
92
- stream: false,
93
- };
94
- }
95
- function isGenerateParams(value) {
96
- return typeof value === "object" && value !== null && "prompt" in value && typeof value.prompt === "string";
97
- }
98
80
  function normalizeBaseUrl(baseUrl) {
99
81
  let url;
100
82
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"openai-images.js","sourceRoot":"","sources":["../../src/api/openai-images.ts"],"names":[],"mappings":"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","sourcesContent":["import OpenAI from \"openai\";\nimport type { Image, ImageGenerateParamsNonStreaming } from \"openai/resources/images.js\";\nimport type {\n\tAssistantImages,\n\tImageContent,\n\tImagesContext,\n\tImagesFunction,\n\tImagesModel,\n\tImagesOptions,\n\tProviderHeaders,\n\tTextContent,\n} from \"../types.ts\";\nimport { formatProviderError, normalizeProviderError } from \"../utils/error-body.ts\";\nimport { headersToRecord } from \"../utils/headers.ts\";\nimport { retryProviderRequest } from \"../utils/provider-retry.ts\";\nimport { sanitizeSurrogates } from \"../utils/sanitize-unicode.ts\";\nimport { resolveOpenAIClientAuth } from \"./openai-client-auth.ts\";\n\nconst MAX_PROMPT_CHARS = 32_000;\nconst MAX_IMAGE_BYTES = 24 * 1024 * 1024;\nconst ENDPOINT_SUFFIXES = [\"/chat/completions\", \"/responses\", \"/models\"] as const;\nconst PNG_MAGIC = [0x89, 0x50, 0x4e, 0x47] as const;\nconst JPEG_MAGIC = [0xff, 0xd8, 0xff] as const;\nconst WEBP_MAGIC = [0x52, 0x49, 0x46, 0x46, 0x57, 0x45, 0x42, 0x50] as const;\n\ntype SupportedImageMime = \"image/png\" | \"image/jpeg\" | \"image/webp\";\n\nexport interface OpenAIImagesOptions extends ImagesOptions {\n\tsize?: \"auto\" | \"1024x1024\" | \"1024x1536\" | \"1536x1024\";\n\tquality?: \"auto\" | \"low\" | \"medium\" | \"high\";\n\tn?: number;\n}\n\nexport const generateImages: ImagesFunction<\"openai-images\", OpenAIImagesOptions> = async (\n\tmodel: ImagesModel<\"openai-images\">,\n\tcontext: ImagesContext,\n\toptions?: OpenAIImagesOptions,\n) => {\n\tconst output: AssistantImages = {\n\t\tapi: model.api,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\toutput: [],\n\t\tstopReason: \"stop\",\n\t\ttimestamp: Date.now(),\n\t};\n\n\ttry {\n\t\tlet params = buildParams(model, context, options);\n\t\tconst nextParams = await options?.onPayload?.(params, model);\n\t\tif (nextParams !== undefined) {\n\t\t\tif (!isGenerateParams(nextParams)) throw new Error(\"onPayload returned an invalid image generation payload\");\n\t\t\tparams = nextParams;\n\t\t}\n\n\t\tconst headers: ProviderHeaders = { ...model.headers, ...options?.headers };\n\t\tconst auth = resolveOpenAIClientAuth(model.provider, options?.apiKey, headers);\n\t\tconst client = new OpenAI({\n\t\t\tapiKey: auth.apiKey,\n\t\t\tbaseURL: normalizeBaseUrl(model.baseUrl),\n\t\t\tdangerouslyAllowBrowser: true,\n\t\t\tfetch: options?.fetch,\n\t\t\tdefaultHeaders: auth.headers,\n\t\t});\n\t\tconst requestOptions = {\n\t\t\t...(options?.signal ? { signal: options.signal } : {}),\n\t\t\t...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),\n\t\t\tmaxRetries: 0,\n\t\t};\n\t\tconst { data: response, response: rawResponse } = await retryProviderRequest(\n\t\t\t() => client.images.generate(params, requestOptions).withResponse(),\n\t\t\t{\n\t\t\t\tmaxRetries: options?.maxRetries,\n\t\t\t\tmaxRetryDelayMs: options?.maxRetryDelayMs,\n\t\t\t\tsignal: options?.signal,\n\t\t\t},\n\t\t);\n\t\tawait options?.onResponse?.({ status: rawResponse.status, headers: headersToRecord(rawResponse.headers) }, model);\n\n\t\tif (response.usage) output.usage = parseUsage(response.usage, model);\n\t\tif (!response.data || response.data.length === 0)\n\t\t\tthrow new Error(\"OpenAI images response contained no image data\");\n\n\t\tfor (const datum of response.data) {\n\t\t\tconst image = await resolveImage(datum, options);\n\t\t\tif (datum.revised_prompt?.trim()) {\n\t\t\t\toutput.output.push({ type: \"text\", text: datum.revised_prompt } satisfies TextContent);\n\t\t\t}\n\t\t\toutput.output.push(image);\n\t\t}\n\t\treturn output;\n\t} catch (error) {\n\t\toutput.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n\t\toutput.errorMessage = formatProviderError(normalizeProviderError(error));\n\t\treturn output;\n\t}\n};\n\nfunction buildParams(\n\tmodel: ImagesModel<\"openai-images\">,\n\tcontext: ImagesContext,\n\toptions?: OpenAIImagesOptions,\n): ImageGenerateParamsNonStreaming {\n\tconst promptParts: string[] = [];\n\tfor (const item of context.input) {\n\t\tif (item.type === \"image\") {\n\t\t\tthrow new Error(\"generations does not accept image input; use the images edit endpoint\");\n\t\t}\n\t\tconst text = sanitizeSurrogates(item.text);\n\t\tif (text.trim()) promptParts.push(text);\n\t}\n\tconst prompt = promptParts.join(\"\\n\\n\");\n\tif (!prompt.trim()) throw new Error(\"Image generation requires a non-empty text prompt\");\n\tif (prompt.length > MAX_PROMPT_CHARS) {\n\t\tthrow new Error(`Image generation prompt exceeds ${MAX_PROMPT_CHARS} characters`);\n\t}\n\treturn {\n\t\tmodel: model.id,\n\t\tprompt,\n\t\tsize: options?.size ?? \"auto\",\n\t\tquality: options?.quality ?? \"auto\",\n\t\tn: options?.n ?? 1,\n\t\toutput_format: \"png\",\n\t\tstream: false,\n\t};\n}\n\nfunction isGenerateParams(value: unknown): value is ImageGenerateParamsNonStreaming {\n\treturn typeof value === \"object\" && value !== null && \"prompt\" in value && typeof value.prompt === \"string\";\n}\n\nfunction normalizeBaseUrl(baseUrl: string): string {\n\tlet url: URL;\n\ttry {\n\t\turl = new URL(baseUrl);\n\t} catch {\n\t\tthrow new Error(`Invalid OpenAI images base URL: ${baseUrl}`);\n\t}\n\tif (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n\t\tthrow new Error(\"OpenAI images base URL must use HTTP or HTTPS\");\n\t}\n\tif (url.search || url.hash) throw new Error(\"OpenAI images base URL must not include a query or fragment\");\n\tconst pathname = url.pathname.replace(/\\/+$/, \"\");\n\tconst normalizedPathname = pathname.toLowerCase();\n\tif (normalizedPathname.includes(\"/images\")) {\n\t\tthrow new Error(\"OpenAI images base URL must not include an images endpoint\");\n\t}\n\tif (ENDPOINT_SUFFIXES.some((suffix) => normalizedPathname.endsWith(suffix))) {\n\t\tthrow new Error(\"OpenAI images base URL must not include a known API endpoint\");\n\t}\n\turl.pathname = pathname.endsWith(\"/v1\") ? pathname : `${pathname}/v1`;\n\treturn url.toString();\n}\n\nasync function resolveImage(datum: Image, options?: OpenAIImagesOptions): Promise<ImageContent> {\n\tconst b64 = datum.b64_json?.trim();\n\tif (b64) return { type: \"image\", mimeType: \"image/png\", data: b64 };\n\tconst url = datum.url?.trim();\n\tif (!url) throw new Error(\"OpenAI images response datum contained no image data\");\n\tif (url.startsWith(\"data:\")) return parseDataUrl(url);\n\treturn hydrateImageUrl(url, options);\n}\n\nfunction parseDataUrl(url: string): ImageContent {\n\tconst match = /^data:([^;,]+);base64,(.+)$/i.exec(url);\n\tif (!match?.[1] || !match[2]) throw new Error(\"OpenAI images response contained an invalid data URL\");\n\tconst mimeType = supportedMime(match[1]);\n\tif (!mimeType) throw new Error(`OpenAI images response used unsupported MIME type: ${match[1]}`);\n\treturn { type: \"image\", mimeType, data: match[2] };\n}\n\nasync function hydrateImageUrl(url: string, options?: OpenAIImagesOptions): Promise<ImageContent> {\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(url);\n\t} catch {\n\t\tthrow new Error(\"OpenAI images response URL must be absolute\");\n\t}\n\tif (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n\t\tthrow new Error(\"OpenAI images response URL must use HTTP or HTTPS\");\n\t}\n\tconst response = await (options?.fetch ?? globalThis.fetch)(url, options?.signal ? { signal: options.signal } : {});\n\tif (!response.ok) throw new Error(`OpenAI image hydration failed with HTTP ${response.status}`);\n\tconst declaredLength = response.headers.get(\"content-length\");\n\tif (declaredLength && Number(declaredLength) > MAX_IMAGE_BYTES) throw oversizedImageError();\n\tconst bytes = new Uint8Array(await response.arrayBuffer());\n\tif (bytes.byteLength === 0) throw new Error(\"OpenAI image hydration returned an empty body\");\n\tif (bytes.byteLength > MAX_IMAGE_BYTES) throw oversizedImageError();\n\tconst declaredMime = supportedMime(response.headers.get(\"content-type\")?.split(\";\", 1)[0]);\n\tconst detectedMime = detectMime(bytes);\n\tif (declaredMime && detectedMime && declaredMime !== detectedMime) {\n\t\tthrow new Error(`OpenAI image MIME mismatch: declared ${declaredMime}, detected ${detectedMime}`);\n\t}\n\tconst mimeType = detectedMime ?? declaredMime;\n\tif (!mimeType) throw new Error(\"OpenAI image hydration returned unsupported image content\");\n\treturn { type: \"image\", mimeType, data: bytesToBase64(bytes) };\n}\n\nfunction supportedMime(value: string | undefined): SupportedImageMime | undefined {\n\tconst normalized = value?.trim().toLowerCase();\n\tif (normalized === \"image/png\" || normalized === \"image/jpeg\" || normalized === \"image/webp\") return normalized;\n\treturn undefined;\n}\n\nfunction detectMime(bytes: Uint8Array): SupportedImageMime | undefined {\n\tif (hasMagic(bytes, PNG_MAGIC)) return \"image/png\";\n\tif (hasMagic(bytes, JPEG_MAGIC)) return \"image/jpeg\";\n\tif (hasMagic(bytes, WEBP_MAGIC.slice(0, 4)) && hasMagic(bytes, WEBP_MAGIC.slice(4), 8)) return \"image/webp\";\n\treturn undefined;\n}\n\nfunction hasMagic(bytes: Uint8Array, magic: readonly number[], offset = 0): boolean {\n\treturn magic.every((value, index) => bytes[offset + index] === value);\n}\n\nfunction bytesToBase64(bytes: Uint8Array): string {\n\tlet binary = \"\";\n\tfor (let offset = 0; offset < bytes.length; offset += 0x8000) {\n\t\tbinary += String.fromCharCode(...bytes.subarray(offset, offset + 0x8000));\n\t}\n\treturn btoa(binary);\n}\n\nfunction oversizedImageError(): Error {\n\treturn new Error(\"OpenAI image hydration exceeded the 24 MiB limit\");\n}\n\nfunction parseUsage(\n\trawUsage: { input_tokens?: number; output_tokens?: number; total_tokens?: number },\n\tmodel: ImagesModel<\"openai-images\">,\n) {\n\tconst input = rawUsage.input_tokens ?? 0;\n\tconst output = rawUsage.output_tokens ?? 0;\n\tconst usage = {\n\t\tinput,\n\t\toutput,\n\t\tcacheRead: 0,\n\t\tcacheWrite: 0,\n\t\ttotalTokens: rawUsage.total_tokens ?? input + output,\n\t\tcost: {\n\t\t\tinput: (model.cost.input / 1_000_000) * input,\n\t\t\toutput: (model.cost.output / 1_000_000) * output,\n\t\t\tcacheRead: 0,\n\t\t\tcacheWrite: 0,\n\t\t\ttotal: 0,\n\t\t},\n\t};\n\tusage.cost.total = usage.cost.input + usage.cost.output;\n\treturn usage;\n}\n"]}
1
+ {"version":3,"file":"openai-images.js","sourceRoot":"","sources":["../../src/api/openai-images.ts"],"names":[],"mappings":"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","sourcesContent":["import OpenAI from \"openai\";\nimport type { Image, ImageEditParamsNonStreaming, ImageGenerateParamsNonStreaming } from \"openai/resources/images.js\";\nimport type {\n\tAssistantImages,\n\tImageContent,\n\tImagesContext,\n\tImagesFunction,\n\tImagesModel,\n\tProviderHeaders,\n\tTextContent,\n} from \"../types.ts\";\nimport { formatProviderError, normalizeProviderError } from \"../utils/error-body.ts\";\nimport { headersToRecord } from \"../utils/headers.ts\";\nimport { retryProviderRequest } from \"../utils/provider-retry.ts\";\nimport { resolveOpenAIClientAuth } from \"./openai-client-auth.ts\";\nimport { buildEditParams } from \"./openai-images-edit.ts\";\nimport { buildParams, isImageParams, type OpenAIImagesOptions } from \"./openai-images-params.ts\";\n\nexport {\n\ttype OpenAIImageQuality,\n\ttype OpenAIImageSize,\n\ttype OpenAIImagesOptions,\n\tparseOpenAIImageSize,\n} from \"./openai-images-params.ts\";\n\nconst MAX_IMAGE_BYTES = 24 * 1024 * 1024;\nconst ENDPOINT_SUFFIXES = [\"/chat/completions\", \"/responses\", \"/models\"] as const;\nconst PNG_MAGIC = [0x89, 0x50, 0x4e, 0x47] as const;\nconst JPEG_MAGIC = [0xff, 0xd8, 0xff] as const;\nconst WEBP_MAGIC = [0x52, 0x49, 0x46, 0x46, 0x57, 0x45, 0x42, 0x50] as const;\n\ntype SupportedImageMime = \"image/png\" | \"image/jpeg\" | \"image/webp\";\n\nexport const generateImages: ImagesFunction<\"openai-images\", OpenAIImagesOptions> = async (\n\tmodel: ImagesModel<\"openai-images\">,\n\tcontext: ImagesContext,\n\toptions?: OpenAIImagesOptions,\n) => {\n\tconst output: AssistantImages = {\n\t\tapi: model.api,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\toutput: [],\n\t\tstopReason: \"stop\",\n\t\ttimestamp: Date.now(),\n\t};\n\n\ttry {\n\t\tlet params = buildParams(model, context, options);\n\t\tconst images = context.input.filter((item): item is ImageContent => item.type === \"image\");\n\t\tconst method = images.length > 0 ? \"edit\" : \"generate\";\n\t\tif (method === \"edit\") params = await buildEditParams(params, images);\n\t\tconst nextParams = await options?.onPayload?.(params, model);\n\t\tif (nextParams !== undefined) {\n\t\t\tif (!isImageParams(nextParams)) throw new Error(\"onPayload returned an invalid image generation payload\");\n\t\t\tparams = nextParams;\n\t\t}\n\n\t\tconst headers: ProviderHeaders = { ...model.headers, ...options?.headers };\n\t\tconst auth = resolveOpenAIClientAuth(model.provider, options?.apiKey, headers);\n\t\tconst client = new OpenAI({\n\t\t\tapiKey: auth.apiKey,\n\t\t\tbaseURL: normalizeBaseUrl(model.baseUrl),\n\t\t\tdangerouslyAllowBrowser: true,\n\t\t\tfetch: options?.fetch,\n\t\t\tdefaultHeaders: auth.headers,\n\t\t});\n\t\tconst requestOptions = {\n\t\t\t...(options?.signal ? { signal: options.signal } : {}),\n\t\t\t...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),\n\t\t\tmaxRetries: 0,\n\t\t};\n\t\tconst { data: response, response: rawResponse } = await retryProviderRequest(\n\t\t\t() => {\n\t\t\t\t// openai SDK pinned at 6.26.0 predates gpt-image-2.5 quality tiers\n\t\t\t\tconst sdkParams = params as ImageGenerateParamsNonStreaming & ImageEditParamsNonStreaming;\n\t\t\t\treturn (\n\t\t\t\t\tmethod === \"edit\"\n\t\t\t\t\t\t? client.images.edit(sdkParams, requestOptions)\n\t\t\t\t\t\t: client.images.generate(sdkParams, requestOptions)\n\t\t\t\t).withResponse();\n\t\t\t},\n\t\t\t{\n\t\t\t\tmaxRetries: options?.maxRetries,\n\t\t\t\tmaxRetryDelayMs: options?.maxRetryDelayMs,\n\t\t\t\tsignal: options?.signal,\n\t\t\t},\n\t\t);\n\t\tawait options?.onResponse?.({ status: rawResponse.status, headers: headersToRecord(rawResponse.headers) }, model);\n\n\t\tif (response.usage) output.usage = parseUsage(response.usage, model);\n\t\tif (!response.data || response.data.length === 0)\n\t\t\tthrow new Error(\"OpenAI images response contained no image data\");\n\n\t\tfor (const datum of response.data) {\n\t\t\tconst image = await resolveImage(datum, options);\n\t\t\tif (datum.revised_prompt?.trim()) {\n\t\t\t\toutput.output.push({ type: \"text\", text: datum.revised_prompt } satisfies TextContent);\n\t\t\t}\n\t\t\toutput.output.push(image);\n\t\t}\n\t\treturn output;\n\t} catch (error) {\n\t\toutput.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n\t\toutput.errorMessage = formatProviderError(normalizeProviderError(error));\n\t\treturn output;\n\t}\n};\n\nfunction normalizeBaseUrl(baseUrl: string): string {\n\tlet url: URL;\n\ttry {\n\t\turl = new URL(baseUrl);\n\t} catch {\n\t\tthrow new Error(`Invalid OpenAI images base URL: ${baseUrl}`);\n\t}\n\tif (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n\t\tthrow new Error(\"OpenAI images base URL must use HTTP or HTTPS\");\n\t}\n\tif (url.search || url.hash) throw new Error(\"OpenAI images base URL must not include a query or fragment\");\n\tconst pathname = url.pathname.replace(/\\/+$/, \"\");\n\tconst normalizedPathname = pathname.toLowerCase();\n\tif (normalizedPathname.includes(\"/images\")) {\n\t\tthrow new Error(\"OpenAI images base URL must not include an images endpoint\");\n\t}\n\tif (ENDPOINT_SUFFIXES.some((suffix) => normalizedPathname.endsWith(suffix))) {\n\t\tthrow new Error(\"OpenAI images base URL must not include a known API endpoint\");\n\t}\n\turl.pathname = pathname.endsWith(\"/v1\") ? pathname : `${pathname}/v1`;\n\treturn url.toString();\n}\n\nasync function resolveImage(datum: Image, options?: OpenAIImagesOptions): Promise<ImageContent> {\n\tconst b64 = datum.b64_json?.trim();\n\tif (b64) return { type: \"image\", mimeType: \"image/png\", data: b64 };\n\tconst url = datum.url?.trim();\n\tif (!url) throw new Error(\"OpenAI images response datum contained no image data\");\n\tif (url.startsWith(\"data:\")) return parseDataUrl(url);\n\treturn hydrateImageUrl(url, options);\n}\n\nfunction parseDataUrl(url: string): ImageContent {\n\tconst match = /^data:([^;,]+);base64,(.+)$/i.exec(url);\n\tif (!match?.[1] || !match[2]) throw new Error(\"OpenAI images response contained an invalid data URL\");\n\tconst mimeType = supportedMime(match[1]);\n\tif (!mimeType) throw new Error(`OpenAI images response used unsupported MIME type: ${match[1]}`);\n\treturn { type: \"image\", mimeType, data: match[2] };\n}\n\nasync function hydrateImageUrl(url: string, options?: OpenAIImagesOptions): Promise<ImageContent> {\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(url);\n\t} catch {\n\t\tthrow new Error(\"OpenAI images response URL must be absolute\");\n\t}\n\tif (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n\t\tthrow new Error(\"OpenAI images response URL must use HTTP or HTTPS\");\n\t}\n\tconst response = await (options?.fetch ?? globalThis.fetch)(url, options?.signal ? { signal: options.signal } : {});\n\tif (!response.ok) throw new Error(`OpenAI image hydration failed with HTTP ${response.status}`);\n\tconst declaredLength = response.headers.get(\"content-length\");\n\tif (declaredLength && Number(declaredLength) > MAX_IMAGE_BYTES) throw oversizedImageError();\n\tconst bytes = new Uint8Array(await response.arrayBuffer());\n\tif (bytes.byteLength === 0) throw new Error(\"OpenAI image hydration returned an empty body\");\n\tif (bytes.byteLength > MAX_IMAGE_BYTES) throw oversizedImageError();\n\tconst declaredMime = supportedMime(response.headers.get(\"content-type\")?.split(\";\", 1)[0]);\n\tconst detectedMime = detectMime(bytes);\n\tif (declaredMime && detectedMime && declaredMime !== detectedMime) {\n\t\tthrow new Error(`OpenAI image MIME mismatch: declared ${declaredMime}, detected ${detectedMime}`);\n\t}\n\tconst mimeType = detectedMime ?? declaredMime;\n\tif (!mimeType) throw new Error(\"OpenAI image hydration returned unsupported image content\");\n\treturn { type: \"image\", mimeType, data: bytesToBase64(bytes) };\n}\n\nfunction supportedMime(value: string | undefined): SupportedImageMime | undefined {\n\tconst normalized = value?.trim().toLowerCase();\n\tif (normalized === \"image/png\" || normalized === \"image/jpeg\" || normalized === \"image/webp\") return normalized;\n\treturn undefined;\n}\n\nfunction detectMime(bytes: Uint8Array): SupportedImageMime | undefined {\n\tif (hasMagic(bytes, PNG_MAGIC)) return \"image/png\";\n\tif (hasMagic(bytes, JPEG_MAGIC)) return \"image/jpeg\";\n\tif (hasMagic(bytes, WEBP_MAGIC.slice(0, 4)) && hasMagic(bytes, WEBP_MAGIC.slice(4), 8)) return \"image/webp\";\n\treturn undefined;\n}\n\nfunction hasMagic(bytes: Uint8Array, magic: readonly number[], offset = 0): boolean {\n\treturn magic.every((value, index) => bytes[offset + index] === value);\n}\n\nfunction bytesToBase64(bytes: Uint8Array): string {\n\tlet binary = \"\";\n\tfor (let offset = 0; offset < bytes.length; offset += 0x8000) {\n\t\tbinary += String.fromCharCode(...bytes.subarray(offset, offset + 0x8000));\n\t}\n\treturn btoa(binary);\n}\n\nfunction oversizedImageError(): Error {\n\treturn new Error(\"OpenAI image hydration exceeded the 24 MiB limit\");\n}\n\nfunction parseUsage(\n\trawUsage: { input_tokens?: number; output_tokens?: number; total_tokens?: number },\n\tmodel: ImagesModel<\"openai-images\">,\n) {\n\tconst input = rawUsage.input_tokens ?? 0;\n\tconst output = rawUsage.output_tokens ?? 0;\n\tconst usage = {\n\t\tinput,\n\t\toutput,\n\t\tcacheRead: 0,\n\t\tcacheWrite: 0,\n\t\ttotalTokens: rawUsage.total_tokens ?? input + output,\n\t\tcost: {\n\t\t\tinput: (model.cost.input / 1_000_000) * input,\n\t\t\toutput: (model.cost.output / 1_000_000) * output,\n\t\t\tcacheRead: 0,\n\t\t\tcacheWrite: 0,\n\t\t\ttotal: 0,\n\t\t},\n\t};\n\tusage.cost.total = usage.cost.input + usage.cost.output;\n\treturn usage;\n}\n"]}
@@ -1,12 +1,42 @@
1
1
  export declare const IMAGE_MODELS: {
2
2
  readonly openai: {
3
+ readonly "gpt-image-2.5-sunburst": {
4
+ id: string;
5
+ name: string;
6
+ api: "openai-images";
7
+ provider: string;
8
+ baseUrl: string;
9
+ input: ("text" | "image")[];
10
+ output: "image"[];
11
+ cost: {
12
+ input: number;
13
+ output: number;
14
+ cacheRead: number;
15
+ cacheWrite: number;
16
+ };
17
+ };
18
+ readonly "gpt-image-2.5-flare": {
19
+ id: string;
20
+ name: string;
21
+ api: "openai-images";
22
+ provider: string;
23
+ baseUrl: string;
24
+ input: ("text" | "image")[];
25
+ output: "image"[];
26
+ cost: {
27
+ input: number;
28
+ output: number;
29
+ cacheRead: number;
30
+ cacheWrite: number;
31
+ };
32
+ };
3
33
  readonly "gpt-image-2": {
4
34
  id: string;
5
35
  name: string;
6
36
  api: "openai-images";
7
37
  provider: string;
8
38
  baseUrl: string;
9
- input: "text"[];
39
+ input: ("text" | "image")[];
10
40
  output: "image"[];
11
41
  cost: {
12
42
  input: number;
@@ -437,6 +467,36 @@ export declare const IMAGE_MODELS: {
437
467
  cacheWrite: number;
438
468
  };
439
469
  };
470
+ readonly "openai/gpt-image-2.5-flare": {
471
+ id: string;
472
+ name: string;
473
+ api: "openrouter-images";
474
+ provider: string;
475
+ baseUrl: string;
476
+ input: ("text" | "image")[];
477
+ output: "image"[];
478
+ cost: {
479
+ input: number;
480
+ output: number;
481
+ cacheRead: number;
482
+ cacheWrite: number;
483
+ };
484
+ };
485
+ readonly "openai/gpt-image-2.5-sunburst": {
486
+ id: string;
487
+ name: string;
488
+ api: "openrouter-images";
489
+ provider: string;
490
+ baseUrl: string;
491
+ input: ("text" | "image")[];
492
+ output: "image"[];
493
+ cost: {
494
+ input: number;
495
+ output: number;
496
+ cacheRead: number;
497
+ cacheWrite: number;
498
+ };
499
+ };
440
500
  readonly "openrouter/auto": {
441
501
  id: string;
442
502
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"image-models.generated.d.ts","sourceRoot":"","sources":["../src/image-models.generated.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+yBkD,CAAC"}
1
+ {"version":3,"file":"image-models.generated.d.ts","sourceRoot":"","sources":["../src/image-models.generated.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA22BkD,CAAC"}
@@ -2,13 +2,43 @@
2
2
  // Do not edit manually - run 'npm run generate-image-models' to update
3
3
  export const IMAGE_MODELS = {
4
4
  openai: {
5
+ "gpt-image-2.5-sunburst": {
6
+ id: "gpt-image-2.5-sunburst",
7
+ name: "GPT Image 2.5 Sunburst",
8
+ api: "openai-images",
9
+ provider: "openai",
10
+ baseUrl: "https://api.openai.com/v1",
11
+ input: ["text", "image"],
12
+ output: ["image"],
13
+ cost: {
14
+ input: 5,
15
+ output: 30,
16
+ cacheRead: 1.25,
17
+ cacheWrite: 0,
18
+ },
19
+ },
20
+ "gpt-image-2.5-flare": {
21
+ id: "gpt-image-2.5-flare",
22
+ name: "GPT Image 2.5 Flare",
23
+ api: "openai-images",
24
+ provider: "openai",
25
+ baseUrl: "https://api.openai.com/v1",
26
+ input: ["text", "image"],
27
+ output: ["image"],
28
+ cost: {
29
+ input: 5,
30
+ output: 30,
31
+ cacheRead: 1.25,
32
+ cacheWrite: 0,
33
+ },
34
+ },
5
35
  "gpt-image-2": {
6
36
  id: "gpt-image-2",
7
37
  name: "GPT Image 2",
8
38
  api: "openai-images",
9
39
  provider: "openai",
10
40
  baseUrl: "https://api.openai.com/v1",
11
- input: ["text"],
41
+ input: ["text", "image"],
12
42
  output: ["image"],
13
43
  cost: {
14
44
  input: 5,
@@ -439,6 +469,36 @@ export const IMAGE_MODELS = {
439
469
  cacheWrite: 0,
440
470
  },
441
471
  },
472
+ "openai/gpt-image-2.5-flare": {
473
+ id: "openai/gpt-image-2.5-flare",
474
+ name: "OpenAI: GPT Image 2.5 Flare",
475
+ api: "openrouter-images",
476
+ provider: "openrouter",
477
+ baseUrl: "https://openrouter.ai/api/v1",
478
+ input: ["text", "image"],
479
+ output: ["image"],
480
+ cost: {
481
+ input: 8,
482
+ output: 8,
483
+ cacheRead: 2,
484
+ cacheWrite: 0,
485
+ },
486
+ },
487
+ "openai/gpt-image-2.5-sunburst": {
488
+ id: "openai/gpt-image-2.5-sunburst",
489
+ name: "OpenAI: GPT Image 2.5 Sunburst",
490
+ api: "openrouter-images",
491
+ provider: "openrouter",
492
+ baseUrl: "https://openrouter.ai/api/v1",
493
+ input: ["text", "image"],
494
+ output: ["image"],
495
+ cost: {
496
+ input: 8,
497
+ output: 8,
498
+ cacheRead: 2,
499
+ cacheWrite: 0,
500
+ },
501
+ },
442
502
  "openrouter/auto": {
443
503
  id: "openrouter/auto",
444
504
  name: "Auto Router",