@ai-sdk/openai 4.0.0-beta.7 → 4.0.0-beta.75

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 (73) hide show
  1. package/CHANGELOG.md +642 -24
  2. package/README.md +2 -0
  3. package/dist/index.d.ts +240 -44
  4. package/dist/index.js +3348 -1685
  5. package/dist/index.js.map +1 -1
  6. package/dist/internal/index.d.ts +390 -36
  7. package/dist/internal/index.js +2710 -1708
  8. package/dist/internal/index.js.map +1 -1
  9. package/docs/03-openai.mdx +414 -40
  10. package/package.json +16 -17
  11. package/src/chat/convert-openai-chat-usage.ts +1 -1
  12. package/src/chat/convert-to-openai-chat-messages.ts +96 -68
  13. package/src/chat/map-openai-finish-reason.ts +1 -1
  14. package/src/chat/openai-chat-api.ts +6 -2
  15. package/src/chat/{openai-chat-options.ts → openai-chat-language-model-options.ts} +11 -1
  16. package/src/chat/openai-chat-language-model.ts +82 -148
  17. package/src/chat/openai-chat-prepare-tools.ts +3 -3
  18. package/src/completion/convert-openai-completion-usage.ts +1 -1
  19. package/src/completion/convert-to-openai-completion-prompt.ts +1 -2
  20. package/src/completion/map-openai-finish-reason.ts +1 -1
  21. package/src/completion/openai-completion-api.ts +5 -2
  22. package/src/completion/{openai-completion-options.ts → openai-completion-language-model-options.ts} +5 -1
  23. package/src/completion/openai-completion-language-model.ts +53 -17
  24. package/src/embedding/{openai-embedding-options.ts → openai-embedding-model-options.ts} +5 -1
  25. package/src/embedding/openai-embedding-model.ts +22 -5
  26. package/src/files/openai-files-api.ts +17 -0
  27. package/src/files/openai-files-options.ts +22 -0
  28. package/src/files/openai-files.ts +100 -0
  29. package/src/image/openai-image-model-options.ts +123 -0
  30. package/src/image/openai-image-model.ts +62 -83
  31. package/src/index.ts +15 -6
  32. package/src/internal/index.ts +7 -6
  33. package/src/openai-config.ts +7 -7
  34. package/src/openai-language-model-capabilities.ts +5 -4
  35. package/src/openai-provider.ts +80 -9
  36. package/src/openai-stream-error.ts +181 -0
  37. package/src/openai-tools.ts +12 -1
  38. package/src/realtime/index.ts +2 -0
  39. package/src/realtime/openai-realtime-event-mapper.ts +436 -0
  40. package/src/realtime/openai-realtime-model-options.ts +3 -0
  41. package/src/realtime/openai-realtime-model.ts +111 -0
  42. package/src/responses/convert-openai-responses-usage.ts +1 -1
  43. package/src/responses/convert-to-openai-responses-input.ts +345 -90
  44. package/src/responses/map-openai-responses-finish-reason.ts +1 -1
  45. package/src/responses/openai-responses-api.ts +186 -17
  46. package/src/responses/{openai-responses-options.ts → openai-responses-language-model-options.ts} +55 -1
  47. package/src/responses/openai-responses-language-model.ts +339 -55
  48. package/src/responses/openai-responses-prepare-tools.ts +129 -18
  49. package/src/responses/openai-responses-provider-metadata.ts +12 -2
  50. package/src/skills/openai-skills-api.ts +31 -0
  51. package/src/skills/openai-skills.ts +83 -0
  52. package/src/speech/{openai-speech-options.ts → openai-speech-model-options.ts} +5 -1
  53. package/src/speech/openai-speech-model.ts +23 -7
  54. package/src/tool/apply-patch.ts +33 -32
  55. package/src/tool/code-interpreter.ts +40 -41
  56. package/src/tool/custom.ts +2 -8
  57. package/src/tool/file-search.ts +3 -3
  58. package/src/tool/image-generation.ts +2 -2
  59. package/src/tool/local-shell.ts +2 -2
  60. package/src/tool/mcp.ts +3 -3
  61. package/src/tool/shell.ts +9 -4
  62. package/src/tool/tool-search.ts +98 -0
  63. package/src/tool/web-search-preview.ts +2 -2
  64. package/src/tool/web-search.ts +10 -2
  65. package/src/transcription/{openai-transcription-options.ts → openai-transcription-model-options.ts} +5 -1
  66. package/src/transcription/openai-transcription-model.ts +35 -13
  67. package/dist/index.d.mts +0 -1107
  68. package/dist/index.mjs +0 -6509
  69. package/dist/index.mjs.map +0 -1
  70. package/dist/internal/index.d.mts +0 -1137
  71. package/dist/internal/index.mjs +0 -6322
  72. package/dist/internal/index.mjs.map +0 -1
  73. package/src/image/openai-image-options.ts +0 -31
@@ -1,18 +1,18 @@
1
1
  import {
2
2
  APICallError,
3
- JSONValue,
4
- LanguageModelV4,
5
- LanguageModelV4Prompt,
6
- LanguageModelV4CallOptions,
7
- LanguageModelV4Content,
8
- LanguageModelV4FinishReason,
9
- LanguageModelV4GenerateResult,
10
- LanguageModelV4ProviderTool,
11
- LanguageModelV4StreamPart,
12
- LanguageModelV4StreamResult,
13
- LanguageModelV4ToolApprovalRequest,
14
- SharedV4ProviderMetadata,
15
- SharedV4Warning,
3
+ type JSONValue,
4
+ type LanguageModelV4,
5
+ type LanguageModelV4Prompt,
6
+ type LanguageModelV4CallOptions,
7
+ type LanguageModelV4Content,
8
+ type LanguageModelV4FinishReason,
9
+ type LanguageModelV4GenerateResult,
10
+ type LanguageModelV4ProviderTool,
11
+ type LanguageModelV4StreamPart,
12
+ type LanguageModelV4StreamResult,
13
+ type LanguageModelV4ToolApprovalRequest,
14
+ type SharedV4ProviderMetadata,
15
+ type SharedV4Warning,
16
16
  } from '@ai-sdk/provider';
17
17
  import {
18
18
  combineHeaders,
@@ -20,49 +20,59 @@ import {
20
20
  createJsonResponseHandler,
21
21
  createToolNameMapping,
22
22
  generateId,
23
- InferSchema,
23
+ isCustomReasoning,
24
24
  parseProviderOptions,
25
- ParseResult,
26
25
  postJsonToApi,
26
+ serializeModelOptions,
27
+ WORKFLOW_DESERIALIZE,
28
+ WORKFLOW_SERIALIZE,
29
+ type InferSchema,
30
+ type ParseResult,
27
31
  } from '@ai-sdk/provider-utils';
28
- import { OpenAIConfig } from '../openai-config';
32
+ import type { OpenAIConfig } from '../openai-config';
29
33
  import { openaiFailedResponseHandler } from '../openai-error';
30
34
  import { getOpenAILanguageModelCapabilities } from '../openai-language-model-capabilities';
31
- import { applyPatchInputSchema } from '../tool/apply-patch';
32
- import {
35
+ import { throwIfOpenAIStreamErrorBeforeOutput } from '../openai-stream-error';
36
+ import type { applyPatchInputSchema } from '../tool/apply-patch';
37
+ import type {
33
38
  codeInterpreterInputSchema,
34
39
  codeInterpreterOutputSchema,
35
40
  } from '../tool/code-interpreter';
36
- import { fileSearchOutputSchema } from '../tool/file-search';
37
- import { imageGenerationOutputSchema } from '../tool/image-generation';
38
- import { localShellInputSchema } from '../tool/local-shell';
39
- import { mcpOutputSchema } from '../tool/mcp';
40
- import { shellInputSchema, shellOutputSchema } from '../tool/shell';
41
- import { webSearchOutputSchema } from '../tool/web-search';
41
+ import type { fileSearchOutputSchema } from '../tool/file-search';
42
+ import type { imageGenerationOutputSchema } from '../tool/image-generation';
43
+ import type { localShellInputSchema } from '../tool/local-shell';
44
+ import type { mcpOutputSchema } from '../tool/mcp';
45
+ import type { shellInputSchema, shellOutputSchema } from '../tool/shell';
46
+ import type {
47
+ toolSearchInputSchema,
48
+ toolSearchOutputSchema,
49
+ } from '../tool/tool-search';
50
+ import type { webSearchOutputSchema } from '../tool/web-search';
42
51
  import {
43
52
  convertOpenAIResponsesUsage,
44
- OpenAIResponsesUsage,
53
+ type OpenAIResponsesUsage,
45
54
  } from './convert-openai-responses-usage';
46
55
  import { convertToOpenAIResponsesInput } from './convert-to-openai-responses-input';
47
56
  import { mapOpenAIResponseFinishReason } from './map-openai-responses-finish-reason';
48
57
  import {
49
- OpenAIResponsesChunk,
50
58
  openaiResponsesChunkSchema,
51
- OpenAIResponsesIncludeOptions,
52
- OpenAIResponsesIncludeValue,
53
- OpenAIResponsesLogprobs,
54
59
  openaiResponsesResponseSchema,
55
- OpenAIResponsesWebSearchAction,
56
- OpenAIResponsesApplyPatchOperationDiffDeltaChunk,
57
- OpenAIResponsesApplyPatchOperationDiffDoneChunk,
60
+ type OpenAIResponsesChunk,
61
+ type OpenAIResponsesIncludeOptions,
62
+ type OpenAIResponsesIncludeValue,
63
+ type OpenAIResponsesLogprobs,
64
+ type OpenAIResponsesWebSearchAction,
65
+ type OpenAIResponsesApplyPatchOperationDiffDeltaChunk,
66
+ type OpenAIResponsesApplyPatchOperationDiffDoneChunk,
58
67
  } from './openai-responses-api';
59
68
  import {
60
- OpenAIResponsesModelId,
61
69
  openaiLanguageModelResponsesOptionsSchema,
62
70
  TOP_LOGPROBS_MAX,
63
- } from './openai-responses-options';
71
+ type OpenAIResponsesModelId,
72
+ } from './openai-responses-language-model-options';
64
73
  import { prepareResponsesTools } from './openai-responses-prepare-tools';
65
- import {
74
+ import type {
75
+ ResponsesCompactionProviderMetadata,
66
76
  ResponsesProviderMetadata,
67
77
  ResponsesReasoningProviderMetadata,
68
78
  ResponsesSourceDocumentProviderMetadata,
@@ -101,6 +111,20 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
101
111
 
102
112
  private readonly config: OpenAIConfig;
103
113
 
114
+ static [WORKFLOW_SERIALIZE](model: OpenAIResponsesLanguageModel) {
115
+ return serializeModelOptions({
116
+ modelId: model.modelId,
117
+ config: model.config,
118
+ });
119
+ }
120
+
121
+ static [WORKFLOW_DESERIALIZE](options: {
122
+ modelId: OpenAIResponsesModelId;
123
+ config: OpenAIConfig;
124
+ }) {
125
+ return new OpenAIResponsesLanguageModel(options.modelId, options.config);
126
+ }
127
+
104
128
  constructor(modelId: OpenAIResponsesModelId, config: OpenAIConfig) {
105
129
  this.modelId = modelId;
106
130
  this.config = config;
@@ -125,6 +149,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
125
149
  frequencyPenalty,
126
150
  seed,
127
151
  prompt,
152
+ reasoning,
128
153
  providerOptions,
129
154
  tools,
130
155
  toolChoice,
@@ -170,6 +195,16 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
170
195
  });
171
196
  }
172
197
 
198
+ const resolvedReasoningEffort =
199
+ openaiOptions?.reasoningEffort ??
200
+ (isCustomReasoning(reasoning) ? reasoning : undefined);
201
+ const resolvedReasoningSummary =
202
+ openaiOptions?.reasoningSummary !== undefined
203
+ ? openaiOptions.reasoningSummary
204
+ : resolvedReasoningEffort != null && resolvedReasoningEffort !== 'none'
205
+ ? 'detailed'
206
+ : undefined;
207
+
173
208
  const isReasoningModel =
174
209
  openaiOptions?.forceReasoning ?? modelCapabilities.isReasoningModel;
175
210
 
@@ -193,11 +228,8 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
193
228
  'openai.web_search_preview': 'web_search_preview',
194
229
  'openai.mcp': 'mcp',
195
230
  'openai.apply_patch': 'apply_patch',
231
+ 'openai.tool_search': 'tool_search',
196
232
  },
197
- resolveProviderToolName: tool =>
198
- tool.id === 'openai.custom'
199
- ? (tool.args as { name?: string }).name
200
- : undefined,
201
233
  });
202
234
 
203
235
  const customProviderToolNames = new Set<string>();
@@ -208,6 +240,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
208
240
  } = await prepareResponsesTools({
209
241
  tools,
210
242
  toolChoice,
243
+ allowedTools: openaiOptions?.allowedTools ?? undefined,
211
244
  toolNameMapping,
212
245
  customProviderToolNames,
213
246
  });
@@ -223,8 +256,11 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
223
256
  : modelCapabilities.systemMessageMode),
224
257
  providerOptionsName,
225
258
  fileIdPrefixes: this.config.fileIdPrefixes,
259
+ passThroughUnsupportedFiles:
260
+ openaiOptions?.passThroughUnsupportedFiles ?? false,
226
261
  store: openaiOptions?.store ?? true,
227
262
  hasConversation: openaiOptions?.conversation != null,
263
+ hasPreviousResponseId: openaiOptions?.previousResponseId != null,
228
264
  hasLocalShellTool: hasOpenAITool('openai.local_shell'),
229
265
  hasShellTool: hasOpenAITool('openai.shell'),
230
266
  hasApplyPatchTool: hasOpenAITool('openai.apply_patch'),
@@ -336,16 +372,24 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
336
372
  top_logprobs: topLogprobs,
337
373
  truncation: openaiOptions?.truncation,
338
374
 
375
+ // context management (server-side compaction):
376
+ ...(openaiOptions?.contextManagement && {
377
+ context_management: openaiOptions.contextManagement.map(cm => ({
378
+ type: cm.type,
379
+ compact_threshold: cm.compactThreshold,
380
+ })),
381
+ }),
382
+
339
383
  // model-specific settings:
340
384
  ...(isReasoningModel &&
341
- (openaiOptions?.reasoningEffort != null ||
342
- openaiOptions?.reasoningSummary != null) && {
385
+ (resolvedReasoningEffort != null ||
386
+ resolvedReasoningSummary != null) && {
343
387
  reasoning: {
344
- ...(openaiOptions?.reasoningEffort != null && {
345
- effort: openaiOptions.reasoningEffort,
388
+ ...(resolvedReasoningEffort != null && {
389
+ effort: resolvedReasoningEffort,
346
390
  }),
347
- ...(openaiOptions?.reasoningSummary != null && {
348
- summary: openaiOptions.reasoningSummary,
391
+ ...(resolvedReasoningSummary != null && {
392
+ summary: resolvedReasoningSummary,
349
393
  }),
350
394
  },
351
395
  }),
@@ -358,7 +402,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
358
402
  // https://platform.openai.com/docs/guides/latest-model#gpt-5-1-parameter-compatibility
359
403
  if (
360
404
  !(
361
- openaiOptions?.reasoningEffort === 'none' &&
405
+ resolvedReasoningEffort === 'none' &&
362
406
  modelCapabilities.supportsNonReasoningParameters
363
407
  )
364
408
  ) {
@@ -478,7 +522,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
478
522
  rawValue: rawResponse,
479
523
  } = await postJsonToApi({
480
524
  url,
481
- headers: combineHeaders(this.config.headers(), options.headers),
525
+ headers: combineHeaders(this.config.headers?.(), options.headers),
482
526
  body,
483
527
  failedResponseHandler: openaiFailedResponseHandler,
484
528
  successfulResponseHandler: createJsonResponseHandler(
@@ -505,6 +549,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
505
549
 
506
550
  // flag that checks if there have been client-side tool calls (not executed by openai)
507
551
  let hasFunctionCall = false;
552
+ const hostedToolSearchCallIds: string[] = [];
508
553
 
509
554
  // map response content to content array (defined when there is no error)
510
555
  for (const part of response.output!) {
@@ -551,6 +596,54 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
551
596
  break;
552
597
  }
553
598
 
599
+ case 'tool_search_call': {
600
+ const toolCallId = part.call_id ?? part.id;
601
+ const isHosted = part.execution === 'server';
602
+
603
+ if (isHosted) {
604
+ hostedToolSearchCallIds.push(toolCallId);
605
+ }
606
+
607
+ content.push({
608
+ type: 'tool-call',
609
+ toolCallId,
610
+ toolName: toolNameMapping.toCustomToolName('tool_search'),
611
+ input: JSON.stringify({
612
+ arguments: part.arguments,
613
+ call_id: part.call_id,
614
+ } satisfies InferSchema<typeof toolSearchInputSchema>),
615
+ ...(isHosted ? { providerExecuted: true } : {}),
616
+ providerMetadata: {
617
+ [providerOptionsName]: {
618
+ itemId: part.id,
619
+ },
620
+ },
621
+ });
622
+
623
+ break;
624
+ }
625
+
626
+ case 'tool_search_output': {
627
+ const toolCallId =
628
+ part.call_id ?? hostedToolSearchCallIds.shift() ?? part.id;
629
+
630
+ content.push({
631
+ type: 'tool-result',
632
+ toolCallId,
633
+ toolName: toolNameMapping.toCustomToolName('tool_search'),
634
+ result: {
635
+ tools: part.tools,
636
+ } satisfies InferSchema<typeof toolSearchOutputSchema>,
637
+ providerMetadata: {
638
+ [providerOptionsName]: {
639
+ itemId: part.id,
640
+ },
641
+ },
642
+ });
643
+
644
+ break;
645
+ }
646
+
554
647
  case 'local_shell_call': {
555
648
  content.push({
556
649
  type: 'tool-call',
@@ -721,6 +814,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
721
814
  providerMetadata: {
722
815
  [providerOptionsName]: {
723
816
  itemId: part.id,
817
+ ...(part.namespace != null && { namespace: part.namespace }),
724
818
  },
725
819
  },
726
820
  });
@@ -927,6 +1021,21 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
927
1021
 
928
1022
  break;
929
1023
  }
1024
+
1025
+ case 'compaction': {
1026
+ content.push({
1027
+ type: 'custom',
1028
+ kind: 'openai.compaction',
1029
+ providerMetadata: {
1030
+ [providerOptionsName]: {
1031
+ type: 'compaction',
1032
+ itemId: part.id,
1033
+ encryptedContent: part.encrypted_content,
1034
+ } satisfies ResponsesCompactionProviderMetadata,
1035
+ },
1036
+ });
1037
+ break;
1038
+ }
930
1039
  }
931
1040
  }
932
1041
 
@@ -978,12 +1087,14 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
978
1087
  isShellProviderExecuted,
979
1088
  } = await this.getArgs(options);
980
1089
 
1090
+ const url = this.config.url({
1091
+ path: '/responses',
1092
+ modelId: this.modelId,
1093
+ });
1094
+
981
1095
  const { responseHeaders, value: response } = await postJsonToApi({
982
- url: this.config.url({
983
- path: '/responses',
984
- modelId: this.modelId,
985
- }),
986
- headers: combineHeaders(this.config.headers(), options.headers),
1096
+ url,
1097
+ headers: combineHeaders(this.config.headers?.(), options.headers),
987
1098
  body: {
988
1099
  ...body,
989
1100
  stream: true,
@@ -996,6 +1107,19 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
996
1107
  fetch: this.config.fetch,
997
1108
  });
998
1109
 
1110
+ const checkedResponse = await throwIfOpenAIStreamErrorBeforeOutput({
1111
+ stream: response,
1112
+ getError: chunk =>
1113
+ isErrorChunk(chunk) ||
1114
+ (isResponseFailedChunk(chunk) && chunk.response.error != null)
1115
+ ? chunk
1116
+ : undefined,
1117
+ isOutputChunk: isResponseOutputChunk,
1118
+ url,
1119
+ requestBodyValues: body,
1120
+ responseHeaders,
1121
+ });
1122
+
999
1123
  const self = this;
1000
1124
 
1001
1125
  const approvalRequestIdToDummyToolCallIdFromPrompt =
@@ -1026,6 +1150,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
1026
1150
  hasDiff: boolean;
1027
1151
  endEmitted: boolean;
1028
1152
  };
1153
+ toolSearchExecution?: 'server' | 'client';
1029
1154
  }
1030
1155
  | undefined
1031
1156
  > = {};
@@ -1054,9 +1179,11 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
1054
1179
  > = {};
1055
1180
 
1056
1181
  let serviceTier: string | undefined;
1182
+ const hostedToolSearchCallIds: string[] = [];
1183
+ let encounteredStreamError = false;
1057
1184
 
1058
- return {
1059
- stream: response.pipeThrough(
1185
+ const result = {
1186
+ stream: checkedResponse.pipeThrough(
1060
1187
  new TransformStream<
1061
1188
  ParseResult<OpenAIResponsesChunk>,
1062
1189
  LanguageModelV4StreamPart
@@ -1188,6 +1315,28 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
1188
1315
  input: '{}',
1189
1316
  providerExecuted: true,
1190
1317
  });
1318
+ } else if (value.item.type === 'tool_search_call') {
1319
+ const toolCallId = value.item.id;
1320
+ const toolName =
1321
+ toolNameMapping.toCustomToolName('tool_search');
1322
+ const isHosted = value.item.execution === 'server';
1323
+
1324
+ ongoingToolCalls[value.output_index] = {
1325
+ toolName,
1326
+ toolCallId,
1327
+ toolSearchExecution: value.item.execution ?? 'server',
1328
+ };
1329
+
1330
+ if (isHosted) {
1331
+ controller.enqueue({
1332
+ type: 'tool-input-start',
1333
+ id: toolCallId,
1334
+ toolName,
1335
+ providerExecuted: true,
1336
+ });
1337
+ }
1338
+ } else if (value.item.type === 'tool_search_output') {
1339
+ // handled on output_item.done so we can pair it with the call
1191
1340
  } else if (
1192
1341
  value.item.type === 'mcp_call' ||
1193
1342
  value.item.type === 'mcp_list_tools' ||
@@ -1305,6 +1454,13 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
1305
1454
  controller.enqueue({
1306
1455
  type: 'tool-input-end',
1307
1456
  id: value.item.call_id,
1457
+ ...(value.item.namespace != null && {
1458
+ providerMetadata: {
1459
+ [providerOptionsName]: {
1460
+ namespace: value.item.namespace,
1461
+ },
1462
+ },
1463
+ }),
1308
1464
  });
1309
1465
 
1310
1466
  controller.enqueue({
@@ -1315,6 +1471,9 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
1315
1471
  providerMetadata: {
1316
1472
  [providerOptionsName]: {
1317
1473
  itemId: value.item.id,
1474
+ ...(value.item.namespace != null && {
1475
+ namespace: value.item.namespace,
1476
+ }),
1318
1477
  },
1319
1478
  },
1320
1479
  });
@@ -1418,6 +1577,67 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
1418
1577
  result: value.item.result,
1419
1578
  } satisfies InferSchema<typeof imageGenerationOutputSchema>,
1420
1579
  });
1580
+ } else if (value.item.type === 'tool_search_call') {
1581
+ const toolCall = ongoingToolCalls[value.output_index];
1582
+ const isHosted = value.item.execution === 'server';
1583
+
1584
+ if (toolCall != null) {
1585
+ const toolCallId = isHosted
1586
+ ? toolCall.toolCallId
1587
+ : (value.item.call_id ?? value.item.id);
1588
+
1589
+ if (isHosted) {
1590
+ hostedToolSearchCallIds.push(toolCallId);
1591
+ } else {
1592
+ controller.enqueue({
1593
+ type: 'tool-input-start',
1594
+ id: toolCallId,
1595
+ toolName: toolCall.toolName,
1596
+ });
1597
+ }
1598
+
1599
+ controller.enqueue({
1600
+ type: 'tool-input-end',
1601
+ id: toolCallId,
1602
+ });
1603
+
1604
+ controller.enqueue({
1605
+ type: 'tool-call',
1606
+ toolCallId,
1607
+ toolName: toolCall.toolName,
1608
+ input: JSON.stringify({
1609
+ arguments: value.item.arguments,
1610
+ call_id: isHosted ? null : toolCallId,
1611
+ } satisfies InferSchema<typeof toolSearchInputSchema>),
1612
+ ...(isHosted ? { providerExecuted: true } : {}),
1613
+ providerMetadata: {
1614
+ [providerOptionsName]: {
1615
+ itemId: value.item.id,
1616
+ },
1617
+ },
1618
+ });
1619
+ }
1620
+
1621
+ ongoingToolCalls[value.output_index] = undefined;
1622
+ } else if (value.item.type === 'tool_search_output') {
1623
+ const toolCallId =
1624
+ value.item.call_id ??
1625
+ hostedToolSearchCallIds.shift() ??
1626
+ value.item.id;
1627
+
1628
+ controller.enqueue({
1629
+ type: 'tool-result',
1630
+ toolCallId,
1631
+ toolName: toolNameMapping.toCustomToolName('tool_search'),
1632
+ result: {
1633
+ tools: value.item.tools,
1634
+ } satisfies InferSchema<typeof toolSearchOutputSchema>,
1635
+ providerMetadata: {
1636
+ [providerOptionsName]: {
1637
+ itemId: value.item.id,
1638
+ },
1639
+ },
1640
+ });
1421
1641
  } else if (value.item.type === 'mcp_call') {
1422
1642
  ongoingToolCalls[value.output_index] = undefined;
1423
1643
 
@@ -1647,6 +1867,18 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
1647
1867
  }
1648
1868
 
1649
1869
  delete activeReasoning[value.item.id];
1870
+ } else if (value.item.type === 'compaction') {
1871
+ controller.enqueue({
1872
+ type: 'custom',
1873
+ kind: 'openai.compaction',
1874
+ providerMetadata: {
1875
+ [providerOptionsName]: {
1876
+ type: 'compaction',
1877
+ itemId: value.item.id,
1878
+ encryptedContent: value.item.encrypted_content,
1879
+ } satisfies ResponsesCompactionProviderMetadata,
1880
+ },
1881
+ });
1650
1882
  }
1651
1883
  } else if (isResponseFunctionCallArgumentsDeltaChunk(value)) {
1652
1884
  const toolCall = ongoingToolCalls[value.output_index];
@@ -1867,6 +2099,35 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
1867
2099
  if (typeof value.response.service_tier === 'string') {
1868
2100
  serviceTier = value.response.service_tier;
1869
2101
  }
2102
+ } else if (isResponseFailedChunk(value)) {
2103
+ const incompleteReason =
2104
+ value.response.incomplete_details?.reason;
2105
+ finishReason = {
2106
+ unified: incompleteReason
2107
+ ? mapOpenAIResponseFinishReason({
2108
+ finishReason: incompleteReason,
2109
+ hasFunctionCall,
2110
+ })
2111
+ : 'error',
2112
+ raw: incompleteReason ?? 'error',
2113
+ };
2114
+ usage = value.response.usage ?? undefined;
2115
+
2116
+ if (!encounteredStreamError && value.response.error != null) {
2117
+ encounteredStreamError = true;
2118
+ controller.enqueue({
2119
+ type: 'error',
2120
+ error: {
2121
+ type: 'response.failed',
2122
+ sequence_number: value.sequence_number,
2123
+ response: {
2124
+ error: value.response.error,
2125
+ incomplete_details: value.response.incomplete_details,
2126
+ service_tier: value.response.service_tier,
2127
+ },
2128
+ },
2129
+ });
2130
+ }
1870
2131
  } else if (isResponseAnnotationAddedChunk(value)) {
1871
2132
  ongoingAnnotations.push(value.annotation);
1872
2133
  if (value.annotation.type === 'url_citation') {
@@ -1936,6 +2197,8 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
1936
2197
  });
1937
2198
  }
1938
2199
  } else if (isErrorChunk(value)) {
2200
+ encounteredStreamError = true;
2201
+ finishReason = { unified: 'error', raw: 'error' };
1939
2202
  controller.enqueue({ type: 'error', error: value });
1940
2203
  }
1941
2204
  },
@@ -1961,6 +2224,8 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
1961
2224
  request: { body },
1962
2225
  response: { headers: responseHeaders },
1963
2226
  };
2227
+
2228
+ return result;
1964
2229
  }
1965
2230
  }
1966
2231
 
@@ -1986,6 +2251,12 @@ function isResponseFinishedChunk(
1986
2251
  );
1987
2252
  }
1988
2253
 
2254
+ function isResponseFailedChunk(
2255
+ chunk: OpenAIResponsesChunk,
2256
+ ): chunk is OpenAIResponsesChunk & { type: 'response.failed' } {
2257
+ return chunk.type === 'response.failed';
2258
+ }
2259
+
1989
2260
  function isResponseCreatedChunk(
1990
2261
  chunk: OpenAIResponsesChunk,
1991
2262
  ): chunk is OpenAIResponsesChunk & { type: 'response.created' } {
@@ -2064,6 +2335,15 @@ function isErrorChunk(
2064
2335
  return chunk.type === 'error';
2065
2336
  }
2066
2337
 
2338
+ function isResponseOutputChunk(chunk: OpenAIResponsesChunk): boolean {
2339
+ return !(
2340
+ chunk.type === 'response.created' ||
2341
+ chunk.type === 'response.failed' ||
2342
+ chunk.type === 'error' ||
2343
+ chunk.type === 'unknown_chunk'
2344
+ );
2345
+ }
2346
+
2067
2347
  function mapWebSearchOutput(
2068
2348
  action: OpenAIResponsesWebSearchAction | null | undefined,
2069
2349
  ): InferSchema<typeof webSearchOutputSchema> {
@@ -2074,7 +2354,11 @@ function mapWebSearchOutput(
2074
2354
  switch (action.type) {
2075
2355
  case 'search':
2076
2356
  return {
2077
- action: { type: 'search', query: action.query ?? undefined },
2357
+ action: {
2358
+ type: 'search',
2359
+ query: action.query ?? undefined,
2360
+ ...(action.queries != null && { queries: action.queries }),
2361
+ },
2078
2362
  // include sources when provided by the Responses API (behind include flag)
2079
2363
  ...(action.sources != null && { sources: action.sources }),
2080
2364
  };