ai 5.1.0-beta.20 → 5.1.0-beta.22

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.
package/dist/index.mjs CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  asSchema as asSchema5,
11
11
  createIdGenerator as createIdGenerator5,
12
12
  dynamicTool as dynamicTool2,
13
- generateId as generateId2,
13
+ generateId,
14
14
  jsonSchema as jsonSchema2,
15
15
  parseJsonEventStream as parseJsonEventStream3,
16
16
  tool as tool2,
@@ -20,7 +20,6 @@ import {
20
20
  // src/generate-text/generate-text.ts
21
21
  import {
22
22
  createIdGenerator,
23
- executeTool,
24
23
  getErrorMessage as getErrorMessage5,
25
24
  withUserAgentSuffix as withUserAgentSuffix2
26
25
  } from "@ai-sdk/provider-utils";
@@ -717,7 +716,7 @@ import {
717
716
  } from "@ai-sdk/provider-utils";
718
717
 
719
718
  // src/version.ts
720
- var VERSION = true ? "5.1.0-beta.20" : "0.0.0-test";
719
+ var VERSION = true ? "5.1.0-beta.22" : "0.0.0-test";
721
720
 
722
721
  // src/util/download/download.ts
723
722
  var download = async ({ url }) => {
@@ -863,12 +862,26 @@ async function convertToLanguageModelPrompt({
863
862
  download2,
864
863
  supportedUrls
865
864
  );
866
- return [
865
+ const messages = [
867
866
  ...prompt.system != null ? [{ role: "system", content: prompt.system }] : [],
868
867
  ...prompt.messages.map(
869
868
  (message) => convertToLanguageModelMessage({ message, downloadedAssets })
870
869
  )
871
870
  ];
871
+ const combinedMessages = [];
872
+ for (const message of messages) {
873
+ if (message.role !== "tool") {
874
+ combinedMessages.push(message);
875
+ continue;
876
+ }
877
+ const lastCombinedMessage = combinedMessages.at(-1);
878
+ if ((lastCombinedMessage == null ? void 0 : lastCombinedMessage.role) === "tool") {
879
+ lastCombinedMessage.content.push(...message.content);
880
+ } else {
881
+ combinedMessages.push(message);
882
+ }
883
+ }
884
+ return combinedMessages;
872
885
  }
873
886
  function convertToLanguageModelMessage({
874
887
  message,
@@ -910,6 +923,8 @@ function convertToLanguageModelMessage({
910
923
  content: message.content.filter(
911
924
  // remove empty text parts (no text, and no provider options):
912
925
  (part) => part.type !== "text" || part.text !== "" || part.providerOptions != null
926
+ ).filter(
927
+ (part) => part.type !== "tool-approval-request"
913
928
  ).map((part) => {
914
929
  const providerOptions = part.providerOptions;
915
930
  switch (part.type) {
@@ -966,7 +981,7 @@ function convertToLanguageModelMessage({
966
981
  case "tool": {
967
982
  return {
968
983
  role: "tool",
969
- content: message.content.map((part) => ({
984
+ content: message.content.filter((part) => part.type !== "tool-approval-response").map((part) => ({
970
985
  type: "tool-result",
971
986
  toolCallId: part.toolCallId,
972
987
  toolName: part.toolName,
@@ -1078,6 +1093,29 @@ function convertPartToLanguageModelPart(part, downloadedAssets) {
1078
1093
  }
1079
1094
  }
1080
1095
 
1096
+ // src/prompt/create-tool-model-output.ts
1097
+ import {
1098
+ getErrorMessage as getErrorMessage3
1099
+ } from "@ai-sdk/provider";
1100
+ function createToolModelOutput({
1101
+ output,
1102
+ tool: tool3,
1103
+ errorMode
1104
+ }) {
1105
+ if (errorMode === "text") {
1106
+ return { type: "error-text", value: getErrorMessage3(output) };
1107
+ } else if (errorMode === "json") {
1108
+ return { type: "error-json", value: toJSONValue(output) };
1109
+ }
1110
+ if (tool3 == null ? void 0 : tool3.toModelOutput) {
1111
+ return tool3.toModelOutput(output);
1112
+ }
1113
+ return typeof output === "string" ? { type: "text", value: output } : { type: "json", value: toJSONValue(output) };
1114
+ }
1115
+ function toJSONValue(value) {
1116
+ return value === void 0 ? null : value;
1117
+ }
1118
+
1081
1119
  // src/prompt/prepare-call-settings.ts
1082
1120
  function prepareCallSettings({
1083
1121
  maxOutputTokens,
@@ -1329,6 +1367,17 @@ var toolResultPartSchema = z4.object({
1329
1367
  output: outputSchema,
1330
1368
  providerOptions: providerMetadataSchema.optional()
1331
1369
  });
1370
+ var toolApprovalRequestSchema = z4.object({
1371
+ type: z4.literal("tool-approval-request"),
1372
+ approvalId: z4.string(),
1373
+ toolCallId: z4.string()
1374
+ });
1375
+ var toolApprovalResponseSchema = z4.object({
1376
+ type: z4.literal("tool-approval-response"),
1377
+ approvalId: z4.string(),
1378
+ approved: z4.boolean(),
1379
+ reason: z4.string().optional()
1380
+ });
1332
1381
 
1333
1382
  // src/prompt/message.ts
1334
1383
  var systemModelMessageSchema = z5.object(
@@ -1358,7 +1407,8 @@ var assistantModelMessageSchema = z5.object({
1358
1407
  filePartSchema,
1359
1408
  reasoningPartSchema,
1360
1409
  toolCallPartSchema,
1361
- toolResultPartSchema
1410
+ toolResultPartSchema,
1411
+ toolApprovalRequestSchema
1362
1412
  ])
1363
1413
  )
1364
1414
  ]),
@@ -1367,7 +1417,7 @@ var assistantModelMessageSchema = z5.object({
1367
1417
  var coreAssistantMessageSchema = assistantModelMessageSchema;
1368
1418
  var toolModelMessageSchema = z5.object({
1369
1419
  role: z5.literal("tool"),
1370
- content: z5.array(toolResultPartSchema),
1420
+ content: z5.array(z5.union([toolResultPartSchema, toolApprovalResponseSchema])),
1371
1421
  providerOptions: providerMetadataSchema.optional()
1372
1422
  });
1373
1423
  var coreToolMessageSchema = toolModelMessageSchema;
@@ -1690,7 +1740,7 @@ function asArray(value) {
1690
1740
 
1691
1741
  // src/util/retry-with-exponential-backoff.ts
1692
1742
  import { APICallError as APICallError2 } from "@ai-sdk/provider";
1693
- import { delay, getErrorMessage as getErrorMessage3, isAbortError } from "@ai-sdk/provider-utils";
1743
+ import { delay, getErrorMessage as getErrorMessage4, isAbortError } from "@ai-sdk/provider-utils";
1694
1744
  function getRetryDelayInMs({
1695
1745
  error,
1696
1746
  exponentialBackoffDelay
@@ -1746,7 +1796,7 @@ async function _retryWithExponentialBackoff(f, {
1746
1796
  if (maxRetries === 0) {
1747
1797
  throw error;
1748
1798
  }
1749
- const errorMessage = getErrorMessage3(error);
1799
+ const errorMessage = getErrorMessage4(error);
1750
1800
  const newErrors = [...errors, error];
1751
1801
  const tryNumber = newErrors.length;
1752
1802
  if (tryNumber > maxRetries) {
@@ -1817,6 +1867,164 @@ function prepareRetries({
1817
1867
  };
1818
1868
  }
1819
1869
 
1870
+ // src/generate-text/collect-tool-approvals.ts
1871
+ function collectToolApprovals({
1872
+ messages
1873
+ }) {
1874
+ const lastMessage = messages.at(-1);
1875
+ if ((lastMessage == null ? void 0 : lastMessage.role) != "tool") {
1876
+ return {
1877
+ approvedToolApprovals: [],
1878
+ deniedToolApprovals: []
1879
+ };
1880
+ }
1881
+ const toolCallsByToolCallId = {};
1882
+ for (const message of messages) {
1883
+ if (message.role === "assistant" && typeof message.content !== "string") {
1884
+ const content = message.content;
1885
+ for (const part of content) {
1886
+ if (part.type === "tool-call") {
1887
+ toolCallsByToolCallId[part.toolCallId] = part;
1888
+ }
1889
+ }
1890
+ }
1891
+ }
1892
+ const toolApprovalRequestsByApprovalId = {};
1893
+ for (const message of messages) {
1894
+ if (message.role === "assistant" && typeof message.content !== "string") {
1895
+ const content = message.content;
1896
+ for (const part of content) {
1897
+ if (part.type === "tool-approval-request") {
1898
+ toolApprovalRequestsByApprovalId[part.approvalId] = part;
1899
+ }
1900
+ }
1901
+ }
1902
+ }
1903
+ const toolResults = {};
1904
+ for (const part of lastMessage.content) {
1905
+ if (part.type === "tool-result") {
1906
+ toolResults[part.toolCallId] = part;
1907
+ }
1908
+ }
1909
+ const approvedToolApprovals = [];
1910
+ const deniedToolApprovals = [];
1911
+ const approvalResponses = lastMessage.content.filter(
1912
+ (part) => part.type === "tool-approval-response"
1913
+ );
1914
+ for (const approvalResponse of approvalResponses) {
1915
+ const approvalRequest = toolApprovalRequestsByApprovalId[approvalResponse.approvalId];
1916
+ if (toolResults[approvalRequest.toolCallId] != null) {
1917
+ continue;
1918
+ }
1919
+ const approval = {
1920
+ approvalRequest,
1921
+ approvalResponse,
1922
+ toolCall: toolCallsByToolCallId[approvalRequest.toolCallId]
1923
+ };
1924
+ if (approvalResponse.approved) {
1925
+ approvedToolApprovals.push(approval);
1926
+ } else {
1927
+ deniedToolApprovals.push(approval);
1928
+ }
1929
+ }
1930
+ return { approvedToolApprovals, deniedToolApprovals };
1931
+ }
1932
+
1933
+ // src/generate-text/execute-tool-call.ts
1934
+ import { executeTool } from "@ai-sdk/provider-utils";
1935
+ async function executeToolCall({
1936
+ toolCall,
1937
+ tools,
1938
+ tracer,
1939
+ telemetry,
1940
+ messages,
1941
+ abortSignal,
1942
+ experimental_context,
1943
+ onPreliminaryToolResult
1944
+ }) {
1945
+ const { toolName, toolCallId, input } = toolCall;
1946
+ const tool3 = tools == null ? void 0 : tools[toolName];
1947
+ if ((tool3 == null ? void 0 : tool3.execute) == null) {
1948
+ return void 0;
1949
+ }
1950
+ return recordSpan({
1951
+ name: "ai.toolCall",
1952
+ attributes: selectTelemetryAttributes({
1953
+ telemetry,
1954
+ attributes: {
1955
+ ...assembleOperationName({
1956
+ operationId: "ai.toolCall",
1957
+ telemetry
1958
+ }),
1959
+ "ai.toolCall.name": toolName,
1960
+ "ai.toolCall.id": toolCallId,
1961
+ "ai.toolCall.args": {
1962
+ output: () => JSON.stringify(input)
1963
+ }
1964
+ }
1965
+ }),
1966
+ tracer,
1967
+ fn: async (span) => {
1968
+ let output;
1969
+ try {
1970
+ const stream = executeTool({
1971
+ execute: tool3.execute.bind(tool3),
1972
+ input,
1973
+ options: {
1974
+ toolCallId,
1975
+ messages,
1976
+ abortSignal,
1977
+ experimental_context
1978
+ }
1979
+ });
1980
+ for await (const part of stream) {
1981
+ if (part.type === "preliminary") {
1982
+ onPreliminaryToolResult == null ? void 0 : onPreliminaryToolResult({
1983
+ ...toolCall,
1984
+ type: "tool-result",
1985
+ output: part.output,
1986
+ preliminary: true
1987
+ });
1988
+ } else {
1989
+ output = part.output;
1990
+ }
1991
+ }
1992
+ } catch (error) {
1993
+ recordErrorOnSpan(span, error);
1994
+ return {
1995
+ type: "tool-error",
1996
+ toolCallId,
1997
+ toolName,
1998
+ input,
1999
+ error,
2000
+ dynamic: tool3.type === "dynamic"
2001
+ };
2002
+ }
2003
+ try {
2004
+ span.setAttributes(
2005
+ selectTelemetryAttributes({
2006
+ telemetry,
2007
+ attributes: {
2008
+ "ai.toolCall.result": {
2009
+ output: () => JSON.stringify(output)
2010
+ }
2011
+ }
2012
+ })
2013
+ );
2014
+ } catch (ignored) {
2015
+ }
2016
+ return {
2017
+ type: "tool-result",
2018
+ toolCallId,
2019
+ toolName,
2020
+ input,
2021
+ output,
2022
+ dynamic: tool3.type === "dynamic"
2023
+ };
2024
+ }
2025
+ });
2026
+ }
2027
+
1820
2028
  // src/generate-text/extract-text-content.ts
1821
2029
  function extractTextContent(content) {
1822
2030
  const parts = content.filter(
@@ -2046,29 +2254,6 @@ async function isStopConditionMet({
2046
2254
  return (await Promise.all(stopConditions.map((condition) => condition({ steps })))).some((result) => result);
2047
2255
  }
2048
2256
 
2049
- // src/prompt/create-tool-model-output.ts
2050
- import {
2051
- getErrorMessage as getErrorMessage4
2052
- } from "@ai-sdk/provider";
2053
- function createToolModelOutput({
2054
- output,
2055
- tool: tool3,
2056
- errorMode
2057
- }) {
2058
- if (errorMode === "text") {
2059
- return { type: "error-text", value: getErrorMessage4(output) };
2060
- } else if (errorMode === "json") {
2061
- return { type: "error-json", value: toJSONValue(output) };
2062
- }
2063
- if (tool3 == null ? void 0 : tool3.toModelOutput) {
2064
- return tool3.toModelOutput(output);
2065
- }
2066
- return typeof output === "string" ? { type: "text", value: output } : { type: "json", value: toJSONValue(output) };
2067
- }
2068
- function toJSONValue(value) {
2069
- return value === void 0 ? null : value;
2070
- }
2071
-
2072
2257
  // src/generate-text/to-response-messages.ts
2073
2258
  function toResponseMessages({
2074
2259
  content: inputContent,
@@ -2132,6 +2317,12 @@ function toResponseMessages({
2132
2317
  }),
2133
2318
  providerOptions: part.providerMetadata
2134
2319
  };
2320
+ case "tool-approval-request":
2321
+ return {
2322
+ type: "tool-approval-request",
2323
+ approvalId: part.approvalId,
2324
+ toolCallId: part.toolCall.toolCallId
2325
+ };
2135
2326
  }
2136
2327
  });
2137
2328
  if (content.length > 0) {
@@ -2186,7 +2377,7 @@ async function generateText({
2186
2377
  experimental_download: download2,
2187
2378
  experimental_context,
2188
2379
  _internal: {
2189
- generateId: generateId3 = originalGenerateId,
2380
+ generateId: generateId2 = originalGenerateId,
2190
2381
  currentDate = () => /* @__PURE__ */ new Date()
2191
2382
  } = {},
2192
2383
  onStepFinish,
@@ -2238,17 +2429,55 @@ async function generateText({
2238
2429
  tracer,
2239
2430
  fn: async (span) => {
2240
2431
  var _a17, _b, _c, _d, _e, _f, _g;
2432
+ const initialMessages = initialPrompt.messages;
2433
+ const responseMessages = [];
2434
+ const { approvedToolApprovals, deniedToolApprovals } = collectToolApprovals({ messages: initialMessages });
2435
+ if (deniedToolApprovals.length > 0 || approvedToolApprovals.length > 0) {
2436
+ const toolOutputs = await executeTools({
2437
+ toolCalls: approvedToolApprovals.map(
2438
+ (toolApproval) => toolApproval.toolCall
2439
+ ),
2440
+ tools,
2441
+ tracer,
2442
+ telemetry,
2443
+ messages: initialMessages,
2444
+ abortSignal,
2445
+ experimental_context
2446
+ });
2447
+ responseMessages.push({
2448
+ role: "tool",
2449
+ content: [
2450
+ // add regular tool results for approved tool calls:
2451
+ ...toolOutputs.map((output2) => ({
2452
+ type: "tool-result",
2453
+ toolCallId: output2.toolCallId,
2454
+ toolName: output2.toolName,
2455
+ output: createToolModelOutput({
2456
+ tool: tools == null ? void 0 : tools[output2.toolName],
2457
+ output: output2.type === "tool-result" ? output2.output : output2.error,
2458
+ errorMode: output2.type === "tool-error" ? "json" : "none"
2459
+ })
2460
+ })),
2461
+ // add execution denied tool results for denied tool approvals:
2462
+ ...deniedToolApprovals.map((toolApproval) => ({
2463
+ type: "tool-result",
2464
+ toolCallId: toolApproval.toolCall.toolCallId,
2465
+ toolName: toolApproval.toolCall.toolName,
2466
+ output: {
2467
+ type: "execution-denied",
2468
+ reason: toolApproval.approvalResponse.reason
2469
+ }
2470
+ }))
2471
+ ]
2472
+ });
2473
+ }
2241
2474
  const callSettings2 = prepareCallSettings(settings);
2242
2475
  let currentModelResponse;
2243
2476
  let clientToolCalls = [];
2244
2477
  let clientToolOutputs = [];
2245
- const responseMessages = [];
2246
2478
  const steps = [];
2247
2479
  do {
2248
- const stepInputMessages = [
2249
- ...initialPrompt.messages,
2250
- ...responseMessages
2251
- ];
2480
+ const stepInputMessages = [...initialMessages, ...responseMessages];
2252
2481
  const prepareStepResult = await (prepareStep == null ? void 0 : prepareStep({
2253
2482
  model,
2254
2483
  steps,
@@ -2324,7 +2553,7 @@ async function generateText({
2324
2553
  headers: headersWithUserAgent
2325
2554
  });
2326
2555
  const responseData = {
2327
- id: (_b2 = (_a19 = result.response) == null ? void 0 : _a19.id) != null ? _b2 : generateId3(),
2556
+ id: (_b2 = (_a19 = result.response) == null ? void 0 : _a19.id) != null ? _b2 : generateId2(),
2328
2557
  timestamp: (_d2 = (_c2 = result.response) == null ? void 0 : _c2.timestamp) != null ? _d2 : currentDate(),
2329
2558
  modelId: (_f2 = (_e2 = result.response) == null ? void 0 : _e2.modelId) != null ? _f2 : stepModel.modelId,
2330
2559
  headers: (_g2 = result.response) == null ? void 0 : _g2.headers,
@@ -2380,6 +2609,7 @@ async function generateText({
2380
2609
  })
2381
2610
  )
2382
2611
  );
2612
+ const toolApprovalRequests = {};
2383
2613
  for (const toolCall of stepToolCalls) {
2384
2614
  if (toolCall.invalid) {
2385
2615
  continue;
@@ -2394,6 +2624,13 @@ async function generateText({
2394
2624
  experimental_context
2395
2625
  });
2396
2626
  }
2627
+ if (tool3 == null ? void 0 : tool3.needsApproval) {
2628
+ toolApprovalRequests[toolCall.toolCallId] = {
2629
+ type: "tool-approval-request",
2630
+ approvalId: generateId2(),
2631
+ toolCall
2632
+ };
2633
+ }
2397
2634
  }
2398
2635
  const invalidToolCalls = stepToolCalls.filter(
2399
2636
  (toolCall) => toolCall.invalid && toolCall.dynamic
@@ -2416,7 +2653,7 @@ async function generateText({
2416
2653
  clientToolOutputs.push(
2417
2654
  ...await executeTools({
2418
2655
  toolCalls: clientToolCalls.filter(
2419
- (toolCall) => !toolCall.invalid
2656
+ (toolCall) => !toolCall.invalid && toolApprovalRequests[toolCall.toolCallId] == null
2420
2657
  ),
2421
2658
  tools,
2422
2659
  tracer,
@@ -2430,7 +2667,8 @@ async function generateText({
2430
2667
  const stepContent = asContent({
2431
2668
  content: currentModelResponse.content,
2432
2669
  toolCalls: stepToolCalls,
2433
- toolOutputs: clientToolOutputs
2670
+ toolOutputs: clientToolOutputs,
2671
+ toolApprovalRequests: Object.values(toolApprovalRequests)
2434
2672
  });
2435
2673
  responseMessages.push(
2436
2674
  ...toResponseMessages({
@@ -2511,81 +2749,17 @@ async function executeTools({
2511
2749
  experimental_context
2512
2750
  }) {
2513
2751
  const toolOutputs = await Promise.all(
2514
- toolCalls.map(async ({ toolCallId, toolName, input }) => {
2515
- const tool3 = tools[toolName];
2516
- if ((tool3 == null ? void 0 : tool3.execute) == null) {
2517
- return void 0;
2518
- }
2519
- return recordSpan({
2520
- name: "ai.toolCall",
2521
- attributes: selectTelemetryAttributes({
2522
- telemetry,
2523
- attributes: {
2524
- ...assembleOperationName({
2525
- operationId: "ai.toolCall",
2526
- telemetry
2527
- }),
2528
- "ai.toolCall.name": toolName,
2529
- "ai.toolCall.id": toolCallId,
2530
- "ai.toolCall.args": {
2531
- output: () => JSON.stringify(input)
2532
- }
2533
- }
2534
- }),
2752
+ toolCalls.map(
2753
+ async (toolCall) => executeToolCall({
2754
+ toolCall,
2755
+ tools,
2535
2756
  tracer,
2536
- fn: async (span) => {
2537
- try {
2538
- const stream = executeTool({
2539
- execute: tool3.execute.bind(tool3),
2540
- input,
2541
- options: {
2542
- toolCallId,
2543
- messages,
2544
- abortSignal,
2545
- experimental_context
2546
- }
2547
- });
2548
- let output;
2549
- for await (const part of stream) {
2550
- if (part.type === "final") {
2551
- output = part.output;
2552
- }
2553
- }
2554
- try {
2555
- span.setAttributes(
2556
- selectTelemetryAttributes({
2557
- telemetry,
2558
- attributes: {
2559
- "ai.toolCall.result": {
2560
- output: () => JSON.stringify(output)
2561
- }
2562
- }
2563
- })
2564
- );
2565
- } catch (ignored) {
2566
- }
2567
- return {
2568
- type: "tool-result",
2569
- toolCallId,
2570
- toolName,
2571
- input,
2572
- output,
2573
- dynamic: tool3.type === "dynamic"
2574
- };
2575
- } catch (error) {
2576
- recordErrorOnSpan(span, error);
2577
- return {
2578
- type: "tool-error",
2579
- toolCallId,
2580
- toolName,
2581
- input,
2582
- error,
2583
- dynamic: tool3.type === "dynamic"
2584
- };
2585
- }
2586
- }
2587
- });
2588
- })
2757
+ telemetry,
2758
+ messages,
2759
+ abortSignal,
2760
+ experimental_context
2761
+ })
2762
+ )
2589
2763
  );
2590
2764
  return toolOutputs.filter(
2591
2765
  (output) => output != null
@@ -2690,7 +2864,8 @@ function asToolCalls(content) {
2690
2864
  function asContent({
2691
2865
  content,
2692
2866
  toolCalls,
2693
- toolOutputs
2867
+ toolOutputs,
2868
+ toolApprovalRequests
2694
2869
  }) {
2695
2870
  return [
2696
2871
  ...content.map((part) => {
@@ -2740,7 +2915,8 @@ function asContent({
2740
2915
  }
2741
2916
  }
2742
2917
  }),
2743
- ...toolOutputs
2918
+ ...toolOutputs,
2919
+ ...toolApprovalRequests
2744
2920
  ];
2745
2921
  }
2746
2922
 
@@ -2946,6 +3122,11 @@ var uiMessageChunkSchema = z7.union([
2946
3122
  dynamic: z7.boolean().optional(),
2947
3123
  errorText: z7.string()
2948
3124
  }),
3125
+ z7.strictObject({
3126
+ type: z7.literal("tool-approval-request"),
3127
+ approvalId: z7.string(),
3128
+ toolCallId: z7.string()
3129
+ }),
2949
3130
  z7.strictObject({
2950
3131
  type: z7.literal("tool-output-available"),
2951
3132
  toolCallId: z7.string(),
@@ -2961,6 +3142,10 @@ var uiMessageChunkSchema = z7.union([
2961
3142
  providerExecuted: z7.boolean().optional(),
2962
3143
  dynamic: z7.boolean().optional()
2963
3144
  }),
3145
+ z7.strictObject({
3146
+ type: z7.literal("tool-output-denied"),
3147
+ toolCallId: z7.string()
3148
+ }),
2964
3149
  z7.strictObject({
2965
3150
  type: z7.literal("reasoning-start"),
2966
3151
  id: z7.string(),
@@ -3745,6 +3930,21 @@ function processUIMessageStream({
3745
3930
  write();
3746
3931
  break;
3747
3932
  }
3933
+ case "tool-approval-request": {
3934
+ const toolInvocation = getToolInvocation(chunk.toolCallId);
3935
+ toolInvocation.state = "approval-requested";
3936
+ toolInvocation.approval = {
3937
+ id: chunk.approvalId
3938
+ };
3939
+ write();
3940
+ break;
3941
+ }
3942
+ case "tool-output-denied": {
3943
+ const toolInvocation = getToolInvocation(chunk.toolCallId);
3944
+ toolInvocation.state = "output-denied";
3945
+ write();
3946
+ break;
3947
+ }
3748
3948
  case "tool-output-available": {
3749
3949
  if (chunk.dynamic) {
3750
3950
  const toolInvocation = getDynamicToolInvocation(
@@ -4096,10 +4296,10 @@ function createStitchableStream() {
4096
4296
  const { value, done } = await innerStreamReaders[0].read();
4097
4297
  if (done) {
4098
4298
  innerStreamReaders.shift();
4099
- if (innerStreamReaders.length > 0) {
4100
- await processPull();
4101
- } else if (isClosed) {
4299
+ if (innerStreamReaders.length === 0 && isClosed) {
4102
4300
  controller == null ? void 0 : controller.close();
4301
+ } else {
4302
+ await processPull();
4103
4303
  }
4104
4304
  } else {
4105
4305
  controller == null ? void 0 : controller.enqueue(value);
@@ -4196,8 +4396,6 @@ function now() {
4196
4396
 
4197
4397
  // src/generate-text/run-tools-transformation.ts
4198
4398
  import {
4199
- executeTool as executeTool2,
4200
- generateId,
4201
4399
  getErrorMessage as getErrorMessage6
4202
4400
  } from "@ai-sdk/provider-utils";
4203
4401
  function runToolsTransformation({
@@ -4209,7 +4407,8 @@ function runToolsTransformation({
4209
4407
  messages,
4210
4408
  abortSignal,
4211
4409
  repairToolCall,
4212
- experimental_context
4410
+ experimental_context,
4411
+ generateId: generateId2
4213
4412
  }) {
4214
4413
  let toolResultsStreamController = null;
4215
4414
  const toolResultsStream = new ReadableStream({
@@ -4291,7 +4490,6 @@ function runToolsTransformation({
4291
4490
  break;
4292
4491
  }
4293
4492
  const tool3 = tools[toolCall.toolName];
4294
- toolInputs.set(toolCall.toolCallId, toolCall.input);
4295
4493
  if (tool3.onInputAvailable != null) {
4296
4494
  await tool3.onInputAvailable({
4297
4495
  input: toolCall.input,
@@ -4301,79 +4499,33 @@ function runToolsTransformation({
4301
4499
  experimental_context
4302
4500
  });
4303
4501
  }
4502
+ if (tool3.needsApproval) {
4503
+ toolResultsStreamController.enqueue({
4504
+ type: "tool-approval-request",
4505
+ approvalId: generateId2(),
4506
+ toolCall
4507
+ });
4508
+ break;
4509
+ }
4510
+ toolInputs.set(toolCall.toolCallId, toolCall.input);
4304
4511
  if (tool3.execute != null && toolCall.providerExecuted !== true) {
4305
- const toolExecutionId = generateId();
4512
+ const toolExecutionId = generateId2();
4306
4513
  outstandingToolResults.add(toolExecutionId);
4307
- recordSpan({
4308
- name: "ai.toolCall",
4309
- attributes: selectTelemetryAttributes({
4310
- telemetry,
4311
- attributes: {
4312
- ...assembleOperationName({
4313
- operationId: "ai.toolCall",
4314
- telemetry
4315
- }),
4316
- "ai.toolCall.name": toolCall.toolName,
4317
- "ai.toolCall.id": toolCall.toolCallId,
4318
- "ai.toolCall.args": {
4319
- output: () => JSON.stringify(toolCall.input)
4320
- }
4321
- }
4322
- }),
4514
+ executeToolCall({
4515
+ toolCall,
4516
+ tools,
4323
4517
  tracer,
4324
- fn: async (span) => {
4325
- let output;
4326
- try {
4327
- const stream = executeTool2({
4328
- execute: tool3.execute.bind(tool3),
4329
- input: toolCall.input,
4330
- options: {
4331
- toolCallId: toolCall.toolCallId,
4332
- messages,
4333
- abortSignal,
4334
- experimental_context
4335
- }
4336
- });
4337
- for await (const part of stream) {
4338
- toolResultsStreamController.enqueue({
4339
- ...toolCall,
4340
- type: "tool-result",
4341
- output: part.output,
4342
- ...part.type === "preliminary" && {
4343
- preliminary: true
4344
- }
4345
- });
4346
- if (part.type === "final") {
4347
- output = part.output;
4348
- }
4349
- }
4350
- } catch (error) {
4351
- recordErrorOnSpan(span, error);
4352
- toolResultsStreamController.enqueue({
4353
- ...toolCall,
4354
- type: "tool-error",
4355
- error
4356
- });
4357
- outstandingToolResults.delete(toolExecutionId);
4358
- attemptClose();
4359
- return;
4360
- }
4361
- outstandingToolResults.delete(toolExecutionId);
4362
- attemptClose();
4363
- try {
4364
- span.setAttributes(
4365
- selectTelemetryAttributes({
4366
- telemetry,
4367
- attributes: {
4368
- "ai.toolCall.result": {
4369
- output: () => JSON.stringify(output)
4370
- }
4371
- }
4372
- })
4373
- );
4374
- } catch (ignored) {
4375
- }
4518
+ telemetry,
4519
+ messages,
4520
+ abortSignal,
4521
+ experimental_context,
4522
+ onPreliminaryToolResult: (result) => {
4523
+ toolResultsStreamController.enqueue(result);
4376
4524
  }
4525
+ }).then((result) => {
4526
+ toolResultsStreamController.enqueue(result);
4527
+ outstandingToolResults.delete(toolExecutionId);
4528
+ attemptClose();
4377
4529
  });
4378
4530
  }
4379
4531
  } catch (error) {
@@ -4478,7 +4630,7 @@ function streamText({
4478
4630
  experimental_context,
4479
4631
  _internal: {
4480
4632
  now: now2 = now,
4481
- generateId: generateId3 = originalGenerateId2,
4633
+ generateId: generateId2 = originalGenerateId2,
4482
4634
  currentDate = () => /* @__PURE__ */ new Date()
4483
4635
  } = {},
4484
4636
  ...settings
@@ -4510,7 +4662,7 @@ function streamText({
4510
4662
  onStepFinish,
4511
4663
  now: now2,
4512
4664
  currentDate,
4513
- generateId: generateId3,
4665
+ generateId: generateId2,
4514
4666
  experimental_context,
4515
4667
  download: download2
4516
4668
  });
@@ -4603,7 +4755,7 @@ var DefaultStreamTextResult = class {
4603
4755
  includeRawChunks,
4604
4756
  now: now2,
4605
4757
  currentDate,
4606
- generateId: generateId3,
4758
+ generateId: generateId2,
4607
4759
  onChunk,
4608
4760
  onError,
4609
4761
  onFinish,
@@ -4728,10 +4880,16 @@ var DefaultStreamTextResult = class {
4728
4880
  if (part.type === "tool-result" && !part.preliminary) {
4729
4881
  recordedContent.push(part);
4730
4882
  }
4883
+ if (part.type === "tool-approval-request") {
4884
+ recordedContent.push(part);
4885
+ }
4731
4886
  if (part.type === "tool-error") {
4732
4887
  recordedContent.push(part);
4733
4888
  }
4734
4889
  if (part.type === "start-step") {
4890
+ recordedContent = [];
4891
+ activeReasoningContent = {};
4892
+ activeTextContent = {};
4735
4893
  recordedRequest = part.request;
4736
4894
  recordedWarnings = part.warnings;
4737
4895
  }
@@ -4755,9 +4913,6 @@ var DefaultStreamTextResult = class {
4755
4913
  await (onStepFinish == null ? void 0 : onStepFinish(currentStepResult));
4756
4914
  logWarnings(recordedWarnings);
4757
4915
  recordedSteps.push(currentStepResult);
4758
- recordedContent = [];
4759
- activeReasoningContent = {};
4760
- activeTextContent = {};
4761
4916
  recordedResponseMessages.push(...stepMessages);
4762
4917
  stepFinish.resolve();
4763
4918
  }
@@ -4917,6 +5072,82 @@ var DefaultStreamTextResult = class {
4917
5072
  endWhenDone: false,
4918
5073
  fn: async (rootSpanArg) => {
4919
5074
  rootSpan = rootSpanArg;
5075
+ const initialPrompt = await standardizePrompt({
5076
+ system,
5077
+ prompt,
5078
+ messages
5079
+ });
5080
+ const initialMessages = initialPrompt.messages;
5081
+ const initialResponseMessages = [];
5082
+ const { approvedToolApprovals, deniedToolApprovals } = collectToolApprovals({ messages: initialMessages });
5083
+ if (deniedToolApprovals.length > 0 || approvedToolApprovals.length > 0) {
5084
+ let toolExecutionStepStreamController;
5085
+ const toolExecutionStepStream = new ReadableStream({
5086
+ start(controller) {
5087
+ toolExecutionStepStreamController = controller;
5088
+ }
5089
+ });
5090
+ self.addStream(toolExecutionStepStream);
5091
+ try {
5092
+ for (const toolApproval of deniedToolApprovals) {
5093
+ toolExecutionStepStreamController == null ? void 0 : toolExecutionStepStreamController.enqueue({
5094
+ type: "tool-output-denied",
5095
+ toolCallId: toolApproval.toolCall.toolCallId,
5096
+ toolName: toolApproval.toolCall.toolName
5097
+ });
5098
+ }
5099
+ const toolOutputs = [];
5100
+ await Promise.all(
5101
+ approvedToolApprovals.map(async (toolApproval) => {
5102
+ const result = await executeToolCall({
5103
+ toolCall: toolApproval.toolCall,
5104
+ tools,
5105
+ tracer,
5106
+ telemetry,
5107
+ messages: initialMessages,
5108
+ abortSignal,
5109
+ experimental_context,
5110
+ onPreliminaryToolResult: (result2) => {
5111
+ toolExecutionStepStreamController == null ? void 0 : toolExecutionStepStreamController.enqueue(result2);
5112
+ }
5113
+ });
5114
+ if (result != null) {
5115
+ toolExecutionStepStreamController == null ? void 0 : toolExecutionStepStreamController.enqueue(result);
5116
+ toolOutputs.push(result);
5117
+ }
5118
+ })
5119
+ );
5120
+ initialResponseMessages.push({
5121
+ role: "tool",
5122
+ content: [
5123
+ // add regular tool results for approved tool calls:
5124
+ ...toolOutputs.map((output2) => ({
5125
+ type: "tool-result",
5126
+ toolCallId: output2.toolCallId,
5127
+ toolName: output2.toolName,
5128
+ output: createToolModelOutput({
5129
+ tool: tools == null ? void 0 : tools[output2.toolName],
5130
+ output: output2.type === "tool-result" ? output2.output : output2.error,
5131
+ errorMode: output2.type === "tool-error" ? "json" : "none"
5132
+ })
5133
+ })),
5134
+ // add execution denied tool results for denied tool approvals:
5135
+ ...deniedToolApprovals.map((toolApproval) => ({
5136
+ type: "tool-result",
5137
+ toolCallId: toolApproval.toolCall.toolCallId,
5138
+ toolName: toolApproval.toolCall.toolName,
5139
+ output: {
5140
+ type: "execution-denied",
5141
+ reason: toolApproval.approvalResponse.reason
5142
+ }
5143
+ }))
5144
+ ]
5145
+ });
5146
+ } finally {
5147
+ toolExecutionStepStreamController == null ? void 0 : toolExecutionStepStreamController.close();
5148
+ }
5149
+ }
5150
+ recordedResponseMessages.push(...initialResponseMessages);
4920
5151
  async function streamStep({
4921
5152
  currentStep,
4922
5153
  responseMessages,
@@ -4925,15 +5156,7 @@ var DefaultStreamTextResult = class {
4925
5156
  var _a17, _b, _c, _d, _e;
4926
5157
  const includeRawChunks2 = self.includeRawChunks;
4927
5158
  stepFinish = new DelayedPromise();
4928
- const initialPrompt = await standardizePrompt({
4929
- system,
4930
- prompt,
4931
- messages
4932
- });
4933
- const stepInputMessages = [
4934
- ...initialPrompt.messages,
4935
- ...responseMessages
4936
- ];
5159
+ const stepInputMessages = [...initialMessages, ...responseMessages];
4937
5160
  const prepareStepResult = await (prepareStep == null ? void 0 : prepareStep({
4938
5161
  model,
4939
5162
  steps: recordedSteps,
@@ -4999,24 +5222,22 @@ var DefaultStreamTextResult = class {
4999
5222
  }),
5000
5223
  tracer,
5001
5224
  endWhenDone: false,
5002
- fn: async (doStreamSpan2) => {
5003
- return {
5004
- startTimestampMs: now2(),
5005
- // get before the call
5006
- doStreamSpan: doStreamSpan2,
5007
- result: await stepModel.doStream({
5008
- ...callSettings,
5009
- tools: stepTools,
5010
- toolChoice: stepToolChoice,
5011
- responseFormat: output == null ? void 0 : output.responseFormat,
5012
- prompt: promptMessages,
5013
- providerOptions,
5014
- abortSignal,
5015
- headers,
5016
- includeRawChunks: includeRawChunks2
5017
- })
5018
- };
5019
- }
5225
+ fn: async (doStreamSpan2) => ({
5226
+ startTimestampMs: now2(),
5227
+ // get before the call
5228
+ doStreamSpan: doStreamSpan2,
5229
+ result: await stepModel.doStream({
5230
+ ...callSettings,
5231
+ tools: stepTools,
5232
+ toolChoice: stepToolChoice,
5233
+ responseFormat: output == null ? void 0 : output.responseFormat,
5234
+ prompt: promptMessages,
5235
+ providerOptions,
5236
+ abortSignal,
5237
+ headers,
5238
+ includeRawChunks: includeRawChunks2
5239
+ })
5240
+ })
5020
5241
  })
5021
5242
  );
5022
5243
  const streamWithToolResults = runToolsTransformation({
@@ -5028,7 +5249,8 @@ var DefaultStreamTextResult = class {
5028
5249
  messages: stepInputMessages,
5029
5250
  repairToolCall,
5030
5251
  abortSignal,
5031
- experimental_context
5252
+ experimental_context,
5253
+ generateId: generateId2
5032
5254
  });
5033
5255
  const stepRequest = request != null ? request : {};
5034
5256
  const stepToolCalls = [];
@@ -5044,7 +5266,7 @@ var DefaultStreamTextResult = class {
5044
5266
  let stepProviderMetadata;
5045
5267
  let stepFirstChunk = true;
5046
5268
  let stepResponse = {
5047
- id: generateId3(),
5269
+ id: generateId2(),
5048
5270
  timestamp: currentDate(),
5049
5271
  modelId: model.modelId
5050
5272
  };
@@ -5075,6 +5297,7 @@ var DefaultStreamTextResult = class {
5075
5297
  }
5076
5298
  const chunkType = chunk.type;
5077
5299
  switch (chunkType) {
5300
+ case "tool-approval-request":
5078
5301
  case "text-start":
5079
5302
  case "text-end": {
5080
5303
  controller.enqueue(chunk);
@@ -5303,7 +5526,7 @@ var DefaultStreamTextResult = class {
5303
5526
  }
5304
5527
  await streamStep({
5305
5528
  currentStep: 0,
5306
- responseMessages: [],
5529
+ responseMessages: initialResponseMessages,
5307
5530
  usage: {
5308
5531
  inputTokens: void 0,
5309
5532
  outputTokens: void 0,
@@ -5610,6 +5833,14 @@ var DefaultStreamTextResult = class {
5610
5833
  }
5611
5834
  break;
5612
5835
  }
5836
+ case "tool-approval-request": {
5837
+ controller.enqueue({
5838
+ type: "tool-approval-request",
5839
+ approvalId: part.approvalId,
5840
+ toolCallId: part.toolCall.toolCallId
5841
+ });
5842
+ break;
5843
+ }
5613
5844
  case "tool-result": {
5614
5845
  const dynamic = isDynamic(part.toolCallId);
5615
5846
  controller.enqueue({
@@ -5633,6 +5864,13 @@ var DefaultStreamTextResult = class {
5633
5864
  });
5634
5865
  break;
5635
5866
  }
5867
+ case "tool-output-denied": {
5868
+ controller.enqueue({
5869
+ type: "tool-output-denied",
5870
+ toolCallId: part.toolCallId
5871
+ });
5872
+ break;
5873
+ }
5636
5874
  case "error": {
5637
5875
  controller.enqueue({
5638
5876
  type: "error",
@@ -5877,6 +6115,13 @@ function convertToModelMessages(messages, options) {
5877
6115
  providerExecuted: part.providerExecuted,
5878
6116
  ...part.callProviderMetadata != null ? { providerOptions: part.callProviderMetadata } : {}
5879
6117
  });
6118
+ if (part.approval != null) {
6119
+ content.push({
6120
+ type: "tool-approval-request",
6121
+ approvalId: part.approval.id,
6122
+ toolCallId: part.toolCallId
6123
+ });
6124
+ }
5880
6125
  if (part.providerExecuted === true && (part.state === "output-available" || part.state === "output-error")) {
5881
6126
  content.push({
5882
6127
  type: "tool-result",
@@ -5905,29 +6150,49 @@ function convertToModelMessages(messages, options) {
5905
6150
  if (toolParts.length > 0) {
5906
6151
  modelMessages.push({
5907
6152
  role: "tool",
5908
- content: toolParts.map((toolPart) => {
5909
- var _a18;
5910
- switch (toolPart.state) {
5911
- case "output-error":
5912
- case "output-available": {
5913
- const toolName = toolPart.type === "dynamic-tool" ? toolPart.toolName : getToolName(toolPart);
5914
- return {
5915
- type: "tool-result",
5916
- toolCallId: toolPart.toolCallId,
5917
- toolName,
5918
- output: createToolModelOutput({
5919
- output: toolPart.state === "output-error" ? toolPart.errorText : toolPart.output,
5920
- tool: (_a18 = options == null ? void 0 : options.tools) == null ? void 0 : _a18[toolName],
5921
- errorMode: toolPart.state === "output-error" ? "text" : "none"
5922
- })
5923
- };
6153
+ content: toolParts.flatMap(
6154
+ (toolPart) => {
6155
+ var _a18, _b2, _c;
6156
+ const outputs = [];
6157
+ if (toolPart.type !== "dynamic-tool" && ((_a18 = toolPart.approval) == null ? void 0 : _a18.approved) != null) {
6158
+ outputs.push({
6159
+ type: "tool-approval-response",
6160
+ approvalId: toolPart.approval.id,
6161
+ approved: toolPart.approval.approved,
6162
+ reason: toolPart.approval.reason
6163
+ });
5924
6164
  }
5925
- default: {
5926
- return null;
6165
+ switch (toolPart.state) {
6166
+ case "output-denied": {
6167
+ outputs.push({
6168
+ type: "tool-result",
6169
+ toolCallId: toolPart.toolCallId,
6170
+ toolName: getToolName(toolPart),
6171
+ output: {
6172
+ type: "error-text",
6173
+ value: (_b2 = toolPart.approval.reason) != null ? _b2 : "Tool execution denied."
6174
+ }
6175
+ });
6176
+ break;
6177
+ }
6178
+ case "output-error":
6179
+ case "output-available": {
6180
+ const toolName = toolPart.type === "dynamic-tool" ? toolPart.toolName : getToolName(toolPart);
6181
+ outputs.push({
6182
+ type: "tool-result",
6183
+ toolCallId: toolPart.toolCallId,
6184
+ toolName,
6185
+ output: createToolModelOutput({
6186
+ output: toolPart.state === "output-error" ? toolPart.errorText : toolPart.output,
6187
+ tool: (_c = options == null ? void 0 : options.tools) == null ? void 0 : _c[toolName],
6188
+ errorMode: toolPart.state === "output-error" ? "text" : "none"
6189
+ })
6190
+ });
6191
+ break;
6192
+ }
5927
6193
  }
6194
+ return outputs;
5928
6195
  }
5929
- }).filter(
5930
- (output) => output != null
5931
6196
  )
5932
6197
  });
5933
6198
  }
@@ -6961,7 +7226,7 @@ async function generateObject(options) {
6961
7226
  experimental_download: download2,
6962
7227
  providerOptions,
6963
7228
  _internal: {
6964
- generateId: generateId3 = originalGenerateId3,
7229
+ generateId: generateId2 = originalGenerateId3,
6965
7230
  currentDate = () => /* @__PURE__ */ new Date()
6966
7231
  } = {},
6967
7232
  ...settings
@@ -7085,7 +7350,7 @@ async function generateObject(options) {
7085
7350
  headers: headersWithUserAgent
7086
7351
  });
7087
7352
  const responseData = {
7088
- id: (_b = (_a18 = result2.response) == null ? void 0 : _a18.id) != null ? _b : generateId3(),
7353
+ id: (_b = (_a18 = result2.response) == null ? void 0 : _a18.id) != null ? _b : generateId2(),
7089
7354
  timestamp: (_d = (_c = result2.response) == null ? void 0 : _c.timestamp) != null ? _d : currentDate(),
7090
7355
  modelId: (_f = (_e = result2.response) == null ? void 0 : _e.modelId) != null ? _f : model.modelId,
7091
7356
  headers: (_g = result2.response) == null ? void 0 : _g.headers,
@@ -7364,7 +7629,7 @@ function streamObject(options) {
7364
7629
  },
7365
7630
  onFinish,
7366
7631
  _internal: {
7367
- generateId: generateId3 = originalGenerateId4,
7632
+ generateId: generateId2 = originalGenerateId4,
7368
7633
  currentDate = () => /* @__PURE__ */ new Date(),
7369
7634
  now: now2 = now
7370
7635
  } = {},
@@ -7406,7 +7671,7 @@ function streamObject(options) {
7406
7671
  onError,
7407
7672
  onFinish,
7408
7673
  download: download2,
7409
- generateId: generateId3,
7674
+ generateId: generateId2,
7410
7675
  currentDate,
7411
7676
  now: now2
7412
7677
  });
@@ -7430,7 +7695,7 @@ var DefaultStreamObjectResult = class {
7430
7695
  onError,
7431
7696
  onFinish,
7432
7697
  download: download2,
7433
- generateId: generateId3,
7698
+ generateId: generateId2,
7434
7699
  currentDate,
7435
7700
  now: now2
7436
7701
  }) {
@@ -7578,7 +7843,7 @@ var DefaultStreamObjectResult = class {
7578
7843
  let accumulatedText = "";
7579
7844
  let textDelta = "";
7580
7845
  let fullResponse = {
7581
- id: generateId3(),
7846
+ id: generateId2(),
7582
7847
  timestamp: currentDate(),
7583
7848
  modelId: model.modelId
7584
7849
  };
@@ -7907,7 +8172,7 @@ async function generateSpeech({
7907
8172
  headers
7908
8173
  }) {
7909
8174
  var _a17;
7910
- if (model.specificationVersion !== "v2") {
8175
+ if (model.specificationVersion !== "v3") {
7911
8176
  throw new UnsupportedModelVersionError({
7912
8177
  version: model.specificationVersion,
7913
8178
  provider: model.provider,
@@ -9261,7 +9526,7 @@ async function transcribe({
9261
9526
  abortSignal,
9262
9527
  headers
9263
9528
  }) {
9264
- if (model.specificationVersion !== "v2") {
9529
+ if (model.specificationVersion !== "v3") {
9265
9530
  throw new UnsupportedModelVersionError({
9266
9531
  version: model.specificationVersion,
9267
9532
  provider: model.provider,
@@ -9640,8 +9905,8 @@ var DefaultChatTransport = class extends HttpChatTransport {
9640
9905
  // src/ui/chat.ts
9641
9906
  var AbstractChat = class {
9642
9907
  constructor({
9643
- generateId: generateId3 = generateIdFunc,
9644
- id = generateId3(),
9908
+ generateId: generateId2 = generateIdFunc,
9909
+ id = generateId2(),
9645
9910
  transport = new DefaultChatTransport(),
9646
9911
  messageMetadataSchema,
9647
9912
  dataPartSchemas,
@@ -9753,6 +10018,33 @@ var AbstractChat = class {
9753
10018
  this.setStatus({ status: "ready" });
9754
10019
  }
9755
10020
  };
10021
+ this.addToolApprovalResponse = async ({
10022
+ id,
10023
+ approved,
10024
+ reason
10025
+ }) => this.jobExecutor.run(async () => {
10026
+ var _a17, _b;
10027
+ const messages = this.state.messages;
10028
+ const lastMessage = messages[messages.length - 1];
10029
+ const updatePart = (part) => isToolUIPart(part) && part.state === "approval-requested" && part.approval.id === id ? {
10030
+ ...part,
10031
+ state: "approval-responded",
10032
+ approval: { id, approved, reason }
10033
+ } : part;
10034
+ this.state.replaceMessage(messages.length - 1, {
10035
+ ...lastMessage,
10036
+ parts: lastMessage.parts.map(updatePart)
10037
+ });
10038
+ if (this.activeResponse) {
10039
+ this.activeResponse.state.message.parts = this.activeResponse.state.message.parts.map(updatePart);
10040
+ }
10041
+ if (this.status !== "streaming" && this.status !== "submitted" && ((_a17 = this.sendAutomaticallyWhen) == null ? void 0 : _a17.call(this, { messages: this.state.messages }))) {
10042
+ this.makeRequest({
10043
+ trigger: "submit-message",
10044
+ messageId: (_b = this.lastMessage) == null ? void 0 : _b.id
10045
+ });
10046
+ }
10047
+ });
9756
10048
  this.addToolResult = async ({
9757
10049
  state = "output-available",
9758
10050
  tool: tool3,
@@ -9763,21 +10055,13 @@ var AbstractChat = class {
9763
10055
  var _a17, _b;
9764
10056
  const messages = this.state.messages;
9765
10057
  const lastMessage = messages[messages.length - 1];
10058
+ const updatePart = (part) => isToolOrDynamicToolUIPart(part) && part.toolCallId === toolCallId ? { ...part, state, output, errorText } : part;
9766
10059
  this.state.replaceMessage(messages.length - 1, {
9767
10060
  ...lastMessage,
9768
- parts: lastMessage.parts.map(
9769
- (part) => isToolOrDynamicToolUIPart(part) && part.toolCallId === toolCallId ? { ...part, state, output, errorText } : part
9770
- )
10061
+ parts: lastMessage.parts.map(updatePart)
9771
10062
  });
9772
10063
  if (this.activeResponse) {
9773
- this.activeResponse.state.message.parts = this.activeResponse.state.message.parts.map(
9774
- (part) => isToolOrDynamicToolUIPart(part) && part.toolCallId === toolCallId ? {
9775
- ...part,
9776
- state,
9777
- output,
9778
- errorText
9779
- } : part
9780
- );
10064
+ this.activeResponse.state.message.parts = this.activeResponse.state.message.parts.map(updatePart);
9781
10065
  }
9782
10066
  if (this.status !== "streaming" && this.status !== "submitted" && ((_a17 = this.sendAutomaticallyWhen) == null ? void 0 : _a17.call(this, { messages: this.state.messages }))) {
9783
10067
  this.makeRequest({
@@ -9799,7 +10083,7 @@ var AbstractChat = class {
9799
10083
  };
9800
10084
  this.id = id;
9801
10085
  this.transport = transport;
9802
- this.generateId = generateId3;
10086
+ this.generateId = generateId2;
9803
10087
  this.messageMetadataSchema = messageMetadataSchema;
9804
10088
  this.dataPartSchemas = dataPartSchemas;
9805
10089
  this.state = state;
@@ -9969,6 +10253,30 @@ var AbstractChat = class {
9969
10253
  }
9970
10254
  };
9971
10255
 
10256
+ // src/ui/last-assistant-message-is-complete-with-approval-responses.ts
10257
+ function lastAssistantMessageIsCompleteWithApprovalResponses({
10258
+ messages
10259
+ }) {
10260
+ const message = messages[messages.length - 1];
10261
+ if (!message) {
10262
+ return false;
10263
+ }
10264
+ if (message.role !== "assistant") {
10265
+ return false;
10266
+ }
10267
+ const lastStepStartIndex = message.parts.reduce((lastIndex, part, index) => {
10268
+ return part.type === "step-start" ? index : lastIndex;
10269
+ }, -1);
10270
+ const lastStepToolInvocations = message.parts.slice(lastStepStartIndex + 1).filter(isToolOrDynamicToolUIPart);
10271
+ return (
10272
+ // has at least one tool approval response
10273
+ lastStepToolInvocations.filter((part) => part.state === "approval-responded").length > 0 && // all tool approvals must have a response
10274
+ lastStepToolInvocations.every(
10275
+ (part) => part.state === "output-available" || part.state === "output-error" || part.state === "approval-responded"
10276
+ )
10277
+ );
10278
+ }
10279
+
9972
10280
  // src/ui/last-assistant-message-is-complete-with-tool-calls.ts
9973
10281
  function lastAssistantMessageIsCompleteWithToolCalls({
9974
10282
  messages
@@ -10122,7 +10430,8 @@ var toolUIPartSchemas = [
10122
10430
  providerExecuted: z10.boolean().optional(),
10123
10431
  input: z10.unknown().optional(),
10124
10432
  output: z10.never().optional(),
10125
- errorText: z10.never().optional()
10433
+ errorText: z10.never().optional(),
10434
+ approval: z10.never().optional()
10126
10435
  }),
10127
10436
  z10.object({
10128
10437
  type: z10.string().startsWith("tool-"),
@@ -10132,7 +10441,38 @@ var toolUIPartSchemas = [
10132
10441
  input: z10.unknown(),
10133
10442
  output: z10.never().optional(),
10134
10443
  errorText: z10.never().optional(),
10135
- callProviderMetadata: providerMetadataSchema.optional()
10444
+ callProviderMetadata: providerMetadataSchema.optional(),
10445
+ approval: z10.never().optional()
10446
+ }),
10447
+ z10.object({
10448
+ type: z10.string().startsWith("tool-"),
10449
+ toolCallId: z10.string(),
10450
+ state: z10.literal("approval-requested"),
10451
+ input: z10.unknown(),
10452
+ providerExecuted: z10.boolean().optional(),
10453
+ output: z10.never().optional(),
10454
+ errorText: z10.never().optional(),
10455
+ callProviderMetadata: providerMetadataSchema.optional(),
10456
+ approval: z10.object({
10457
+ id: z10.string(),
10458
+ approved: z10.never().optional(),
10459
+ reason: z10.never().optional()
10460
+ })
10461
+ }),
10462
+ z10.object({
10463
+ type: z10.string().startsWith("tool-"),
10464
+ toolCallId: z10.string(),
10465
+ state: z10.literal("approval-responded"),
10466
+ input: z10.unknown(),
10467
+ providerExecuted: z10.boolean().optional(),
10468
+ output: z10.never().optional(),
10469
+ errorText: z10.never().optional(),
10470
+ callProviderMetadata: providerMetadataSchema.optional(),
10471
+ approval: z10.object({
10472
+ id: z10.string(),
10473
+ approved: z10.boolean(),
10474
+ reason: z10.string().optional()
10475
+ })
10136
10476
  }),
10137
10477
  z10.object({
10138
10478
  type: z10.string().startsWith("tool-"),
@@ -10143,7 +10483,12 @@ var toolUIPartSchemas = [
10143
10483
  output: z10.unknown(),
10144
10484
  errorText: z10.never().optional(),
10145
10485
  callProviderMetadata: providerMetadataSchema.optional(),
10146
- preliminary: z10.boolean().optional()
10486
+ preliminary: z10.boolean().optional(),
10487
+ approval: z10.object({
10488
+ id: z10.string(),
10489
+ approved: z10.literal(true),
10490
+ reason: z10.string().optional()
10491
+ }).optional()
10147
10492
  }),
10148
10493
  z10.object({
10149
10494
  type: z10.string().startsWith("tool-"),
@@ -10153,7 +10498,27 @@ var toolUIPartSchemas = [
10153
10498
  input: z10.unknown(),
10154
10499
  output: z10.never().optional(),
10155
10500
  errorText: z10.string(),
10156
- callProviderMetadata: providerMetadataSchema.optional()
10501
+ callProviderMetadata: providerMetadataSchema.optional(),
10502
+ approval: z10.object({
10503
+ id: z10.string(),
10504
+ approved: z10.literal(true),
10505
+ reason: z10.string().optional()
10506
+ }).optional()
10507
+ }),
10508
+ z10.object({
10509
+ type: z10.string().startsWith("tool-"),
10510
+ toolCallId: z10.string(),
10511
+ state: z10.literal("output-denied"),
10512
+ providerExecuted: z10.boolean().optional(),
10513
+ input: z10.unknown(),
10514
+ output: z10.never().optional(),
10515
+ errorText: z10.never().optional(),
10516
+ callProviderMetadata: providerMetadataSchema.optional(),
10517
+ approval: z10.object({
10518
+ id: z10.string(),
10519
+ approved: z10.literal(false),
10520
+ reason: z10.string().optional()
10521
+ })
10157
10522
  })
10158
10523
  ];
10159
10524
  var uiMessageSchema = z10.object({
@@ -10298,7 +10663,7 @@ function createUIMessageStream({
10298
10663
  onError = getErrorMessage8,
10299
10664
  originalMessages,
10300
10665
  onFinish,
10301
- generateId: generateId3 = generateIdFunc2
10666
+ generateId: generateId2 = generateIdFunc2
10302
10667
  }) {
10303
10668
  let controller;
10304
10669
  const ongoingStreamPromises = [];
@@ -10370,7 +10735,7 @@ function createUIMessageStream({
10370
10735
  });
10371
10736
  return handleUIMessageStreamFinish({
10372
10737
  stream,
10373
- messageId: generateId3(),
10738
+ messageId: generateId2(),
10374
10739
  originalMessages,
10375
10740
  onFinish,
10376
10741
  onError
@@ -10497,7 +10862,7 @@ export {
10497
10862
  transcribe as experimental_transcribe,
10498
10863
  extractReasoningMiddleware,
10499
10864
  gateway2 as gateway,
10500
- generateId2 as generateId,
10865
+ generateId,
10501
10866
  generateObject,
10502
10867
  generateText,
10503
10868
  getTextFromDataUrl,
@@ -10508,6 +10873,7 @@ export {
10508
10873
  isToolOrDynamicToolUIPart,
10509
10874
  isToolUIPart,
10510
10875
  jsonSchema2 as jsonSchema,
10876
+ lastAssistantMessageIsCompleteWithApprovalResponses,
10511
10877
  lastAssistantMessageIsCompleteWithToolCalls,
10512
10878
  modelMessageSchema,
10513
10879
  parseJsonEventStream3 as parseJsonEventStream,