@ai-sdk/openai 4.0.0-beta.6 → 4.0.0-beta.74

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 +644 -24
  2. package/README.md +2 -0
  3. package/dist/index.d.ts +240 -44
  4. package/dist/index.js +3345 -1683
  5. package/dist/index.js.map +1 -1
  6. package/dist/internal/index.d.ts +390 -36
  7. package/dist/internal/index.js +2707 -1706
  8. package/dist/internal/index.js.map +1 -1
  9. package/docs/03-openai.mdx +413 -39
  10. package/package.json +17 -18
  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 +330 -52
  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,10 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
170
195
  });
171
196
  }
172
197
 
198
+ const resolvedReasoningEffort =
199
+ openaiOptions?.reasoningEffort ??
200
+ (isCustomReasoning(reasoning) ? reasoning : undefined);
201
+
173
202
  const isReasoningModel =
174
203
  openaiOptions?.forceReasoning ?? modelCapabilities.isReasoningModel;
175
204
 
@@ -193,11 +222,8 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
193
222
  'openai.web_search_preview': 'web_search_preview',
194
223
  'openai.mcp': 'mcp',
195
224
  'openai.apply_patch': 'apply_patch',
225
+ 'openai.tool_search': 'tool_search',
196
226
  },
197
- resolveProviderToolName: tool =>
198
- tool.id === 'openai.custom'
199
- ? (tool.args as { name?: string }).name
200
- : undefined,
201
227
  });
202
228
 
203
229
  const customProviderToolNames = new Set<string>();
@@ -208,6 +234,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
208
234
  } = await prepareResponsesTools({
209
235
  tools,
210
236
  toolChoice,
237
+ allowedTools: openaiOptions?.allowedTools ?? undefined,
211
238
  toolNameMapping,
212
239
  customProviderToolNames,
213
240
  });
@@ -223,8 +250,11 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
223
250
  : modelCapabilities.systemMessageMode),
224
251
  providerOptionsName,
225
252
  fileIdPrefixes: this.config.fileIdPrefixes,
253
+ passThroughUnsupportedFiles:
254
+ openaiOptions?.passThroughUnsupportedFiles ?? false,
226
255
  store: openaiOptions?.store ?? true,
227
256
  hasConversation: openaiOptions?.conversation != null,
257
+ hasPreviousResponseId: openaiOptions?.previousResponseId != null,
228
258
  hasLocalShellTool: hasOpenAITool('openai.local_shell'),
229
259
  hasShellTool: hasOpenAITool('openai.shell'),
230
260
  hasApplyPatchTool: hasOpenAITool('openai.apply_patch'),
@@ -336,13 +366,21 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
336
366
  top_logprobs: topLogprobs,
337
367
  truncation: openaiOptions?.truncation,
338
368
 
369
+ // context management (server-side compaction):
370
+ ...(openaiOptions?.contextManagement && {
371
+ context_management: openaiOptions.contextManagement.map(cm => ({
372
+ type: cm.type,
373
+ compact_threshold: cm.compactThreshold,
374
+ })),
375
+ }),
376
+
339
377
  // model-specific settings:
340
378
  ...(isReasoningModel &&
341
- (openaiOptions?.reasoningEffort != null ||
379
+ (resolvedReasoningEffort != null ||
342
380
  openaiOptions?.reasoningSummary != null) && {
343
381
  reasoning: {
344
- ...(openaiOptions?.reasoningEffort != null && {
345
- effort: openaiOptions.reasoningEffort,
382
+ ...(resolvedReasoningEffort != null && {
383
+ effort: resolvedReasoningEffort,
346
384
  }),
347
385
  ...(openaiOptions?.reasoningSummary != null && {
348
386
  summary: openaiOptions.reasoningSummary,
@@ -358,7 +396,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
358
396
  // https://platform.openai.com/docs/guides/latest-model#gpt-5-1-parameter-compatibility
359
397
  if (
360
398
  !(
361
- openaiOptions?.reasoningEffort === 'none' &&
399
+ resolvedReasoningEffort === 'none' &&
362
400
  modelCapabilities.supportsNonReasoningParameters
363
401
  )
364
402
  ) {
@@ -478,7 +516,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
478
516
  rawValue: rawResponse,
479
517
  } = await postJsonToApi({
480
518
  url,
481
- headers: combineHeaders(this.config.headers(), options.headers),
519
+ headers: combineHeaders(this.config.headers?.(), options.headers),
482
520
  body,
483
521
  failedResponseHandler: openaiFailedResponseHandler,
484
522
  successfulResponseHandler: createJsonResponseHandler(
@@ -505,6 +543,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
505
543
 
506
544
  // flag that checks if there have been client-side tool calls (not executed by openai)
507
545
  let hasFunctionCall = false;
546
+ const hostedToolSearchCallIds: string[] = [];
508
547
 
509
548
  // map response content to content array (defined when there is no error)
510
549
  for (const part of response.output!) {
@@ -551,6 +590,54 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
551
590
  break;
552
591
  }
553
592
 
593
+ case 'tool_search_call': {
594
+ const toolCallId = part.call_id ?? part.id;
595
+ const isHosted = part.execution === 'server';
596
+
597
+ if (isHosted) {
598
+ hostedToolSearchCallIds.push(toolCallId);
599
+ }
600
+
601
+ content.push({
602
+ type: 'tool-call',
603
+ toolCallId,
604
+ toolName: toolNameMapping.toCustomToolName('tool_search'),
605
+ input: JSON.stringify({
606
+ arguments: part.arguments,
607
+ call_id: part.call_id,
608
+ } satisfies InferSchema<typeof toolSearchInputSchema>),
609
+ ...(isHosted ? { providerExecuted: true } : {}),
610
+ providerMetadata: {
611
+ [providerOptionsName]: {
612
+ itemId: part.id,
613
+ },
614
+ },
615
+ });
616
+
617
+ break;
618
+ }
619
+
620
+ case 'tool_search_output': {
621
+ const toolCallId =
622
+ part.call_id ?? hostedToolSearchCallIds.shift() ?? part.id;
623
+
624
+ content.push({
625
+ type: 'tool-result',
626
+ toolCallId,
627
+ toolName: toolNameMapping.toCustomToolName('tool_search'),
628
+ result: {
629
+ tools: part.tools,
630
+ } satisfies InferSchema<typeof toolSearchOutputSchema>,
631
+ providerMetadata: {
632
+ [providerOptionsName]: {
633
+ itemId: part.id,
634
+ },
635
+ },
636
+ });
637
+
638
+ break;
639
+ }
640
+
554
641
  case 'local_shell_call': {
555
642
  content.push({
556
643
  type: 'tool-call',
@@ -721,6 +808,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
721
808
  providerMetadata: {
722
809
  [providerOptionsName]: {
723
810
  itemId: part.id,
811
+ ...(part.namespace != null && { namespace: part.namespace }),
724
812
  },
725
813
  },
726
814
  });
@@ -927,6 +1015,21 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
927
1015
 
928
1016
  break;
929
1017
  }
1018
+
1019
+ case 'compaction': {
1020
+ content.push({
1021
+ type: 'custom',
1022
+ kind: 'openai.compaction',
1023
+ providerMetadata: {
1024
+ [providerOptionsName]: {
1025
+ type: 'compaction',
1026
+ itemId: part.id,
1027
+ encryptedContent: part.encrypted_content,
1028
+ } satisfies ResponsesCompactionProviderMetadata,
1029
+ },
1030
+ });
1031
+ break;
1032
+ }
930
1033
  }
931
1034
  }
932
1035
 
@@ -978,12 +1081,14 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
978
1081
  isShellProviderExecuted,
979
1082
  } = await this.getArgs(options);
980
1083
 
1084
+ const url = this.config.url({
1085
+ path: '/responses',
1086
+ modelId: this.modelId,
1087
+ });
1088
+
981
1089
  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),
1090
+ url,
1091
+ headers: combineHeaders(this.config.headers?.(), options.headers),
987
1092
  body: {
988
1093
  ...body,
989
1094
  stream: true,
@@ -996,6 +1101,19 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
996
1101
  fetch: this.config.fetch,
997
1102
  });
998
1103
 
1104
+ const checkedResponse = await throwIfOpenAIStreamErrorBeforeOutput({
1105
+ stream: response,
1106
+ getError: chunk =>
1107
+ isErrorChunk(chunk) ||
1108
+ (isResponseFailedChunk(chunk) && chunk.response.error != null)
1109
+ ? chunk
1110
+ : undefined,
1111
+ isOutputChunk: isResponseOutputChunk,
1112
+ url,
1113
+ requestBodyValues: body,
1114
+ responseHeaders,
1115
+ });
1116
+
999
1117
  const self = this;
1000
1118
 
1001
1119
  const approvalRequestIdToDummyToolCallIdFromPrompt =
@@ -1026,6 +1144,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
1026
1144
  hasDiff: boolean;
1027
1145
  endEmitted: boolean;
1028
1146
  };
1147
+ toolSearchExecution?: 'server' | 'client';
1029
1148
  }
1030
1149
  | undefined
1031
1150
  > = {};
@@ -1054,9 +1173,11 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
1054
1173
  > = {};
1055
1174
 
1056
1175
  let serviceTier: string | undefined;
1176
+ const hostedToolSearchCallIds: string[] = [];
1177
+ let encounteredStreamError = false;
1057
1178
 
1058
- return {
1059
- stream: response.pipeThrough(
1179
+ const result = {
1180
+ stream: checkedResponse.pipeThrough(
1060
1181
  new TransformStream<
1061
1182
  ParseResult<OpenAIResponsesChunk>,
1062
1183
  LanguageModelV4StreamPart
@@ -1188,6 +1309,28 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
1188
1309
  input: '{}',
1189
1310
  providerExecuted: true,
1190
1311
  });
1312
+ } else if (value.item.type === 'tool_search_call') {
1313
+ const toolCallId = value.item.id;
1314
+ const toolName =
1315
+ toolNameMapping.toCustomToolName('tool_search');
1316
+ const isHosted = value.item.execution === 'server';
1317
+
1318
+ ongoingToolCalls[value.output_index] = {
1319
+ toolName,
1320
+ toolCallId,
1321
+ toolSearchExecution: value.item.execution ?? 'server',
1322
+ };
1323
+
1324
+ if (isHosted) {
1325
+ controller.enqueue({
1326
+ type: 'tool-input-start',
1327
+ id: toolCallId,
1328
+ toolName,
1329
+ providerExecuted: true,
1330
+ });
1331
+ }
1332
+ } else if (value.item.type === 'tool_search_output') {
1333
+ // handled on output_item.done so we can pair it with the call
1191
1334
  } else if (
1192
1335
  value.item.type === 'mcp_call' ||
1193
1336
  value.item.type === 'mcp_list_tools' ||
@@ -1305,6 +1448,13 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
1305
1448
  controller.enqueue({
1306
1449
  type: 'tool-input-end',
1307
1450
  id: value.item.call_id,
1451
+ ...(value.item.namespace != null && {
1452
+ providerMetadata: {
1453
+ [providerOptionsName]: {
1454
+ namespace: value.item.namespace,
1455
+ },
1456
+ },
1457
+ }),
1308
1458
  });
1309
1459
 
1310
1460
  controller.enqueue({
@@ -1315,6 +1465,9 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
1315
1465
  providerMetadata: {
1316
1466
  [providerOptionsName]: {
1317
1467
  itemId: value.item.id,
1468
+ ...(value.item.namespace != null && {
1469
+ namespace: value.item.namespace,
1470
+ }),
1318
1471
  },
1319
1472
  },
1320
1473
  });
@@ -1418,6 +1571,67 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
1418
1571
  result: value.item.result,
1419
1572
  } satisfies InferSchema<typeof imageGenerationOutputSchema>,
1420
1573
  });
1574
+ } else if (value.item.type === 'tool_search_call') {
1575
+ const toolCall = ongoingToolCalls[value.output_index];
1576
+ const isHosted = value.item.execution === 'server';
1577
+
1578
+ if (toolCall != null) {
1579
+ const toolCallId = isHosted
1580
+ ? toolCall.toolCallId
1581
+ : (value.item.call_id ?? value.item.id);
1582
+
1583
+ if (isHosted) {
1584
+ hostedToolSearchCallIds.push(toolCallId);
1585
+ } else {
1586
+ controller.enqueue({
1587
+ type: 'tool-input-start',
1588
+ id: toolCallId,
1589
+ toolName: toolCall.toolName,
1590
+ });
1591
+ }
1592
+
1593
+ controller.enqueue({
1594
+ type: 'tool-input-end',
1595
+ id: toolCallId,
1596
+ });
1597
+
1598
+ controller.enqueue({
1599
+ type: 'tool-call',
1600
+ toolCallId,
1601
+ toolName: toolCall.toolName,
1602
+ input: JSON.stringify({
1603
+ arguments: value.item.arguments,
1604
+ call_id: isHosted ? null : toolCallId,
1605
+ } satisfies InferSchema<typeof toolSearchInputSchema>),
1606
+ ...(isHosted ? { providerExecuted: true } : {}),
1607
+ providerMetadata: {
1608
+ [providerOptionsName]: {
1609
+ itemId: value.item.id,
1610
+ },
1611
+ },
1612
+ });
1613
+ }
1614
+
1615
+ ongoingToolCalls[value.output_index] = undefined;
1616
+ } else if (value.item.type === 'tool_search_output') {
1617
+ const toolCallId =
1618
+ value.item.call_id ??
1619
+ hostedToolSearchCallIds.shift() ??
1620
+ value.item.id;
1621
+
1622
+ controller.enqueue({
1623
+ type: 'tool-result',
1624
+ toolCallId,
1625
+ toolName: toolNameMapping.toCustomToolName('tool_search'),
1626
+ result: {
1627
+ tools: value.item.tools,
1628
+ } satisfies InferSchema<typeof toolSearchOutputSchema>,
1629
+ providerMetadata: {
1630
+ [providerOptionsName]: {
1631
+ itemId: value.item.id,
1632
+ },
1633
+ },
1634
+ });
1421
1635
  } else if (value.item.type === 'mcp_call') {
1422
1636
  ongoingToolCalls[value.output_index] = undefined;
1423
1637
 
@@ -1647,6 +1861,18 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
1647
1861
  }
1648
1862
 
1649
1863
  delete activeReasoning[value.item.id];
1864
+ } else if (value.item.type === 'compaction') {
1865
+ controller.enqueue({
1866
+ type: 'custom',
1867
+ kind: 'openai.compaction',
1868
+ providerMetadata: {
1869
+ [providerOptionsName]: {
1870
+ type: 'compaction',
1871
+ itemId: value.item.id,
1872
+ encryptedContent: value.item.encrypted_content,
1873
+ } satisfies ResponsesCompactionProviderMetadata,
1874
+ },
1875
+ });
1650
1876
  }
1651
1877
  } else if (isResponseFunctionCallArgumentsDeltaChunk(value)) {
1652
1878
  const toolCall = ongoingToolCalls[value.output_index];
@@ -1867,6 +2093,35 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
1867
2093
  if (typeof value.response.service_tier === 'string') {
1868
2094
  serviceTier = value.response.service_tier;
1869
2095
  }
2096
+ } else if (isResponseFailedChunk(value)) {
2097
+ const incompleteReason =
2098
+ value.response.incomplete_details?.reason;
2099
+ finishReason = {
2100
+ unified: incompleteReason
2101
+ ? mapOpenAIResponseFinishReason({
2102
+ finishReason: incompleteReason,
2103
+ hasFunctionCall,
2104
+ })
2105
+ : 'error',
2106
+ raw: incompleteReason ?? 'error',
2107
+ };
2108
+ usage = value.response.usage ?? undefined;
2109
+
2110
+ if (!encounteredStreamError && value.response.error != null) {
2111
+ encounteredStreamError = true;
2112
+ controller.enqueue({
2113
+ type: 'error',
2114
+ error: {
2115
+ type: 'response.failed',
2116
+ sequence_number: value.sequence_number,
2117
+ response: {
2118
+ error: value.response.error,
2119
+ incomplete_details: value.response.incomplete_details,
2120
+ service_tier: value.response.service_tier,
2121
+ },
2122
+ },
2123
+ });
2124
+ }
1870
2125
  } else if (isResponseAnnotationAddedChunk(value)) {
1871
2126
  ongoingAnnotations.push(value.annotation);
1872
2127
  if (value.annotation.type === 'url_citation') {
@@ -1936,6 +2191,8 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
1936
2191
  });
1937
2192
  }
1938
2193
  } else if (isErrorChunk(value)) {
2194
+ encounteredStreamError = true;
2195
+ finishReason = { unified: 'error', raw: 'error' };
1939
2196
  controller.enqueue({ type: 'error', error: value });
1940
2197
  }
1941
2198
  },
@@ -1961,6 +2218,8 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
1961
2218
  request: { body },
1962
2219
  response: { headers: responseHeaders },
1963
2220
  };
2221
+
2222
+ return result;
1964
2223
  }
1965
2224
  }
1966
2225
 
@@ -1986,6 +2245,12 @@ function isResponseFinishedChunk(
1986
2245
  );
1987
2246
  }
1988
2247
 
2248
+ function isResponseFailedChunk(
2249
+ chunk: OpenAIResponsesChunk,
2250
+ ): chunk is OpenAIResponsesChunk & { type: 'response.failed' } {
2251
+ return chunk.type === 'response.failed';
2252
+ }
2253
+
1989
2254
  function isResponseCreatedChunk(
1990
2255
  chunk: OpenAIResponsesChunk,
1991
2256
  ): chunk is OpenAIResponsesChunk & { type: 'response.created' } {
@@ -2064,6 +2329,15 @@ function isErrorChunk(
2064
2329
  return chunk.type === 'error';
2065
2330
  }
2066
2331
 
2332
+ function isResponseOutputChunk(chunk: OpenAIResponsesChunk): boolean {
2333
+ return !(
2334
+ chunk.type === 'response.created' ||
2335
+ chunk.type === 'response.failed' ||
2336
+ chunk.type === 'error' ||
2337
+ chunk.type === 'unknown_chunk'
2338
+ );
2339
+ }
2340
+
2067
2341
  function mapWebSearchOutput(
2068
2342
  action: OpenAIResponsesWebSearchAction | null | undefined,
2069
2343
  ): InferSchema<typeof webSearchOutputSchema> {
@@ -2074,7 +2348,11 @@ function mapWebSearchOutput(
2074
2348
  switch (action.type) {
2075
2349
  case 'search':
2076
2350
  return {
2077
- action: { type: 'search', query: action.query ?? undefined },
2351
+ action: {
2352
+ type: 'search',
2353
+ query: action.query ?? undefined,
2354
+ ...(action.queries != null && { queries: action.queries }),
2355
+ },
2078
2356
  // include sources when provided by the Responses API (behind include flag)
2079
2357
  ...(action.sources != null && { sources: action.sources }),
2080
2358
  };