@ai-sdk/openai 3.0.81 → 3.0.82

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.
@@ -7,7 +7,6 @@ import {
7
7
  createEventSourceResponseHandler,
8
8
  createJsonResponseHandler,
9
9
  generateId,
10
- isParsableJson,
11
10
  parseProviderOptions,
12
11
  postJsonToApi
13
12
  } from "@ai-sdk/provider-utils";
@@ -47,6 +46,129 @@ function getOpenAILanguageModelCapabilities(modelId) {
47
46
  };
48
47
  }
49
48
 
49
+ // src/openai-stream-error.ts
50
+ import { APICallError } from "@ai-sdk/provider";
51
+ async function throwIfOpenAIStreamErrorBeforeOutput({
52
+ stream,
53
+ getError,
54
+ isOutputChunk,
55
+ url,
56
+ requestBodyValues,
57
+ responseHeaders
58
+ }) {
59
+ const [streamForEarlyError, streamForConsumer] = stream.tee();
60
+ const reader = streamForEarlyError.getReader();
61
+ try {
62
+ while (true) {
63
+ const result = await reader.read();
64
+ if (result.done) {
65
+ return streamForConsumer;
66
+ }
67
+ const chunk = result.value;
68
+ if (!chunk.success) {
69
+ return streamForConsumer;
70
+ }
71
+ const errorFrame = getError(chunk.value);
72
+ if (errorFrame != null) {
73
+ streamForConsumer.cancel().catch(() => {
74
+ });
75
+ throw createOpenAIStreamError({
76
+ frame: errorFrame,
77
+ url,
78
+ requestBodyValues,
79
+ responseHeaders
80
+ });
81
+ }
82
+ if (isOutputChunk(chunk.value)) {
83
+ return streamForConsumer;
84
+ }
85
+ }
86
+ } finally {
87
+ reader.cancel().catch(() => {
88
+ });
89
+ reader.releaseLock();
90
+ }
91
+ }
92
+ function createOpenAIStreamError({
93
+ frame,
94
+ url,
95
+ requestBodyValues,
96
+ responseHeaders
97
+ }) {
98
+ var _a;
99
+ const streamError = parseStreamError(frame);
100
+ return new APICallError({
101
+ message: (_a = streamError == null ? void 0 : streamError.message) != null ? _a : "OpenAI stream failed before any output was generated",
102
+ url,
103
+ requestBodyValues,
104
+ statusCode: streamError == null ? 500 : getStatusCode(streamError),
105
+ responseHeaders,
106
+ responseBody: JSON.stringify(frame),
107
+ data: frame
108
+ });
109
+ }
110
+ function parseStreamError(frame) {
111
+ var _a;
112
+ const value = asRecord(frame);
113
+ if (value == null) {
114
+ return void 0;
115
+ }
116
+ if (value.type === "response.failed") {
117
+ const response = asRecord(value.response);
118
+ const responseError = asRecord(response == null ? void 0 : response.error);
119
+ return typeof (responseError == null ? void 0 : responseError.message) === "string" ? {
120
+ message: responseError.message,
121
+ code: getStringOrNumber(responseError.code),
122
+ type: "response.failed",
123
+ frame
124
+ } : void 0;
125
+ }
126
+ const error = (_a = asRecord(value.error)) != null ? _a : value;
127
+ return typeof error.message === "string" && (asRecord(value.error) != null || typeof error.type === "string" || "code" in error || "param" in error) ? {
128
+ message: error.message,
129
+ code: getStringOrNumber(error.code),
130
+ type: typeof error.type === "string" ? error.type : void 0,
131
+ frame
132
+ } : void 0;
133
+ }
134
+ function getStatusCode(error) {
135
+ if (typeof error.code === "number" && isHttpErrorStatusCode(error.code)) {
136
+ return error.code;
137
+ }
138
+ if (typeof error.code === "string" && /^\d{3}$/.test(error.code)) {
139
+ const numericCode = Number(error.code);
140
+ if (isHttpErrorStatusCode(numericCode)) {
141
+ return numericCode;
142
+ }
143
+ }
144
+ const discriminator = [error.code, error.type].filter((value) => typeof value === "string" || typeof value === "number").join(" ").toLowerCase();
145
+ if (["insufficient_quota", "rate_limit"].some(
146
+ (term) => discriminator.includes(term)
147
+ )) {
148
+ return 429;
149
+ }
150
+ if (discriminator.includes("authentication")) return 401;
151
+ if (discriminator.includes("permission")) return 403;
152
+ if (discriminator.includes("not_found")) return 404;
153
+ if (["invalid", "bad_request", "context_length"].some(
154
+ (term) => discriminator.includes(term)
155
+ )) {
156
+ return 400;
157
+ }
158
+ if (discriminator.includes("overload")) return 503;
159
+ if (discriminator.includes("timeout")) return 504;
160
+ return 500;
161
+ }
162
+ function asRecord(value) {
163
+ return typeof value === "object" && value != null ? value : void 0;
164
+ }
165
+ function getStringOrNumber(value) {
166
+ return typeof value === "string" || typeof value === "number" ? value : void 0;
167
+ }
168
+ function isHttpErrorStatusCode(value) {
169
+ return Number.isInteger(value) && value >= 400 && value <= 599;
170
+ }
171
+
50
172
  // src/chat/convert-openai-chat-usage.ts
51
173
  function convertOpenAIChatUsage(usage) {
52
174
  var _a, _b, _c, _d, _e, _f;
@@ -251,7 +373,7 @@ function convertToOpenAIChatMessages({
251
373
  contentValue = output.value;
252
374
  break;
253
375
  case "execution-denied":
254
- contentValue = (_a = output.reason) != null ? _a : "Tool execution denied.";
376
+ contentValue = (_a = output.reason) != null ? _a : "Tool call execution denied.";
255
377
  break;
256
378
  case "content":
257
379
  case "json":
@@ -913,11 +1035,12 @@ var OpenAIChatLanguageModel = class {
913
1035
  include_usage: true
914
1036
  }
915
1037
  };
1038
+ const url = this.config.url({
1039
+ path: "/chat/completions",
1040
+ modelId: this.modelId
1041
+ });
916
1042
  const { responseHeaders, value: response } = await postJsonToApi({
917
- url: this.config.url({
918
- path: "/chat/completions",
919
- modelId: this.modelId
920
- }),
1043
+ url,
921
1044
  headers: combineHeaders(this.config.headers(), options.headers),
922
1045
  body,
923
1046
  failedResponseHandler: openaiFailedResponseHandler,
@@ -927,6 +1050,14 @@ var OpenAIChatLanguageModel = class {
927
1050
  abortSignal: options.abortSignal,
928
1051
  fetch: this.config.fetch
929
1052
  });
1053
+ const checkedResponse = await throwIfOpenAIStreamErrorBeforeOutput({
1054
+ stream: response,
1055
+ getError: (chunk) => "error" in chunk ? chunk.error : void 0,
1056
+ isOutputChunk: isOpenAIChatOutputChunk,
1057
+ url,
1058
+ requestBodyValues: body,
1059
+ responseHeaders
1060
+ });
930
1061
  const toolCalls = [];
931
1062
  let finishReason = {
932
1063
  unified: "other",
@@ -936,14 +1067,14 @@ var OpenAIChatLanguageModel = class {
936
1067
  let metadataExtracted = false;
937
1068
  let isActiveText = false;
938
1069
  const providerMetadata = { openai: {} };
939
- return {
940
- stream: response.pipeThrough(
1070
+ const result = {
1071
+ stream: checkedResponse.pipeThrough(
941
1072
  new TransformStream({
942
1073
  start(controller) {
943
1074
  controller.enqueue({ type: "stream-start", warnings });
944
1075
  },
945
1076
  transform(chunk, controller) {
946
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
1077
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
947
1078
  if (options.includeRawChunks) {
948
1079
  controller.enqueue({ type: "raw", rawValue: chunk.rawValue });
949
1080
  }
@@ -1047,19 +1178,6 @@ var OpenAIChatLanguageModel = class {
1047
1178
  delta: toolCall2.function.arguments
1048
1179
  });
1049
1180
  }
1050
- if (isParsableJson(toolCall2.function.arguments)) {
1051
- controller.enqueue({
1052
- type: "tool-input-end",
1053
- id: toolCall2.id
1054
- });
1055
- controller.enqueue({
1056
- type: "tool-call",
1057
- toolCallId: (_j = toolCall2.id) != null ? _j : generateId(),
1058
- toolName: toolCall2.function.name,
1059
- input: toolCall2.function.arguments
1060
- });
1061
- toolCall2.hasFinished = true;
1062
- }
1063
1181
  }
1064
1182
  continue;
1065
1183
  }
@@ -1067,27 +1185,14 @@ var OpenAIChatLanguageModel = class {
1067
1185
  if (toolCall.hasFinished) {
1068
1186
  continue;
1069
1187
  }
1070
- if (((_k = toolCallDelta.function) == null ? void 0 : _k.arguments) != null) {
1071
- toolCall.function.arguments += (_m = (_l = toolCallDelta.function) == null ? void 0 : _l.arguments) != null ? _m : "";
1188
+ if (((_j = toolCallDelta.function) == null ? void 0 : _j.arguments) != null) {
1189
+ toolCall.function.arguments += (_l = (_k = toolCallDelta.function) == null ? void 0 : _k.arguments) != null ? _l : "";
1072
1190
  }
1073
1191
  controller.enqueue({
1074
1192
  type: "tool-input-delta",
1075
1193
  id: toolCall.id,
1076
- delta: (_n = toolCallDelta.function.arguments) != null ? _n : ""
1194
+ delta: (_m = toolCallDelta.function.arguments) != null ? _m : ""
1077
1195
  });
1078
- if (((_o = toolCall.function) == null ? void 0 : _o.name) != null && ((_p = toolCall.function) == null ? void 0 : _p.arguments) != null && isParsableJson(toolCall.function.arguments)) {
1079
- controller.enqueue({
1080
- type: "tool-input-end",
1081
- id: toolCall.id
1082
- });
1083
- controller.enqueue({
1084
- type: "tool-call",
1085
- toolCallId: (_q = toolCall.id) != null ? _q : generateId(),
1086
- toolName: toolCall.function.name,
1087
- input: toolCall.function.arguments
1088
- });
1089
- toolCall.hasFinished = true;
1090
- }
1091
1196
  }
1092
1197
  }
1093
1198
  if (delta.annotations != null) {
@@ -1103,9 +1208,25 @@ var OpenAIChatLanguageModel = class {
1103
1208
  }
1104
1209
  },
1105
1210
  flush(controller) {
1211
+ var _a;
1106
1212
  if (isActiveText) {
1107
1213
  controller.enqueue({ type: "text-end", id: "0" });
1108
1214
  }
1215
+ for (const toolCall of toolCalls) {
1216
+ if (!toolCall.hasFinished) {
1217
+ controller.enqueue({
1218
+ type: "tool-input-end",
1219
+ id: toolCall.id
1220
+ });
1221
+ controller.enqueue({
1222
+ type: "tool-call",
1223
+ toolCallId: (_a = toolCall.id) != null ? _a : generateId(),
1224
+ toolName: toolCall.function.name,
1225
+ input: toolCall.function.arguments
1226
+ });
1227
+ toolCall.hasFinished = true;
1228
+ }
1229
+ }
1109
1230
  controller.enqueue({
1110
1231
  type: "finish",
1111
1232
  finishReason,
@@ -1118,8 +1239,18 @@ var OpenAIChatLanguageModel = class {
1118
1239
  request: { body },
1119
1240
  response: { headers: responseHeaders }
1120
1241
  };
1242
+ return result;
1121
1243
  }
1122
1244
  };
1245
+ function isOpenAIChatOutputChunk(chunk) {
1246
+ if ("error" in chunk) {
1247
+ return false;
1248
+ }
1249
+ return chunk.choices.some((choice) => {
1250
+ const delta = choice.delta;
1251
+ return (delta == null ? void 0 : delta.content) != null && delta.content.length > 0 || (delta == null ? void 0 : delta.tool_calls) != null && delta.tool_calls.length > 0 || (delta == null ? void 0 : delta.annotations) != null && delta.annotations.length > 0;
1252
+ });
1253
+ }
1123
1254
 
1124
1255
  // src/completion/openai-completion-language-model.ts
1125
1256
  import {
@@ -1526,11 +1657,12 @@ var OpenAICompletionLanguageModel = class {
1526
1657
  include_usage: true
1527
1658
  }
1528
1659
  };
1660
+ const url = this.config.url({
1661
+ path: "/completions",
1662
+ modelId: this.modelId
1663
+ });
1529
1664
  const { responseHeaders, value: response } = await postJsonToApi2({
1530
- url: this.config.url({
1531
- path: "/completions",
1532
- modelId: this.modelId
1533
- }),
1665
+ url,
1534
1666
  headers: combineHeaders2(this.config.headers(), options.headers),
1535
1667
  body,
1536
1668
  failedResponseHandler: openaiFailedResponseHandler,
@@ -1540,6 +1672,14 @@ var OpenAICompletionLanguageModel = class {
1540
1672
  abortSignal: options.abortSignal,
1541
1673
  fetch: this.config.fetch
1542
1674
  });
1675
+ const checkedResponse = await throwIfOpenAIStreamErrorBeforeOutput({
1676
+ stream: response,
1677
+ getError: (chunk) => "error" in chunk ? chunk.error : void 0,
1678
+ isOutputChunk: isOpenAICompletionOutputChunk,
1679
+ url,
1680
+ requestBodyValues: body,
1681
+ responseHeaders
1682
+ });
1543
1683
  let finishReason = {
1544
1684
  unified: "other",
1545
1685
  raw: void 0
@@ -1547,8 +1687,8 @@ var OpenAICompletionLanguageModel = class {
1547
1687
  const providerMetadata = { openai: {} };
1548
1688
  let usage = void 0;
1549
1689
  let isFirstChunk = true;
1550
- return {
1551
- stream: response.pipeThrough(
1690
+ const result = {
1691
+ stream: checkedResponse.pipeThrough(
1552
1692
  new TransformStream({
1553
1693
  start(controller) {
1554
1694
  controller.enqueue({ type: "stream-start", warnings });
@@ -1613,8 +1753,12 @@ var OpenAICompletionLanguageModel = class {
1613
1753
  request: { body },
1614
1754
  response: { headers: responseHeaders }
1615
1755
  };
1756
+ return result;
1616
1757
  }
1617
1758
  };
1759
+ function isOpenAICompletionOutputChunk(chunk) {
1760
+ return !("error" in chunk) && chunk.choices.some((choice) => choice.text.length > 0);
1761
+ }
1618
1762
 
1619
1763
  // src/embedding/openai-embedding-model.ts
1620
1764
  import {
@@ -2442,7 +2586,7 @@ var OpenAISpeechModel = class {
2442
2586
 
2443
2587
  // src/responses/openai-responses-language-model.ts
2444
2588
  import {
2445
- APICallError
2589
+ APICallError as APICallError2
2446
2590
  } from "@ai-sdk/provider";
2447
2591
  import {
2448
2592
  combineHeaders as combineHeaders7,
@@ -3196,7 +3340,7 @@ async function convertToOpenAIResponsesInput({
3196
3340
  outputValue = output.value;
3197
3341
  break;
3198
3342
  case "execution-denied":
3199
- outputValue = (_v = output.reason) != null ? _v : "Tool execution denied.";
3343
+ outputValue = (_v = output.reason) != null ? _v : "Tool call execution denied.";
3200
3344
  break;
3201
3345
  case "json":
3202
3346
  case "error-json":
@@ -3257,7 +3401,7 @@ async function convertToOpenAIResponsesInput({
3257
3401
  contentValue = output.value;
3258
3402
  break;
3259
3403
  case "execution-denied":
3260
- contentValue = (_w = output.reason) != null ? _w : "Tool execution denied.";
3404
+ contentValue = (_w = output.reason) != null ? _w : "Tool call execution denied.";
3261
3405
  break;
3262
3406
  case "json":
3263
3407
  case "error-json":
@@ -3374,6 +3518,23 @@ var jsonValueSchema = z18.lazy(
3374
3518
  z18.record(z18.string(), jsonValueSchema.optional())
3375
3519
  ])
3376
3520
  );
3521
+ var openaiResponsesNestedErrorChunkSchema = z18.object({
3522
+ type: z18.literal("error"),
3523
+ sequence_number: z18.number(),
3524
+ error: z18.object({
3525
+ type: z18.string(),
3526
+ code: z18.string(),
3527
+ message: z18.string(),
3528
+ param: z18.string().nullish()
3529
+ })
3530
+ });
3531
+ var openaiResponsesErrorChunkSchema = z18.object({
3532
+ type: z18.literal("error"),
3533
+ sequence_number: z18.number(),
3534
+ code: z18.string().nullish(),
3535
+ message: z18.string(),
3536
+ param: z18.string().nullish()
3537
+ });
3377
3538
  var openaiResponsesChunkSchema = lazySchema16(
3378
3539
  () => zodSchema16(
3379
3540
  z18.union([
@@ -3416,6 +3577,7 @@ var openaiResponsesChunkSchema = lazySchema16(
3416
3577
  }),
3417
3578
  z18.object({
3418
3579
  type: z18.literal("response.failed"),
3580
+ sequence_number: z18.number(),
3419
3581
  response: z18.object({
3420
3582
  error: z18.object({
3421
3583
  code: z18.string().nullish(),
@@ -3904,16 +4066,8 @@ var openaiResponsesChunkSchema = lazySchema16(
3904
4066
  output_index: z18.number(),
3905
4067
  diff: z18.string()
3906
4068
  }),
3907
- z18.object({
3908
- type: z18.literal("error"),
3909
- sequence_number: z18.number(),
3910
- error: z18.object({
3911
- type: z18.string(),
3912
- code: z18.string(),
3913
- message: z18.string(),
3914
- param: z18.string().nullish()
3915
- })
3916
- }),
4069
+ openaiResponsesNestedErrorChunkSchema,
4070
+ openaiResponsesErrorChunkSchema,
3917
4071
  z18.object({ type: z18.string() }).loose().transform((value) => ({
3918
4072
  type: "unknown_chunk",
3919
4073
  message: value.type
@@ -5460,7 +5614,7 @@ var OpenAIResponsesLanguageModel = class {
5460
5614
  fetch: this.config.fetch
5461
5615
  });
5462
5616
  if (response.error) {
5463
- throw new APICallError({
5617
+ throw new APICallError2({
5464
5618
  message: response.error.message,
5465
5619
  url,
5466
5620
  requestBodyValues: body,
@@ -5933,6 +6087,14 @@ var OpenAIResponsesLanguageModel = class {
5933
6087
  abortSignal: options.abortSignal,
5934
6088
  fetch: this.config.fetch
5935
6089
  });
6090
+ const checkedResponse = await throwIfOpenAIStreamErrorBeforeOutput({
6091
+ stream: response,
6092
+ getError: (chunk) => isErrorChunk(chunk) || isResponseFailedChunk(chunk) && chunk.response.error != null ? chunk : void 0,
6093
+ isOutputChunk: isResponseOutputChunk,
6094
+ url,
6095
+ requestBodyValues: body,
6096
+ responseHeaders
6097
+ });
5936
6098
  const self = this;
5937
6099
  const approvalRequestIdToDummyToolCallIdFromPrompt = extractApprovalRequestIdToToolCallIdMapping(options.prompt);
5938
6100
  const approvalRequestIdToDummyToolCallIdFromStream = /* @__PURE__ */ new Map();
@@ -5950,8 +6112,9 @@ var OpenAIResponsesLanguageModel = class {
5950
6112
  const activeReasoning = {};
5951
6113
  let serviceTier;
5952
6114
  const hostedToolSearchCallIds = [];
5953
- return {
5954
- stream: response.pipeThrough(
6115
+ let encounteredStreamError = false;
6116
+ const result = {
6117
+ stream: checkedResponse.pipeThrough(
5955
6118
  new TransformStream({
5956
6119
  start(controller) {
5957
6120
  controller.enqueue({ type: "stream-start", warnings });
@@ -6271,12 +6434,12 @@ var OpenAIResponsesLanguageModel = class {
6271
6434
  toolName: toolNameMapping.toCustomToolName("file_search"),
6272
6435
  result: {
6273
6436
  queries: value.item.queries,
6274
- results: (_f = (_e = value.item.results) == null ? void 0 : _e.map((result) => ({
6275
- attributes: result.attributes,
6276
- fileId: result.file_id,
6277
- filename: result.filename,
6278
- score: result.score,
6279
- text: result.text
6437
+ results: (_f = (_e = value.item.results) == null ? void 0 : _e.map((result2) => ({
6438
+ attributes: result2.attributes,
6439
+ fileId: result2.file_id,
6440
+ filename: result2.filename,
6441
+ score: result2.score,
6442
+ text: result2.text
6280
6443
  }))) != null ? _f : null
6281
6444
  }
6282
6445
  });
@@ -6709,6 +6872,21 @@ var OpenAIResponsesLanguageModel = class {
6709
6872
  raw: incompleteReason != null ? incompleteReason : "error"
6710
6873
  };
6711
6874
  usage = (_z = value.response.usage) != null ? _z : void 0;
6875
+ if (!encounteredStreamError && value.response.error != null) {
6876
+ encounteredStreamError = true;
6877
+ controller.enqueue({
6878
+ type: "error",
6879
+ error: {
6880
+ type: "response.failed",
6881
+ sequence_number: value.sequence_number,
6882
+ response: {
6883
+ error: value.response.error,
6884
+ incomplete_details: value.response.incomplete_details,
6885
+ service_tier: value.response.service_tier
6886
+ }
6887
+ }
6888
+ });
6889
+ }
6712
6890
  } else if (isResponseAnnotationAddedChunk(value)) {
6713
6891
  ongoingAnnotations.push(value.annotation);
6714
6892
  if (value.annotation.type === "url_citation") {
@@ -6769,6 +6947,8 @@ var OpenAIResponsesLanguageModel = class {
6769
6947
  });
6770
6948
  }
6771
6949
  } else if (isErrorChunk(value)) {
6950
+ encounteredStreamError = true;
6951
+ finishReason = { unified: "error", raw: "error" };
6772
6952
  controller.enqueue({ type: "error", error: value });
6773
6953
  }
6774
6954
  },
@@ -6792,13 +6972,14 @@ var OpenAIResponsesLanguageModel = class {
6792
6972
  request: { body },
6793
6973
  response: { headers: responseHeaders }
6794
6974
  };
6975
+ return result;
6795
6976
  }
6796
6977
  };
6797
6978
  function isTextDeltaChunk(chunk) {
6798
6979
  return chunk.type === "response.output_text.delta";
6799
6980
  }
6800
6981
  function isOpenAIChatCompletionChunk(value) {
6801
- const chunk = asRecord(value);
6982
+ const chunk = asRecord2(value);
6802
6983
  return chunk != null && Array.isArray(chunk.choices) && typeof chunk.type !== "string";
6803
6984
  }
6804
6985
  function createOpenAIResponsesChatCompletionsMismatchError({
@@ -6808,7 +6989,7 @@ function createOpenAIResponsesChatCompletionsMismatchError({
6808
6989
  requestBodyValues,
6809
6990
  responseHeaders
6810
6991
  }) {
6811
- return new APICallError({
6992
+ return new APICallError2({
6812
6993
  message: "Received a Chat Completions stream while using the OpenAI Responses API. The default OpenAI provider model uses the Responses API. If your custom baseURL targets a Chat Completions-compatible endpoint, use openai.chat('model-id') or createOpenAI(...).chat('model-id') instead. You can also use @ai-sdk/openai-compatible for OpenAI-compatible providers.",
6813
6994
  url,
6814
6995
  requestBodyValues,
@@ -6819,7 +7000,7 @@ function createOpenAIResponsesChatCompletionsMismatchError({
6819
7000
  isRetryable: false
6820
7001
  });
6821
7002
  }
6822
- function asRecord(value) {
7003
+ function asRecord2(value) {
6823
7004
  return typeof value === "object" && value != null ? value : void 0;
6824
7005
  }
6825
7006
  function isResponseOutputItemDoneChunk(chunk) {
@@ -6864,6 +7045,9 @@ function isResponseAnnotationAddedChunk(chunk) {
6864
7045
  function isErrorChunk(chunk) {
6865
7046
  return chunk.type === "error";
6866
7047
  }
7048
+ function isResponseOutputChunk(chunk) {
7049
+ return !(chunk.type === "response.created" || chunk.type === "response.failed" || chunk.type === "error" || chunk.type === "unknown_chunk");
7050
+ }
6867
7051
  function mapWebSearchOutput(action) {
6868
7052
  var _a;
6869
7053
  if (action == null) {