@code-yeongyu/senpi 2026.9.9-2 → 2026.9.9

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 (90) hide show
  1. package/CHANGELOG.md +1 -22
  2. package/dist/core/agent-session.d.ts +1 -8
  3. package/dist/core/agent-session.d.ts.map +1 -1
  4. package/dist/core/agent-session.js +0 -33
  5. package/dist/core/agent-session.js.map +1 -1
  6. package/dist/core/extensions/builtin/claude-sdk-oauth/session-stream.d.ts.map +1 -1
  7. package/dist/core/extensions/builtin/claude-sdk-oauth/session-stream.js +1 -4
  8. package/dist/core/extensions/builtin/claude-sdk-oauth/session-stream.js.map +1 -1
  9. package/dist/core/extensions/builtin/imagegen/skill/SKILL.md +4 -47
  10. package/dist/core/extensions/builtin/imagegen/tool.d.ts +19 -10
  11. package/dist/core/extensions/builtin/imagegen/tool.d.ts.map +1 -1
  12. package/dist/core/extensions/builtin/imagegen/tool.js +45 -21
  13. package/dist/core/extensions/builtin/imagegen/tool.js.map +1 -1
  14. package/dist/core/extensions/loader.d.ts +1 -2
  15. package/dist/core/extensions/loader.d.ts.map +1 -1
  16. package/dist/core/extensions/loader.js +8 -17
  17. package/dist/core/extensions/loader.js.map +1 -1
  18. package/dist/core/extensions/types.d.ts +0 -5
  19. package/dist/core/extensions/types.d.ts.map +1 -1
  20. package/dist/core/extensions/types.js.map +1 -1
  21. package/dist/core/resource-loader.d.ts +0 -2
  22. package/dist/core/resource-loader.d.ts.map +1 -1
  23. package/dist/core/resource-loader.js +7 -11
  24. package/dist/core/resource-loader.js.map +1 -1
  25. package/dist/core/sdk.d.ts.map +1 -1
  26. package/dist/core/sdk.js +1 -13
  27. package/dist/core/sdk.js.map +1 -1
  28. package/dist/core/tools/read.d.ts +1 -5
  29. package/dist/core/tools/read.d.ts.map +1 -1
  30. package/dist/core/tools/read.js +1 -21
  31. package/dist/core/tools/read.js.map +1 -1
  32. package/dist/index.d.ts +0 -1
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +0 -1
  35. package/dist/index.js.map +1 -1
  36. package/dist/main.d.ts.map +1 -1
  37. package/dist/main.js +0 -4
  38. package/dist/main.js.map +1 -1
  39. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  40. package/dist/modes/interactive/interactive-mode.js +0 -3
  41. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  42. package/docs/skills.md +1 -1
  43. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +0 -12
  44. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  45. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  46. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.d.ts +6 -3
  47. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.d.ts.map +1 -1
  48. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.js +33 -15
  49. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.js.map +1 -1
  50. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts +1 -31
  51. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts.map +1 -1
  52. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js +1 -31
  53. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js.map +1 -1
  54. package/node_modules/@earendil-works/pi-ai/dist/images.d.ts +0 -1
  55. package/node_modules/@earendil-works/pi-ai/dist/images.d.ts.map +1 -1
  56. package/node_modules/@earendil-works/pi-ai/dist/images.js +0 -1
  57. package/node_modules/@earendil-works/pi-ai/dist/images.js.map +1 -1
  58. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  59. package/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -1
  60. package/node_modules/@earendil-works/pi-ai/dist/providers/data/nvidia.json +1 -1
  61. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  62. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  63. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  64. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  65. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  66. package/package.json +7 -7
  67. package/dist/core/extensions/builtin/compaction/resume-admission.d.ts +0 -7
  68. package/dist/core/extensions/builtin/compaction/resume-admission.d.ts.map +0 -1
  69. package/dist/core/extensions/builtin/compaction/resume-admission.js +0 -7
  70. package/dist/core/extensions/builtin/compaction/resume-admission.js.map +0 -1
  71. package/dist/core/extensions/builtin/imagegen/params.d.ts +0 -36
  72. package/dist/core/extensions/builtin/imagegen/params.d.ts.map +0 -1
  73. package/dist/core/extensions/builtin/imagegen/params.js +0 -55
  74. package/dist/core/extensions/builtin/imagegen/params.js.map +0 -1
  75. package/dist/core/extensions/builtin/imagegen/reference-images.d.ts +0 -11
  76. package/dist/core/extensions/builtin/imagegen/reference-images.d.ts.map +0 -1
  77. package/dist/core/extensions/builtin/imagegen/reference-images.js +0 -55
  78. package/dist/core/extensions/builtin/imagegen/reference-images.js.map +0 -1
  79. package/dist/core/tools/read-classifiers.d.ts +0 -17
  80. package/dist/core/tools/read-classifiers.d.ts.map +0 -1
  81. package/dist/core/tools/read-classifiers.js +0 -26
  82. package/dist/core/tools/read-classifiers.js.map +0 -1
  83. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images-edit.d.ts +0 -4
  84. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images-edit.d.ts.map +0 -1
  85. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images-edit.js +0 -11
  86. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images-edit.js.map +0 -1
  87. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images-params.d.ts +0 -25
  88. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images-params.d.ts.map +0 -1
  89. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images-params.js +0 -58
  90. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images-params.js.map +0 -1
package/docs/skills.md CHANGED
@@ -270,7 +270,7 @@ cd /path/to/brave-search && bun install
270
270
 
271
271
  Senpi contributes built-in skills conditionally based on available credentials and capabilities.
272
272
 
273
- **gpt-image-gen** is contributed by the `imagegen` builtin extension when image-generation credentials exist (a stored OpenAI key, `OPENAI_API_KEY`, or a configured OpenAI-compatible gateway). It provides a prompt-crafting guide for GPT Image 2.5, covering detail-maxxing techniques, verbatim quoted render text, revised-prompt feedback loops, and routing guidance for the native server tool vs. the client `generate_image` tool. For `generate_image`, `model` selects `gpt-image-2.5-sunburst` (default, precise edits), `gpt-image-2.5-flare` (speed), or legacy `gpt-image-2`; `quality` accepts `auto`, `low`, `medium`, `high`, `xhigh`, or `max` (the last two require 2.5); `size` accepts `auto`, presets, or validated custom dimensions. `reference_image_paths` supplies 1-5 local PNG/JPEG/WEBP files for editing or references. The skill is absent from `<available_skills>` when no credentials are configured.
273
+ **gpt-image-gen** is contributed by the `imagegen` builtin extension when image-generation credentials exist (a stored OpenAI key, `OPENAI_API_KEY`, or a configured OpenAI-compatible gateway). It provides a prompt-crafting guide for `gpt-image-2`, covering detail-maxxing techniques, verbatim quoted render text, revised-prompt feedback loops, and routing guidance for the native server tool vs. the client `generate_image` tool. The skill is absent from `<available_skills>` when no credentials are configured.
274
274
 
275
275
  Skill visibility refreshes at startup and on `/reload`. Mid-session credential changes (login, environment variable updates) take effect on the tool and injector immediately but are reflected in the skill list only after the next reload.
276
276
 
@@ -12,18 +12,6 @@
12
12
 
13
13
  ### Removed
14
14
 
15
- ## [2026.9.9-2] - 2026-09-09
16
-
17
- ### Breaking Changes
18
-
19
- ### Added
20
-
21
- ### Changed
22
-
23
- ### Fixed
24
-
25
- ### Removed
26
-
27
15
  ## [2026.9.9] - 2026-09-09
28
16
 
29
17
  ### Breaking Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-yeongyu/senpi-codemode",
3
- "version": "2026.9.9-2",
3
+ "version": "2026.9.9",
4
4
  "private": true,
5
5
  "description": "Source-only senpi extension package for codemode evaluation tools",
6
6
  "type": "module",
@@ -31,14 +31,14 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "@babel/parser": "8.0.4",
34
- "@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.9.9-2",
34
+ "@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.9.9",
35
35
  "typebox": "1.3.18"
36
36
  },
37
37
  "peerDependencies": {
38
- "@code-yeongyu/senpi": "2026.9.9-2"
38
+ "@code-yeongyu/senpi": "2026.9.9"
39
39
  },
40
40
  "devDependencies": {
41
- "@code-yeongyu/senpi": "2026.9.9-2"
41
+ "@code-yeongyu/senpi": "2026.9.9"
42
42
  },
43
43
  "keywords": [
44
44
  "senpi",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@earendil-works/pi-agent-core",
3
- "version": "2026.9.9-2",
3
+ "version": "2026.9.9",
4
4
  "description": "General-purpose agent with transport abstraction, state management, and attachment support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -35,8 +35,8 @@
35
35
  "prepublishOnly": "npm run build"
36
36
  },
37
37
  "dependencies": {
38
- "@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.9.9-2",
39
- "@earendil-works/pi-telemetry": "npm:@code-yeongyu/senpi-telemetry@2026.9.9-2",
38
+ "@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.9.9",
39
+ "@earendil-works/pi-telemetry": "npm:@code-yeongyu/senpi-telemetry@2026.9.9",
40
40
  "diff": "9.0.0",
41
41
  "ignore": "7.0.6",
42
42
  "typebox": "1.3.18",
@@ -1,5 +1,8 @@
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";
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
+ }
4
7
  export declare const generateImages: ImagesFunction<"openai-images", OpenAIImagesOptions>;
5
8
  //# 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,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"}
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"}
@@ -2,10 +2,9 @@ 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";
5
6
  import { resolveOpenAIClientAuth } from "./openai-client-auth.js";
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";
7
+ const MAX_PROMPT_CHARS = 32_000;
9
8
  const MAX_IMAGE_BYTES = 24 * 1024 * 1024;
10
9
  const ENDPOINT_SUFFIXES = ["/chat/completions", "/responses", "/models"];
11
10
  const PNG_MAGIC = [0x89, 0x50, 0x4e, 0x47];
@@ -22,13 +21,9 @@ export const generateImages = async (model, context, options) => {
22
21
  };
23
22
  try {
24
23
  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);
29
24
  const nextParams = await options?.onPayload?.(params, model);
30
25
  if (nextParams !== undefined) {
31
- if (!isImageParams(nextParams))
26
+ if (!isGenerateParams(nextParams))
32
27
  throw new Error("onPayload returned an invalid image generation payload");
33
28
  params = nextParams;
34
29
  }
@@ -46,13 +41,7 @@ export const generateImages = async (model, context, options) => {
46
41
  ...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),
47
42
  maxRetries: 0,
48
43
  };
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
- }, {
44
+ const { data: response, response: rawResponse } = await retryProviderRequest(() => client.images.generate(params, requestOptions).withResponse(), {
56
45
  maxRetries: options?.maxRetries,
57
46
  maxRetryDelayMs: options?.maxRetryDelayMs,
58
47
  signal: options?.signal,
@@ -77,6 +66,35 @@ export const generateImages = async (model, context, options) => {
77
66
  return output;
78
67
  }
79
68
  };
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
+ }
80
98
  function normalizeBaseUrl(baseUrl) {
81
99
  let url;
82
100
  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, 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
+ {"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,42 +1,12 @@
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
- };
33
3
  readonly "gpt-image-2": {
34
4
  id: string;
35
5
  name: string;
36
6
  api: "openai-images";
37
7
  provider: string;
38
8
  baseUrl: string;
39
- input: ("text" | "image")[];
9
+ input: "text"[];
40
10
  output: "image"[];
41
11
  cost: {
42
12
  input: number;
@@ -1 +1 @@
1
- {"version":3,"file":"image-models.generated.d.ts","sourceRoot":"","sources":["../src/image-models.generated.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA22BkD,CAAC"}
1
+ {"version":3,"file":"image-models.generated.d.ts","sourceRoot":"","sources":["../src/image-models.generated.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA60BkD,CAAC"}
@@ -2,43 +2,13 @@
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
- },
35
5
  "gpt-image-2": {
36
6
  id: "gpt-image-2",
37
7
  name: "GPT Image 2",
38
8
  api: "openai-images",
39
9
  provider: "openai",
40
10
  baseUrl: "https://api.openai.com/v1",
41
- input: ["text", "image"],
11
+ input: ["text"],
42
12
  output: ["image"],
43
13
  cost: {
44
14
  input: 5,