@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
@@ -1,5 +1,5 @@
1
1
  import { APICallError, InvalidPromptError, InvalidResponseDataError, TooManyEmbeddingValuesForCallError, UnsupportedFunctionalityError, isJSONObject } from "@ai-sdk/provider";
2
- import { EXPERIMENTAL_EMBEDDING_MODEL_MAX_INPUT_BYTES_PER_CALL, StreamingToolCallTracker, WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE, combineHeaders, connectToWebSocket, convertBase64ToUint8Array, convertToBase64, convertToFormData, createBinaryResponseHandler, createEventSourceResponseHandler, createJsonErrorResponseHandler, createJsonResponseHandler, createLanguageModelResponseMetadata, createLanguageModelResponseMetadata as getResponseMetadata, createNullLanguageModelUsage, createProviderDefinedToolFactory, createProviderDefinedToolFactoryWithOutputSchema, createProviderExecutedToolFactory, createProviderStreamError, createToolNameMapping, downloadBlob, experimental_toolCaller, generateId, getTopLevelMediaType, isCustomReasoning, isNonNullable, isRecord, lazySchema, mapReasoningToProviderEffort, mediaTypeToExtension, parseJSON, parseProviderOptions, postFormDataToApi, postJsonToApi, resolveFullMediaType, resolveProviderReference, safeParseJSON, safeValidateTypes, serializeModelOptions, toWebSocketUrl, validateTypes, waitForWebSocketBufferDrain, zodSchema } from "@ai-sdk/provider-utils";
2
+ import { EXPERIMENTAL_EMBEDDING_MODEL_MAX_INPUT_BYTES_PER_CALL, StreamingToolCallTracker, WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE, combineHeaders, connectToWebSocket, convertBase64ToUint8Array, convertToBase64, convertToFormData, createBinaryResponseHandler, createEventSourceResponseHandler, createJsonErrorResponseHandler, createJsonResponseHandler, createLanguageModelResponseMetadata, createLanguageModelResponseMetadata as getResponseMetadata, createNullLanguageModelUsage, createProviderDefinedToolFactory, createProviderDefinedToolFactoryWithOutputSchema, createProviderExecutedToolFactory, createProviderStreamError, createToolNameMapping, downloadBlob, experimental_toolCaller, generateId, getTopLevelMediaType, isCustomReasoning, isNonNullable, isRecord, lazySchema, mapReasoningToProviderEffort, mediaTypeToExtension, parseJSON, parseProviderOptions, postFormDataToApi, postJsonToApi, resolve, resolveFullMediaType, resolveProviderReference, safeParseJSON, safeValidateTypes, secureJsonParse, serializeModelOptions, stringifyWithBigIntAndCycles, toWebSocketUrl, validateTypes, waitForWebSocketBufferDrain, zodSchema } from "@ai-sdk/provider-utils";
3
3
  import { z } from "zod/v4";
4
4
  //#region src/openai-error.ts
5
5
  const openaiErrorDataSchema = () => z.object({ error: z.object({
@@ -14,54 +14,182 @@ const openaiFailedResponseHandler = createJsonErrorResponseHandler({
14
14
  errorToMessage: (data) => data.error.message
15
15
  });
16
16
  //#endregion
17
- //#region src/openai-language-model-capabilities.ts
18
- const ALL_OPENAI_REASONING_EFFORTS = [
19
- "none",
20
- "minimal",
21
- "low",
22
- "medium",
23
- "high",
24
- "xhigh",
25
- "max"
26
- ];
27
- function getOpenAILanguageModelCapabilities(modelId) {
17
+ //#region src/openai-model-catalog.ts
18
+ /**
19
+ * Options accepted under `providerOptions.openai`. Language options are the
20
+ * Responses API options. The `satisfies` check keeps this list in sync with
21
+ * the option schema.
22
+ */
23
+ const openaiProviderOptions = { language: {
24
+ conversation: { description: "OpenAI Conversation ID to continue." },
25
+ include: { description: "Extra fields to include in the response." },
26
+ includeWebSearchSources: { description: "Include web search action sources." },
27
+ instructions: { description: "Instructions for the model." },
28
+ logprobs: { description: "Return token log probabilities." },
29
+ maxToolCalls: { description: "Maximum number of built-in tool calls." },
30
+ metadata: { description: "Metadata to store with the generation." },
31
+ parallelToolCalls: { description: "Whether to use parallel tool calls." },
32
+ previousResponseId: { description: "Previous response ID to continue." },
33
+ promptCacheKey: { description: "Cache key for prompt caching." },
34
+ promptCacheOptions: { description: "Prompt cache mode, TTL, and prewarm." },
35
+ promptCacheRetention: { description: "Prompt cache retention policy." },
36
+ reasoningEffort: { description: "Reasoning effort." },
37
+ reasoningEffortUpdate: { description: "Reasoning effort update from this response onward." },
38
+ reasoningMode: { description: "Standard or pro reasoning mode." },
39
+ reasoningContext: { description: "Which reasoning items can be used." },
40
+ reasoningSummary: { description: "Reasoning summary output." },
41
+ safetyIdentifier: { description: "Identifier for safety monitoring." },
42
+ serviceTier: { description: "Service tier for the request." },
43
+ store: { description: "Whether to store the generation." },
44
+ passThroughUnsupportedFiles: { description: "Send non-image file types as generic input files." },
45
+ strictJsonSchema: { description: "Use strict JSON schema validation." },
46
+ textVerbosity: { description: "Verbosity of text responses." },
47
+ truncation: { description: "Output truncation behavior." },
48
+ user: { description: "End-user identifier for abuse monitoring." },
49
+ systemMessageMode: { description: "System message role override." },
50
+ forceReasoning: { description: "Treat the model as a reasoning model." },
51
+ contextManagement: { description: "Server-side context compaction." },
52
+ compactionTrigger: { description: "Request explicit compaction." },
53
+ allowedTools: { description: "Restrict callable tools to a subset." }
54
+ } };
55
+ const configurableNonReasoning = { capabilities: { language: { reasoning: {
56
+ support: true,
57
+ efforts: [
58
+ "none",
59
+ "low",
60
+ "medium",
61
+ "high",
62
+ "xhigh",
63
+ "max"
64
+ ],
65
+ sampling: "reasoning-effort-none"
66
+ } } } };
67
+ const openaiLanguageModelEntries = Object.fromEntries(Object.entries({
68
+ "gpt-6-astra": {},
69
+ "gpt-6.1-sol": {},
70
+ "gpt-6.1-terra": configurableNonReasoning,
71
+ "gpt-6-luna": configurableNonReasoning,
72
+ "gpt-6-sol": configurableNonReasoning,
73
+ "gpt-5.6": {},
74
+ "gpt-5.6-luna": {},
75
+ "gpt-5.6-sol": {},
76
+ "gpt-5.6-terra": {},
77
+ "gpt-5.5": {},
78
+ "gpt-5.4-pro": {},
79
+ "gpt-5.4": {},
80
+ "gpt-5.4-mini": {},
81
+ "gpt-5.4-nano": {},
82
+ "gpt-5.3-chat-latest": {},
83
+ "gpt-5.2-pro": {},
84
+ "gpt-5.2-chat-latest": {},
85
+ "gpt-5.2": {},
86
+ "gpt-5.1-codex-mini": {},
87
+ "gpt-5.1-codex": {},
88
+ "gpt-5.1-chat-latest": {},
89
+ "gpt-5.1": {},
90
+ "gpt-5-pro": {},
91
+ "gpt-5": {},
92
+ "gpt-5-mini": {},
93
+ "gpt-5-nano": {},
94
+ "gpt-5-codex": {},
95
+ "gpt-5-chat-latest": { capabilities: { language: {
96
+ objectGeneration: false,
97
+ tools: {
98
+ usage: false,
99
+ streaming: false,
100
+ async: false
101
+ }
102
+ } } },
103
+ "gpt-4.1": {},
104
+ "gpt-4.1-mini": {},
105
+ "gpt-4.1-nano": {},
106
+ "gpt-4o": {},
107
+ "gpt-4o-mini": {}
108
+ }).map(([modelId, definition]) => [modelId, createOpenAILanguageModelEntry(modelId, definition)]));
109
+ function createOpenAILanguageModelEntry(modelId, definition) {
28
110
  const oSeriesVersion = getOSeriesVersion(modelId);
29
111
  const gptVersion = getGptVersion(modelId);
112
+ const isRecognizedModelFamily = oSeriesVersion != null || gptVersion != null || /^gpt-4o(?:-|$)/.test(modelId);
30
113
  const isGptChatModel = gptVersion?.minor == null && (gptVersion?.variant?.startsWith("chat") ?? false);
31
114
  const isGptNanoModel = gptVersion?.variant?.startsWith("nano") ?? false;
32
115
  const isGpt6OrLaterModel = gptVersion != null && gptVersion.major >= 6;
116
+ const isGpt56OrLaterModel = isGpt6OrLaterModel || gptVersion?.major === 5 && (gptVersion.minor ?? 0) >= 6;
33
117
  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));
34
- const isGpt6OrLaterModelWithNoneEffort = modelId === "gpt-6-sol" || modelId === "gpt-6-luna" || modelId === "gpt-6.1-terra";
35
118
  const supportsFlexProcessing = oSeriesVersion != null && oSeriesVersion >= 3 || gptVersion != null && gptVersion.major >= 5 && !isGptChatModel;
36
119
  const supportsPriorityProcessing = modelId.startsWith("gpt-4") || gptVersion != null && gptVersion.major >= 5 && !isGptNanoModel && !isGptChatModel || oSeriesVersion != null && oSeriesVersion >= 3;
37
120
  const isReasoningModel = oSeriesVersion != null || gptVersion != null && gptVersion.major >= 5 && !isGptChatModel;
38
- const supportsNonReasoningParameters = isGpt6OrLaterModelWithNoneEffort || !isGpt6OrLaterModel && gptVersion != null && (gptVersion.major > 5 || gptVersion.major === 5 && (gptVersion.minor ?? 0) >= 1);
39
- const systemMessageMode = isReasoningModel ? "developer" : "system";
121
+ const reasoningSampling = definition?.capabilities?.language?.reasoning?.sampling ?? (!isGpt6OrLaterModel && gptVersion != null && (gptVersion.major > 5 || gptVersion.major === 5 && (gptVersion.minor ?? 0) >= 1) ? "reasoning-effort-none" : "unsupported");
122
+ const sampling = !isRecognizedModelFamily ? "unknown" : !isReasoningModel ? true : reasoningSampling === "reasoning-effort-none" ? { condition: "Only when reasoning effort is none." } : false;
123
+ const chatTemperatureSupportedWithoutReasoning = !modelId.startsWith("gpt-4o-search-preview") && !modelId.startsWith("gpt-4o-mini-search-preview");
124
+ const entry = {
125
+ capabilities: { language: {
126
+ inputs: definition?.capabilities?.language?.inputs ?? {
127
+ image: definition != null ? true : "unknown",
128
+ audio: definition != null ? false : "unknown"
129
+ },
130
+ objectGeneration: definition?.capabilities?.language?.objectGeneration ?? (definition != null ? true : "unknown"),
131
+ tools: definition?.capabilities?.language?.tools ?? {
132
+ usage: definition != null ? true : "unknown",
133
+ streaming: definition != null ? true : "unknown",
134
+ async: isGpt6OrLaterModel
135
+ },
136
+ reasoning: {
137
+ support: isRecognizedModelFamily ? isReasoningModel : "unknown",
138
+ efforts: definition?.capabilities?.language?.reasoning?.efforts ?? (isGpt6OrLaterModel ? [
139
+ "low",
140
+ "medium",
141
+ "high",
142
+ "xhigh",
143
+ "max"
144
+ ] : isStandardGpt5Model ? getGpt5ReasoningEfforts(gptVersion.minor ?? 0) : void 0),
145
+ sampling: reasoningSampling
146
+ },
147
+ sampling: {
148
+ temperature: chatTemperatureSupportedWithoutReasoning ? sampling : { condition: "Not supported by Chat Completions search preview models." },
149
+ topP: sampling,
150
+ 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
151
+ },
152
+ serviceTiers: {
153
+ flex: supportsFlexProcessing,
154
+ priority: supportsPriorityProcessing
155
+ },
156
+ configurationUpdates: isGpt6OrLaterModel,
157
+ promptCache: {
158
+ retention: !isGpt6OrLaterModel,
159
+ options: isRecognizedModelFamily ? isGpt56OrLaterModel : "unknown"
160
+ },
161
+ endpoints: {
162
+ chat: {
163
+ temperatureWithoutReasoning: chatTemperatureSupportedWithoutReasoning,
164
+ functionToolsWithReasoning: !(gptVersion?.major === 5 && (gptVersion.minor ?? 0) >= 6)
165
+ },
166
+ responses: { logprobsRequireNonReasoning: isGpt6OrLaterModel }
167
+ }
168
+ } },
169
+ requestConfig: { language: { systemMessageMode: definition?.requestConfig?.language?.systemMessageMode ?? (isReasoningModel ? "developer" : "system") } }
170
+ };
171
+ const { language } = entry.capabilities;
40
172
  return {
41
- supportsFlexProcessing,
42
- supportsPriorityProcessing,
43
- supportsConfigurationUpdate: isGpt6OrLaterModel,
44
- supportsAsyncToolCalling: isGpt6OrLaterModel,
45
- supportedReasoningEfforts: isGpt6OrLaterModelWithNoneEffort ? [
46
- "none",
47
- "low",
48
- "medium",
49
- "high",
50
- "xhigh",
51
- "max"
52
- ] : isGpt6OrLaterModel ? [
53
- "low",
54
- "medium",
55
- "high",
56
- "xhigh",
57
- "max"
58
- ] : isStandardGpt5Model ? getGpt5ReasoningEfforts(gptVersion.minor ?? 0) : void 0,
59
- supportsChatFunctionToolsWithReasoning: !(gptVersion?.major === 5 && (gptVersion.minor ?? 0) >= 6),
60
- isReasoningModel,
61
- systemMessageMode,
62
- supportsNonReasoningParameters
173
+ ...entry,
174
+ providerOptions: { language: declareProviderOptions(openaiProviderOptions.language, definition != null ? true : "unknown", {
175
+ logprobs: language.sampling.logprobs,
176
+ maxToolCalls: language.tools.usage,
177
+ parallelToolCalls: language.tools.usage,
178
+ allowedTools: language.tools.usage,
179
+ reasoningEffort: language.reasoning.support,
180
+ reasoningSummary: language.reasoning.support,
181
+ reasoningMode: language.reasoning.support,
182
+ reasoningContext: language.reasoning.support,
183
+ reasoningEffortUpdate: language.configurationUpdates,
184
+ promptCacheOptions: language.promptCache.options,
185
+ promptCacheRetention: language.promptCache.retention
186
+ }) }
63
187
  };
64
188
  }
189
+ /** Applies one default support value to every option, except the listed ones. */
190
+ function declareProviderOptions(definitions, support, exceptions) {
191
+ return Object.fromEntries(Object.keys(definitions).map((option) => [option, exceptions[option] ?? support]));
192
+ }
65
193
  function getGpt5ReasoningEfforts(minor) {
66
194
  if (minor === 0) return [
67
195
  "minimal",
@@ -97,27 +225,303 @@ function getOSeriesVersion(modelId) {
97
225
  }
98
226
  function getGptVersion(modelId) {
99
227
  const match = /^gpt-(\d+)(?:\.(\d+))?(?:-(.+))?$/.exec(modelId);
100
- if (match == null) return;
101
- return {
228
+ return match == null ? void 0 : {
102
229
  major: Number(match[1]),
103
230
  minor: match[2] == null ? void 0 : Number(match[2]),
104
231
  variant: match[3]
105
232
  };
106
233
  }
234
+ const openaiEmbeddingModelEntries = {
235
+ "text-embedding-3-large": { capabilities: { embedding: {
236
+ defaultDimensions: 3072,
237
+ customDimensions: true
238
+ } } },
239
+ "text-embedding-3-small": { capabilities: { embedding: {
240
+ defaultDimensions: 1536,
241
+ customDimensions: true
242
+ } } },
243
+ "text-embedding-ada-002": { capabilities: { embedding: {
244
+ defaultDimensions: 1536,
245
+ customDimensions: false
246
+ } } }
247
+ };
248
+ const gptImageSizes = [
249
+ "1024x1024",
250
+ "1536x1024",
251
+ "1024x1536"
252
+ ];
253
+ const customImageSizes = { description: "Standard presets and custom dimensions" };
254
+ function createGptImageEntry(sizes) {
255
+ return {
256
+ capabilities: { image: {
257
+ sizes,
258
+ fileInput: true,
259
+ maskInput: true,
260
+ maxImagesPerCall: 10
261
+ } },
262
+ requestConfig: { image: { responseFormat: "provider-default" } }
263
+ };
264
+ }
265
+ const openaiImageModelEntries = {
266
+ "gpt-image-2.5-flare": createGptImageEntry(customImageSizes),
267
+ "gpt-image-2.5-sunburst": createGptImageEntry(customImageSizes),
268
+ "gpt-image-2": createGptImageEntry(gptImageSizes),
269
+ "gpt-image-1.5": createGptImageEntry(gptImageSizes),
270
+ "gpt-image-1-mini": createGptImageEntry(gptImageSizes),
271
+ "gpt-image-1": createGptImageEntry(gptImageSizes),
272
+ "dall-e-3": {
273
+ capabilities: { image: {
274
+ sizes: [
275
+ "1024x1024",
276
+ "1792x1024",
277
+ "1024x1792"
278
+ ],
279
+ fileInput: false,
280
+ maskInput: false,
281
+ maxImagesPerCall: 1
282
+ } },
283
+ requestConfig: { image: { responseFormat: "b64_json" } }
284
+ },
285
+ "dall-e-2": {
286
+ capabilities: { image: {
287
+ sizes: [
288
+ "256x256",
289
+ "512x512",
290
+ "1024x1024"
291
+ ],
292
+ fileInput: true,
293
+ maskInput: true,
294
+ maxImagesPerCall: 10
295
+ } },
296
+ requestConfig: { image: { responseFormat: "b64_json" } }
297
+ }
298
+ };
299
+ const imageModelAliases = {
300
+ "gpt-image-2.5-flare-2026-09-08": openaiImageModelEntries["gpt-image-2.5-flare"],
301
+ "gpt-image-2.5-sunburst-2026-09-08": openaiImageModelEntries["gpt-image-2.5-sunburst"],
302
+ "chatgpt-image-latest": createGptImageEntry({ description: "Unknown" })
303
+ };
304
+ function resolveOpenAIImageModelEntry(modelId) {
305
+ if (Object.prototype.hasOwnProperty.call(openaiImageModelEntries, modelId)) return openaiImageModelEntries[modelId];
306
+ if (Object.prototype.hasOwnProperty.call(imageModelAliases, modelId)) return imageModelAliases[modelId];
307
+ return {
308
+ capabilities: { image: {
309
+ sizes: { description: "Unknown" },
310
+ fileInput: "unknown",
311
+ maskInput: "unknown",
312
+ maxImagesPerCall: modelId.startsWith("gpt-image-") ? 10 : 1
313
+ } },
314
+ requestConfig: { image: { responseFormat: modelId.startsWith("chatgpt-image-") || modelId.startsWith("gpt-image-") ? "provider-default" : "b64_json" } }
315
+ };
316
+ }
317
+ const openaiImageModelMaxImagesPerCall = Object.fromEntries(Object.entries({
318
+ ...openaiImageModelEntries,
319
+ ...imageModelAliases
320
+ }).map(([modelId, entry]) => [modelId, entry.capabilities.image.maxImagesPerCall ?? 1]));
321
+ const defaultTranscriptionRequestConfig = { languageField: "language" };
322
+ const openaiTranscriptionModelEntries = {
323
+ "whisper-1": {
324
+ capabilities: { transcription: {
325
+ transcription: true,
326
+ streaming: false,
327
+ streamingDelay: false,
328
+ duration: true,
329
+ segments: true,
330
+ language: true
331
+ } },
332
+ requestConfig: { transcription: {
333
+ ...defaultTranscriptionRequestConfig,
334
+ responseFormat: "verbose_json"
335
+ } }
336
+ },
337
+ "gpt-4o-mini-transcribe": {
338
+ capabilities: { transcription: {
339
+ transcription: true,
340
+ streaming: false,
341
+ streamingDelay: false,
342
+ duration: false,
343
+ segments: false,
344
+ language: false
345
+ } },
346
+ requestConfig: { transcription: defaultTranscriptionRequestConfig }
347
+ },
348
+ "gpt-4o-transcribe": {
349
+ capabilities: { transcription: {
350
+ transcription: true,
351
+ streaming: false,
352
+ streamingDelay: false,
353
+ duration: false,
354
+ segments: false,
355
+ language: false
356
+ } },
357
+ requestConfig: { transcription: defaultTranscriptionRequestConfig }
358
+ },
359
+ "gpt-4o-transcribe-diarize": {
360
+ capabilities: { transcription: {
361
+ transcription: true,
362
+ streaming: false,
363
+ streamingDelay: false,
364
+ duration: true,
365
+ segments: true,
366
+ language: false
367
+ } },
368
+ requestConfig: { transcription: {
369
+ ...defaultTranscriptionRequestConfig,
370
+ responseFormat: "diarized_json",
371
+ chunkingStrategy: "auto"
372
+ } }
373
+ },
374
+ "gpt-transcribe": {
375
+ capabilities: { transcription: {
376
+ transcription: true,
377
+ streaming: true,
378
+ streamingDelay: false,
379
+ duration: false,
380
+ segments: false,
381
+ language: true
382
+ } },
383
+ requestConfig: { transcription: { languageField: "languages" } }
384
+ },
385
+ "gpt-live-transcribe": {
386
+ capabilities: { transcription: {
387
+ transcription: false,
388
+ streaming: true,
389
+ streamingDelay: true,
390
+ duration: false,
391
+ segments: false,
392
+ language: false
393
+ } },
394
+ requestConfig: { transcription: { languageField: "languages" } }
395
+ },
396
+ "gpt-realtime-whisper": {
397
+ capabilities: { transcription: {
398
+ transcription: false,
399
+ streaming: true,
400
+ streamingDelay: true,
401
+ duration: false,
402
+ segments: false,
403
+ language: false
404
+ } },
405
+ requestConfig: { transcription: defaultTranscriptionRequestConfig }
406
+ }
407
+ };
408
+ const transcriptionSnapshotModelIds = [
409
+ "gpt-transcribe",
410
+ "gpt-live-transcribe",
411
+ "gpt-realtime-whisper"
412
+ ];
413
+ function resolveOpenAITranscriptionModelEntry(modelId) {
414
+ if (Object.prototype.hasOwnProperty.call(openaiTranscriptionModelEntries, modelId)) return openaiTranscriptionModelEntries[modelId];
415
+ for (const baseModelId of transcriptionSnapshotModelIds) if (modelId.startsWith(`${baseModelId}-`)) return openaiTranscriptionModelEntries[baseModelId];
416
+ return {
417
+ capabilities: { transcription: {
418
+ transcription: "unknown",
419
+ streaming: "unknown",
420
+ streamingDelay: "unknown",
421
+ duration: "unknown",
422
+ segments: "unknown",
423
+ language: "unknown"
424
+ } },
425
+ requestConfig: { transcription: defaultTranscriptionRequestConfig }
426
+ };
427
+ }
428
+ const openaiSpeechTranslationModelEntries = { "gpt-realtime-translate": { capabilities: { speechTranslation: {
429
+ translatedAudio: true,
430
+ translatedText: true,
431
+ sourceTranscript: true
432
+ } } } };
433
+ const openaiSpeechModelEntries = {
434
+ "tts-1": { capabilities: { speech: { instructions: false } } },
435
+ "tts-1-hd": { capabilities: { speech: { instructions: false } } },
436
+ "gpt-4o-mini-tts": { capabilities: { speech: { instructions: true } } }
437
+ };
438
+ const liveModelEntry = {
439
+ capabilities: { realtime: {
440
+ conversation: "continuous",
441
+ transports: ["websocket", "webrtc"],
442
+ connections: ["server-websocket", "webrtc"]
443
+ } },
444
+ requestConfig: { realtime: {
445
+ api: "live",
446
+ startup: "session-start",
447
+ finalization: "session-close"
448
+ } }
449
+ };
450
+ const realtimeModelEntries = {
451
+ "gpt-live-1": liveModelEntry,
452
+ "gpt-realtime": {
453
+ capabilities: { realtime: {
454
+ conversation: "turn-based",
455
+ transports: ["websocket"],
456
+ connections: ["client-secret-websocket"]
457
+ } },
458
+ requestConfig: { realtime: {
459
+ api: "realtime",
460
+ startup: "session-update",
461
+ finalization: "transport-close"
462
+ } }
463
+ }
464
+ };
465
+ ({ ...liveModelEntry.capabilities.realtime }), liveModelEntry.requestConfig.realtime.startup, liveModelEntry.requestConfig.realtime.finalization;
107
466
  /**
108
- * Resolves the reasoning effort to send to OpenAI.
109
- *
110
- * A reasoning effort from provider options is sent unchanged. Otherwise the
111
- * top-level reasoning value is mapped to the closest effort that the model
112
- * family supports, or sent directly when the supported efforts are not known.
467
+ * The catalog consumed by request builders and documentation. Source declarations
468
+ * are grouped by operation; entries for the same model combine their sections.
469
+ * An absent section is undeclared, not an instruction to reject a request.
113
470
  */
114
- function resolveOpenAIReasoningEffort({ providerReasoningEffort, reasoning, supportedReasoningEfforts, warnings }) {
115
- return mapReasoningToProviderEffort({
116
- reasoning,
117
- providerOptionsEffort: providerReasoningEffort,
118
- effortMap: Object.fromEntries((supportedReasoningEfforts ?? ALL_OPENAI_REASONING_EFFORTS).map((effort) => [effort, effort])),
119
- warnings
120
- });
471
+ const openaiModelCatalog = combineModelEntries([
472
+ openaiLanguageModelEntries,
473
+ openaiEmbeddingModelEntries,
474
+ openaiImageModelEntries,
475
+ openaiTranscriptionModelEntries,
476
+ openaiSpeechTranslationModelEntries,
477
+ openaiSpeechModelEntries,
478
+ realtimeModelEntries
479
+ ]);
480
+ function combineModelEntries(catalogs) {
481
+ const entries = /* @__PURE__ */ new Map();
482
+ for (const catalog of catalogs) for (const [modelId, entry] of Object.entries(catalog)) {
483
+ const previous = entries.get(modelId);
484
+ entries.set(modelId, {
485
+ capabilities: {
486
+ ...previous?.capabilities,
487
+ ...entry.capabilities
488
+ },
489
+ ...previous?.providerOptions != null || entry.providerOptions != null ? { providerOptions: {
490
+ ...previous?.providerOptions,
491
+ ...entry.providerOptions
492
+ } } : {},
493
+ ...previous?.requestConfig != null || entry.requestConfig != null ? { requestConfig: {
494
+ ...previous?.requestConfig,
495
+ ...entry.requestConfig
496
+ } } : {}
497
+ });
498
+ }
499
+ return Object.fromEntries(entries);
500
+ }
501
+ function findModelEntry(modelId) {
502
+ return Object.prototype.hasOwnProperty.call(openaiModelCatalog, modelId) ? openaiModelCatalog[modelId] : void 0;
503
+ }
504
+ function getOpenAILanguageModelEntry(modelId) {
505
+ const entry = findModelEntry(modelId);
506
+ return entry?.capabilities.language != null && entry.providerOptions?.language != null && entry.requestConfig?.language != null ? {
507
+ capabilities: { language: entry.capabilities.language },
508
+ providerOptions: { language: entry.providerOptions.language },
509
+ requestConfig: { language: entry.requestConfig.language }
510
+ } : createOpenAILanguageModelEntry(modelId);
511
+ }
512
+ function getOpenAIImageModelEntry(modelId) {
513
+ const entry = findModelEntry(modelId);
514
+ return entry?.capabilities.image != null && entry.requestConfig?.image != null ? {
515
+ capabilities: { image: entry.capabilities.image },
516
+ requestConfig: { image: entry.requestConfig.image }
517
+ } : resolveOpenAIImageModelEntry(modelId);
518
+ }
519
+ function getOpenAITranscriptionModelEntry(modelId) {
520
+ const entry = findModelEntry(modelId);
521
+ return entry?.capabilities.transcription != null && entry.requestConfig?.transcription != null ? {
522
+ capabilities: { transcription: entry.capabilities.transcription },
523
+ requestConfig: { transcription: entry.requestConfig.transcription }
524
+ } : resolveOpenAITranscriptionModelEntry(modelId);
121
525
  }
122
526
  //#endregion
123
527
  //#region src/openai-stream-error.ts
@@ -268,6 +672,26 @@ function isRetryableStreamError(error, statusCode) {
268
672
  return isRetryableStatusCode(statusCode);
269
673
  }
270
674
  //#endregion
675
+ //#region src/resolve-openai-reasoning-effort.ts
676
+ const allOpenAIReasoningEfforts = [
677
+ "none",
678
+ "minimal",
679
+ "low",
680
+ "medium",
681
+ "high",
682
+ "xhigh",
683
+ "max"
684
+ ];
685
+ /** Resolve portable reasoning against the efforts declared by the catalog. */
686
+ function resolveOpenAIReasoningEffort({ providerReasoningEffort, reasoning, supportedReasoningEfforts, warnings }) {
687
+ return mapReasoningToProviderEffort({
688
+ reasoning,
689
+ providerOptionsEffort: providerReasoningEffort,
690
+ effortMap: Object.fromEntries((supportedReasoningEfforts ?? allOpenAIReasoningEfforts).map((effort) => [effort, effort])),
691
+ warnings
692
+ });
693
+ }
694
+ //#endregion
271
695
  //#region src/chat/convert-openai-chat-usage.ts
272
696
  function convertOpenAIChatUsage(usage) {
273
697
  if (usage == null) return createNullLanguageModelUsage();
@@ -294,7 +718,14 @@ function convertOpenAIChatUsage(usage) {
294
718
  //#endregion
295
719
  //#region src/chat/convert-to-openai-chat-messages.ts
296
720
  function serializeToolCallArguments$1(input) {
297
- return JSON.stringify(typeof input === "object" && input !== null && !Array.isArray(input) ? input : {});
721
+ if (typeof input === "string") try {
722
+ const parsed = secureJsonParse(input);
723
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return "{}";
724
+ return input;
725
+ } catch {
726
+ return "{}";
727
+ }
728
+ return stringifyWithBigIntAndCycles(typeof input === "object" && input !== null && !Array.isArray(input) ? input : {});
298
729
  }
299
730
  function getPromptCacheBreakpoint$1(providerOptions) {
300
731
  return providerOptions?.openai?.promptCacheBreakpoint;
@@ -470,13 +901,13 @@ function convertToOpenAIChatMessages({ prompt, systemMessageMode = "system" }) {
470
901
  break;
471
902
  case "error-text":
472
903
  case "error-json":
473
- contentValue = JSON.stringify({ error: output.value });
904
+ contentValue = stringifyWithBigIntAndCycles({ error: output.value });
474
905
  break;
475
906
  case "execution-denied":
476
907
  contentValue = output.reason ?? "Tool call execution denied.";
477
908
  break;
478
909
  case "content":
479
- case "json": contentValue = JSON.stringify(output.value);
910
+ case "json": contentValue = stringifyWithBigIntAndCycles(output.value);
480
911
  }
481
912
  messages.push({
482
913
  role: "tool",
@@ -990,8 +1421,8 @@ var OpenAIChatLanguageModel = class OpenAIChatLanguageModel {
990
1421
  providerOptions,
991
1422
  schema: openaiLanguageModelChatOptions
992
1423
  }) ?? {};
993
- const modelCapabilities = getOpenAILanguageModelCapabilities(this.modelId);
994
- const requiresNoReasoningEffort = !modelCapabilities.supportsChatFunctionToolsWithReasoning && openaiOptions.reasoningEffort == null && (tools?.some((tool) => tool.type === "function") ?? false);
1424
+ const { capabilities: { language: modelCapabilities }, requestConfig: { language: modelRequestConfig } } = getOpenAILanguageModelEntry(this.modelId);
1425
+ const requiresNoReasoningEffort = !modelCapabilities.endpoints.chat.functionToolsWithReasoning && openaiOptions.reasoningEffort == null && (tools?.some((tool) => tool.type === "function") ?? false);
995
1426
  if (requiresNoReasoningEffort && isCustomReasoning(reasoning) && reasoning !== "none") warnings.push({
996
1427
  type: "compatibility",
997
1428
  feature: "reasoning",
@@ -1000,10 +1431,10 @@ var OpenAIChatLanguageModel = class OpenAIChatLanguageModel {
1000
1431
  const resolvedReasoningEffort = requiresNoReasoningEffort ? "none" : resolveOpenAIReasoningEffort({
1001
1432
  providerReasoningEffort: openaiOptions.reasoningEffort,
1002
1433
  reasoning,
1003
- supportedReasoningEfforts: modelCapabilities.supportedReasoningEfforts?.filter((effort) => effort !== "max"),
1434
+ supportedReasoningEfforts: modelCapabilities.reasoning.efforts?.filter((effort) => effort !== "max"),
1004
1435
  warnings
1005
1436
  });
1006
- const isReasoningModel = openaiOptions.forceReasoning ?? modelCapabilities.isReasoningModel;
1437
+ const isReasoningModel = openaiOptions.forceReasoning ?? modelCapabilities.reasoning.support === true;
1007
1438
  if (topK != null) warnings.push({
1008
1439
  type: "unsupported",
1009
1440
  feature: "topK"
@@ -1015,7 +1446,7 @@ var OpenAIChatLanguageModel = class OpenAIChatLanguageModel {
1015
1446
  });
1016
1447
  const { messages, warnings: messageWarnings } = convertToOpenAIChatMessages({
1017
1448
  prompt,
1018
- systemMessageMode: openaiOptions.systemMessageMode ?? (isReasoningModel ? "developer" : modelCapabilities.systemMessageMode)
1449
+ systemMessageMode: openaiOptions.systemMessageMode ?? (isReasoningModel ? "developer" : modelRequestConfig.systemMessageMode)
1019
1450
  });
1020
1451
  warnings.push(...messageWarnings);
1021
1452
  const strictJsonSchema = openaiOptions.strictJsonSchema ?? true;
@@ -1057,7 +1488,7 @@ var OpenAIChatLanguageModel = class OpenAIChatLanguageModel {
1057
1488
  safety_identifier: openaiOptions.safetyIdentifier,
1058
1489
  messages
1059
1490
  };
1060
- if (modelCapabilities.supportsConfigurationUpdate && baseArgs.prompt_cache_retention != null) {
1491
+ if (!modelCapabilities.promptCache.retention && baseArgs.prompt_cache_retention != null) {
1061
1492
  baseArgs.prompt_cache_retention = void 0;
1062
1493
  warnings.push({
1063
1494
  type: "unsupported",
@@ -1066,7 +1497,7 @@ var OpenAIChatLanguageModel = class OpenAIChatLanguageModel {
1066
1497
  });
1067
1498
  }
1068
1499
  if (isReasoningModel) {
1069
- if (resolvedReasoningEffort !== "none" || !modelCapabilities.supportsNonReasoningParameters) {
1500
+ if (resolvedReasoningEffort !== "none" || modelCapabilities.reasoning.sampling !== "reasoning-effort-none") {
1070
1501
  if (baseArgs.temperature != null) {
1071
1502
  baseArgs.temperature = void 0;
1072
1503
  warnings.push({
@@ -1125,7 +1556,7 @@ var OpenAIChatLanguageModel = class OpenAIChatLanguageModel {
1125
1556
  if (baseArgs.max_completion_tokens == null) baseArgs.max_completion_tokens = baseArgs.max_tokens;
1126
1557
  baseArgs.max_tokens = void 0;
1127
1558
  }
1128
- } else if (this.modelId.startsWith("gpt-4o-search-preview") || this.modelId.startsWith("gpt-4o-mini-search-preview")) {
1559
+ } else if (!modelCapabilities.endpoints.chat.temperatureWithoutReasoning) {
1129
1560
  if (baseArgs.temperature != null) {
1130
1561
  baseArgs.temperature = void 0;
1131
1562
  warnings.push({
@@ -1135,7 +1566,7 @@ var OpenAIChatLanguageModel = class OpenAIChatLanguageModel {
1135
1566
  });
1136
1567
  }
1137
1568
  }
1138
- if (openaiOptions.serviceTier === "flex" && !modelCapabilities.supportsFlexProcessing) {
1569
+ if (openaiOptions.serviceTier === "flex" && !modelCapabilities.serviceTiers.flex) {
1139
1570
  warnings.push({
1140
1571
  type: "unsupported",
1141
1572
  feature: "serviceTier",
@@ -1143,7 +1574,7 @@ var OpenAIChatLanguageModel = class OpenAIChatLanguageModel {
1143
1574
  });
1144
1575
  baseArgs.service_tier = void 0;
1145
1576
  }
1146
- if ((openaiOptions.serviceTier === "priority" || openaiOptions.serviceTier === "fast") && !modelCapabilities.supportsPriorityProcessing) {
1577
+ if ((openaiOptions.serviceTier === "priority" || openaiOptions.serviceTier === "fast") && !modelCapabilities.serviceTiers.priority) {
1147
1578
  warnings.push({
1148
1579
  type: "unsupported",
1149
1580
  feature: "serviceTier",
@@ -1171,7 +1602,7 @@ var OpenAIChatLanguageModel = class OpenAIChatLanguageModel {
1171
1602
  path: "/chat/completions",
1172
1603
  modelId: this.config.requestModelId ?? this.modelId
1173
1604
  }),
1174
- headers: combineHeaders(this.config.headers?.(), options.headers),
1605
+ headers: combineHeaders(await resolve(this.config.headers), options.headers),
1175
1606
  body,
1176
1607
  failedResponseHandler: openaiFailedResponseHandler,
1177
1608
  successfulResponseHandler: createJsonResponseHandler(openaiChatResponseSchema),
@@ -1237,7 +1668,7 @@ var OpenAIChatLanguageModel = class OpenAIChatLanguageModel {
1237
1668
  });
1238
1669
  const { responseHeaders, value: response } = await postJsonToApi({
1239
1670
  url,
1240
- headers: combineHeaders(this.config.headers?.(), options.headers),
1671
+ headers: combineHeaders(await resolve(this.config.headers), options.headers),
1241
1672
  body,
1242
1673
  failedResponseHandler: openaiFailedResponseHandler,
1243
1674
  successfulResponseHandler: createEventSourceResponseHandler(openaiChatChunkSchema),
@@ -1614,7 +2045,7 @@ var OpenAICompletionLanguageModel = class OpenAICompletionLanguageModel {
1614
2045
  path: "/completions",
1615
2046
  modelId: this.config.requestModelId ?? this.modelId
1616
2047
  }),
1617
- headers: combineHeaders(this.config.headers?.(), options.headers),
2048
+ headers: combineHeaders(await resolve(this.config.headers), options.headers),
1618
2049
  body: args,
1619
2050
  failedResponseHandler: openaiFailedResponseHandler,
1620
2051
  successfulResponseHandler: createJsonResponseHandler(openaiCompletionResponseSchema),
@@ -1657,7 +2088,7 @@ var OpenAICompletionLanguageModel = class OpenAICompletionLanguageModel {
1657
2088
  });
1658
2089
  const { responseHeaders, value: response } = await postJsonToApi({
1659
2090
  url,
1660
- headers: combineHeaders(this.config.headers?.(), options.headers),
2091
+ headers: combineHeaders(await resolve(this.config.headers), options.headers),
1661
2092
  body,
1662
2093
  failedResponseHandler: openaiFailedResponseHandler,
1663
2094
  successfulResponseHandler: createEventSourceResponseHandler(openaiCompletionChunkSchema),
@@ -1820,7 +2251,7 @@ var OpenAIEmbeddingModel = class OpenAIEmbeddingModel {
1820
2251
  path: "/embeddings",
1821
2252
  modelId: this.modelId
1822
2253
  }),
1823
- headers: combineHeaders(this.config.headers?.(), headers),
2254
+ headers: combineHeaders(await resolve(this.config.headers), headers),
1824
2255
  body: {
1825
2256
  model: this.modelId,
1826
2257
  input: values,
@@ -1868,25 +2299,12 @@ const openaiImageResponseSchema = lazySchema(() => zodSchema(z.object({
1868
2299
  })));
1869
2300
  //#endregion
1870
2301
  //#region src/image/openai-image-model-options.ts
1871
- const modelMaxImagesPerCall = {
1872
- "dall-e-3": 1,
1873
- "dall-e-2": 10,
1874
- "gpt-image-1": 10,
1875
- "gpt-image-1-mini": 10,
1876
- "gpt-image-1.5": 10,
1877
- "gpt-image-2": 10,
1878
- "gpt-image-2.5-flare": 10,
1879
- "gpt-image-2.5-flare-2026-09-08": 10,
1880
- "gpt-image-2.5-sunburst": 10,
1881
- "gpt-image-2.5-sunburst-2026-09-08": 10,
1882
- "chatgpt-image-latest": 10
1883
- };
1884
- const defaultResponseFormatPrefixes = ["chatgpt-image-", "gpt-image-"];
2302
+ const modelMaxImagesPerCall = openaiImageModelMaxImagesPerCall;
1885
2303
  function hasDefaultResponseFormat(modelId) {
1886
- return defaultResponseFormatPrefixes.some((prefix) => modelId.startsWith(prefix));
2304
+ return getOpenAIImageModelEntry(modelId).requestConfig.image.responseFormat === "provider-default";
1887
2305
  }
1888
2306
  function getMaxImagesPerCall(modelId) {
1889
- return modelMaxImagesPerCall[modelId] ?? (modelId.startsWith("gpt-image-") ? 10 : 1);
2307
+ return getOpenAIImageModelEntry(modelId).capabilities.image.maxImagesPerCall ?? 1;
1890
2308
  }
1891
2309
  const baseImageModelOptionsObject = () => z.object({
1892
2310
  /**
@@ -1971,23 +2389,13 @@ var OpenAIImageModel = class OpenAIImageModel {
1971
2389
  }
1972
2390
  get supportsFileInputs() {
1973
2391
  if (this.config.imageInputCapabilities != null) return this.config.imageInputCapabilities.supportsFileInputs;
1974
- if ([
1975
- "dall-e-2",
1976
- "gpt-image-1",
1977
- "gpt-image-1-mini",
1978
- "gpt-image-1.5",
1979
- "gpt-image-2",
1980
- "gpt-image-2.5-flare",
1981
- "gpt-image-2.5-flare-2026-09-08",
1982
- "gpt-image-2.5-sunburst",
1983
- "gpt-image-2.5-sunburst-2026-09-08",
1984
- "chatgpt-image-latest"
1985
- ].includes(this.modelId)) return true;
1986
- return this.modelId === "dall-e-3" ? false : void 0;
2392
+ const support = getOpenAIImageModelEntry(this.modelId).capabilities.image.fileInput;
2393
+ return typeof support === "boolean" ? support : void 0;
1987
2394
  }
1988
2395
  get supportsMaskInputs() {
1989
2396
  if (this.config.imageInputCapabilities != null) return this.config.imageInputCapabilities.supportsMaskInputs;
1990
- return this.supportsFileInputs;
2397
+ const support = getOpenAIImageModelEntry(this.modelId).capabilities.image.maskInput;
2398
+ return typeof support === "boolean" ? support : void 0;
1991
2399
  }
1992
2400
  get provider() {
1993
2401
  return this.config.provider;
@@ -2020,7 +2428,7 @@ var OpenAIImageModel = class OpenAIImageModel {
2020
2428
  path: "/images/edits",
2021
2429
  modelId: this.modelId
2022
2430
  }),
2023
- headers: combineHeaders(this.config.headers?.(), headers),
2431
+ headers: combineHeaders(await resolve(this.config.headers), headers),
2024
2432
  formData: convertToFormData({
2025
2433
  model: this.modelId,
2026
2434
  prompt,
@@ -2074,7 +2482,7 @@ var OpenAIImageModel = class OpenAIImageModel {
2074
2482
  path: "/images/generations",
2075
2483
  modelId: this.modelId
2076
2484
  }),
2077
- headers: combineHeaders(this.config.headers?.(), headers),
2485
+ headers: combineHeaders(await resolve(this.config.headers), headers),
2078
2486
  body: {
2079
2487
  model: this.modelId,
2080
2488
  prompt,
@@ -2190,6 +2598,16 @@ const openAITranscriptionModelOptions = lazySchema(() => zodSchema(z.object({
2190
2598
  */
2191
2599
  language: z.string().optional(),
2192
2600
  /**
2601
+ * Expected languages for REST transcription, e.g. with gpt-transcribe.
2602
+ * Use this instead of language. The API validates model support.
2603
+ */
2604
+ languages: z.array(z.string()).optional(),
2605
+ /**
2606
+ * Vocabulary hints for REST transcription, e.g. names or technical terms.
2607
+ * The API validates model support.
2608
+ */
2609
+ keywords: z.array(z.string()).optional(),
2610
+ /**
2193
2611
  * An optional text to guide the model's style or continue a previous audio segment.
2194
2612
  */
2195
2613
  prompt: z.string().optional(),
@@ -2242,34 +2660,6 @@ const openAITranscriptionModelOptions = lazySchema(() => zodSchema(z.object({
2242
2660
  })));
2243
2661
  //#endregion
2244
2662
  //#region src/transcription/openai-transcription-model.ts
2245
- /**
2246
- * Whether `modelId` is `base` or one of its dated snapshots
2247
- * (e.g. `gpt-realtime-whisper-2026-01-01`).
2248
- */
2249
- function isModelOrSnapshot(modelId, base) {
2250
- return modelId === base || modelId.startsWith(`${base}-`);
2251
- }
2252
- /**
2253
- * Model IDs that stream over the realtime transcription WebSocket and do not
2254
- * support the REST transcription endpoint.
2255
- */
2256
- function isRealtimeTranscriptionModelId(modelId) {
2257
- return isModelOrSnapshot(modelId, "gpt-realtime-whisper") || isModelOrSnapshot(modelId, "gpt-live-transcribe");
2258
- }
2259
- /**
2260
- * Model IDs that support streaming transcription. `gpt-transcribe` also
2261
- * supports the REST transcription endpoint.
2262
- */
2263
- function supportsStreamingTranscription(modelId) {
2264
- return isRealtimeTranscriptionModelId(modelId) || isModelOrSnapshot(modelId, "gpt-transcribe");
2265
- }
2266
- /**
2267
- * Models whose realtime transcription session takes a `languages` list
2268
- * instead of the singular `language` field.
2269
- */
2270
- function usesLanguagesList(modelId) {
2271
- return isModelOrSnapshot(modelId, "gpt-live-transcribe") || isModelOrSnapshot(modelId, "gpt-transcribe");
2272
- }
2273
2663
  const languageMap = {
2274
2664
  afrikaans: "af",
2275
2665
  arabic: "ar",
@@ -2362,14 +2752,16 @@ var OpenAITranscriptionModel = class OpenAITranscriptionModel {
2362
2752
  formData.append("model", this.modelId);
2363
2753
  const fileExtension = mediaTypeToExtension(mediaType);
2364
2754
  formData.append("file", new File([blob], "audio", { type: mediaType }), `audio.${fileExtension}`);
2365
- const isDiarizationModel = this.modelId === "gpt-4o-transcribe-diarize";
2366
- const responseFormat = openAIOptions?.responseFormat ?? (isDiarizationModel ? "diarized_json" : this.modelId === "whisper-1" ? "verbose_json" : void 0);
2755
+ const { transcription: requestConfig } = getOpenAITranscriptionModelEntry(this.modelId).requestConfig;
2756
+ const responseFormat = openAIOptions?.responseFormat ?? requestConfig.responseFormat;
2367
2757
  const timestampGranularities = openAIOptions?.timestampGranularities ?? (responseFormat === "verbose_json" ? ["segment"] : void 0);
2368
- const chunkingStrategy = openAIOptions?.chunkingStrategy ?? (isDiarizationModel ? "auto" : void 0);
2758
+ const chunkingStrategy = openAIOptions?.chunkingStrategy ?? requestConfig.chunkingStrategy;
2369
2759
  const transcriptionModelOptions = {
2370
2760
  response_format: responseFormat,
2371
2761
  include: openAIOptions?.include,
2372
2762
  language: openAIOptions?.language,
2763
+ languages: openAIOptions?.languages,
2764
+ keywords: openAIOptions?.keywords,
2373
2765
  prompt: openAIOptions?.prompt,
2374
2766
  temperature: openAIOptions?.temperature,
2375
2767
  timestamp_granularities: timestampGranularities
@@ -2390,7 +2782,7 @@ var OpenAITranscriptionModel = class OpenAITranscriptionModel {
2390
2782
  };
2391
2783
  }
2392
2784
  async doGenerate(options) {
2393
- if (isRealtimeTranscriptionModelId(this.modelId)) throw new UnsupportedFunctionalityError({ functionality: `non-streaming transcription with ${this.modelId}` });
2785
+ if (getOpenAITranscriptionModelEntry(this.modelId).capabilities.transcription.transcription === false) throw new UnsupportedFunctionalityError({ functionality: `non-streaming transcription with ${this.modelId}` });
2394
2786
  const currentDate = this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date();
2395
2787
  const { formData, warnings } = await this.getArgs(options);
2396
2788
  const { value: response, responseHeaders, rawValue: rawResponse } = await postFormDataToApi({
@@ -2398,7 +2790,7 @@ var OpenAITranscriptionModel = class OpenAITranscriptionModel {
2398
2790
  path: "/audio/transcriptions",
2399
2791
  modelId: this.modelId
2400
2792
  }),
2401
- headers: combineHeaders(this.config.headers?.(), options.headers),
2793
+ headers: combineHeaders(await resolve(this.config.headers), options.headers),
2402
2794
  formData,
2403
2795
  failedResponseHandler: openaiFailedResponseHandler,
2404
2796
  successfulResponseHandler: createJsonResponseHandler(openaiTranscriptionResponseSchema),
@@ -2440,7 +2832,8 @@ var OpenAITranscriptionModel = class OpenAITranscriptionModel {
2440
2832
  };
2441
2833
  }
2442
2834
  async doStream(options) {
2443
- if (!supportsStreamingTranscription(this.modelId)) throw new UnsupportedFunctionalityError({ functionality: `streaming transcription with ${this.modelId}` });
2835
+ const entry = getOpenAITranscriptionModelEntry(this.modelId);
2836
+ if (entry.capabilities.transcription.streaming !== true) throw new UnsupportedFunctionalityError({ functionality: `streaming transcription with ${this.modelId}` });
2444
2837
  const currentDate = this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date();
2445
2838
  const openAIOptions = await parseProviderOptions({
2446
2839
  provider: "openai",
@@ -2451,6 +2844,8 @@ var OpenAITranscriptionModel = class OpenAITranscriptionModel {
2451
2844
  const rawOpenAIOptions = options.providerOptions?.openai ?? {};
2452
2845
  for (const option of [
2453
2846
  "include",
2847
+ "languages",
2848
+ "keywords",
2454
2849
  "prompt",
2455
2850
  "temperature",
2456
2851
  "timestampGranularities"
@@ -2459,13 +2854,13 @@ var OpenAITranscriptionModel = class OpenAITranscriptionModel {
2459
2854
  feature: `providerOptions.openai.${option}`,
2460
2855
  details: `OpenAI streaming transcription does not support ${option}.`
2461
2856
  });
2462
- const supportsDelay = !isModelOrSnapshot(this.modelId, "gpt-transcribe");
2857
+ const supportsDelay = entry.capabilities.transcription.streamingDelay === true;
2463
2858
  if (!supportsDelay && openAIOptions?.streaming?.delay != null) warnings.push({
2464
2859
  type: "unsupported",
2465
2860
  feature: "providerOptions.openai.streaming.delay",
2466
2861
  details: `OpenAI streaming transcription with ${this.modelId} does not support delay.`
2467
2862
  });
2468
- const headers = combineHeaders(this.config.headers?.(), options.headers);
2863
+ const headers = combineHeaders(await resolve(this.config.headers), options.headers);
2469
2864
  const sessionUpdate = buildOpenAIRealtimeTranscriptionSession({
2470
2865
  modelId: this.modelId,
2471
2866
  inputAudioFormat: options.inputAudioFormat,
@@ -2617,7 +3012,7 @@ function buildOpenAIRealtimeTranscriptionSession({ modelId, inputAudioFormat, pr
2617
3012
  },
2618
3013
  transcription: {
2619
3014
  model: modelId,
2620
- ...providerOptions?.language != null ? usesLanguagesList(modelId) ? { languages: [providerOptions.language] } : { language: providerOptions.language } : {},
3015
+ ...providerOptions?.language != null ? getOpenAITranscriptionModelEntry(modelId).requestConfig.transcription.languageField === "languages" ? { languages: [providerOptions.language] } : { language: providerOptions.language } : {},
2621
3016
  ...supportsDelay && providerOptions?.streaming?.delay != null ? { delay: providerOptions.streaming.delay } : {}
2622
3017
  },
2623
3018
  turn_detection: null
@@ -2723,7 +3118,7 @@ var OpenAISpeechModel = class OpenAISpeechModel {
2723
3118
  path: "/audio/speech",
2724
3119
  modelId: this.modelId
2725
3120
  }),
2726
- headers: combineHeaders(this.config.headers?.(), options.headers),
3121
+ headers: combineHeaders(await resolve(this.config.headers), options.headers),
2727
3122
  body: requestBody,
2728
3123
  failedResponseHandler: openaiFailedResponseHandler,
2729
3124
  successfulResponseHandler: createBinaryResponseHandler(),
@@ -3457,7 +3852,13 @@ async function expandParallelToolCall({ toolCall, tools, providerOptionsName, it
3457
3852
  //#endregion
3458
3853
  //#region src/responses/convert-to-openai-responses-input.ts
3459
3854
  function serializeToolCallArguments(input) {
3460
- return JSON.stringify(input === void 0 ? {} : input);
3855
+ if (typeof input === "string") try {
3856
+ secureJsonParse(input);
3857
+ return input;
3858
+ } catch {
3859
+ return stringifyWithBigIntAndCycles(input);
3860
+ }
3861
+ return stringifyWithBigIntAndCycles(input === void 0 ? {} : input);
3461
3862
  }
3462
3863
  function mapToolCaller(caller) {
3463
3864
  return caller == null ? void 0 : caller.type === "program" ? {
@@ -3514,14 +3915,14 @@ async function convertFunctionToolResultOutput({ output, toolName, outputSchemaT
3514
3915
  prompt_cache_breakpoint: promptCacheBreakpoint
3515
3916
  }];
3516
3917
  switch (output.type) {
3517
- case "text": return convertScalarOutput(hasOutputSchema ? JSON.stringify(output.value) : output.value);
3918
+ case "text": return convertScalarOutput(hasOutputSchema ? stringifyWithBigIntAndCycles(output.value) : output.value);
3518
3919
  case "error-text":
3519
- case "error-json": return convertScalarOutput(JSON.stringify({ error: output.value }));
3920
+ case "error-json": return convertScalarOutput(stringifyWithBigIntAndCycles({ error: output.value }));
3520
3921
  case "execution-denied": {
3521
3922
  const reason = output.reason ?? "Tool call execution denied.";
3522
- return convertScalarOutput(hasOutputSchema ? JSON.stringify(reason) : reason);
3923
+ return convertScalarOutput(hasOutputSchema ? stringifyWithBigIntAndCycles(reason) : reason);
3523
3924
  }
3524
- case "json": return convertScalarOutput(JSON.stringify(output.value));
3925
+ case "json": return convertScalarOutput(stringifyWithBigIntAndCycles(output.value));
3525
3926
  case "content": return output.value.map((item) => {
3526
3927
  const promptCacheBreakpoint = getPromptCacheBreakpoint(item.providerOptions, providerOptionsName);
3527
3928
  switch (item.type) {
@@ -4003,7 +4404,7 @@ async function convertToOpenAIResponsesInput({ prompt, toolNameMapping, systemMe
4003
4404
  type: "custom_tool_call",
4004
4405
  call_id: part.toolCallId,
4005
4406
  name: resolvedToolName,
4006
- input: typeof part.input === "string" ? part.input : JSON.stringify(part.input),
4407
+ input: typeof part.input === "string" ? part.input : stringifyWithBigIntAndCycles(part.input),
4007
4408
  ...isAsync != null && { async: isAsync },
4008
4409
  id
4009
4410
  });
@@ -4150,7 +4551,7 @@ async function convertToOpenAIResponsesInput({ prompt, toolNameMapping, systemMe
4150
4551
  });
4151
4552
  else if (reasoningMessage !== void 0) warnings.push({
4152
4553
  type: "other",
4153
- message: `Cannot append empty reasoning part to existing reasoning sequence. Skipping reasoning part: ${JSON.stringify(part)}.`
4554
+ message: `Cannot append empty reasoning part to existing reasoning sequence. Skipping reasoning part: ${stringifyWithBigIntAndCycles(part)}.`
4154
4555
  });
4155
4556
  if (reasoningMessage === void 0) {
4156
4557
  reasoningMessages[reasoningId] = {
@@ -4180,7 +4581,7 @@ async function convertToOpenAIResponsesInput({ prompt, toolNameMapping, systemMe
4180
4581
  });
4181
4582
  } else warnings.push({
4182
4583
  type: "other",
4183
- message: `Non-OpenAI reasoning parts are not supported. Skipping reasoning part: ${JSON.stringify(part)}.`
4584
+ message: `Non-OpenAI reasoning parts are not supported. Skipping reasoning part: ${stringifyWithBigIntAndCycles(part)}.`
4184
4585
  });
4185
4586
  }
4186
4587
  break;
@@ -4248,7 +4649,7 @@ async function convertToOpenAIResponsesInput({ prompt, toolNameMapping, systemMe
4248
4649
  promptCacheBreakpoint
4249
4650
  };
4250
4651
  }));
4251
- const serializedToolOutputs = toolOutputs.map(({ output }) => typeof output === "string" ? output : JSON.stringify(output));
4652
+ const serializedToolOutputs = toolOutputs.map(({ output }) => typeof output === "string" ? output : stringifyWithBigIntAndCycles(output));
4252
4653
  const hasPromptCacheBreakpoint = toolOutputs.some(({ promptCacheBreakpoint }) => promptCacheBreakpoint != null);
4253
4654
  input.push({
4254
4655
  type: "function_call_output",
@@ -4366,13 +4767,13 @@ async function convertToOpenAIResponsesInput({ prompt, toolNameMapping, systemMe
4366
4767
  break;
4367
4768
  case "error-text":
4368
4769
  case "error-json":
4369
- outputValue = convertScalarOutput(JSON.stringify({ error: output.value }));
4770
+ outputValue = convertScalarOutput(stringifyWithBigIntAndCycles({ error: output.value }));
4370
4771
  break;
4371
4772
  case "execution-denied":
4372
4773
  outputValue = convertScalarOutput(output.reason ?? "Tool call execution denied.");
4373
4774
  break;
4374
4775
  case "json":
4375
- outputValue = convertScalarOutput(JSON.stringify(output.value));
4776
+ outputValue = convertScalarOutput(stringifyWithBigIntAndCycles(output.value));
4376
4777
  break;
4377
4778
  case "content":
4378
4779
  outputValue = output.value.map((item) => {
@@ -6339,7 +6740,7 @@ const openaiResponsesSupportedUrls = {
6339
6740
  * @see https://developers.openai.com/api/docs/guides/reasoning#change-reasoning-mid-conversation
6340
6741
  */
6341
6742
  function getConfigurationUpdateUnsupportedReason({ modelCapabilities, options }) {
6342
- if (!modelCapabilities.supportsConfigurationUpdate) return "reasoningEffortUpdate is only supported by GPT-6 and later models";
6743
+ if (!modelCapabilities.configurationUpdates) return "reasoningEffortUpdate is only supported by GPT-6 and later models";
6343
6744
  if (options?.reasoningMode === "pro" || options?.contextManagement != null || options?.truncation === "auto") return "reasoningEffortUpdate requires standard reasoning mode without automatic compaction or automatic truncation";
6344
6745
  }
6345
6746
  var OpenAIResponsesLanguageModel = class OpenAIResponsesLanguageModel {
@@ -6363,7 +6764,7 @@ var OpenAIResponsesLanguageModel = class OpenAIResponsesLanguageModel {
6363
6764
  }
6364
6765
  static async prepareRequest({ modelId, config, options: { maxOutputTokens, temperature, stopSequences, topP, topK, presencePenalty, frequencyPenalty, seed, prompt, reasoning, providerOptions, tools, toolChoice, responseFormat } }) {
6365
6766
  const warnings = [];
6366
- const modelCapabilities = getOpenAILanguageModelCapabilities(modelId);
6767
+ const { capabilities: { language: modelCapabilities }, requestConfig: { language: modelRequestConfig } } = getOpenAILanguageModelEntry(modelId);
6367
6768
  if (topK != null) warnings.push({
6368
6769
  type: "unsupported",
6369
6770
  feature: "topK"
@@ -6398,11 +6799,11 @@ var OpenAIResponsesLanguageModel = class OpenAIResponsesLanguageModel {
6398
6799
  const resolvedReasoningEffort = resolveOpenAIReasoningEffort({
6399
6800
  providerReasoningEffort: openaiOptions?.reasoningEffort,
6400
6801
  reasoning,
6401
- supportedReasoningEfforts: modelCapabilities.supportedReasoningEfforts,
6802
+ supportedReasoningEfforts: modelCapabilities.reasoning.efforts,
6402
6803
  warnings
6403
6804
  });
6404
6805
  const resolvedReasoningSummary = openaiOptions?.reasoningSummary !== void 0 ? openaiOptions.reasoningSummary : resolvedReasoningEffort != null && resolvedReasoningEffort !== "none" ? "detailed" : void 0;
6405
- const isReasoningModel = openaiOptions?.forceReasoning ?? modelCapabilities.isReasoningModel;
6806
+ const isReasoningModel = openaiOptions?.forceReasoning ?? modelCapabilities.reasoning.support === true;
6406
6807
  if (openaiOptions?.conversation && openaiOptions?.previousResponseId) warnings.push({
6407
6808
  type: "unsupported",
6408
6809
  feature: "conversation",
@@ -6434,7 +6835,7 @@ var OpenAIResponsesLanguageModel = class OpenAIResponsesLanguageModel {
6434
6835
  toolNameMapping,
6435
6836
  customProviderToolNames,
6436
6837
  outputSchemaToolNames,
6437
- supportsAsyncToolCalling: modelCapabilities.supportsAsyncToolCalling,
6838
+ supportsAsyncToolCalling: modelCapabilities.tools.async,
6438
6839
  providerOptionsName
6439
6840
  });
6440
6841
  const configurationUpdateUnsupportedReason = getConfigurationUpdateUnsupportedReason({
@@ -6444,7 +6845,7 @@ var OpenAIResponsesLanguageModel = class OpenAIResponsesLanguageModel {
6444
6845
  const { input, warnings: inputWarnings } = await convertToOpenAIResponsesInput({
6445
6846
  prompt,
6446
6847
  toolNameMapping,
6447
- systemMessageMode: openaiOptions?.systemMessageMode ?? (isReasoningModel ? "developer" : modelCapabilities.systemMessageMode),
6848
+ systemMessageMode: openaiOptions?.systemMessageMode ?? (isReasoningModel ? "developer" : modelRequestConfig.systemMessageMode),
6448
6849
  providerOptionsName,
6449
6850
  configurationUpdateUnsupportedReason,
6450
6851
  explicitMessageItemType: config.explicitMessageItemType,
@@ -6463,7 +6864,7 @@ var OpenAIResponsesLanguageModel = class OpenAIResponsesLanguageModel {
6463
6864
  outputSchemaToolNames: outputSchemaToolNames.size > 0 ? outputSchemaToolNames : void 0
6464
6865
  });
6465
6866
  warnings.push(...inputWarnings);
6466
- const supportedReasoningEfforts = modelCapabilities.supportedReasoningEfforts;
6867
+ const supportedReasoningEfforts = modelCapabilities.reasoning.efforts;
6467
6868
  const getUpdateEffortUnsupportedReason = (effort) => effort != null && supportedReasoningEfforts?.includes(effort) === false ? `${modelId} only supports the following reasoning efforts: ${supportedReasoningEfforts.join(", ")}` : void 0;
6468
6869
  for (const item of input) if (item.type === "configuration_update") {
6469
6870
  const unsupportedReason = getUpdateEffortUnsupportedReason(item.reasoning.effort);
@@ -6552,7 +6953,7 @@ var OpenAIResponsesLanguageModel = class OpenAIResponsesLanguageModel {
6552
6953
  ...openaiOptions?.reasoningContext != null && { context: openaiOptions.reasoningContext }
6553
6954
  } }
6554
6955
  };
6555
- if (modelCapabilities.supportsConfigurationUpdate && baseArgs.prompt_cache_retention != null) {
6956
+ if (!modelCapabilities.promptCache.retention && baseArgs.prompt_cache_retention != null) {
6556
6957
  baseArgs.prompt_cache_retention = void 0;
6557
6958
  warnings.push({
6558
6959
  type: "unsupported",
@@ -6563,7 +6964,7 @@ var OpenAIResponsesLanguageModel = class OpenAIResponsesLanguageModel {
6563
6964
  if (isReasoningModel) {
6564
6965
  let effectiveReasoningEffort = resolvedReasoningEffort;
6565
6966
  for (const item of input) if (item.type === "configuration_update") effectiveReasoningEffort = item.reasoning.effort;
6566
- if (!(effectiveReasoningEffort === "none" && modelCapabilities.supportsNonReasoningParameters)) {
6967
+ if (!(effectiveReasoningEffort === "none" && modelCapabilities.reasoning.sampling === "reasoning-effort-none")) {
6567
6968
  if (baseArgs.temperature != null) {
6568
6969
  baseArgs.temperature = void 0;
6569
6970
  warnings.push({
@@ -6580,7 +6981,7 @@ var OpenAIResponsesLanguageModel = class OpenAIResponsesLanguageModel {
6580
6981
  details: "topP is not supported for reasoning models"
6581
6982
  });
6582
6983
  }
6583
- if (modelCapabilities.supportsConfigurationUpdate && (baseArgs.top_logprobs != null || baseArgs.include?.includes("message.output_text.logprobs"))) {
6984
+ if (modelCapabilities.endpoints.responses.logprobsRequireNonReasoning && (baseArgs.top_logprobs != null || baseArgs.include?.includes("message.output_text.logprobs"))) {
6584
6985
  baseArgs.top_logprobs = void 0;
6585
6986
  const filteredInclude = baseArgs.include?.filter((value) => value !== "message.output_text.logprobs");
6586
6987
  baseArgs.include = filteredInclude != null && filteredInclude.length > 0 ? filteredInclude : void 0;
@@ -6613,7 +7014,7 @@ var OpenAIResponsesLanguageModel = class OpenAIResponsesLanguageModel {
6613
7014
  details: "reasoningContext is not supported for non-reasoning models"
6614
7015
  });
6615
7016
  }
6616
- if (openaiOptions?.serviceTier === "flex" && !modelCapabilities.supportsFlexProcessing) {
7017
+ if (openaiOptions?.serviceTier === "flex" && !modelCapabilities.serviceTiers.flex) {
6617
7018
  warnings.push({
6618
7019
  type: "unsupported",
6619
7020
  feature: "serviceTier",
@@ -6621,7 +7022,7 @@ var OpenAIResponsesLanguageModel = class OpenAIResponsesLanguageModel {
6621
7022
  });
6622
7023
  delete baseArgs.service_tier;
6623
7024
  }
6624
- if ((openaiOptions?.serviceTier === "priority" || openaiOptions?.serviceTier === "fast") && !modelCapabilities.supportsPriorityProcessing) {
7025
+ if ((openaiOptions?.serviceTier === "priority" || openaiOptions?.serviceTier === "fast") && !modelCapabilities.serviceTiers.priority) {
6625
7026
  warnings.push({
6626
7027
  type: "unsupported",
6627
7028
  feature: "serviceTier",
@@ -6661,7 +7062,7 @@ var OpenAIResponsesLanguageModel = class OpenAIResponsesLanguageModel {
6661
7062
  const approvalRequestIdToDummyToolCallIdFromPrompt = extractApprovalRequestIdToToolCallIdMapping(options.prompt);
6662
7063
  const { responseHeaders, value: response, rawValue: rawResponse } = await postJsonToApi({
6663
7064
  url,
6664
- headers: combineHeaders(this.config.headers?.(), options.headers),
7065
+ headers: combineHeaders(await resolve(this.config.headers), options.headers),
6665
7066
  body,
6666
7067
  failedResponseHandler: openaiFailedResponseHandler,
6667
7068
  successfulResponseHandler: createJsonResponseHandler(openaiResponsesResponseSchema),
@@ -7111,7 +7512,7 @@ var OpenAIResponsesLanguageModel = class OpenAIResponsesLanguageModel {
7111
7512
  });
7112
7513
  const { responseHeaders, value: response } = await postJsonToApi({
7113
7514
  url,
7114
- headers: combineHeaders(this.config.headers?.(), options.headers),
7515
+ headers: combineHeaders(await resolve(this.config.headers), options.headers),
7115
7516
  body: {
7116
7517
  ...body,
7117
7518
  stream: true