@ai-sdk/openai 4.0.105 → 4.0.107

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 (35) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/index.d.ts +51 -9
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +611 -202
  5. package/dist/index.js.map +1 -1
  6. package/dist/internal/index.d.ts +6 -4
  7. package/dist/internal/index.d.ts.map +1 -1
  8. package/dist/internal/index.js +565 -164
  9. package/dist/internal/index.js.map +1 -1
  10. package/docs/03-openai.mdx +127 -5
  11. package/package.json +3 -3
  12. package/src/chat/convert-to-openai-chat-messages.ts +22 -3
  13. package/src/chat/openai-chat-language-model.ts +27 -20
  14. package/src/completion/openai-completion-language-model.ts +11 -3
  15. package/src/embedding/openai-embedding-model.ts +2 -1
  16. package/src/files/openai-files.ts +10 -8
  17. package/src/image/openai-image-model-options.ts +10 -20
  18. package/src/image/openai-image-model.ts +10 -21
  19. package/src/live/openai-realtime-model-live.ts +15 -16
  20. package/src/openai-batch.ts +22 -6
  21. package/src/openai-config.ts +2 -1
  22. package/src/openai-decision-model.ts +2 -1
  23. package/src/openai-model-catalog.ts +935 -0
  24. package/src/openai-provider.ts +18 -13
  25. package/src/realtime/openai-realtime-factory.ts +6 -6
  26. package/src/realtime/openai-realtime-model.ts +7 -3
  27. package/src/resolve-openai-reasoning-effort.ts +45 -0
  28. package/src/responses/convert-to-openai-responses-input.ts +29 -11
  29. package/src/responses/openai-responses-language-model.ts +28 -22
  30. package/src/skills/openai-skills.ts +4 -2
  31. package/src/speech/openai-speech-model.ts +5 -1
  32. package/src/speech-translation/openai-speech-translation-model.ts +5 -1
  33. package/src/transcription/openai-transcription-model-options.ts +12 -0
  34. package/src/transcription/openai-transcription-model.ts +29 -56
  35. package/src/openai-language-model-capabilities.ts +0 -196
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { EXPERIMENTAL_EMBEDDING_MODEL_MAX_INPUT_BYTES_PER_CALL, StreamingToolCallTracker, WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE, combineHeaders, connectToWebSocket, convertAsyncIteratorToReadableStream, convertBase64ToUint8Array, convertInlineFileDataToUint8Array, convertToBase64, convertToFormData, convertUint8ArrayToBase64, createBinaryResponseHandler, createBinaryStreamResponseHandler, createEventSourceResponseHandler, createJsonErrorResponseHandler, createJsonLinesResponseHandler, createJsonResponseHandler, createLanguageModelResponseMetadata, createLanguageModelResponseMetadata as getResponseMetadata, createNullLanguageModelUsage, createProviderDefinedToolFactory, createProviderDefinedToolFactoryWithOutputSchema, createProviderExecutedToolFactory, createProviderStreamError, createToolNameMapping, deleteFromApi, detectMediaType, downloadBlob, encodePathSegment, experimental_toolCaller, generateId, getFromApi, getTopLevelMediaType, isCustomReasoning, isFullMediaType, isNonNullable, isRecord, lazySchema, loadApiKey, loadOptionalSetting, mapReasoningToProviderEffort, mediaTypeToExtension, normalizeBatchRequestCounts, parseJSON, parseProviderOptions, postFormDataToApi, postJsonToApi, postMultipartStreamToApi, postToApi, resolveFullMediaType, resolveProviderReference, safeParseJSON, safeValidateTypes, serializeModelOptions, toWebSocketUrl, validateBaseURL, validateTypes, waitForWebSocketBufferDrain, withUserAgentSuffix, withoutTrailingSlash, zodSchema } from "@ai-sdk/provider-utils";
1
+ import { EXPERIMENTAL_EMBEDDING_MODEL_MAX_INPUT_BYTES_PER_CALL, StreamingToolCallTracker, WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE, combineHeaders, connectToWebSocket, convertAsyncIteratorToReadableStream, convertBase64ToUint8Array, convertInlineFileDataToUint8Array, convertToBase64, convertToFormData, convertUint8ArrayToBase64, createBinaryResponseHandler, createBinaryStreamResponseHandler, createEventSourceResponseHandler, createJsonErrorResponseHandler, createJsonLinesResponseHandler, createJsonResponseHandler, createLanguageModelResponseMetadata, createLanguageModelResponseMetadata as getResponseMetadata, createNullLanguageModelUsage, createProviderDefinedToolFactory, createProviderDefinedToolFactoryWithOutputSchema, createProviderExecutedToolFactory, createProviderStreamError, createToolNameMapping, deleteFromApi, detectMediaType, downloadBlob, encodePathSegment, experimental_toolCaller, generateId, getFromApi, getTopLevelMediaType, isCustomReasoning, isFullMediaType, isNonNullable, isRecord, lazySchema, loadApiKey, loadOptionalSetting, mapReasoningToProviderEffort, mediaTypeToExtension, normalizeBatchRequestCounts, parseJSON, parseProviderOptions, postFormDataToApi, postJsonToApi, postMultipartStreamToApi, postToApi, resolve, resolveFullMediaType, resolveProviderReference, resolveWith, safeParseJSON, safeValidateTypes, secureJsonParse, serializeModelOptions, stringifyWithBigIntAndCycles, toWebSocketUrl, validateBaseURL, validateTypes, waitForWebSocketBufferDrain, withUserAgentSuffix, withoutTrailingSlash, zodSchema } from "@ai-sdk/provider-utils";
2
2
  import { APICallError, InvalidArgumentError, InvalidPromptError, InvalidResponseDataError, TooManyEmbeddingValuesForCallError, UnsupportedFunctionalityError, isJSONObject } from "@ai-sdk/provider";
3
3
  import { z } from "zod/v4";
4
4
  //#region src/openai-config.ts
@@ -119,7 +119,7 @@ var DecisionOpenAIModel = class DecisionOpenAIModel {
119
119
  path: "/decisions",
120
120
  modelId: this.modelId
121
121
  }),
122
- headers: combineHeaders(this.config.headers?.(), headers),
122
+ headers: combineHeaders(await resolve(this.config.headers), headers),
123
123
  body: {
124
124
  model: this.modelId,
125
125
  safety_identifier: openaiOptions?.safetyIdentifier,
@@ -288,54 +288,182 @@ function isJSONObject$1(value) {
288
288
  return typeof value === "object" && value !== null && !Array.isArray(value);
289
289
  }
290
290
  //#endregion
291
- //#region src/openai-language-model-capabilities.ts
292
- const ALL_OPENAI_REASONING_EFFORTS = [
293
- "none",
294
- "minimal",
295
- "low",
296
- "medium",
297
- "high",
298
- "xhigh",
299
- "max"
300
- ];
301
- function getOpenAILanguageModelCapabilities(modelId) {
291
+ //#region src/openai-model-catalog.ts
292
+ /**
293
+ * Options accepted under `providerOptions.openai`. Language options are the
294
+ * Responses API options. The `satisfies` check keeps this list in sync with
295
+ * the option schema.
296
+ */
297
+ const openaiProviderOptions = { language: {
298
+ conversation: { description: "OpenAI Conversation ID to continue." },
299
+ include: { description: "Extra fields to include in the response." },
300
+ includeWebSearchSources: { description: "Include web search action sources." },
301
+ instructions: { description: "Instructions for the model." },
302
+ logprobs: { description: "Return token log probabilities." },
303
+ maxToolCalls: { description: "Maximum number of built-in tool calls." },
304
+ metadata: { description: "Metadata to store with the generation." },
305
+ parallelToolCalls: { description: "Whether to use parallel tool calls." },
306
+ previousResponseId: { description: "Previous response ID to continue." },
307
+ promptCacheKey: { description: "Cache key for prompt caching." },
308
+ promptCacheOptions: { description: "Prompt cache mode, TTL, and prewarm." },
309
+ promptCacheRetention: { description: "Prompt cache retention policy." },
310
+ reasoningEffort: { description: "Reasoning effort." },
311
+ reasoningEffortUpdate: { description: "Reasoning effort update from this response onward." },
312
+ reasoningMode: { description: "Standard or pro reasoning mode." },
313
+ reasoningContext: { description: "Which reasoning items can be used." },
314
+ reasoningSummary: { description: "Reasoning summary output." },
315
+ safetyIdentifier: { description: "Identifier for safety monitoring." },
316
+ serviceTier: { description: "Service tier for the request." },
317
+ store: { description: "Whether to store the generation." },
318
+ passThroughUnsupportedFiles: { description: "Send non-image file types as generic input files." },
319
+ strictJsonSchema: { description: "Use strict JSON schema validation." },
320
+ textVerbosity: { description: "Verbosity of text responses." },
321
+ truncation: { description: "Output truncation behavior." },
322
+ user: { description: "End-user identifier for abuse monitoring." },
323
+ systemMessageMode: { description: "System message role override." },
324
+ forceReasoning: { description: "Treat the model as a reasoning model." },
325
+ contextManagement: { description: "Server-side context compaction." },
326
+ compactionTrigger: { description: "Request explicit compaction." },
327
+ allowedTools: { description: "Restrict callable tools to a subset." }
328
+ } };
329
+ const configurableNonReasoning = { capabilities: { language: { reasoning: {
330
+ support: true,
331
+ efforts: [
332
+ "none",
333
+ "low",
334
+ "medium",
335
+ "high",
336
+ "xhigh",
337
+ "max"
338
+ ],
339
+ sampling: "reasoning-effort-none"
340
+ } } } };
341
+ const openaiLanguageModelEntries = Object.fromEntries(Object.entries({
342
+ "gpt-6-astra": {},
343
+ "gpt-6.1-sol": {},
344
+ "gpt-6.1-terra": configurableNonReasoning,
345
+ "gpt-6-luna": configurableNonReasoning,
346
+ "gpt-6-sol": configurableNonReasoning,
347
+ "gpt-5.6": {},
348
+ "gpt-5.6-luna": {},
349
+ "gpt-5.6-sol": {},
350
+ "gpt-5.6-terra": {},
351
+ "gpt-5.5": {},
352
+ "gpt-5.4-pro": {},
353
+ "gpt-5.4": {},
354
+ "gpt-5.4-mini": {},
355
+ "gpt-5.4-nano": {},
356
+ "gpt-5.3-chat-latest": {},
357
+ "gpt-5.2-pro": {},
358
+ "gpt-5.2-chat-latest": {},
359
+ "gpt-5.2": {},
360
+ "gpt-5.1-codex-mini": {},
361
+ "gpt-5.1-codex": {},
362
+ "gpt-5.1-chat-latest": {},
363
+ "gpt-5.1": {},
364
+ "gpt-5-pro": {},
365
+ "gpt-5": {},
366
+ "gpt-5-mini": {},
367
+ "gpt-5-nano": {},
368
+ "gpt-5-codex": {},
369
+ "gpt-5-chat-latest": { capabilities: { language: {
370
+ objectGeneration: false,
371
+ tools: {
372
+ usage: false,
373
+ streaming: false,
374
+ async: false
375
+ }
376
+ } } },
377
+ "gpt-4.1": {},
378
+ "gpt-4.1-mini": {},
379
+ "gpt-4.1-nano": {},
380
+ "gpt-4o": {},
381
+ "gpt-4o-mini": {}
382
+ }).map(([modelId, definition]) => [modelId, createOpenAILanguageModelEntry(modelId, definition)]));
383
+ function createOpenAILanguageModelEntry(modelId, definition) {
302
384
  const oSeriesVersion = getOSeriesVersion(modelId);
303
385
  const gptVersion = getGptVersion(modelId);
386
+ const isRecognizedModelFamily = oSeriesVersion != null || gptVersion != null || /^gpt-4o(?:-|$)/.test(modelId);
304
387
  const isGptChatModel = gptVersion?.minor == null && (gptVersion?.variant?.startsWith("chat") ?? false);
305
388
  const isGptNanoModel = gptVersion?.variant?.startsWith("nano") ?? false;
306
389
  const isGpt6OrLaterModel = gptVersion != null && gptVersion.major >= 6;
390
+ const isGpt56OrLaterModel = isGpt6OrLaterModel || gptVersion?.major === 5 && (gptVersion.minor ?? 0) >= 6;
307
391
  const isStandardGpt5Model = gptVersion?.major === 5 && (gptVersion.variant == null || /^(?:(?:mini|nano|sol|luna|terra)(?:-\d{4}-\d{2}-\d{2})?|\d{4}-\d{2}-\d{2})$/.test(gptVersion.variant));
308
- const isGpt6OrLaterModelWithNoneEffort = modelId === "gpt-6-sol" || modelId === "gpt-6-luna" || modelId === "gpt-6.1-terra";
309
392
  const supportsFlexProcessing = oSeriesVersion != null && oSeriesVersion >= 3 || gptVersion != null && gptVersion.major >= 5 && !isGptChatModel;
310
393
  const supportsPriorityProcessing = modelId.startsWith("gpt-4") || gptVersion != null && gptVersion.major >= 5 && !isGptNanoModel && !isGptChatModel || oSeriesVersion != null && oSeriesVersion >= 3;
311
394
  const isReasoningModel = oSeriesVersion != null || gptVersion != null && gptVersion.major >= 5 && !isGptChatModel;
312
- const supportsNonReasoningParameters = isGpt6OrLaterModelWithNoneEffort || !isGpt6OrLaterModel && gptVersion != null && (gptVersion.major > 5 || gptVersion.major === 5 && (gptVersion.minor ?? 0) >= 1);
313
- const systemMessageMode = isReasoningModel ? "developer" : "system";
395
+ const reasoningSampling = definition?.capabilities?.language?.reasoning?.sampling ?? (!isGpt6OrLaterModel && gptVersion != null && (gptVersion.major > 5 || gptVersion.major === 5 && (gptVersion.minor ?? 0) >= 1) ? "reasoning-effort-none" : "unsupported");
396
+ const sampling = !isRecognizedModelFamily ? "unknown" : !isReasoningModel ? true : reasoningSampling === "reasoning-effort-none" ? { condition: "Only when reasoning effort is none." } : false;
397
+ const chatTemperatureSupportedWithoutReasoning = !modelId.startsWith("gpt-4o-search-preview") && !modelId.startsWith("gpt-4o-mini-search-preview");
398
+ const entry = {
399
+ capabilities: { language: {
400
+ inputs: definition?.capabilities?.language?.inputs ?? {
401
+ image: definition != null ? true : "unknown",
402
+ audio: definition != null ? false : "unknown"
403
+ },
404
+ objectGeneration: definition?.capabilities?.language?.objectGeneration ?? (definition != null ? true : "unknown"),
405
+ tools: definition?.capabilities?.language?.tools ?? {
406
+ usage: definition != null ? true : "unknown",
407
+ streaming: definition != null ? true : "unknown",
408
+ async: isGpt6OrLaterModel
409
+ },
410
+ reasoning: {
411
+ support: isRecognizedModelFamily ? isReasoningModel : "unknown",
412
+ efforts: definition?.capabilities?.language?.reasoning?.efforts ?? (isGpt6OrLaterModel ? [
413
+ "low",
414
+ "medium",
415
+ "high",
416
+ "xhigh",
417
+ "max"
418
+ ] : isStandardGpt5Model ? getGpt5ReasoningEfforts(gptVersion.minor ?? 0) : void 0),
419
+ sampling: reasoningSampling
420
+ },
421
+ sampling: {
422
+ temperature: chatTemperatureSupportedWithoutReasoning ? sampling : { condition: "Not supported by Chat Completions search preview models." },
423
+ topP: sampling,
424
+ logprobs: isReasoningModel && !isGpt6OrLaterModel ? { condition: reasoningSampling === "reasoning-effort-none" ? "Chat Completions requires reasoning effort none; Responses support is model-dependent." : "Not supported by Chat Completions while reasoning; Responses support is model-dependent." } : sampling
425
+ },
426
+ serviceTiers: {
427
+ flex: supportsFlexProcessing,
428
+ priority: supportsPriorityProcessing
429
+ },
430
+ configurationUpdates: isGpt6OrLaterModel,
431
+ promptCache: {
432
+ retention: !isGpt6OrLaterModel,
433
+ options: isRecognizedModelFamily ? isGpt56OrLaterModel : "unknown"
434
+ },
435
+ endpoints: {
436
+ chat: {
437
+ temperatureWithoutReasoning: chatTemperatureSupportedWithoutReasoning,
438
+ functionToolsWithReasoning: !(gptVersion?.major === 5 && (gptVersion.minor ?? 0) >= 6)
439
+ },
440
+ responses: { logprobsRequireNonReasoning: isGpt6OrLaterModel }
441
+ }
442
+ } },
443
+ requestConfig: { language: { systemMessageMode: definition?.requestConfig?.language?.systemMessageMode ?? (isReasoningModel ? "developer" : "system") } }
444
+ };
445
+ const { language } = entry.capabilities;
314
446
  return {
315
- supportsFlexProcessing,
316
- supportsPriorityProcessing,
317
- supportsConfigurationUpdate: isGpt6OrLaterModel,
318
- supportsAsyncToolCalling: isGpt6OrLaterModel,
319
- supportedReasoningEfforts: isGpt6OrLaterModelWithNoneEffort ? [
320
- "none",
321
- "low",
322
- "medium",
323
- "high",
324
- "xhigh",
325
- "max"
326
- ] : isGpt6OrLaterModel ? [
327
- "low",
328
- "medium",
329
- "high",
330
- "xhigh",
331
- "max"
332
- ] : isStandardGpt5Model ? getGpt5ReasoningEfforts(gptVersion.minor ?? 0) : void 0,
333
- supportsChatFunctionToolsWithReasoning: !(gptVersion?.major === 5 && (gptVersion.minor ?? 0) >= 6),
334
- isReasoningModel,
335
- systemMessageMode,
336
- supportsNonReasoningParameters
447
+ ...entry,
448
+ providerOptions: { language: declareProviderOptions(openaiProviderOptions.language, definition != null ? true : "unknown", {
449
+ logprobs: language.sampling.logprobs,
450
+ maxToolCalls: language.tools.usage,
451
+ parallelToolCalls: language.tools.usage,
452
+ allowedTools: language.tools.usage,
453
+ reasoningEffort: language.reasoning.support,
454
+ reasoningSummary: language.reasoning.support,
455
+ reasoningMode: language.reasoning.support,
456
+ reasoningContext: language.reasoning.support,
457
+ reasoningEffortUpdate: language.configurationUpdates,
458
+ promptCacheOptions: language.promptCache.options,
459
+ promptCacheRetention: language.promptCache.retention
460
+ }) }
337
461
  };
338
462
  }
463
+ /** Applies one default support value to every option, except the listed ones. */
464
+ function declareProviderOptions(definitions, support, exceptions) {
465
+ return Object.fromEntries(Object.keys(definitions).map((option) => [option, exceptions[option] ?? support]));
466
+ }
339
467
  function getGpt5ReasoningEfforts(minor) {
340
468
  if (minor === 0) return [
341
469
  "minimal",
@@ -371,27 +499,317 @@ function getOSeriesVersion(modelId) {
371
499
  }
372
500
  function getGptVersion(modelId) {
373
501
  const match = /^gpt-(\d+)(?:\.(\d+))?(?:-(.+))?$/.exec(modelId);
374
- if (match == null) return;
375
- return {
502
+ return match == null ? void 0 : {
376
503
  major: Number(match[1]),
377
504
  minor: match[2] == null ? void 0 : Number(match[2]),
378
505
  variant: match[3]
379
506
  };
380
507
  }
508
+ const openaiEmbeddingModelEntries = {
509
+ "text-embedding-3-large": { capabilities: { embedding: {
510
+ defaultDimensions: 3072,
511
+ customDimensions: true
512
+ } } },
513
+ "text-embedding-3-small": { capabilities: { embedding: {
514
+ defaultDimensions: 1536,
515
+ customDimensions: true
516
+ } } },
517
+ "text-embedding-ada-002": { capabilities: { embedding: {
518
+ defaultDimensions: 1536,
519
+ customDimensions: false
520
+ } } }
521
+ };
522
+ const gptImageSizes = [
523
+ "1024x1024",
524
+ "1536x1024",
525
+ "1024x1536"
526
+ ];
527
+ const customImageSizes = { description: "Standard presets and custom dimensions" };
528
+ function createGptImageEntry(sizes) {
529
+ return {
530
+ capabilities: { image: {
531
+ sizes,
532
+ fileInput: true,
533
+ maskInput: true,
534
+ maxImagesPerCall: 10
535
+ } },
536
+ requestConfig: { image: { responseFormat: "provider-default" } }
537
+ };
538
+ }
539
+ const openaiImageModelEntries = {
540
+ "gpt-image-2.5-flare": createGptImageEntry(customImageSizes),
541
+ "gpt-image-2.5-sunburst": createGptImageEntry(customImageSizes),
542
+ "gpt-image-2": createGptImageEntry(gptImageSizes),
543
+ "gpt-image-1.5": createGptImageEntry(gptImageSizes),
544
+ "gpt-image-1-mini": createGptImageEntry(gptImageSizes),
545
+ "gpt-image-1": createGptImageEntry(gptImageSizes),
546
+ "dall-e-3": {
547
+ capabilities: { image: {
548
+ sizes: [
549
+ "1024x1024",
550
+ "1792x1024",
551
+ "1024x1792"
552
+ ],
553
+ fileInput: false,
554
+ maskInput: false,
555
+ maxImagesPerCall: 1
556
+ } },
557
+ requestConfig: { image: { responseFormat: "b64_json" } }
558
+ },
559
+ "dall-e-2": {
560
+ capabilities: { image: {
561
+ sizes: [
562
+ "256x256",
563
+ "512x512",
564
+ "1024x1024"
565
+ ],
566
+ fileInput: true,
567
+ maskInput: true,
568
+ maxImagesPerCall: 10
569
+ } },
570
+ requestConfig: { image: { responseFormat: "b64_json" } }
571
+ }
572
+ };
573
+ const imageModelAliases = {
574
+ "gpt-image-2.5-flare-2026-09-08": openaiImageModelEntries["gpt-image-2.5-flare"],
575
+ "gpt-image-2.5-sunburst-2026-09-08": openaiImageModelEntries["gpt-image-2.5-sunburst"],
576
+ "chatgpt-image-latest": createGptImageEntry({ description: "Unknown" })
577
+ };
578
+ function resolveOpenAIImageModelEntry(modelId) {
579
+ if (Object.prototype.hasOwnProperty.call(openaiImageModelEntries, modelId)) return openaiImageModelEntries[modelId];
580
+ if (Object.prototype.hasOwnProperty.call(imageModelAliases, modelId)) return imageModelAliases[modelId];
581
+ return {
582
+ capabilities: { image: {
583
+ sizes: { description: "Unknown" },
584
+ fileInput: "unknown",
585
+ maskInput: "unknown",
586
+ maxImagesPerCall: modelId.startsWith("gpt-image-") ? 10 : 1
587
+ } },
588
+ requestConfig: { image: { responseFormat: modelId.startsWith("chatgpt-image-") || modelId.startsWith("gpt-image-") ? "provider-default" : "b64_json" } }
589
+ };
590
+ }
591
+ Object.fromEntries(Object.entries({
592
+ ...openaiImageModelEntries,
593
+ ...imageModelAliases
594
+ }).map(([modelId, entry]) => [modelId, entry.capabilities.image.maxImagesPerCall ?? 1]));
595
+ const defaultTranscriptionRequestConfig = { languageField: "language" };
596
+ const openaiTranscriptionModelEntries = {
597
+ "whisper-1": {
598
+ capabilities: { transcription: {
599
+ transcription: true,
600
+ streaming: false,
601
+ streamingDelay: false,
602
+ duration: true,
603
+ segments: true,
604
+ language: true
605
+ } },
606
+ requestConfig: { transcription: {
607
+ ...defaultTranscriptionRequestConfig,
608
+ responseFormat: "verbose_json"
609
+ } }
610
+ },
611
+ "gpt-4o-mini-transcribe": {
612
+ capabilities: { transcription: {
613
+ transcription: true,
614
+ streaming: false,
615
+ streamingDelay: false,
616
+ duration: false,
617
+ segments: false,
618
+ language: false
619
+ } },
620
+ requestConfig: { transcription: defaultTranscriptionRequestConfig }
621
+ },
622
+ "gpt-4o-transcribe": {
623
+ capabilities: { transcription: {
624
+ transcription: true,
625
+ streaming: false,
626
+ streamingDelay: false,
627
+ duration: false,
628
+ segments: false,
629
+ language: false
630
+ } },
631
+ requestConfig: { transcription: defaultTranscriptionRequestConfig }
632
+ },
633
+ "gpt-4o-transcribe-diarize": {
634
+ capabilities: { transcription: {
635
+ transcription: true,
636
+ streaming: false,
637
+ streamingDelay: false,
638
+ duration: true,
639
+ segments: true,
640
+ language: false
641
+ } },
642
+ requestConfig: { transcription: {
643
+ ...defaultTranscriptionRequestConfig,
644
+ responseFormat: "diarized_json",
645
+ chunkingStrategy: "auto"
646
+ } }
647
+ },
648
+ "gpt-transcribe": {
649
+ capabilities: { transcription: {
650
+ transcription: true,
651
+ streaming: true,
652
+ streamingDelay: false,
653
+ duration: false,
654
+ segments: false,
655
+ language: true
656
+ } },
657
+ requestConfig: { transcription: { languageField: "languages" } }
658
+ },
659
+ "gpt-live-transcribe": {
660
+ capabilities: { transcription: {
661
+ transcription: false,
662
+ streaming: true,
663
+ streamingDelay: true,
664
+ duration: false,
665
+ segments: false,
666
+ language: false
667
+ } },
668
+ requestConfig: { transcription: { languageField: "languages" } }
669
+ },
670
+ "gpt-realtime-whisper": {
671
+ capabilities: { transcription: {
672
+ transcription: false,
673
+ streaming: true,
674
+ streamingDelay: true,
675
+ duration: false,
676
+ segments: false,
677
+ language: false
678
+ } },
679
+ requestConfig: { transcription: defaultTranscriptionRequestConfig }
680
+ }
681
+ };
682
+ const transcriptionSnapshotModelIds = [
683
+ "gpt-transcribe",
684
+ "gpt-live-transcribe",
685
+ "gpt-realtime-whisper"
686
+ ];
687
+ function resolveOpenAITranscriptionModelEntry(modelId) {
688
+ if (Object.prototype.hasOwnProperty.call(openaiTranscriptionModelEntries, modelId)) return openaiTranscriptionModelEntries[modelId];
689
+ for (const baseModelId of transcriptionSnapshotModelIds) if (modelId.startsWith(`${baseModelId}-`)) return openaiTranscriptionModelEntries[baseModelId];
690
+ return {
691
+ capabilities: { transcription: {
692
+ transcription: "unknown",
693
+ streaming: "unknown",
694
+ streamingDelay: "unknown",
695
+ duration: "unknown",
696
+ segments: "unknown",
697
+ language: "unknown"
698
+ } },
699
+ requestConfig: { transcription: defaultTranscriptionRequestConfig }
700
+ };
701
+ }
702
+ const openaiSpeechTranslationModelEntries = { "gpt-realtime-translate": { capabilities: { speechTranslation: {
703
+ translatedAudio: true,
704
+ translatedText: true,
705
+ sourceTranscript: true
706
+ } } } };
707
+ const openaiSpeechModelEntries = {
708
+ "tts-1": { capabilities: { speech: { instructions: false } } },
709
+ "tts-1-hd": { capabilities: { speech: { instructions: false } } },
710
+ "gpt-4o-mini-tts": { capabilities: { speech: { instructions: true } } }
711
+ };
712
+ const liveModelEntry = {
713
+ capabilities: { realtime: {
714
+ conversation: "continuous",
715
+ transports: ["websocket", "webrtc"],
716
+ connections: ["server-websocket", "webrtc"]
717
+ } },
718
+ requestConfig: { realtime: {
719
+ api: "live",
720
+ startup: "session-start",
721
+ finalization: "session-close"
722
+ } }
723
+ };
724
+ const realtimeModelEntry = {
725
+ capabilities: { realtime: {
726
+ conversation: "turn-based",
727
+ transports: ["websocket"],
728
+ connections: ["client-secret-websocket"]
729
+ } },
730
+ requestConfig: { realtime: {
731
+ api: "realtime",
732
+ startup: "session-update",
733
+ finalization: "transport-close"
734
+ } }
735
+ };
736
+ const realtimeModelEntries = {
737
+ "gpt-live-1": liveModelEntry,
738
+ "gpt-realtime": realtimeModelEntry
739
+ };
740
+ /** Keep the existing realtime interface's shape while deriving it from the catalog. */
741
+ const openaiLiveRealtimeCapabilities = {
742
+ ...liveModelEntry.capabilities.realtime,
743
+ startup: liveModelEntry.requestConfig.realtime.startup,
744
+ finalization: liveModelEntry.requestConfig.realtime.finalization
745
+ };
381
746
  /**
382
- * Resolves the reasoning effort to send to OpenAI.
383
- *
384
- * A reasoning effort from provider options is sent unchanged. Otherwise the
385
- * top-level reasoning value is mapped to the closest effort that the model
386
- * family supports, or sent directly when the supported efforts are not known.
747
+ * The catalog consumed by request builders and documentation. Source declarations
748
+ * are grouped by operation; entries for the same model combine their sections.
749
+ * An absent section is undeclared, not an instruction to reject a request.
387
750
  */
388
- function resolveOpenAIReasoningEffort({ providerReasoningEffort, reasoning, supportedReasoningEfforts, warnings }) {
389
- return mapReasoningToProviderEffort({
390
- reasoning,
391
- providerOptionsEffort: providerReasoningEffort,
392
- effortMap: Object.fromEntries((supportedReasoningEfforts ?? ALL_OPENAI_REASONING_EFFORTS).map((effort) => [effort, effort])),
393
- warnings
394
- });
751
+ const openaiModelCatalog = combineModelEntries([
752
+ openaiLanguageModelEntries,
753
+ openaiEmbeddingModelEntries,
754
+ openaiImageModelEntries,
755
+ openaiTranscriptionModelEntries,
756
+ openaiSpeechTranslationModelEntries,
757
+ openaiSpeechModelEntries,
758
+ realtimeModelEntries
759
+ ]);
760
+ function combineModelEntries(catalogs) {
761
+ const entries = /* @__PURE__ */ new Map();
762
+ for (const catalog of catalogs) for (const [modelId, entry] of Object.entries(catalog)) {
763
+ const previous = entries.get(modelId);
764
+ entries.set(modelId, {
765
+ capabilities: {
766
+ ...previous?.capabilities,
767
+ ...entry.capabilities
768
+ },
769
+ ...previous?.providerOptions != null || entry.providerOptions != null ? { providerOptions: {
770
+ ...previous?.providerOptions,
771
+ ...entry.providerOptions
772
+ } } : {},
773
+ ...previous?.requestConfig != null || entry.requestConfig != null ? { requestConfig: {
774
+ ...previous?.requestConfig,
775
+ ...entry.requestConfig
776
+ } } : {}
777
+ });
778
+ }
779
+ return Object.fromEntries(entries);
780
+ }
781
+ function findModelEntry(modelId) {
782
+ return Object.prototype.hasOwnProperty.call(openaiModelCatalog, modelId) ? openaiModelCatalog[modelId] : void 0;
783
+ }
784
+ function getOpenAILanguageModelEntry(modelId) {
785
+ const entry = findModelEntry(modelId);
786
+ return entry?.capabilities.language != null && entry.providerOptions?.language != null && entry.requestConfig?.language != null ? {
787
+ capabilities: { language: entry.capabilities.language },
788
+ providerOptions: { language: entry.providerOptions.language },
789
+ requestConfig: { language: entry.requestConfig.language }
790
+ } : createOpenAILanguageModelEntry(modelId);
791
+ }
792
+ function getOpenAIImageModelEntry(modelId) {
793
+ const entry = findModelEntry(modelId);
794
+ return entry?.capabilities.image != null && entry.requestConfig?.image != null ? {
795
+ capabilities: { image: entry.capabilities.image },
796
+ requestConfig: { image: entry.requestConfig.image }
797
+ } : resolveOpenAIImageModelEntry(modelId);
798
+ }
799
+ function getOpenAITranscriptionModelEntry(modelId) {
800
+ const entry = findModelEntry(modelId);
801
+ return entry?.capabilities.transcription != null && entry.requestConfig?.transcription != null ? {
802
+ capabilities: { transcription: entry.capabilities.transcription },
803
+ requestConfig: { transcription: entry.requestConfig.transcription }
804
+ } : resolveOpenAITranscriptionModelEntry(modelId);
805
+ }
806
+ function getOpenAIRealtimeModelEntry(modelId, api) {
807
+ const entry = findModelEntry(modelId);
808
+ if (entry?.capabilities.realtime != null && entry.requestConfig?.realtime != null && (api == null || entry.requestConfig.realtime.api === api)) return {
809
+ capabilities: { realtime: entry.capabilities.realtime },
810
+ requestConfig: { realtime: entry.requestConfig.realtime }
811
+ };
812
+ return api === "live" ? liveModelEntry : realtimeModelEntry;
395
813
  }
396
814
  //#endregion
397
815
  //#region src/openai-stream-error.ts
@@ -542,6 +960,26 @@ function isRetryableStreamError(error, statusCode) {
542
960
  return isRetryableStatusCode(statusCode);
543
961
  }
544
962
  //#endregion
963
+ //#region src/resolve-openai-reasoning-effort.ts
964
+ const allOpenAIReasoningEfforts = [
965
+ "none",
966
+ "minimal",
967
+ "low",
968
+ "medium",
969
+ "high",
970
+ "xhigh",
971
+ "max"
972
+ ];
973
+ /** Resolve portable reasoning against the efforts declared by the catalog. */
974
+ function resolveOpenAIReasoningEffort({ providerReasoningEffort, reasoning, supportedReasoningEfforts, warnings }) {
975
+ return mapReasoningToProviderEffort({
976
+ reasoning,
977
+ providerOptionsEffort: providerReasoningEffort,
978
+ effortMap: Object.fromEntries((supportedReasoningEfforts ?? allOpenAIReasoningEfforts).map((effort) => [effort, effort])),
979
+ warnings
980
+ });
981
+ }
982
+ //#endregion
545
983
  //#region src/chat/convert-openai-chat-usage.ts
546
984
  function convertOpenAIChatUsage(usage) {
547
985
  if (usage == null) return createNullLanguageModelUsage();
@@ -568,7 +1006,14 @@ function convertOpenAIChatUsage(usage) {
568
1006
  //#endregion
569
1007
  //#region src/chat/convert-to-openai-chat-messages.ts
570
1008
  function serializeToolCallArguments$1(input) {
571
- return JSON.stringify(typeof input === "object" && input !== null && !Array.isArray(input) ? input : {});
1009
+ if (typeof input === "string") try {
1010
+ const parsed = secureJsonParse(input);
1011
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return "{}";
1012
+ return input;
1013
+ } catch {
1014
+ return "{}";
1015
+ }
1016
+ return stringifyWithBigIntAndCycles(typeof input === "object" && input !== null && !Array.isArray(input) ? input : {});
572
1017
  }
573
1018
  function getPromptCacheBreakpoint$1(providerOptions) {
574
1019
  return providerOptions?.openai?.promptCacheBreakpoint;
@@ -744,13 +1189,13 @@ function convertToOpenAIChatMessages({ prompt, systemMessageMode = "system" }) {
744
1189
  break;
745
1190
  case "error-text":
746
1191
  case "error-json":
747
- contentValue = JSON.stringify({ error: output.value });
1192
+ contentValue = stringifyWithBigIntAndCycles({ error: output.value });
748
1193
  break;
749
1194
  case "execution-denied":
750
1195
  contentValue = output.reason ?? "Tool call execution denied.";
751
1196
  break;
752
1197
  case "content":
753
- case "json": contentValue = JSON.stringify(output.value);
1198
+ case "json": contentValue = stringifyWithBigIntAndCycles(output.value);
754
1199
  }
755
1200
  messages.push({
756
1201
  role: "tool",
@@ -1264,8 +1709,8 @@ var OpenAIChatLanguageModel = class OpenAIChatLanguageModel {
1264
1709
  providerOptions,
1265
1710
  schema: openaiLanguageModelChatOptions
1266
1711
  }) ?? {};
1267
- const modelCapabilities = getOpenAILanguageModelCapabilities(this.modelId);
1268
- const requiresNoReasoningEffort = !modelCapabilities.supportsChatFunctionToolsWithReasoning && openaiOptions.reasoningEffort == null && (tools?.some((tool) => tool.type === "function") ?? false);
1712
+ const { capabilities: { language: modelCapabilities }, requestConfig: { language: modelRequestConfig } } = getOpenAILanguageModelEntry(this.modelId);
1713
+ const requiresNoReasoningEffort = !modelCapabilities.endpoints.chat.functionToolsWithReasoning && openaiOptions.reasoningEffort == null && (tools?.some((tool) => tool.type === "function") ?? false);
1269
1714
  if (requiresNoReasoningEffort && isCustomReasoning(reasoning) && reasoning !== "none") warnings.push({
1270
1715
  type: "compatibility",
1271
1716
  feature: "reasoning",
@@ -1274,10 +1719,10 @@ var OpenAIChatLanguageModel = class OpenAIChatLanguageModel {
1274
1719
  const resolvedReasoningEffort = requiresNoReasoningEffort ? "none" : resolveOpenAIReasoningEffort({
1275
1720
  providerReasoningEffort: openaiOptions.reasoningEffort,
1276
1721
  reasoning,
1277
- supportedReasoningEfforts: modelCapabilities.supportedReasoningEfforts?.filter((effort) => effort !== "max"),
1722
+ supportedReasoningEfforts: modelCapabilities.reasoning.efforts?.filter((effort) => effort !== "max"),
1278
1723
  warnings
1279
1724
  });
1280
- const isReasoningModel = openaiOptions.forceReasoning ?? modelCapabilities.isReasoningModel;
1725
+ const isReasoningModel = openaiOptions.forceReasoning ?? modelCapabilities.reasoning.support === true;
1281
1726
  if (topK != null) warnings.push({
1282
1727
  type: "unsupported",
1283
1728
  feature: "topK"
@@ -1289,7 +1734,7 @@ var OpenAIChatLanguageModel = class OpenAIChatLanguageModel {
1289
1734
  });
1290
1735
  const { messages, warnings: messageWarnings } = convertToOpenAIChatMessages({
1291
1736
  prompt,
1292
- systemMessageMode: openaiOptions.systemMessageMode ?? (isReasoningModel ? "developer" : modelCapabilities.systemMessageMode)
1737
+ systemMessageMode: openaiOptions.systemMessageMode ?? (isReasoningModel ? "developer" : modelRequestConfig.systemMessageMode)
1293
1738
  });
1294
1739
  warnings.push(...messageWarnings);
1295
1740
  const strictJsonSchema = openaiOptions.strictJsonSchema ?? true;
@@ -1331,7 +1776,7 @@ var OpenAIChatLanguageModel = class OpenAIChatLanguageModel {
1331
1776
  safety_identifier: openaiOptions.safetyIdentifier,
1332
1777
  messages
1333
1778
  };
1334
- if (modelCapabilities.supportsConfigurationUpdate && baseArgs.prompt_cache_retention != null) {
1779
+ if (!modelCapabilities.promptCache.retention && baseArgs.prompt_cache_retention != null) {
1335
1780
  baseArgs.prompt_cache_retention = void 0;
1336
1781
  warnings.push({
1337
1782
  type: "unsupported",
@@ -1340,7 +1785,7 @@ var OpenAIChatLanguageModel = class OpenAIChatLanguageModel {
1340
1785
  });
1341
1786
  }
1342
1787
  if (isReasoningModel) {
1343
- if (resolvedReasoningEffort !== "none" || !modelCapabilities.supportsNonReasoningParameters) {
1788
+ if (resolvedReasoningEffort !== "none" || modelCapabilities.reasoning.sampling !== "reasoning-effort-none") {
1344
1789
  if (baseArgs.temperature != null) {
1345
1790
  baseArgs.temperature = void 0;
1346
1791
  warnings.push({
@@ -1399,7 +1844,7 @@ var OpenAIChatLanguageModel = class OpenAIChatLanguageModel {
1399
1844
  if (baseArgs.max_completion_tokens == null) baseArgs.max_completion_tokens = baseArgs.max_tokens;
1400
1845
  baseArgs.max_tokens = void 0;
1401
1846
  }
1402
- } else if (this.modelId.startsWith("gpt-4o-search-preview") || this.modelId.startsWith("gpt-4o-mini-search-preview")) {
1847
+ } else if (!modelCapabilities.endpoints.chat.temperatureWithoutReasoning) {
1403
1848
  if (baseArgs.temperature != null) {
1404
1849
  baseArgs.temperature = void 0;
1405
1850
  warnings.push({
@@ -1409,7 +1854,7 @@ var OpenAIChatLanguageModel = class OpenAIChatLanguageModel {
1409
1854
  });
1410
1855
  }
1411
1856
  }
1412
- if (openaiOptions.serviceTier === "flex" && !modelCapabilities.supportsFlexProcessing) {
1857
+ if (openaiOptions.serviceTier === "flex" && !modelCapabilities.serviceTiers.flex) {
1413
1858
  warnings.push({
1414
1859
  type: "unsupported",
1415
1860
  feature: "serviceTier",
@@ -1417,7 +1862,7 @@ var OpenAIChatLanguageModel = class OpenAIChatLanguageModel {
1417
1862
  });
1418
1863
  baseArgs.service_tier = void 0;
1419
1864
  }
1420
- if ((openaiOptions.serviceTier === "priority" || openaiOptions.serviceTier === "fast") && !modelCapabilities.supportsPriorityProcessing) {
1865
+ if ((openaiOptions.serviceTier === "priority" || openaiOptions.serviceTier === "fast") && !modelCapabilities.serviceTiers.priority) {
1421
1866
  warnings.push({
1422
1867
  type: "unsupported",
1423
1868
  feature: "serviceTier",
@@ -1445,7 +1890,7 @@ var OpenAIChatLanguageModel = class OpenAIChatLanguageModel {
1445
1890
  path: "/chat/completions",
1446
1891
  modelId: this.config.requestModelId ?? this.modelId
1447
1892
  }),
1448
- headers: combineHeaders(this.config.headers?.(), options.headers),
1893
+ headers: combineHeaders(await resolve(this.config.headers), options.headers),
1449
1894
  body,
1450
1895
  failedResponseHandler: openaiFailedResponseHandler,
1451
1896
  successfulResponseHandler: createJsonResponseHandler(openaiChatResponseSchema),
@@ -1511,7 +1956,7 @@ var OpenAIChatLanguageModel = class OpenAIChatLanguageModel {
1511
1956
  });
1512
1957
  const { responseHeaders, value: response } = await postJsonToApi({
1513
1958
  url,
1514
- headers: combineHeaders(this.config.headers?.(), options.headers),
1959
+ headers: combineHeaders(await resolve(this.config.headers), options.headers),
1515
1960
  body,
1516
1961
  failedResponseHandler: openaiFailedResponseHandler,
1517
1962
  successfulResponseHandler: createEventSourceResponseHandler(openaiChatChunkSchema),
@@ -1888,7 +2333,7 @@ var OpenAICompletionLanguageModel = class OpenAICompletionLanguageModel {
1888
2333
  path: "/completions",
1889
2334
  modelId: this.config.requestModelId ?? this.modelId
1890
2335
  }),
1891
- headers: combineHeaders(this.config.headers?.(), options.headers),
2336
+ headers: combineHeaders(await resolve(this.config.headers), options.headers),
1892
2337
  body: args,
1893
2338
  failedResponseHandler: openaiFailedResponseHandler,
1894
2339
  successfulResponseHandler: createJsonResponseHandler(openaiCompletionResponseSchema),
@@ -1931,7 +2376,7 @@ var OpenAICompletionLanguageModel = class OpenAICompletionLanguageModel {
1931
2376
  });
1932
2377
  const { responseHeaders, value: response } = await postJsonToApi({
1933
2378
  url,
1934
- headers: combineHeaders(this.config.headers?.(), options.headers),
2379
+ headers: combineHeaders(await resolve(this.config.headers), options.headers),
1935
2380
  body,
1936
2381
  failedResponseHandler: openaiFailedResponseHandler,
1937
2382
  successfulResponseHandler: createEventSourceResponseHandler(openaiCompletionChunkSchema),
@@ -2094,7 +2539,7 @@ var OpenAIEmbeddingModel = class OpenAIEmbeddingModel {
2094
2539
  path: "/embeddings",
2095
2540
  modelId: this.modelId
2096
2541
  }),
2097
- headers: combineHeaders(this.config.headers?.(), headers),
2542
+ headers: combineHeaders(await resolve(this.config.headers), headers),
2098
2543
  body: {
2099
2544
  model: this.modelId,
2100
2545
  input: values,
@@ -2159,8 +2604,8 @@ var OpenAIFiles = class {
2159
2604
  });
2160
2605
  return fileId;
2161
2606
  }
2162
- getHeaders(headers) {
2163
- return combineHeaders(this.config.headers(), headers);
2607
+ async getHeaders(headers) {
2608
+ return combineHeaders(await resolve(this.config.headers), headers);
2164
2609
  }
2165
2610
  async uploadFile({ data, mediaType, filename, abortSignal, headers, providerOptions }) {
2166
2611
  let openaiOptions;
@@ -2175,7 +2620,7 @@ var OpenAIFiles = class {
2175
2620
  throw error;
2176
2621
  }
2177
2622
  const purpose = openaiOptions?.purpose ?? "assistants";
2178
- const requestHeaders = this.getHeaders(headers);
2623
+ const requestHeaders = await this.getHeaders(headers);
2179
2624
  const url = `${this.config.baseURL}/files`;
2180
2625
  let response;
2181
2626
  if (data.type === "stream") {
@@ -2245,7 +2690,7 @@ var OpenAIFiles = class {
2245
2690
  const fileId = this.getFileId(file);
2246
2691
  const { value: response } = await getFromApi({
2247
2692
  url: `${this.config.baseURL}/files/${encodePathSegment(fileId)}`,
2248
- headers: this.getHeaders(headers),
2693
+ headers: await this.getHeaders(headers),
2249
2694
  failedResponseHandler: openaiFailedResponseHandler,
2250
2695
  successfulResponseHandler: createJsonResponseHandler(openaiFilesResponseSchema),
2251
2696
  abortSignal,
@@ -2266,7 +2711,7 @@ var OpenAIFiles = class {
2266
2711
  const fileId = this.getFileId(file);
2267
2712
  const { value: content, responseHeaders } = await getFromApi({
2268
2713
  url: `${this.config.baseURL}/files/${encodePathSegment(fileId)}/content`,
2269
- headers: this.getHeaders(headers),
2714
+ headers: await this.getHeaders(headers),
2270
2715
  failedResponseHandler: openaiFailedResponseHandler,
2271
2716
  successfulResponseHandler: createBinaryStreamResponseHandler(),
2272
2717
  abortSignal,
@@ -2284,7 +2729,7 @@ var OpenAIFiles = class {
2284
2729
  const fileId = this.getFileId(file);
2285
2730
  const { value: response } = await deleteFromApi({
2286
2731
  url: `${this.config.baseURL}/files/${encodePathSegment(fileId)}`,
2287
- headers: this.getHeaders(headers),
2732
+ headers: await this.getHeaders(headers),
2288
2733
  failedResponseHandler: openaiFailedResponseHandler,
2289
2734
  successfulResponseHandler: createJsonResponseHandler(openaiFileDeleteResponseSchema),
2290
2735
  abortSignal,
@@ -2331,25 +2776,11 @@ const openaiImageResponseSchema = lazySchema(() => zodSchema(z.object({
2331
2776
  })));
2332
2777
  //#endregion
2333
2778
  //#region src/image/openai-image-model-options.ts
2334
- const modelMaxImagesPerCall = {
2335
- "dall-e-3": 1,
2336
- "dall-e-2": 10,
2337
- "gpt-image-1": 10,
2338
- "gpt-image-1-mini": 10,
2339
- "gpt-image-1.5": 10,
2340
- "gpt-image-2": 10,
2341
- "gpt-image-2.5-flare": 10,
2342
- "gpt-image-2.5-flare-2026-09-08": 10,
2343
- "gpt-image-2.5-sunburst": 10,
2344
- "gpt-image-2.5-sunburst-2026-09-08": 10,
2345
- "chatgpt-image-latest": 10
2346
- };
2347
- const defaultResponseFormatPrefixes = ["chatgpt-image-", "gpt-image-"];
2348
2779
  function hasDefaultResponseFormat(modelId) {
2349
- return defaultResponseFormatPrefixes.some((prefix) => modelId.startsWith(prefix));
2780
+ return getOpenAIImageModelEntry(modelId).requestConfig.image.responseFormat === "provider-default";
2350
2781
  }
2351
2782
  function getMaxImagesPerCall(modelId) {
2352
- return modelMaxImagesPerCall[modelId] ?? (modelId.startsWith("gpt-image-") ? 10 : 1);
2783
+ return getOpenAIImageModelEntry(modelId).capabilities.image.maxImagesPerCall ?? 1;
2353
2784
  }
2354
2785
  const baseImageModelOptionsObject = () => z.object({
2355
2786
  /**
@@ -2434,23 +2865,13 @@ var OpenAIImageModel = class OpenAIImageModel {
2434
2865
  }
2435
2866
  get supportsFileInputs() {
2436
2867
  if (this.config.imageInputCapabilities != null) return this.config.imageInputCapabilities.supportsFileInputs;
2437
- if ([
2438
- "dall-e-2",
2439
- "gpt-image-1",
2440
- "gpt-image-1-mini",
2441
- "gpt-image-1.5",
2442
- "gpt-image-2",
2443
- "gpt-image-2.5-flare",
2444
- "gpt-image-2.5-flare-2026-09-08",
2445
- "gpt-image-2.5-sunburst",
2446
- "gpt-image-2.5-sunburst-2026-09-08",
2447
- "chatgpt-image-latest"
2448
- ].includes(this.modelId)) return true;
2449
- return this.modelId === "dall-e-3" ? false : void 0;
2868
+ const support = getOpenAIImageModelEntry(this.modelId).capabilities.image.fileInput;
2869
+ return typeof support === "boolean" ? support : void 0;
2450
2870
  }
2451
2871
  get supportsMaskInputs() {
2452
2872
  if (this.config.imageInputCapabilities != null) return this.config.imageInputCapabilities.supportsMaskInputs;
2453
- return this.supportsFileInputs;
2873
+ const support = getOpenAIImageModelEntry(this.modelId).capabilities.image.maskInput;
2874
+ return typeof support === "boolean" ? support : void 0;
2454
2875
  }
2455
2876
  get provider() {
2456
2877
  return this.config.provider;
@@ -2483,7 +2904,7 @@ var OpenAIImageModel = class OpenAIImageModel {
2483
2904
  path: "/images/edits",
2484
2905
  modelId: this.modelId
2485
2906
  }),
2486
- headers: combineHeaders(this.config.headers?.(), headers),
2907
+ headers: combineHeaders(await resolve(this.config.headers), headers),
2487
2908
  formData: convertToFormData({
2488
2909
  model: this.modelId,
2489
2910
  prompt,
@@ -2537,7 +2958,7 @@ var OpenAIImageModel = class OpenAIImageModel {
2537
2958
  path: "/images/generations",
2538
2959
  modelId: this.modelId
2539
2960
  }),
2540
- headers: combineHeaders(this.config.headers?.(), headers),
2961
+ headers: combineHeaders(await resolve(this.config.headers), headers),
2541
2962
  body: {
2542
2963
  model: this.modelId,
2543
2964
  prompt,
@@ -4703,7 +5124,13 @@ async function expandParallelToolCall({ toolCall, tools, providerOptionsName, it
4703
5124
  //#endregion
4704
5125
  //#region src/responses/convert-to-openai-responses-input.ts
4705
5126
  function serializeToolCallArguments(input) {
4706
- return JSON.stringify(input === void 0 ? {} : input);
5127
+ if (typeof input === "string") try {
5128
+ secureJsonParse(input);
5129
+ return input;
5130
+ } catch {
5131
+ return stringifyWithBigIntAndCycles(input);
5132
+ }
5133
+ return stringifyWithBigIntAndCycles(input === void 0 ? {} : input);
4707
5134
  }
4708
5135
  function mapToolCaller(caller) {
4709
5136
  return caller == null ? void 0 : caller.type === "program" ? {
@@ -4760,14 +5187,14 @@ async function convertFunctionToolResultOutput({ output, toolName, outputSchemaT
4760
5187
  prompt_cache_breakpoint: promptCacheBreakpoint
4761
5188
  }];
4762
5189
  switch (output.type) {
4763
- case "text": return convertScalarOutput(hasOutputSchema ? JSON.stringify(output.value) : output.value);
5190
+ case "text": return convertScalarOutput(hasOutputSchema ? stringifyWithBigIntAndCycles(output.value) : output.value);
4764
5191
  case "error-text":
4765
- case "error-json": return convertScalarOutput(JSON.stringify({ error: output.value }));
5192
+ case "error-json": return convertScalarOutput(stringifyWithBigIntAndCycles({ error: output.value }));
4766
5193
  case "execution-denied": {
4767
5194
  const reason = output.reason ?? "Tool call execution denied.";
4768
- return convertScalarOutput(hasOutputSchema ? JSON.stringify(reason) : reason);
5195
+ return convertScalarOutput(hasOutputSchema ? stringifyWithBigIntAndCycles(reason) : reason);
4769
5196
  }
4770
- case "json": return convertScalarOutput(JSON.stringify(output.value));
5197
+ case "json": return convertScalarOutput(stringifyWithBigIntAndCycles(output.value));
4771
5198
  case "content": return output.value.map((item) => {
4772
5199
  const promptCacheBreakpoint = getPromptCacheBreakpoint(item.providerOptions, providerOptionsName);
4773
5200
  switch (item.type) {
@@ -5249,7 +5676,7 @@ async function convertToOpenAIResponsesInput({ prompt, toolNameMapping, systemMe
5249
5676
  type: "custom_tool_call",
5250
5677
  call_id: part.toolCallId,
5251
5678
  name: resolvedToolName,
5252
- input: typeof part.input === "string" ? part.input : JSON.stringify(part.input),
5679
+ input: typeof part.input === "string" ? part.input : stringifyWithBigIntAndCycles(part.input),
5253
5680
  ...isAsync != null && { async: isAsync },
5254
5681
  id
5255
5682
  });
@@ -5396,7 +5823,7 @@ async function convertToOpenAIResponsesInput({ prompt, toolNameMapping, systemMe
5396
5823
  });
5397
5824
  else if (reasoningMessage !== void 0) warnings.push({
5398
5825
  type: "other",
5399
- message: `Cannot append empty reasoning part to existing reasoning sequence. Skipping reasoning part: ${JSON.stringify(part)}.`
5826
+ message: `Cannot append empty reasoning part to existing reasoning sequence. Skipping reasoning part: ${stringifyWithBigIntAndCycles(part)}.`
5400
5827
  });
5401
5828
  if (reasoningMessage === void 0) {
5402
5829
  reasoningMessages[reasoningId] = {
@@ -5426,7 +5853,7 @@ async function convertToOpenAIResponsesInput({ prompt, toolNameMapping, systemMe
5426
5853
  });
5427
5854
  } else warnings.push({
5428
5855
  type: "other",
5429
- message: `Non-OpenAI reasoning parts are not supported. Skipping reasoning part: ${JSON.stringify(part)}.`
5856
+ message: `Non-OpenAI reasoning parts are not supported. Skipping reasoning part: ${stringifyWithBigIntAndCycles(part)}.`
5430
5857
  });
5431
5858
  }
5432
5859
  break;
@@ -5494,7 +5921,7 @@ async function convertToOpenAIResponsesInput({ prompt, toolNameMapping, systemMe
5494
5921
  promptCacheBreakpoint
5495
5922
  };
5496
5923
  }));
5497
- const serializedToolOutputs = toolOutputs.map(({ output }) => typeof output === "string" ? output : JSON.stringify(output));
5924
+ const serializedToolOutputs = toolOutputs.map(({ output }) => typeof output === "string" ? output : stringifyWithBigIntAndCycles(output));
5498
5925
  const hasPromptCacheBreakpoint = toolOutputs.some(({ promptCacheBreakpoint }) => promptCacheBreakpoint != null);
5499
5926
  input.push({
5500
5927
  type: "function_call_output",
@@ -5612,13 +6039,13 @@ async function convertToOpenAIResponsesInput({ prompt, toolNameMapping, systemMe
5612
6039
  break;
5613
6040
  case "error-text":
5614
6041
  case "error-json":
5615
- outputValue = convertScalarOutput(JSON.stringify({ error: output.value }));
6042
+ outputValue = convertScalarOutput(stringifyWithBigIntAndCycles({ error: output.value }));
5616
6043
  break;
5617
6044
  case "execution-denied":
5618
6045
  outputValue = convertScalarOutput(output.reason ?? "Tool call execution denied.");
5619
6046
  break;
5620
6047
  case "json":
5621
- outputValue = convertScalarOutput(JSON.stringify(output.value));
6048
+ outputValue = convertScalarOutput(stringifyWithBigIntAndCycles(output.value));
5622
6049
  break;
5623
6050
  case "content":
5624
6051
  outputValue = output.value.map((item) => {
@@ -6311,7 +6738,7 @@ const openaiResponsesSupportedUrls = {
6311
6738
  * @see https://developers.openai.com/api/docs/guides/reasoning#change-reasoning-mid-conversation
6312
6739
  */
6313
6740
  function getConfigurationUpdateUnsupportedReason({ modelCapabilities, options }) {
6314
- if (!modelCapabilities.supportsConfigurationUpdate) return "reasoningEffortUpdate is only supported by GPT-6 and later models";
6741
+ if (!modelCapabilities.configurationUpdates) return "reasoningEffortUpdate is only supported by GPT-6 and later models";
6315
6742
  if (options?.reasoningMode === "pro" || options?.contextManagement != null || options?.truncation === "auto") return "reasoningEffortUpdate requires standard reasoning mode without automatic compaction or automatic truncation";
6316
6743
  }
6317
6744
  var OpenAIResponsesLanguageModel = class OpenAIResponsesLanguageModel {
@@ -6335,7 +6762,7 @@ var OpenAIResponsesLanguageModel = class OpenAIResponsesLanguageModel {
6335
6762
  }
6336
6763
  static async prepareRequest({ modelId, config, options: { maxOutputTokens, temperature, stopSequences, topP, topK, presencePenalty, frequencyPenalty, seed, prompt, reasoning, providerOptions, tools, toolChoice, responseFormat } }) {
6337
6764
  const warnings = [];
6338
- const modelCapabilities = getOpenAILanguageModelCapabilities(modelId);
6765
+ const { capabilities: { language: modelCapabilities }, requestConfig: { language: modelRequestConfig } } = getOpenAILanguageModelEntry(modelId);
6339
6766
  if (topK != null) warnings.push({
6340
6767
  type: "unsupported",
6341
6768
  feature: "topK"
@@ -6370,11 +6797,11 @@ var OpenAIResponsesLanguageModel = class OpenAIResponsesLanguageModel {
6370
6797
  const resolvedReasoningEffort = resolveOpenAIReasoningEffort({
6371
6798
  providerReasoningEffort: openaiOptions?.reasoningEffort,
6372
6799
  reasoning,
6373
- supportedReasoningEfforts: modelCapabilities.supportedReasoningEfforts,
6800
+ supportedReasoningEfforts: modelCapabilities.reasoning.efforts,
6374
6801
  warnings
6375
6802
  });
6376
6803
  const resolvedReasoningSummary = openaiOptions?.reasoningSummary !== void 0 ? openaiOptions.reasoningSummary : resolvedReasoningEffort != null && resolvedReasoningEffort !== "none" ? "detailed" : void 0;
6377
- const isReasoningModel = openaiOptions?.forceReasoning ?? modelCapabilities.isReasoningModel;
6804
+ const isReasoningModel = openaiOptions?.forceReasoning ?? modelCapabilities.reasoning.support === true;
6378
6805
  if (openaiOptions?.conversation && openaiOptions?.previousResponseId) warnings.push({
6379
6806
  type: "unsupported",
6380
6807
  feature: "conversation",
@@ -6406,7 +6833,7 @@ var OpenAIResponsesLanguageModel = class OpenAIResponsesLanguageModel {
6406
6833
  toolNameMapping,
6407
6834
  customProviderToolNames,
6408
6835
  outputSchemaToolNames,
6409
- supportsAsyncToolCalling: modelCapabilities.supportsAsyncToolCalling,
6836
+ supportsAsyncToolCalling: modelCapabilities.tools.async,
6410
6837
  providerOptionsName
6411
6838
  });
6412
6839
  const configurationUpdateUnsupportedReason = getConfigurationUpdateUnsupportedReason({
@@ -6416,7 +6843,7 @@ var OpenAIResponsesLanguageModel = class OpenAIResponsesLanguageModel {
6416
6843
  const { input, warnings: inputWarnings } = await convertToOpenAIResponsesInput({
6417
6844
  prompt,
6418
6845
  toolNameMapping,
6419
- systemMessageMode: openaiOptions?.systemMessageMode ?? (isReasoningModel ? "developer" : modelCapabilities.systemMessageMode),
6846
+ systemMessageMode: openaiOptions?.systemMessageMode ?? (isReasoningModel ? "developer" : modelRequestConfig.systemMessageMode),
6420
6847
  providerOptionsName,
6421
6848
  configurationUpdateUnsupportedReason,
6422
6849
  explicitMessageItemType: config.explicitMessageItemType,
@@ -6435,7 +6862,7 @@ var OpenAIResponsesLanguageModel = class OpenAIResponsesLanguageModel {
6435
6862
  outputSchemaToolNames: outputSchemaToolNames.size > 0 ? outputSchemaToolNames : void 0
6436
6863
  });
6437
6864
  warnings.push(...inputWarnings);
6438
- const supportedReasoningEfforts = modelCapabilities.supportedReasoningEfforts;
6865
+ const supportedReasoningEfforts = modelCapabilities.reasoning.efforts;
6439
6866
  const getUpdateEffortUnsupportedReason = (effort) => effort != null && supportedReasoningEfforts?.includes(effort) === false ? `${modelId} only supports the following reasoning efforts: ${supportedReasoningEfforts.join(", ")}` : void 0;
6440
6867
  for (const item of input) if (item.type === "configuration_update") {
6441
6868
  const unsupportedReason = getUpdateEffortUnsupportedReason(item.reasoning.effort);
@@ -6524,7 +6951,7 @@ var OpenAIResponsesLanguageModel = class OpenAIResponsesLanguageModel {
6524
6951
  ...openaiOptions?.reasoningContext != null && { context: openaiOptions.reasoningContext }
6525
6952
  } }
6526
6953
  };
6527
- if (modelCapabilities.supportsConfigurationUpdate && baseArgs.prompt_cache_retention != null) {
6954
+ if (!modelCapabilities.promptCache.retention && baseArgs.prompt_cache_retention != null) {
6528
6955
  baseArgs.prompt_cache_retention = void 0;
6529
6956
  warnings.push({
6530
6957
  type: "unsupported",
@@ -6535,7 +6962,7 @@ var OpenAIResponsesLanguageModel = class OpenAIResponsesLanguageModel {
6535
6962
  if (isReasoningModel) {
6536
6963
  let effectiveReasoningEffort = resolvedReasoningEffort;
6537
6964
  for (const item of input) if (item.type === "configuration_update") effectiveReasoningEffort = item.reasoning.effort;
6538
- if (!(effectiveReasoningEffort === "none" && modelCapabilities.supportsNonReasoningParameters)) {
6965
+ if (!(effectiveReasoningEffort === "none" && modelCapabilities.reasoning.sampling === "reasoning-effort-none")) {
6539
6966
  if (baseArgs.temperature != null) {
6540
6967
  baseArgs.temperature = void 0;
6541
6968
  warnings.push({
@@ -6552,7 +6979,7 @@ var OpenAIResponsesLanguageModel = class OpenAIResponsesLanguageModel {
6552
6979
  details: "topP is not supported for reasoning models"
6553
6980
  });
6554
6981
  }
6555
- if (modelCapabilities.supportsConfigurationUpdate && (baseArgs.top_logprobs != null || baseArgs.include?.includes("message.output_text.logprobs"))) {
6982
+ if (modelCapabilities.endpoints.responses.logprobsRequireNonReasoning && (baseArgs.top_logprobs != null || baseArgs.include?.includes("message.output_text.logprobs"))) {
6556
6983
  baseArgs.top_logprobs = void 0;
6557
6984
  const filteredInclude = baseArgs.include?.filter((value) => value !== "message.output_text.logprobs");
6558
6985
  baseArgs.include = filteredInclude != null && filteredInclude.length > 0 ? filteredInclude : void 0;
@@ -6585,7 +7012,7 @@ var OpenAIResponsesLanguageModel = class OpenAIResponsesLanguageModel {
6585
7012
  details: "reasoningContext is not supported for non-reasoning models"
6586
7013
  });
6587
7014
  }
6588
- if (openaiOptions?.serviceTier === "flex" && !modelCapabilities.supportsFlexProcessing) {
7015
+ if (openaiOptions?.serviceTier === "flex" && !modelCapabilities.serviceTiers.flex) {
6589
7016
  warnings.push({
6590
7017
  type: "unsupported",
6591
7018
  feature: "serviceTier",
@@ -6593,7 +7020,7 @@ var OpenAIResponsesLanguageModel = class OpenAIResponsesLanguageModel {
6593
7020
  });
6594
7021
  delete baseArgs.service_tier;
6595
7022
  }
6596
- if ((openaiOptions?.serviceTier === "priority" || openaiOptions?.serviceTier === "fast") && !modelCapabilities.supportsPriorityProcessing) {
7023
+ if ((openaiOptions?.serviceTier === "priority" || openaiOptions?.serviceTier === "fast") && !modelCapabilities.serviceTiers.priority) {
6597
7024
  warnings.push({
6598
7025
  type: "unsupported",
6599
7026
  feature: "serviceTier",
@@ -6633,7 +7060,7 @@ var OpenAIResponsesLanguageModel = class OpenAIResponsesLanguageModel {
6633
7060
  const approvalRequestIdToDummyToolCallIdFromPrompt = extractApprovalRequestIdToToolCallIdMapping(options.prompt);
6634
7061
  const { responseHeaders, value: response, rawValue: rawResponse } = await postJsonToApi({
6635
7062
  url,
6636
- headers: combineHeaders(this.config.headers?.(), options.headers),
7063
+ headers: combineHeaders(await resolve(this.config.headers), options.headers),
6637
7064
  body,
6638
7065
  failedResponseHandler: openaiFailedResponseHandler,
6639
7066
  successfulResponseHandler: createJsonResponseHandler(openaiResponsesResponseSchema),
@@ -7083,7 +7510,7 @@ var OpenAIResponsesLanguageModel = class OpenAIResponsesLanguageModel {
7083
7510
  });
7084
7511
  const { responseHeaders, value: response } = await postJsonToApi({
7085
7512
  url,
7086
- headers: combineHeaders(this.config.headers?.(), options.headers),
7513
+ headers: combineHeaders(await resolve(this.config.headers), options.headers),
7087
7514
  body: {
7088
7515
  ...body,
7089
7516
  stream: true
@@ -8236,7 +8663,7 @@ var OpenAIBatch = class {
8236
8663
  formData.append("expires_after[seconds]", String(inputFileExpiresAfterSeconds));
8237
8664
  const { value: uploadedFile } = await postToApi({
8238
8665
  url: this.getUrl("/files"),
8239
- headers: combineHeaders(this.options.config.headers?.(), options.headers),
8666
+ headers: combineHeaders(await resolve(this.options.config.headers), options.headers),
8240
8667
  body: {
8241
8668
  content: formData,
8242
8669
  values: {
@@ -8257,7 +8684,7 @@ var OpenAIBatch = class {
8257
8684
  });
8258
8685
  const { value: batch } = await postJsonToApi({
8259
8686
  url: this.getUrl("/batches"),
8260
- headers: combineHeaders(this.options.config.headers?.(), options.headers),
8687
+ headers: combineHeaders(await resolve(this.options.config.headers), options.headers),
8261
8688
  body: {
8262
8689
  input_file_id: uploadedFile.id,
8263
8690
  endpoint: openaiBatchEndpoint,
@@ -8299,7 +8726,7 @@ var OpenAIBatch = class {
8299
8726
  async doCancelBatch(options) {
8300
8727
  await postJsonToApi({
8301
8728
  url: this.getUrl(`/batches/${encodeURIComponent(options.batchId)}/cancel`),
8302
- headers: combineHeaders(this.options.config.headers?.(), options.headers),
8729
+ headers: combineHeaders(await resolve(this.options.config.headers), options.headers),
8303
8730
  body: {},
8304
8731
  failedResponseHandler: openaiFailedResponseHandler,
8305
8732
  successfulResponseHandler: createJsonResponseHandler(openaiBatchResponseSchema),
@@ -8314,7 +8741,7 @@ var OpenAIBatch = class {
8314
8741
  if (options.cursor != null) url.searchParams.set("after", options.cursor);
8315
8742
  const { value: page } = await getFromApi({
8316
8743
  url: url.toString(),
8317
- headers: combineHeaders(this.options.config.headers?.(), options.headers),
8744
+ headers: combineHeaders(await resolve(this.options.config.headers), options.headers),
8318
8745
  failedResponseHandler: openaiFailedResponseHandler,
8319
8746
  successfulResponseHandler: createJsonResponseHandler(openaiBatchListResponseSchema),
8320
8747
  abortSignal: options.abortSignal,
@@ -8350,7 +8777,7 @@ var OpenAIBatch = class {
8350
8777
  async retrieveBatch(options) {
8351
8778
  const { value: batch } = await getFromApi({
8352
8779
  url: this.getUrl(`/batches/${encodeURIComponent(options.batchId)}`),
8353
- headers: combineHeaders(this.options.config.headers?.(), options.headers),
8780
+ headers: combineHeaders(await resolve(this.options.config.headers), options.headers),
8354
8781
  failedResponseHandler: openaiFailedResponseHandler,
8355
8782
  successfulResponseHandler: createJsonResponseHandler(openaiBatchResponseSchema),
8356
8783
  abortSignal: options.abortSignal,
@@ -8363,7 +8790,7 @@ var OpenAIBatch = class {
8363
8790
  for (const fileId of fileIds) {
8364
8791
  const { value: lines } = await getFromApi({
8365
8792
  url: this.getUrl(`/files/${encodeURIComponent(fileId)}/content`),
8366
- headers: combineHeaders(this.options.config.headers?.(), options.headers),
8793
+ headers: combineHeaders(await resolve(this.options.config.headers), options.headers),
8367
8794
  failedResponseHandler: openaiFailedResponseHandler,
8368
8795
  successfulResponseHandler: createJsonLinesResponseHandler(openaiBatchResultLineSchema, { maxLineBytes: this.options.maxLineBytes }),
8369
8796
  abortSignal: options.abortSignal,
@@ -9036,13 +9463,7 @@ var OpenAIRealtimeModelLive = class {
9036
9463
  this.modelId = modelId;
9037
9464
  this.config = config;
9038
9465
  this.specificationVersion = "v4";
9039
- this.capabilities = {
9040
- conversation: "continuous",
9041
- transports: ["websocket", "webrtc"],
9042
- connections: ["server-websocket", "webrtc"],
9043
- startup: "session-start",
9044
- finalization: "session-close"
9045
- };
9466
+ this.capabilities = openaiLiveRealtimeCapabilities;
9046
9467
  }
9047
9468
  get provider() {
9048
9469
  return this.config.provider;
@@ -9051,20 +9472,22 @@ var OpenAIRealtimeModelLive = class {
9051
9472
  return { dataChannelLabel: "oai-events" };
9052
9473
  }
9053
9474
  getServerWebSocketConfig() {
9054
- const url = new URL(`${this.config.baseURL}/live/sessions`);
9055
- url.protocol = url.protocol === "http:" ? "ws:" : "wss:";
9056
- const headers = {};
9057
- for (const [key, value] of Object.entries(this.config.headers())) if (value !== void 0) headers[key] = value;
9058
- return {
9059
- url: url.toString(),
9060
- headers
9061
- };
9475
+ return resolveWith(this.config.headers, (configHeaders) => {
9476
+ const url = new URL(`${this.config.baseURL}/live/sessions`);
9477
+ url.protocol = url.protocol === "http:" ? "ws:" : "wss:";
9478
+ const headers = {};
9479
+ for (const [key, value] of Object.entries(configHeaders)) if (value !== void 0) headers[key] = value;
9480
+ return {
9481
+ url: url.toString(),
9482
+ headers
9483
+ };
9484
+ });
9062
9485
  }
9063
9486
  async doCreateWebRTCSession({ sdp, sessionConfig = {}, abortSignal }) {
9064
9487
  const session = buildOpenAILiveSessionConfig(sessionConfig, this.modelId, "webrtc");
9065
9488
  const { value } = await postJsonToApi({
9066
9489
  url: `${this.config.baseURL}/live/sessions`,
9067
- headers: this.config.headers(),
9490
+ headers: await resolve(this.config.headers),
9068
9491
  body: {
9069
9492
  session,
9070
9493
  transport: {
@@ -9393,7 +9816,7 @@ var OpenAIRealtimeModel = class {
9393
9816
  const response = await fetchFn(url, {
9394
9817
  method: "POST",
9395
9818
  headers: {
9396
- ...this.config.headers(),
9819
+ ...await resolve(this.config.headers),
9397
9820
  "Content-Type": "application/json"
9398
9821
  },
9399
9822
  body: JSON.stringify({
@@ -9433,7 +9856,6 @@ var OpenAIRealtimeModel = class {
9433
9856
  };
9434
9857
  //#endregion
9435
9858
  //#region src/realtime/openai-realtime-factory.ts
9436
- const knownLiveModelIds = ["gpt-live-1"];
9437
9859
  function resolveRealtimeApi(modelId, { api } = {}) {
9438
9860
  if (api !== void 0) {
9439
9861
  if (api !== "live" && api !== "realtime") throw new InvalidArgumentError({
@@ -9442,7 +9864,7 @@ function resolveRealtimeApi(modelId, { api } = {}) {
9442
9864
  });
9443
9865
  return api;
9444
9866
  }
9445
- return knownLiveModelIds.some((knownModelId) => knownModelId === modelId) ? "live" : "realtime";
9867
+ return getOpenAIRealtimeModelEntry(modelId).requestConfig.realtime.api;
9446
9868
  }
9447
9869
  function createOpenAIRealtimeFactory(config) {
9448
9870
  const createModel = (modelId, options) => {
@@ -9551,7 +9973,7 @@ var OpenAISpeechModel = class OpenAISpeechModel {
9551
9973
  path: "/audio/speech",
9552
9974
  modelId: this.modelId
9553
9975
  }),
9554
- headers: combineHeaders(this.config.headers?.(), options.headers),
9976
+ headers: combineHeaders(await resolve(this.config.headers), options.headers),
9555
9977
  body: requestBody,
9556
9978
  failedResponseHandler: openaiFailedResponseHandler,
9557
9979
  successfulResponseHandler: createBinaryResponseHandler(),
@@ -9616,6 +10038,16 @@ const openAITranscriptionModelOptions = lazySchema(() => zodSchema(z.object({
9616
10038
  */
9617
10039
  language: z.string().optional(),
9618
10040
  /**
10041
+ * Expected languages for REST transcription, e.g. with gpt-transcribe.
10042
+ * Use this instead of language. The API validates model support.
10043
+ */
10044
+ languages: z.array(z.string()).optional(),
10045
+ /**
10046
+ * Vocabulary hints for REST transcription, e.g. names or technical terms.
10047
+ * The API validates model support.
10048
+ */
10049
+ keywords: z.array(z.string()).optional(),
10050
+ /**
9619
10051
  * An optional text to guide the model's style or continue a previous audio segment.
9620
10052
  */
9621
10053
  prompt: z.string().optional(),
@@ -9668,34 +10100,6 @@ const openAITranscriptionModelOptions = lazySchema(() => zodSchema(z.object({
9668
10100
  })));
9669
10101
  //#endregion
9670
10102
  //#region src/transcription/openai-transcription-model.ts
9671
- /**
9672
- * Whether `modelId` is `base` or one of its dated snapshots
9673
- * (e.g. `gpt-realtime-whisper-2026-01-01`).
9674
- */
9675
- function isModelOrSnapshot(modelId, base) {
9676
- return modelId === base || modelId.startsWith(`${base}-`);
9677
- }
9678
- /**
9679
- * Model IDs that stream over the realtime transcription WebSocket and do not
9680
- * support the REST transcription endpoint.
9681
- */
9682
- function isRealtimeTranscriptionModelId(modelId) {
9683
- return isModelOrSnapshot(modelId, "gpt-realtime-whisper") || isModelOrSnapshot(modelId, "gpt-live-transcribe");
9684
- }
9685
- /**
9686
- * Model IDs that support streaming transcription. `gpt-transcribe` also
9687
- * supports the REST transcription endpoint.
9688
- */
9689
- function supportsStreamingTranscription(modelId) {
9690
- return isRealtimeTranscriptionModelId(modelId) || isModelOrSnapshot(modelId, "gpt-transcribe");
9691
- }
9692
- /**
9693
- * Models whose realtime transcription session takes a `languages` list
9694
- * instead of the singular `language` field.
9695
- */
9696
- function usesLanguagesList(modelId) {
9697
- return isModelOrSnapshot(modelId, "gpt-live-transcribe") || isModelOrSnapshot(modelId, "gpt-transcribe");
9698
- }
9699
10103
  const languageMap = {
9700
10104
  afrikaans: "af",
9701
10105
  arabic: "ar",
@@ -9788,14 +10192,16 @@ var OpenAITranscriptionModel = class OpenAITranscriptionModel {
9788
10192
  formData.append("model", this.modelId);
9789
10193
  const fileExtension = mediaTypeToExtension(mediaType);
9790
10194
  formData.append("file", new File([blob], "audio", { type: mediaType }), `audio.${fileExtension}`);
9791
- const isDiarizationModel = this.modelId === "gpt-4o-transcribe-diarize";
9792
- const responseFormat = openAIOptions?.responseFormat ?? (isDiarizationModel ? "diarized_json" : this.modelId === "whisper-1" ? "verbose_json" : void 0);
10195
+ const { transcription: requestConfig } = getOpenAITranscriptionModelEntry(this.modelId).requestConfig;
10196
+ const responseFormat = openAIOptions?.responseFormat ?? requestConfig.responseFormat;
9793
10197
  const timestampGranularities = openAIOptions?.timestampGranularities ?? (responseFormat === "verbose_json" ? ["segment"] : void 0);
9794
- const chunkingStrategy = openAIOptions?.chunkingStrategy ?? (isDiarizationModel ? "auto" : void 0);
10198
+ const chunkingStrategy = openAIOptions?.chunkingStrategy ?? requestConfig.chunkingStrategy;
9795
10199
  const transcriptionModelOptions = {
9796
10200
  response_format: responseFormat,
9797
10201
  include: openAIOptions?.include,
9798
10202
  language: openAIOptions?.language,
10203
+ languages: openAIOptions?.languages,
10204
+ keywords: openAIOptions?.keywords,
9799
10205
  prompt: openAIOptions?.prompt,
9800
10206
  temperature: openAIOptions?.temperature,
9801
10207
  timestamp_granularities: timestampGranularities
@@ -9816,7 +10222,7 @@ var OpenAITranscriptionModel = class OpenAITranscriptionModel {
9816
10222
  };
9817
10223
  }
9818
10224
  async doGenerate(options) {
9819
- if (isRealtimeTranscriptionModelId(this.modelId)) throw new UnsupportedFunctionalityError({ functionality: `non-streaming transcription with ${this.modelId}` });
10225
+ if (getOpenAITranscriptionModelEntry(this.modelId).capabilities.transcription.transcription === false) throw new UnsupportedFunctionalityError({ functionality: `non-streaming transcription with ${this.modelId}` });
9820
10226
  const currentDate = this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date();
9821
10227
  const { formData, warnings } = await this.getArgs(options);
9822
10228
  const { value: response, responseHeaders, rawValue: rawResponse } = await postFormDataToApi({
@@ -9824,7 +10230,7 @@ var OpenAITranscriptionModel = class OpenAITranscriptionModel {
9824
10230
  path: "/audio/transcriptions",
9825
10231
  modelId: this.modelId
9826
10232
  }),
9827
- headers: combineHeaders(this.config.headers?.(), options.headers),
10233
+ headers: combineHeaders(await resolve(this.config.headers), options.headers),
9828
10234
  formData,
9829
10235
  failedResponseHandler: openaiFailedResponseHandler,
9830
10236
  successfulResponseHandler: createJsonResponseHandler(openaiTranscriptionResponseSchema),
@@ -9866,7 +10272,8 @@ var OpenAITranscriptionModel = class OpenAITranscriptionModel {
9866
10272
  };
9867
10273
  }
9868
10274
  async doStream(options) {
9869
- if (!supportsStreamingTranscription(this.modelId)) throw new UnsupportedFunctionalityError({ functionality: `streaming transcription with ${this.modelId}` });
10275
+ const entry = getOpenAITranscriptionModelEntry(this.modelId);
10276
+ if (entry.capabilities.transcription.streaming !== true) throw new UnsupportedFunctionalityError({ functionality: `streaming transcription with ${this.modelId}` });
9870
10277
  const currentDate = this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date();
9871
10278
  const openAIOptions = await parseProviderOptions({
9872
10279
  provider: "openai",
@@ -9877,6 +10284,8 @@ var OpenAITranscriptionModel = class OpenAITranscriptionModel {
9877
10284
  const rawOpenAIOptions = options.providerOptions?.openai ?? {};
9878
10285
  for (const option of [
9879
10286
  "include",
10287
+ "languages",
10288
+ "keywords",
9880
10289
  "prompt",
9881
10290
  "temperature",
9882
10291
  "timestampGranularities"
@@ -9885,13 +10294,13 @@ var OpenAITranscriptionModel = class OpenAITranscriptionModel {
9885
10294
  feature: `providerOptions.openai.${option}`,
9886
10295
  details: `OpenAI streaming transcription does not support ${option}.`
9887
10296
  });
9888
- const supportsDelay = !isModelOrSnapshot(this.modelId, "gpt-transcribe");
10297
+ const supportsDelay = entry.capabilities.transcription.streamingDelay === true;
9889
10298
  if (!supportsDelay && openAIOptions?.streaming?.delay != null) warnings.push({
9890
10299
  type: "unsupported",
9891
10300
  feature: "providerOptions.openai.streaming.delay",
9892
10301
  details: `OpenAI streaming transcription with ${this.modelId} does not support delay.`
9893
10302
  });
9894
- const headers = combineHeaders(this.config.headers?.(), options.headers);
10303
+ const headers = combineHeaders(await resolve(this.config.headers), options.headers);
9895
10304
  const sessionUpdate = buildOpenAIRealtimeTranscriptionSession({
9896
10305
  modelId: this.modelId,
9897
10306
  inputAudioFormat: options.inputAudioFormat,
@@ -10043,7 +10452,7 @@ function buildOpenAIRealtimeTranscriptionSession({ modelId, inputAudioFormat, pr
10043
10452
  },
10044
10453
  transcription: {
10045
10454
  model: modelId,
10046
- ...providerOptions?.language != null ? usesLanguagesList(modelId) ? { languages: [providerOptions.language] } : { language: providerOptions.language } : {},
10455
+ ...providerOptions?.language != null ? getOpenAITranscriptionModelEntry(modelId).requestConfig.transcription.languageField === "languages" ? { languages: [providerOptions.language] } : { language: providerOptions.language } : {},
10047
10456
  ...supportsDelay && providerOptions?.streaming?.delay != null ? { delay: providerOptions.streaming.delay } : {}
10048
10457
  },
10049
10458
  turn_detection: null
@@ -10111,7 +10520,7 @@ var OpenAISpeechTranslationModel = class OpenAISpeechTranslationModel {
10111
10520
  feature: "outputAudioFormat",
10112
10521
  details: "The OpenAI Realtime translation API always outputs 24kHz 16-bit PCM audio and does not accept an output audio format."
10113
10522
  });
10114
- const headers = combineHeaders(this.config.headers?.(), options.headers);
10523
+ const headers = combineHeaders(await resolve(this.config.headers), options.headers);
10115
10524
  const sessionUpdate = buildOpenAIRealtimeSpeechTranslationSession({ targetLanguage: options.targetLanguage });
10116
10525
  return {
10117
10526
  request: { body: sessionUpdate },
@@ -10336,7 +10745,7 @@ var OpenAISkills = class {
10336
10745
  }
10337
10746
  const { value: response } = await postFormDataToApi({
10338
10747
  url: this.config.url({ path: "/skills" }),
10339
- headers: combineHeaders(this.config.headers()),
10748
+ headers: combineHeaders(await resolve(this.config.headers)),
10340
10749
  formData,
10341
10750
  failedResponseHandler: openaiFailedResponseHandler,
10342
10751
  successfulResponseHandler: createJsonResponseHandler(openaiSkillResponseSchema),
@@ -10358,7 +10767,7 @@ var OpenAISkills = class {
10358
10767
  };
10359
10768
  //#endregion
10360
10769
  //#region src/version.ts
10361
- const VERSION = "4.0.105";
10770
+ const VERSION = "4.0.107";
10362
10771
  //#endregion
10363
10772
  //#region src/openai-provider.ts
10364
10773
  /**
@@ -10370,16 +10779,16 @@ function createOpenAI(options = {}) {
10370
10779
  environmentVariableName: "OPENAI_BASE_URL"
10371
10780
  }))) ?? "https://api.openai.com/v1";
10372
10781
  const providerName = options.name ?? "openai";
10373
- const getHeaders = () => withUserAgentSuffix({
10782
+ const getHeaders = () => resolveWith(options.apiKey, (apiKey) => withUserAgentSuffix({
10374
10783
  Authorization: `Bearer ${loadApiKey({
10375
- apiKey: options.apiKey,
10784
+ apiKey,
10376
10785
  environmentVariableName: "OPENAI_API_KEY",
10377
10786
  description: "OpenAI"
10378
10787
  })}`,
10379
10788
  "OpenAI-Organization": options.organization,
10380
10789
  "OpenAI-Project": options.project,
10381
10790
  ...options.headers
10382
- }, `ai-sdk-openai/${VERSION}`);
10791
+ }, `ai-sdk-openai/${VERSION}`));
10383
10792
  const createChatModel = (modelId) => new OpenAIChatLanguageModel(modelId, {
10384
10793
  provider: `${providerName}.chat`,
10385
10794
  url: ({ path }) => `${baseURL}${path}`,