@ljoukov/llm 7.0.12 → 7.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -15,6 +15,7 @@ import {
15
15
  } from "@google/genai";
16
16
  import { zodToJsonSchema } from "@alcyone-labs/zod-to-json-schema";
17
17
  import { z as z3 } from "zod";
18
+ import { toFile } from "openai";
18
19
 
19
20
  // src/utils/asyncQueue.ts
20
21
  function createAsyncQueue() {
@@ -216,6 +217,81 @@ var OPENAI_MODEL_IDS = [
216
217
  function isOpenAiModelId(value) {
217
218
  return OPENAI_MODEL_IDS.includes(value);
218
219
  }
220
+ var OPENAI_IMAGE_MODEL_IDS = ["gpt-image-2"];
221
+ function isOpenAiImageModelId(value) {
222
+ return OPENAI_IMAGE_MODEL_IDS.includes(value);
223
+ }
224
+ var OPENAI_GPT_IMAGE_2_POPULAR_RESOLUTIONS = [
225
+ "1024x1024",
226
+ "1536x1024",
227
+ "1024x1536",
228
+ "2048x2048",
229
+ "2048x1152",
230
+ "3840x2160",
231
+ "2160x3840"
232
+ ];
233
+ var OPENAI_GPT_IMAGE_2_AUTO_RESOLUTION = "auto";
234
+ var OPENAI_GPT_IMAGE_2_RESOLUTIONS = [
235
+ ...OPENAI_GPT_IMAGE_2_POPULAR_RESOLUTIONS,
236
+ OPENAI_GPT_IMAGE_2_AUTO_RESOLUTION
237
+ ];
238
+ var OPENAI_GPT_IMAGE_2_SIZE_CONSTRAINTS = {
239
+ maxEdgePixels: 3840,
240
+ edgeMultiplePixels: 16,
241
+ maxLongToShortEdgeRatio: 3,
242
+ minTotalPixels: 655360,
243
+ maxTotalPixels: 8294400,
244
+ experimentalTotalPixelsThreshold: 3686400
245
+ };
246
+ function validateOpenAiGptImage2Resolution(value) {
247
+ if (value === OPENAI_GPT_IMAGE_2_AUTO_RESOLUTION) {
248
+ return { valid: true };
249
+ }
250
+ const match = /^([1-9]\d*)x([1-9]\d*)$/.exec(value);
251
+ if (!match) {
252
+ return { valid: false, reason: 'Expected "auto" or a WIDTHxHEIGHT pixel string.' };
253
+ }
254
+ const width = Number(match[1]);
255
+ const height = Number(match[2]);
256
+ if (!Number.isSafeInteger(width) || !Number.isSafeInteger(height)) {
257
+ return { valid: false, reason: "Width and height must be safe integer pixel counts." };
258
+ }
259
+ const constraints = OPENAI_GPT_IMAGE_2_SIZE_CONSTRAINTS;
260
+ if (width > constraints.maxEdgePixels || height > constraints.maxEdgePixels) {
261
+ return {
262
+ valid: false,
263
+ reason: `Width and height must each be at most ${constraints.maxEdgePixels}px.`
264
+ };
265
+ }
266
+ if (width % constraints.edgeMultiplePixels !== 0 || height % constraints.edgeMultiplePixels !== 0) {
267
+ return {
268
+ valid: false,
269
+ reason: `Width and height must each be multiples of ${constraints.edgeMultiplePixels}px.`
270
+ };
271
+ }
272
+ const totalPixels = width * height;
273
+ if (totalPixels < constraints.minTotalPixels || totalPixels > constraints.maxTotalPixels) {
274
+ return {
275
+ valid: false,
276
+ reason: `Total pixels must be between ${constraints.minTotalPixels} and ${constraints.maxTotalPixels}.`
277
+ };
278
+ }
279
+ const longEdge = Math.max(width, height);
280
+ const shortEdge = Math.min(width, height);
281
+ if (longEdge / shortEdge > constraints.maxLongToShortEdgeRatio) {
282
+ return {
283
+ valid: false,
284
+ reason: `The long edge must be at most ${constraints.maxLongToShortEdgeRatio}:1 relative to the short edge.`
285
+ };
286
+ }
287
+ return { valid: true };
288
+ }
289
+ var OPENAI_GPT_IMAGE_2_QUALITY_LEVELS = ["low", "medium", "high", "auto"];
290
+ var OPENAI_GPT_IMAGE_2_OUTPUT_FORMATS = ["png", "jpeg", "webp"];
291
+ var OPENAI_GPT_IMAGE_2_BACKGROUNDS = ["opaque", "auto"];
292
+ var OPENAI_GPT_IMAGE_2_MODERATION_LEVELS = ["low", "auto"];
293
+ var OPENAI_GPT_IMAGE_2_PARTIAL_IMAGE_COUNTS = [0, 1, 2, 3];
294
+ var OPENAI_GPT_IMAGE_2_NUM_IMAGES = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
219
295
  var CHATGPT_MODEL_IDS = [
220
296
  "chatgpt-gpt-5.5",
221
297
  "chatgpt-gpt-5.5-fast",
@@ -298,6 +374,27 @@ var OPENAI_GPT_54_NANO_PRICING = {
298
374
  cachedRate: 5e-3 / 1e6,
299
375
  outputRate: 0.4 / 1e6
300
376
  };
377
+ var OPENAI_GPT_IMAGE_2_PRICING = {
378
+ defaultQuality: "medium",
379
+ defaultResolution: "1024x1024",
380
+ imagePrices: {
381
+ low: {
382
+ "1024x1024": 6e-3,
383
+ "1024x1536": 5e-3,
384
+ "1536x1024": 5e-3
385
+ },
386
+ medium: {
387
+ "1024x1024": 0.053,
388
+ "1024x1536": 0.041,
389
+ "1536x1024": 0.041
390
+ },
391
+ high: {
392
+ "1024x1024": 0.211,
393
+ "1024x1536": 0.165,
394
+ "1536x1024": 0.165
395
+ }
396
+ }
397
+ };
301
398
  function getOpenAiPricing(modelId) {
302
399
  if (isExperimentalChatGptModelId(modelId)) {
303
400
  return OPENAI_GPT_54_PRICING;
@@ -325,6 +422,9 @@ function getOpenAiPricing(modelId) {
325
422
  }
326
423
  return void 0;
327
424
  }
425
+ function getOpenAiImagePricing(modelId) {
426
+ return isOpenAiImageModelId(modelId) ? OPENAI_GPT_IMAGE_2_PRICING : void 0;
427
+ }
328
428
 
329
429
  // src/utils/cost.ts
330
430
  function resolveUsageNumber(value) {
@@ -337,8 +437,18 @@ function estimateCallCostUsd({
337
437
  modelId,
338
438
  tokens,
339
439
  responseImages,
340
- imageSize
440
+ imageSize,
441
+ imageQuality
341
442
  }) {
443
+ const openAiImagePricing = getOpenAiImagePricing(modelId);
444
+ if (openAiImagePricing) {
445
+ return estimateOpenAiImageCostUsd({
446
+ pricing: openAiImagePricing,
447
+ responseImages,
448
+ imageSize,
449
+ imageQuality
450
+ });
451
+ }
342
452
  if (!tokens) {
343
453
  return 0;
344
454
  }
@@ -400,6 +510,40 @@ function estimateCallCostUsd({
400
510
  }
401
511
  return 0;
402
512
  }
513
+ function estimateOpenAiImageCostUsd({
514
+ pricing,
515
+ responseImages,
516
+ imageSize,
517
+ imageQuality
518
+ }) {
519
+ if (responseImages <= 0) {
520
+ return 0;
521
+ }
522
+ const quality = imageQuality === "low" || imageQuality === "medium" || imageQuality === "high" ? imageQuality : pricing.defaultQuality;
523
+ const resolution = resolveOpenAiImagePriceResolution(imageSize) ?? pricing.defaultResolution;
524
+ return responseImages * pricing.imagePrices[quality][resolution];
525
+ }
526
+ function resolveOpenAiImagePriceResolution(imageSize) {
527
+ if (imageSize === "1024x1024" || imageSize === "1024x1536" || imageSize === "1536x1024") {
528
+ return imageSize;
529
+ }
530
+ if (!imageSize || imageSize === "auto") {
531
+ return void 0;
532
+ }
533
+ const match = /^(\d+)x(\d+)$/.exec(imageSize);
534
+ if (!match) {
535
+ return void 0;
536
+ }
537
+ const width = Number(match[1]);
538
+ const height = Number(match[2]);
539
+ if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) {
540
+ return void 0;
541
+ }
542
+ if (width === height) {
543
+ return "1024x1024";
544
+ }
545
+ return width > height ? "1536x1024" : "1024x1536";
546
+ }
403
547
 
404
548
  // src/openai/chatgpt-codex.ts
405
549
  import os2 from "os";
@@ -4380,13 +4524,13 @@ var LLM_TEXT_MODEL_IDS = [
4380
4524
  ...FIREWORKS_MODEL_IDS,
4381
4525
  ...GEMINI_TEXT_MODEL_IDS
4382
4526
  ];
4383
- var LLM_IMAGE_MODEL_IDS = [...GEMINI_IMAGE_MODEL_IDS];
4527
+ var LLM_IMAGE_MODEL_IDS = [...OPENAI_IMAGE_MODEL_IDS, ...GEMINI_IMAGE_MODEL_IDS];
4384
4528
  var LLM_MODEL_IDS = [...LLM_TEXT_MODEL_IDS, ...LLM_IMAGE_MODEL_IDS];
4385
4529
  function isLlmTextModelId(value) {
4386
4530
  return isOpenAiModelId(value) || isChatGptModelId(value) || isFireworksModelId(value) || isGeminiTextModelId(value);
4387
4531
  }
4388
4532
  function isLlmImageModelId(value) {
4389
- return isGeminiImageModelId(value);
4533
+ return isOpenAiImageModelId(value) || isGeminiImageModelId(value);
4390
4534
  }
4391
4535
  function isLlmModelId(value) {
4392
4536
  return isLlmTextModelId(value) || isLlmImageModelId(value);
@@ -4398,6 +4542,9 @@ var LlmJsonCallError = class extends Error {
4398
4542
  this.name = "LlmJsonCallError";
4399
4543
  }
4400
4544
  };
4545
+ function isOpenAiGenerateImagesRequest(request) {
4546
+ return isOpenAiImageModelId(request.model);
4547
+ }
4401
4548
  function tool(options) {
4402
4549
  return {
4403
4550
  type: "function",
@@ -4988,6 +5135,9 @@ function resolveProvider(model) {
4988
5135
  return { provider: "fireworks", model: fireworksModel };
4989
5136
  }
4990
5137
  }
5138
+ if (isOpenAiImageModelId(model)) {
5139
+ return { provider: "openai", model };
5140
+ }
4991
5141
  if (isOpenAiModelId(model)) {
4992
5142
  return {
4993
5143
  provider: "openai",
@@ -4995,7 +5145,7 @@ function resolveProvider(model) {
4995
5145
  serviceTier: resolveOpenAiServiceTier(model)
4996
5146
  };
4997
5147
  }
4998
- throw new Error(`Unsupported text model: ${model}`);
5148
+ throw new Error(`Unsupported model: ${model}`);
4999
5149
  }
5000
5150
  function isOpenAiCodexModel(modelId) {
5001
5151
  return modelId.includes("codex");
@@ -6151,8 +6301,11 @@ function mergeTokenUpdates(current, next) {
6151
6301
  }
6152
6302
  return {
6153
6303
  promptTokens: next.promptTokens ?? current.promptTokens,
6304
+ promptTextTokens: next.promptTextTokens ?? current.promptTextTokens,
6305
+ promptImageTokens: next.promptImageTokens ?? current.promptImageTokens,
6154
6306
  cachedTokens: next.cachedTokens ?? current.cachedTokens,
6155
6307
  responseTokens: next.responseTokens ?? current.responseTokens,
6308
+ responseTextTokens: next.responseTextTokens ?? current.responseTextTokens,
6156
6309
  responseImageTokens: next.responseImageTokens ?? current.responseImageTokens,
6157
6310
  thinkingTokens: next.thinkingTokens ?? current.thinkingTokens,
6158
6311
  totalTokens: next.totalTokens ?? current.totalTokens,
@@ -6175,8 +6328,11 @@ function sumUsageTokens(current, next) {
6175
6328
  }
6176
6329
  return {
6177
6330
  promptTokens: sumUsageValue(current?.promptTokens, next.promptTokens),
6331
+ promptTextTokens: sumUsageValue(current?.promptTextTokens, next.promptTextTokens),
6332
+ promptImageTokens: sumUsageValue(current?.promptImageTokens, next.promptImageTokens),
6178
6333
  cachedTokens: sumUsageValue(current?.cachedTokens, next.cachedTokens),
6179
6334
  responseTokens: sumUsageValue(current?.responseTokens, next.responseTokens),
6335
+ responseTextTokens: sumUsageValue(current?.responseTextTokens, next.responseTextTokens),
6180
6336
  responseImageTokens: sumUsageValue(current?.responseImageTokens, next.responseImageTokens),
6181
6337
  thinkingTokens: sumUsageValue(current?.thinkingTokens, next.thinkingTokens),
6182
6338
  totalTokens: sumUsageValue(current?.totalTokens, next.totalTokens),
@@ -6291,10 +6447,22 @@ function extractOpenAiUsageTokens(usage) {
6291
6447
  const cachedTokens = toMaybeNumber(
6292
6448
  usage.input_tokens_details?.cached_tokens
6293
6449
  );
6450
+ const promptTextTokens = toMaybeNumber(
6451
+ usage.input_tokens_details?.text_tokens
6452
+ );
6453
+ const promptImageTokens = toMaybeNumber(
6454
+ usage.input_tokens_details?.image_tokens
6455
+ );
6294
6456
  const outputTokensRaw = toMaybeNumber(usage.output_tokens);
6295
6457
  const reasoningTokens = toMaybeNumber(
6296
6458
  usage.output_tokens_details?.reasoning_tokens
6297
6459
  );
6460
+ const responseTextTokens = toMaybeNumber(
6461
+ usage.output_tokens_details?.text_tokens
6462
+ );
6463
+ const responseImageTokens = toMaybeNumber(
6464
+ usage.output_tokens_details?.image_tokens
6465
+ );
6298
6466
  const totalTokens = toMaybeNumber(usage.total_tokens);
6299
6467
  let responseTokens;
6300
6468
  if (outputTokensRaw !== void 0) {
@@ -6306,8 +6474,12 @@ function extractOpenAiUsageTokens(usage) {
6306
6474
  }
6307
6475
  return {
6308
6476
  promptTokens,
6477
+ promptTextTokens,
6478
+ promptImageTokens,
6309
6479
  cachedTokens,
6310
6480
  responseTokens,
6481
+ responseTextTokens,
6482
+ responseImageTokens,
6311
6483
  thinkingTokens: reasoningTokens,
6312
6484
  totalTokens
6313
6485
  };
@@ -7783,6 +7955,9 @@ async function runTextCall(params) {
7783
7955
  const { result } = await collectFileUploadMetrics(async () => {
7784
7956
  try {
7785
7957
  if (provider === "openai") {
7958
+ if (isOpenAiImageModelId(request.model)) {
7959
+ throw new Error("gpt-image-2 is an image generation model; use generateImages().");
7960
+ }
7786
7961
  const openAiInput = await maybePrepareOpenAiPromptInput(
7787
7962
  toOpenAiInput(contents, {
7788
7963
  defaultMediaResolution: request.mediaResolution,
@@ -10148,7 +10323,184 @@ async function gradeGeneratedImage(params) {
10148
10323
  });
10149
10324
  return { grade: value.grade, result };
10150
10325
  }
10326
+ function resolveOpenAiImageMimeType(outputFormat) {
10327
+ switch (outputFormat) {
10328
+ case "jpeg":
10329
+ return "image/jpeg";
10330
+ case "webp":
10331
+ return "image/webp";
10332
+ case "png":
10333
+ case void 0:
10334
+ return "image/png";
10335
+ }
10336
+ }
10337
+ function buildOpenAiImagePrompt(params) {
10338
+ return [
10339
+ "Follow the requested visual style.",
10340
+ "",
10341
+ "Style:",
10342
+ params.stylePrompt.trim(),
10343
+ ...params.hasStyleImages ? [
10344
+ "",
10345
+ "Use the attached reference image or images for palette, lighting, mood, composition, and material feel."
10346
+ ] : [],
10347
+ "",
10348
+ "Image:",
10349
+ params.imagePrompt.trim()
10350
+ ].filter((line) => line.length > 0).join("\n");
10351
+ }
10352
+ function resolveOpenAiImageRequestParams(request) {
10353
+ if (request.partialImages !== void 0) {
10354
+ throw new Error("partialImages is only supported for streaming image generation.");
10355
+ }
10356
+ if (request.outputCompression !== void 0 && (!Number.isInteger(request.outputCompression) || request.outputCompression < 0 || request.outputCompression > 100)) {
10357
+ throw new Error("outputCompression must be an integer from 0 to 100.");
10358
+ }
10359
+ if (request.outputCompression !== void 0 && request.outputFormat !== "jpeg" && request.outputFormat !== "webp") {
10360
+ throw new Error("outputCompression requires outputFormat to be jpeg or webp.");
10361
+ }
10362
+ const size = request.imageResolution ?? "auto";
10363
+ const sizeValidation = validateOpenAiGptImage2Resolution(size);
10364
+ if (!sizeValidation.valid) {
10365
+ throw new Error(
10366
+ `imageResolution ${JSON.stringify(size)} is not supported by gpt-image-2: ${sizeValidation.reason}`
10367
+ );
10368
+ }
10369
+ return {
10370
+ size,
10371
+ quality: request.imageQuality ?? "auto",
10372
+ outputFormat: request.outputFormat,
10373
+ n: request.numImages ?? 1,
10374
+ background: request.background,
10375
+ moderation: request.moderation
10376
+ };
10377
+ }
10378
+ async function createOpenAiStyleImageFiles(styleImages) {
10379
+ if (!styleImages || styleImages.length === 0) {
10380
+ return void 0;
10381
+ }
10382
+ return await Promise.all(
10383
+ styleImages.map(async (image, index) => {
10384
+ const mimeType = image.mimeType ?? "image/png";
10385
+ const extension = resolveAttachmentExtension(mimeType);
10386
+ return await toFile(image.data, `style-${index + 1}.${extension}`, { type: mimeType });
10387
+ })
10388
+ );
10389
+ }
10390
+ async function generateImagesWithOpenAiImageApi(request) {
10391
+ const promptEntries = Array.from(request.imagePrompts, (rawPrompt, index) => {
10392
+ const prompt = rawPrompt.trim();
10393
+ if (!prompt) {
10394
+ throw new Error(`imagePrompts[${index}] must be a non-empty string`);
10395
+ }
10396
+ return prompt;
10397
+ });
10398
+ if (promptEntries.length === 0) {
10399
+ return [];
10400
+ }
10401
+ const provider = resolveProvider(request.model).provider;
10402
+ const telemetry = createLlmTelemetryEmitter({
10403
+ telemetry: request.telemetry,
10404
+ operation: "generateImages",
10405
+ provider,
10406
+ model: request.model
10407
+ });
10408
+ const startedAtMs = Date.now();
10409
+ const params = resolveOpenAiImageRequestParams(request);
10410
+ const styleImages = await createOpenAiStyleImageFiles(request.styleImages);
10411
+ const hasStyleImages = Boolean(styleImages && styleImages.length > 0);
10412
+ const outputMimeType = resolveOpenAiImageMimeType(params.outputFormat);
10413
+ let totalUsage;
10414
+ let costUsd = 0;
10415
+ let outputImages = 0;
10416
+ telemetry.emit({
10417
+ type: "llm.call.started",
10418
+ imagePromptCount: promptEntries.length,
10419
+ styleImageCount: request.styleImages?.length ?? 0,
10420
+ numImagesPerPrompt: params.n
10421
+ });
10422
+ try {
10423
+ const images = [];
10424
+ for (const imagePrompt of promptEntries) {
10425
+ const prompt = buildOpenAiImagePrompt({
10426
+ stylePrompt: request.stylePrompt,
10427
+ imagePrompt,
10428
+ hasStyleImages
10429
+ });
10430
+ const response = await runOpenAiCall(async (client) => {
10431
+ const payload = {
10432
+ model: request.model,
10433
+ prompt,
10434
+ n: params.n,
10435
+ size: params.size,
10436
+ quality: params.quality,
10437
+ ...params.outputFormat ? { output_format: params.outputFormat } : {},
10438
+ ...request.outputCompression !== void 0 ? { output_compression: request.outputCompression } : {},
10439
+ ...params.background ? { background: params.background } : {},
10440
+ ...params.moderation ? { moderation: params.moderation } : {}
10441
+ };
10442
+ if (styleImages && styleImages.length > 0) {
10443
+ return await client.images.edit(
10444
+ {
10445
+ ...payload,
10446
+ image: styleImages
10447
+ },
10448
+ { signal: request.signal }
10449
+ );
10450
+ }
10451
+ return await client.images.generate(payload, { signal: request.signal });
10452
+ }, request.model);
10453
+ const data = Array.isArray(response.data) ? response.data ?? [] : [];
10454
+ for (const item of data) {
10455
+ if (typeof item.b64_json !== "string" || item.b64_json.length === 0) {
10456
+ continue;
10457
+ }
10458
+ images.push({
10459
+ mimeType: outputMimeType,
10460
+ data: Buffer5.from(item.b64_json, "base64")
10461
+ });
10462
+ }
10463
+ outputImages = images.length;
10464
+ const usage = extractOpenAiUsageTokens(response.usage);
10465
+ totalUsage = sumUsageTokens(totalUsage, usage);
10466
+ costUsd += estimateCallCostUsd({
10467
+ modelId: request.model,
10468
+ tokens: usage,
10469
+ responseImages: data.length,
10470
+ imageSize: params.size,
10471
+ imageQuality: params.quality
10472
+ });
10473
+ }
10474
+ telemetry.emit({
10475
+ type: "llm.call.completed",
10476
+ success: true,
10477
+ durationMs: Math.max(0, Date.now() - startedAtMs),
10478
+ usage: totalUsage,
10479
+ costUsd,
10480
+ imageCount: images.length,
10481
+ attempts: promptEntries.length
10482
+ });
10483
+ return images;
10484
+ } catch (error) {
10485
+ const err = error instanceof Error ? error : new Error(String(error));
10486
+ telemetry.emit({
10487
+ type: "llm.call.completed",
10488
+ success: false,
10489
+ durationMs: Math.max(0, Date.now() - startedAtMs),
10490
+ usage: totalUsage,
10491
+ costUsd,
10492
+ imageCount: outputImages,
10493
+ error: err.message
10494
+ });
10495
+ throw err;
10496
+ } finally {
10497
+ await telemetry.flush();
10498
+ }
10499
+ }
10151
10500
  async function generateImages(request) {
10501
+ if (isOpenAiGenerateImagesRequest(request)) {
10502
+ return await generateImagesWithOpenAiImageApi(request);
10503
+ }
10152
10504
  const maxAttempts = Math.max(1, Math.floor(request.maxAttempts ?? 4));
10153
10505
  const promptList = Array.from(request.imagePrompts);
10154
10506
  if (promptList.length === 0) {
@@ -10162,7 +10514,7 @@ async function generateImages(request) {
10162
10514
  }
10163
10515
  return { index: arrayIndex + 1, prompt: trimmedPrompt };
10164
10516
  });
10165
- const gradingPrompt = request.imageGradingPrompt.trim();
10517
+ const gradingPrompt = request.imageGradingPrompt?.trim() ?? "";
10166
10518
  if (!gradingPrompt) {
10167
10519
  throw new Error("imageGradingPrompt must be a non-empty string");
10168
10520
  }
@@ -13460,8 +13812,11 @@ function summarizeResultUsage(result) {
13460
13812
  }
13461
13813
  summary = {
13462
13814
  promptTokens: sumUsageValue2(summary?.promptTokens, usage.promptTokens),
13815
+ promptTextTokens: sumUsageValue2(summary?.promptTextTokens, usage.promptTextTokens),
13816
+ promptImageTokens: sumUsageValue2(summary?.promptImageTokens, usage.promptImageTokens),
13463
13817
  cachedTokens: sumUsageValue2(summary?.cachedTokens, usage.cachedTokens),
13464
13818
  responseTokens: sumUsageValue2(summary?.responseTokens, usage.responseTokens),
13819
+ responseTextTokens: sumUsageValue2(summary?.responseTextTokens, usage.responseTextTokens),
13465
13820
  responseImageTokens: sumUsageValue2(summary?.responseImageTokens, usage.responseImageTokens),
13466
13821
  thinkingTokens: sumUsageValue2(summary?.thinkingTokens, usage.thinkingTokens),
13467
13822
  totalTokens: sumUsageValue2(summary?.totalTokens, usage.totalTokens),
@@ -14192,6 +14547,17 @@ export {
14192
14547
  LLM_MODEL_IDS,
14193
14548
  LLM_TEXT_MODEL_IDS,
14194
14549
  LlmJsonCallError,
14550
+ OPENAI_GPT_IMAGE_2_AUTO_RESOLUTION,
14551
+ OPENAI_GPT_IMAGE_2_BACKGROUNDS,
14552
+ OPENAI_GPT_IMAGE_2_MODERATION_LEVELS,
14553
+ OPENAI_GPT_IMAGE_2_NUM_IMAGES,
14554
+ OPENAI_GPT_IMAGE_2_OUTPUT_FORMATS,
14555
+ OPENAI_GPT_IMAGE_2_PARTIAL_IMAGE_COUNTS,
14556
+ OPENAI_GPT_IMAGE_2_POPULAR_RESOLUTIONS,
14557
+ OPENAI_GPT_IMAGE_2_QUALITY_LEVELS,
14558
+ OPENAI_GPT_IMAGE_2_RESOLUTIONS,
14559
+ OPENAI_GPT_IMAGE_2_SIZE_CONSTRAINTS,
14560
+ OPENAI_IMAGE_MODEL_IDS,
14195
14561
  OPENAI_MODEL_IDS,
14196
14562
  appendMarkdownSourcesSection,
14197
14563
  applyPatch,
@@ -14241,6 +14607,7 @@ export {
14241
14607
  isLlmImageModelId,
14242
14608
  isLlmModelId,
14243
14609
  isLlmTextModelId,
14610
+ isOpenAiImageModelId,
14244
14611
  isOpenAiModelId,
14245
14612
  loadEnvFromFile,
14246
14613
  loadLocalEnv,
@@ -14260,6 +14627,7 @@ export {
14260
14627
  streamToolLoop,
14261
14628
  stripCodexCitationMarkers,
14262
14629
  toGeminiJsonSchema,
14263
- tool
14630
+ tool,
14631
+ validateOpenAiGptImage2Resolution
14264
14632
  };
14265
14633
  //# sourceMappingURL=index.js.map