@ai-sdk/openai 3.0.135 → 3.0.137

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.
@@ -362,9 +362,24 @@ function convertOpenAIChatUsage(usage) {
362
362
  import {
363
363
  UnsupportedFunctionalityError
364
364
  } from "@ai-sdk/provider";
365
- import { convertToBase64 } from "@ai-sdk/provider-utils";
365
+ import {
366
+ secureJsonParse,
367
+ stringifyWithBigIntAndCycles,
368
+ convertToBase64
369
+ } from "@ai-sdk/provider-utils";
366
370
  function serializeToolCallArguments(input) {
367
- return JSON.stringify(
371
+ if (typeof input === "string") {
372
+ try {
373
+ const parsed = secureJsonParse(input);
374
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
375
+ return "{}";
376
+ }
377
+ return input;
378
+ } catch (e) {
379
+ return "{}";
380
+ }
381
+ }
382
+ return stringifyWithBigIntAndCycles(
368
383
  typeof input === "object" && input !== null && !Array.isArray(input) ? input : {}
369
384
  );
370
385
  }
@@ -592,7 +607,7 @@ function convertToOpenAIChatMessages({
592
607
  case "content":
593
608
  case "json":
594
609
  case "error-json":
595
- contentValue = JSON.stringify(output.value);
610
+ contentValue = stringifyWithBigIntAndCycles(output.value);
596
611
  break;
597
612
  }
598
613
  messages.push({
@@ -2073,6 +2088,9 @@ var OpenAIEmbeddingModel = class {
2073
2088
  };
2074
2089
 
2075
2090
  // src/image/openai-image-model.ts
2091
+ import {
2092
+ InvalidArgumentError
2093
+ } from "@ai-sdk/provider";
2076
2094
  import {
2077
2095
  combineHeaders as combineHeaders4,
2078
2096
  convertBase64ToUint8Array,
@@ -2127,6 +2145,8 @@ var modelMaxImagesPerCall = {
2127
2145
  "gpt-image-1-mini": 10,
2128
2146
  "gpt-image-1.5": 10,
2129
2147
  "gpt-image-2": 10,
2148
+ "gpt-image-2.6-flare": 10,
2149
+ "gpt-image-2.6-sunburst": 10,
2130
2150
  "gpt-image-2.5-flare": 10,
2131
2151
  "gpt-image-2.5-flare-2026-09-08": 10,
2132
2152
  "gpt-image-2.5-sunburst": 10,
@@ -2162,6 +2182,11 @@ var baseImageModelOptionsObject = () => z9.object({
2162
2182
  * Format in which the generated image(s) are returned.
2163
2183
  */
2164
2184
  outputFormat: z9.enum(["png", "jpeg", "webp"]).optional(),
2185
+ /**
2186
+ * How much detail the model puts into the image. Supported by GPT Image
2187
+ * 2.6 models. The API defaults to `high`.
2188
+ */
2189
+ complexity: z9.enum(["low", "medium", "high"]).optional(),
2165
2190
  /**
2166
2191
  * Compression level (0-100) for the generated image(s). Applies to the
2167
2192
  * `jpeg` and `webp` output formats.
@@ -2171,7 +2196,13 @@ var baseImageModelOptionsObject = () => z9.object({
2171
2196
  * A unique identifier representing your end-user, which can help OpenAI
2172
2197
  * to monitor and detect abuse.
2173
2198
  */
2174
- user: z9.string().optional()
2199
+ user: z9.string().optional(),
2200
+ /**
2201
+ * A stable identifier used to help detect users of your application that
2202
+ * may be violating OpenAI's usage policies. Should be a hashed username
2203
+ * or email address.
2204
+ */
2205
+ safetyIdentifier: z9.string().max(128).optional()
2175
2206
  });
2176
2207
  var openaiImageModelOptions = lazySchema9(
2177
2208
  () => zodSchema9(baseImageModelOptionsObject())
@@ -2185,6 +2216,22 @@ var openaiImageModelGenerationOptions = lazySchema9(
2185
2216
  * looking images.
2186
2217
  */
2187
2218
  style: z9.enum(["vivid", "natural"]).optional(),
2219
+ /**
2220
+ * Format in which the generated image(s) are returned. `gif` produces
2221
+ * an animated GIF and is supported by GPT Image 2.6 models.
2222
+ */
2223
+ outputFormat: z9.enum(["png", "jpeg", "webp", "gif"]).optional(),
2224
+ /**
2225
+ * Number of frames (2-64) of an animated GIF. Only applies to the `gif`
2226
+ * output format. The API defaults to 9.
2227
+ */
2228
+ frameCount: z9.number().int().min(2).max(64).optional(),
2229
+ /**
2230
+ * Duration of each frame in milliseconds (20-2000) of an animated GIF.
2231
+ * The API rounds it to the nearest 10 ms. Only applies to the `gif`
2232
+ * output format. The API defaults to 200.
2233
+ */
2234
+ frameDurationMs: z9.number().int().min(20).max(2e3).optional(),
2188
2235
  /**
2189
2236
  * Content moderation level for the generated image(s). `low` applies
2190
2237
  * less restrictive filtering.
@@ -2199,7 +2246,14 @@ var openaiImageModelEditOptions = lazySchema9(
2199
2246
  /**
2200
2247
  * Fidelity of the output image(s) to the input image(s).
2201
2248
  */
2202
- inputFidelity: z9.enum(["high", "low"]).optional()
2249
+ inputFidelity: z9.enum(["high", "low"]).optional(),
2250
+ /**
2251
+ * A transparent PNG overlaid on the first input image to mark up the
2252
+ * regions to change, as an HTTPS URL or a base64 data URL. It must match
2253
+ * the dimensions of the first image. Supported by GPT Image 2.5 and 2.6
2254
+ * models. Cannot be combined with a `mask`.
2255
+ */
2256
+ markup: z9.string().optional()
2203
2257
  })
2204
2258
  )
2205
2259
  );
@@ -2248,6 +2302,12 @@ var OpenAIImageModel = class {
2248
2302
  providerOptions,
2249
2303
  schema: openaiImageModelEditOptions
2250
2304
  })) != null ? _d : {};
2305
+ if (mask != null && openaiOptions2.markup != null) {
2306
+ throw new InvalidArgumentError({
2307
+ argument: "providerOptions.openai.markup",
2308
+ message: "`markup` cannot be combined with `mask`."
2309
+ });
2310
+ }
2251
2311
  const { value: response2, responseHeaders: responseHeaders2 } = await postFormDataToApi({
2252
2312
  url: this.config.url({
2253
2313
  path: "/images/edits",
@@ -2272,14 +2332,17 @@ var OpenAIImageModel = class {
2272
2332
  )
2273
2333
  ),
2274
2334
  mask: mask != null ? await fileToBlob(mask) : void 0,
2335
+ markup: openaiOptions2.markup != null ? await markupToBlob(openaiOptions2.markup) : void 0,
2275
2336
  n,
2276
2337
  size,
2277
2338
  quality: openaiOptions2.quality,
2278
2339
  background: openaiOptions2.background,
2279
2340
  output_format: openaiOptions2.outputFormat,
2280
2341
  output_compression: openaiOptions2.outputCompression,
2342
+ complexity: openaiOptions2.complexity,
2281
2343
  input_fidelity: openaiOptions2.inputFidelity,
2282
- user: openaiOptions2.user
2344
+ user: openaiOptions2.user,
2345
+ safety_identifier: openaiOptions2.safetyIdentifier
2283
2346
  }),
2284
2347
  failedResponseHandler: openaiFailedResponseHandler,
2285
2348
  successfulResponseHandler: createJsonResponseHandler4(
@@ -2345,7 +2408,11 @@ var OpenAIImageModel = class {
2345
2408
  moderation: openaiOptions.moderation,
2346
2409
  output_format: openaiOptions.outputFormat,
2347
2410
  output_compression: openaiOptions.outputCompression,
2411
+ complexity: openaiOptions.complexity,
2412
+ frame_count: openaiOptions.frameCount,
2413
+ frame_duration_ms: openaiOptions.frameDurationMs,
2348
2414
  user: openaiOptions.user,
2415
+ safety_identifier: openaiOptions.safetyIdentifier,
2349
2416
  ...!hasDefaultResponseFormat(this.modelId) ? { response_format: "b64_json" } : {}
2350
2417
  },
2351
2418
  failedResponseHandler: openaiFailedResponseHandler,
@@ -2408,6 +2475,21 @@ function distributeTokenDetails(details, index, total) {
2408
2475
  }
2409
2476
  return result;
2410
2477
  }
2478
+ async function markupToBlob(markup) {
2479
+ const dataUrl = /^data:([^;,]*)(;base64)?,(.*)$/s.exec(markup);
2480
+ if (dataUrl == null) {
2481
+ return downloadBlob(markup);
2482
+ }
2483
+ if (dataUrl[2] == null) {
2484
+ throw new InvalidArgumentError({
2485
+ argument: "providerOptions.openai.markup",
2486
+ message: "`markup` data URLs must be base64 encoded."
2487
+ });
2488
+ }
2489
+ return new Blob([convertBase64ToUint8Array(dataUrl[3])], {
2490
+ type: dataUrl[1] || "image/png"
2491
+ });
2492
+ }
2411
2493
  async function fileToBlob(file) {
2412
2494
  if (!file) return void 0;
2413
2495
  if (file.type === "url") {
@@ -2483,6 +2565,16 @@ var openAITranscriptionModelOptions = lazySchema11(
2483
2565
  * The language of the input audio in ISO-639-1 format.
2484
2566
  */
2485
2567
  language: z11.string().optional(),
2568
+ /**
2569
+ * Expected languages for REST transcription, e.g. with gpt-transcribe.
2570
+ * Use this instead of language. The API validates model support.
2571
+ */
2572
+ languages: z11.array(z11.string()).optional(),
2573
+ /**
2574
+ * Vocabulary hints for REST transcription, e.g. names or technical terms.
2575
+ * The API validates model support.
2576
+ */
2577
+ keywords: z11.array(z11.string()).optional(),
2486
2578
  /**
2487
2579
  * An optional text to guide the model's style or continue a previous audio segment.
2488
2580
  */
@@ -2594,6 +2686,8 @@ var OpenAITranscriptionModel = class {
2594
2686
  const transcriptionModelOptions = {
2595
2687
  include: openAIOptions.include,
2596
2688
  language: openAIOptions.language,
2689
+ languages: openAIOptions.languages,
2690
+ keywords: openAIOptions.keywords,
2597
2691
  prompt: openAIOptions.prompt,
2598
2692
  // https://platform.openai.com/docs/api-reference/audio/createTranscription#audio_createtranscription-response_format
2599
2693
  // prefer verbose_json to get segments for models that support it
@@ -2853,6 +2947,8 @@ import {
2853
2947
  UnsupportedFunctionalityError as UnsupportedFunctionalityError4
2854
2948
  } from "@ai-sdk/provider";
2855
2949
  import {
2950
+ secureJsonParse as secureJsonParse2,
2951
+ stringifyWithBigIntAndCycles as stringifyWithBigIntAndCycles2,
2856
2952
  lazySchema as lazySchema19,
2857
2953
  zodSchema as zodSchema19,
2858
2954
  convertToBase64 as convertToBase642,
@@ -3527,7 +3623,15 @@ async function expandParallelToolCall({
3527
3623
 
3528
3624
  // src/responses/convert-to-openai-responses-input.ts
3529
3625
  function serializeToolCallArguments2(input) {
3530
- return JSON.stringify(input === void 0 ? {} : input);
3626
+ if (typeof input === "string") {
3627
+ try {
3628
+ secureJsonParse2(input);
3629
+ return input;
3630
+ } catch (e) {
3631
+ return stringifyWithBigIntAndCycles2(input);
3632
+ }
3633
+ }
3634
+ return stringifyWithBigIntAndCycles2(input === void 0 ? {} : input);
3531
3635
  }
3532
3636
  async function convertWebSearchToolResultOutput({
3533
3637
  output,
@@ -3605,7 +3709,7 @@ async function convertFunctionToolResultOutput({
3605
3709
  }
3606
3710
  case "json":
3607
3711
  case "error-json":
3608
- return convertScalarOutput(JSON.stringify(output.value));
3712
+ return convertScalarOutput(stringifyWithBigIntAndCycles2(output.value));
3609
3713
  case "content":
3610
3714
  return output.value.map((item) => {
3611
3715
  var _a3, _b, _c, _d, _e, _f, _g;
@@ -4108,7 +4212,7 @@ async function convertToOpenAIResponsesInput({
4108
4212
  type: "custom_tool_call",
4109
4213
  call_id: part.toolCallId,
4110
4214
  name: resolvedToolName,
4111
- input: typeof part.input === "string" ? part.input : JSON.stringify(part.input),
4215
+ input: typeof part.input === "string" ? part.input : stringifyWithBigIntAndCycles2(part.input),
4112
4216
  ...isAsync != null && { async: isAsync },
4113
4217
  id
4114
4218
  });
@@ -4234,7 +4338,7 @@ async function convertToOpenAIResponsesInput({
4234
4338
  } else if (reasoningMessage !== void 0) {
4235
4339
  warnings.push({
4236
4340
  type: "other",
4237
- message: `Cannot append empty reasoning part to existing reasoning sequence. Skipping reasoning part: ${JSON.stringify(part)}.`
4341
+ message: `Cannot append empty reasoning part to existing reasoning sequence. Skipping reasoning part: ${stringifyWithBigIntAndCycles2(part)}.`
4238
4342
  });
4239
4343
  }
4240
4344
  if (reasoningMessage === void 0) {
@@ -4270,7 +4374,7 @@ async function convertToOpenAIResponsesInput({
4270
4374
  } else {
4271
4375
  warnings.push({
4272
4376
  type: "other",
4273
- message: `Non-OpenAI reasoning parts are not supported. Skipping reasoning part: ${JSON.stringify(part)}.`
4377
+ message: `Non-OpenAI reasoning parts are not supported. Skipping reasoning part: ${stringifyWithBigIntAndCycles2(part)}.`
4274
4378
  });
4275
4379
  }
4276
4380
  }
@@ -4336,7 +4440,7 @@ async function convertToOpenAIResponsesInput({
4336
4440
  })
4337
4441
  );
4338
4442
  const serializedToolOutputs = toolOutputs.map(
4339
- ({ output: output2 }) => typeof output2 === "string" ? output2 : JSON.stringify(output2)
4443
+ ({ output: output2 }) => typeof output2 === "string" ? output2 : stringifyWithBigIntAndCycles2(output2)
4340
4444
  );
4341
4445
  const hasPromptCacheBreakpoint = toolOutputs.some(
4342
4446
  ({ promptCacheBreakpoint }) => promptCacheBreakpoint != null
@@ -4452,7 +4556,9 @@ ${text}`,
4452
4556
  break;
4453
4557
  case "json":
4454
4558
  case "error-json":
4455
- outputValue = convertScalarOutput(JSON.stringify(output.value));
4559
+ outputValue = convertScalarOutput(
4560
+ stringifyWithBigIntAndCycles2(output.value)
4561
+ );
4456
4562
  break;
4457
4563
  case "content":
4458
4564
  outputValue = output.value.map((item) => {