@ai-sdk/workflow 2.0.15 → 2.0.16

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/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @ai-sdk/workflow
2
2
 
3
+ ## 2.0.16
4
+
5
+ ### Patch Changes
6
+
7
+ - 11109ae: feat(ai): support signed tool approvals in WorkflowAgent
8
+ - Updated dependencies [11109ae]
9
+ - ai@7.0.86
10
+
3
11
  ## 2.0.15
4
12
 
5
13
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -4,6 +4,11 @@ import { ToolSet, Experimental_LanguageModelStreamPart, LanguageModel, Instructi
4
4
  export { Output, ToolCallRepairFunction } from 'ai';
5
5
 
6
6
  type ModelCallStreamPart<TTools extends ToolSet = ToolSet> = Experimental_LanguageModelStreamPart<TTools> | {
7
+ type: 'tool-approval-request';
8
+ approvalId: string;
9
+ toolCallId: string;
10
+ signature?: string;
11
+ } | {
7
12
  type: 'reset-step';
8
13
  };
9
14
 
@@ -64,6 +69,16 @@ interface OutputSpecification<OUTPUT, PARTIAL> {
64
69
  * Provider-specific options type. This is equivalent to SharedV4ProviderOptions from @ai-sdk/provider.
65
70
  */
66
71
  type ProviderOptions = SharedV4ProviderOptions;
72
+ /**
73
+ * Workflow-safe reference to the environment variable that contains the
74
+ * secret used to sign and verify tool approvals.
75
+ */
76
+ type WorkflowToolApprovalSecret = {
77
+ /**
78
+ * Name of an environment variable containing a high-entropy secret.
79
+ */
80
+ environmentVariable: string;
81
+ };
67
82
  type WorkflowAgentToolsContextParameter<TTools extends ToolSet> = HasRequiredKey<InferToolSetContext<TTools>> extends true ? {
68
83
  toolsContext: InferToolSetContext<TTools>;
69
84
  } : {
@@ -396,6 +411,17 @@ type WorkflowAgentOptions<TTools extends ToolSet = ToolSet, TRuntimeContext exte
396
411
  * Per-stream `experimental_sandbox` values passed to `stream()` override this default.
397
412
  */
398
413
  experimental_sandbox?: Experimental_SandboxSession;
414
+ /**
415
+ * Workflow-safe reference to the environment variable containing the
416
+ * secret for HMAC-signing tool approval requests. When set, the agent signs
417
+ * each approval request and verifies the signature before executing an
418
+ * approved tool replayed from client-supplied message history.
419
+ *
420
+ * Only the environment variable name crosses workflow boundaries. The
421
+ * secret value is read inside signing and verification steps and is never
422
+ * serialized. Per-stream values override this default.
423
+ */
424
+ experimental_toolApprovalSecret?: WorkflowToolApprovalSecret;
399
425
  /**
400
426
  * Default callback function called before each step in the agent loop.
401
427
  * Use this to modify settings, manage context, or inject messages dynamically
@@ -762,6 +788,17 @@ type WorkflowAgentStreamOptions<TTools extends ToolSet = ToolSet, TRuntimeContex
762
788
  * `experimental_sandbox`. Overrides the constructor-level value if provided.
763
789
  */
764
790
  experimental_sandbox?: Experimental_SandboxSession;
791
+ /**
792
+ * Workflow-safe reference to the environment variable containing the
793
+ * secret for HMAC-signing tool approval requests. When set, the agent signs
794
+ * each approval request and verifies the signature before executing an
795
+ * approved tool replayed from client-supplied message history.
796
+ *
797
+ * Only the environment variable name crosses workflow boundaries. The
798
+ * secret value is read inside signing and verification steps and is never
799
+ * serialized. Overrides the constructor-level value if provided.
800
+ */
801
+ experimental_toolApprovalSecret?: WorkflowToolApprovalSecret;
765
802
  /**
766
803
  * Callback function to be called after each step completes.
767
804
  */
@@ -981,6 +1018,7 @@ declare class WorkflowAgent<TBaseTools extends ToolSet = ToolSet, TRuntimeContex
981
1018
  private repairToolCall?;
982
1019
  private experimentalDownload?;
983
1020
  private experimentalSandbox?;
1021
+ private experimentalToolApprovalSecret?;
984
1022
  private prepareStep?;
985
1023
  private allowSystemInMessages;
986
1024
  private constructorOnStepEnd?;
@@ -1227,4 +1265,4 @@ declare class WorkflowChatTransport<UI_MESSAGE extends UIMessage> implements Cha
1227
1265
  */
1228
1266
  declare function normalizeUIMessageStreamParts(source: AsyncIterable<UIMessageChunk>): AsyncGenerator<UIMessageChunk>;
1229
1267
 
1230
- export { type CompatibleLanguageModel, type DownloadFunction, type GenerationSettings, type InferWorkflowAgentTools, type InferWorkflowAgentUIMessage, type ModelCallStreamPart, type OutputSpecification, type PrepareCallCallback, type PrepareCallOptions, type PrepareCallResult, type PrepareStepCallback, type PrepareStepInfo, type PrepareStepResult, type ProviderOptions, type ReconnectToStreamOptions, type SendMessagesOptions, type StreamTextTransform, type TelemetryOptions, WorkflowAgent, type WorkflowAgentOnAbortCallback, type WorkflowAgentOnEndCallback, type WorkflowAgentOnErrorCallback, type WorkflowAgentOnFinishCallback, type WorkflowAgentOnStartCallback, type WorkflowAgentOnStepEndCallback, type WorkflowAgentOnStepFinishCallback, type WorkflowAgentOnStepStartCallback, type WorkflowAgentOnToolExecutionEndCallback, type WorkflowAgentOnToolExecutionStartCallback, type WorkflowAgentOptions, type WorkflowAgentStreamOptions, type WorkflowAgentStreamResult, WorkflowChatTransport, type WorkflowChatTransportOptions, createModelCallToUIChunkTransform, normalizeUIMessageStreamParts, toUIMessageChunk };
1268
+ export { type CompatibleLanguageModel, type DownloadFunction, type GenerationSettings, type InferWorkflowAgentTools, type InferWorkflowAgentUIMessage, type ModelCallStreamPart, type OutputSpecification, type PrepareCallCallback, type PrepareCallOptions, type PrepareCallResult, type PrepareStepCallback, type PrepareStepInfo, type PrepareStepResult, type ProviderOptions, type ReconnectToStreamOptions, type SendMessagesOptions, type StreamTextTransform, type TelemetryOptions, WorkflowAgent, type WorkflowAgentOnAbortCallback, type WorkflowAgentOnEndCallback, type WorkflowAgentOnErrorCallback, type WorkflowAgentOnFinishCallback, type WorkflowAgentOnStartCallback, type WorkflowAgentOnStepEndCallback, type WorkflowAgentOnStepFinishCallback, type WorkflowAgentOnStepStartCallback, type WorkflowAgentOnToolExecutionEndCallback, type WorkflowAgentOnToolExecutionStartCallback, type WorkflowAgentOptions, type WorkflowAgentStreamOptions, type WorkflowAgentStreamResult, WorkflowChatTransport, type WorkflowChatTransportOptions, type WorkflowToolApprovalSecret, createModelCallToUIChunkTransform, normalizeUIMessageStreamParts, toUIMessageChunk };
package/dist/index.js CHANGED
@@ -9,15 +9,18 @@ import {
9
9
  } from "@ai-sdk/provider-utils";
10
10
  import {
11
11
  Output,
12
- experimental_filterActiveTools as filterActiveTools2
12
+ experimental_filterActiveTools as filterActiveTools2,
13
+ InvalidToolApprovalSignatureError
13
14
  } from "ai";
14
15
  import {
15
16
  createRestrictedTelemetryDispatcher as createRestrictedTelemetryDispatcher2,
16
17
  collectToolApprovals,
17
18
  convertToLanguageModelPrompt,
18
19
  mergeCallbacks,
20
+ signToolApproval,
19
21
  standardizePrompt,
20
- validateApprovedToolApprovals
22
+ validateApprovedToolApprovals,
23
+ verifyToolApprovalSignature
21
24
  } from "ai/internal";
22
25
 
23
26
  // src/create-language-model-tool-result-output.ts
@@ -314,7 +317,16 @@ async function doStreamStep(conversationPrompt, modelInit, writable, serializedT
314
317
  break;
315
318
  }
316
319
  if (writer) {
317
- await writer.write(part);
320
+ if (part.type === "tool-approval-request") {
321
+ await writer.write({
322
+ type: "tool-approval-request",
323
+ approvalId: part.approvalId,
324
+ toolCallId: part.toolCall.toolCallId,
325
+ ...part.signature != null ? { signature: part.signature } : {}
326
+ });
327
+ } else {
328
+ await writer.write(part);
329
+ }
318
330
  }
319
331
  if (part.type === "error" && !hasTerminalError) {
320
332
  terminalError = part.error;
@@ -806,6 +818,7 @@ var WorkflowAgent = class {
806
818
  this.repairToolCall = (_c = options.repairToolCall) != null ? _c : options.experimental_repairToolCall;
807
819
  this.experimentalDownload = options.experimental_download;
808
820
  this.experimentalSandbox = options.experimental_sandbox;
821
+ this.experimentalToolApprovalSecret = options.experimental_toolApprovalSecret;
809
822
  this.prepareStep = options.prepareStep;
810
823
  this.constructorOnStepEnd = (_d = options.onStepEnd) != null ? _d : options.onStepFinish;
811
824
  const { onFinish, onEnd = onFinish } = options;
@@ -836,7 +849,7 @@ var WorkflowAgent = class {
836
849
  throw new Error("Not implemented");
837
850
  }
838
851
  async stream(options) {
839
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U;
852
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V;
840
853
  const { onFinish, onEnd = onFinish } = options;
841
854
  let effectiveModel = this.model;
842
855
  let effectiveInstructions = (_b = (_a = options.instructions) != null ? _a : options.system) != null ? _b : this.instructions;
@@ -849,8 +862,9 @@ var WorkflowAgent = class {
849
862
  let effectiveStopWhenFromPrepare = (_h = options.stopWhen) != null ? _h : this.stopWhen;
850
863
  let effectiveActiveToolsFromPrepare = (_i = options.activeTools) != null ? _i : this.activeTools;
851
864
  let effectiveDownloadFromPrepare = (_j = options.experimental_download) != null ? _j : this.experimentalDownload;
852
- let effectiveTelemetryFromPrepare = (_k = options.telemetry) != null ? _k : this.telemetry;
853
- const resolvedMessagesForPrepareCall = (_l = effectiveMessages != null ? effectiveMessages : typeof effectivePrompt === "string" ? [{ role: "user", content: effectivePrompt }] : effectivePrompt) != null ? _l : [];
865
+ const effectiveToolApprovalSecret = (_k = options.experimental_toolApprovalSecret) != null ? _k : this.experimentalToolApprovalSecret;
866
+ let effectiveTelemetryFromPrepare = (_l = options.telemetry) != null ? _l : this.telemetry;
867
+ const resolvedMessagesForPrepareCall = (_m = effectiveMessages != null ? effectiveMessages : typeof effectivePrompt === "string" ? [{ role: "user", content: effectivePrompt }] : effectivePrompt) != null ? _m : [];
854
868
  if (this.prepareCall) {
855
869
  const prepared = await this.prepareCall({
856
870
  model: effectiveModel,
@@ -926,7 +940,7 @@ var WorkflowAgent = class {
926
940
  ...effectivePrompt != null ? { prompt: effectivePrompt } : { messages: effectiveMessages }
927
941
  });
928
942
  const download = effectiveDownloadFromPrepare;
929
- const sandbox = (_m = options.experimental_sandbox) != null ? _m : this.experimentalSandbox;
943
+ const sandbox = (_n = options.experimental_sandbox) != null ? _n : this.experimentalSandbox;
930
944
  const collectedApprovals = collectToolApprovals({
931
945
  messages: prompt.messages
932
946
  });
@@ -986,6 +1000,14 @@ var WorkflowAgent = class {
986
1000
  }
987
1001
  let revalidationReason;
988
1002
  try {
1003
+ await validateWorkflowToolApprovalSignature({
1004
+ secret: effectiveToolApprovalSecret,
1005
+ approvalId: approval.collected.approvalRequest.approvalId,
1006
+ toolCallId: approval.toolCallId,
1007
+ toolName: approval.toolName,
1008
+ input: approval.input,
1009
+ signature: approval.collected.approvalRequest.signature
1010
+ });
989
1011
  const { deniedToolApprovals: policyDenied, invalidToolApprovals } = await validateApprovedToolApprovals({
990
1012
  approvedToolApprovals: [approval.collected],
991
1013
  tools: this.tools,
@@ -999,7 +1021,7 @@ var WorkflowAgent = class {
999
1021
  invalidToolApprovals[0].error
1000
1022
  );
1001
1023
  } else if (policyDenied.length > 0) {
1002
- revalidationReason = (_n = policyDenied[0].approvalResponse.reason) != null ? _n : "Tool approval denied";
1024
+ revalidationReason = (_o = policyDenied[0].approvalResponse.reason) != null ? _o : "Tool approval denied";
1003
1025
  }
1004
1026
  } catch (error) {
1005
1027
  revalidationReason = getErrorMessage(error);
@@ -1036,7 +1058,7 @@ var WorkflowAgent = class {
1036
1058
  input: approval.input
1037
1059
  };
1038
1060
  const messages2 = prompt.messages;
1039
- await ((_o = telemetryDispatcher.onToolExecutionStart) == null ? void 0 : _o.call(telemetryDispatcher, {
1061
+ await ((_p = telemetryDispatcher.onToolExecutionStart) == null ? void 0 : _p.call(telemetryDispatcher, {
1040
1062
  toolCall: toolCallEvent,
1041
1063
  stepNumber: 0,
1042
1064
  messages: messages2,
@@ -1054,7 +1076,7 @@ var WorkflowAgent = class {
1054
1076
  toolCallId: approval.toolCallId,
1055
1077
  execute: executeApprovedTool
1056
1078
  }) : await executeApprovedTool();
1057
- await ((_p = telemetryDispatcher.onToolExecutionEnd) == null ? void 0 : _p.call(telemetryDispatcher, {
1079
+ await ((_q = telemetryDispatcher.onToolExecutionEnd) == null ? void 0 : _q.call(telemetryDispatcher, {
1058
1080
  toolCall: toolCallEvent,
1059
1081
  stepNumber: 0,
1060
1082
  durationMs: Date.now() - startTime,
@@ -1086,7 +1108,7 @@ var WorkflowAgent = class {
1086
1108
  });
1087
1109
  } catch (error) {
1088
1110
  const errorMessage = getErrorMessage(error);
1089
- await ((_q = telemetryDispatcher.onToolExecutionEnd) == null ? void 0 : _q.call(telemetryDispatcher, {
1111
+ await ((_r = telemetryDispatcher.onToolExecutionEnd) == null ? void 0 : _r.call(telemetryDispatcher, {
1090
1112
  toolCall: {
1091
1113
  type: "tool-call",
1092
1114
  toolCallId: approval.toolCallId,
@@ -1185,7 +1207,7 @@ var WorkflowAgent = class {
1185
1207
  supportedUrls: {},
1186
1208
  download
1187
1209
  });
1188
- const effectiveAbortSignal = (_r = options.abortSignal) != null ? _r : effectiveGenerationSettings.abortSignal;
1210
+ const effectiveAbortSignal = (_s = options.abortSignal) != null ? _s : effectiveGenerationSettings.abortSignal;
1189
1211
  const timeoutAt = options.timeout == null ? void 0 : Date.now() + options.timeout;
1190
1212
  const mergedGenerationSettings = {
1191
1213
  ...effectiveGenerationSettings,
@@ -1220,12 +1242,12 @@ var WorkflowAgent = class {
1220
1242
  }
1221
1243
  };
1222
1244
  mergedGenerationSettings.headers = withUserAgentSuffix(
1223
- (_s = mergedGenerationSettings.headers) != null ? _s : {},
1245
+ (_t = mergedGenerationSettings.headers) != null ? _t : {},
1224
1246
  "ai-sdk-agent/workflow"
1225
1247
  );
1226
1248
  const mergedOnStepEnd = mergeCallbacks(
1227
1249
  this.constructorOnStepEnd,
1228
- (_t = options.onStepEnd) != null ? _t : options.onStepFinish
1250
+ (_u = options.onStepEnd) != null ? _u : options.onStepFinish
1229
1251
  );
1230
1252
  const mergedOnEnd = mergeCallbacks(
1231
1253
  this.constructorOnEnd,
@@ -1249,10 +1271,10 @@ var WorkflowAgent = class {
1249
1271
  );
1250
1272
  const effectiveToolChoice = effectiveToolChoiceFromPrepare;
1251
1273
  const effectiveActiveTools = effectiveActiveToolsFromPrepare;
1252
- const effectiveTools = effectiveActiveTools && effectiveActiveTools.length > 0 ? (_u = filterActiveTools2({
1274
+ const effectiveTools = effectiveActiveTools && effectiveActiveTools.length > 0 ? (_v = filterActiveTools2({
1253
1275
  tools: this.tools,
1254
1276
  activeTools: effectiveActiveTools
1255
- })) != null ? _u : this.tools : this.tools;
1277
+ })) != null ? _v : this.tools : this.tools;
1256
1278
  const effectiveModelInfo = getModelInfo2(effectiveModel);
1257
1279
  let runtimeContext = effectiveRuntimeContext;
1258
1280
  let toolsContext = effectiveToolsContext;
@@ -1267,7 +1289,7 @@ var WorkflowAgent = class {
1267
1289
  toolsContext
1268
1290
  });
1269
1291
  }
1270
- await ((_x = telemetryDispatcher.onStart) == null ? void 0 : _x.call(telemetryDispatcher, {
1292
+ await ((_y = telemetryDispatcher.onStart) == null ? void 0 : _y.call(telemetryDispatcher, {
1271
1293
  callId: "workflow-agent",
1272
1294
  operationId: "ai.workflowAgent.stream",
1273
1295
  provider: effectiveModelInfo.provider,
@@ -1285,12 +1307,12 @@ var WorkflowAgent = class {
1285
1307
  frequencyPenalty: mergedGenerationSettings.frequencyPenalty,
1286
1308
  stopSequences: mergedGenerationSettings.stopSequences,
1287
1309
  seed: mergedGenerationSettings.seed,
1288
- maxRetries: (_v = mergedGenerationSettings.maxRetries) != null ? _v : 2,
1310
+ maxRetries: (_w = mergedGenerationSettings.maxRetries) != null ? _w : 2,
1289
1311
  timeout: void 0,
1290
1312
  headers: mergedGenerationSettings.headers,
1291
1313
  reasoning: mergedGenerationSettings.reasoning,
1292
1314
  providerOptions: mergedGenerationSettings.providerOptions,
1293
- output: (_w = options.output) != null ? _w : this.output,
1315
+ output: (_x = options.output) != null ? _x : this.output,
1294
1316
  runtimeContext,
1295
1317
  toolsContext
1296
1318
  }));
@@ -1440,7 +1462,7 @@ var WorkflowAgent = class {
1440
1462
  }
1441
1463
  }));
1442
1464
  };
1443
- if ((_y = mergedGenerationSettings.abortSignal) == null ? void 0 : _y.aborted) {
1465
+ if ((_z = mergedGenerationSettings.abortSignal) == null ? void 0 : _z.aborted) {
1444
1466
  if (options.onAbort) {
1445
1467
  await options.onAbort({ steps });
1446
1468
  }
@@ -1464,16 +1486,16 @@ var WorkflowAgent = class {
1464
1486
  stopConditions: effectiveStopWhenFromPrepare,
1465
1487
  onStepEnd: mergedOnStepEnd,
1466
1488
  onStepStart: mergedOnStepStart,
1467
- prepareStep: (_z = options.prepareStep) != null ? _z : this.prepareStep,
1489
+ prepareStep: (_A = options.prepareStep) != null ? _A : this.prepareStep,
1468
1490
  generationSettings: mergedGenerationSettings,
1469
1491
  toolChoice: effectiveToolChoice,
1470
1492
  runtimeContext,
1471
1493
  toolsContext,
1472
1494
  telemetry: effectiveTelemetry,
1473
- includeRawChunks: (_A = options.includeRawChunks) != null ? _A : false,
1495
+ includeRawChunks: (_B = options.includeRawChunks) != null ? _B : false,
1474
1496
  timeoutAt,
1475
- repairToolCall: (_C = (_B = options.repairToolCall) != null ? _B : options.experimental_repairToolCall) != null ? _C : this.repairToolCall,
1476
- responseFormat: await ((_E = (_D = options.output) != null ? _D : this.output) == null ? void 0 : _E.responseFormat),
1497
+ repairToolCall: (_D = (_C = options.repairToolCall) != null ? _C : options.experimental_repairToolCall) != null ? _D : this.repairToolCall,
1498
+ responseFormat: await ((_F = (_E = options.output) != null ? _E : this.output) == null ? void 0 : _F.responseFormat),
1477
1499
  experimental_sandbox: sandbox
1478
1500
  });
1479
1501
  let finalMessages;
@@ -1485,7 +1507,7 @@ var WorkflowAgent = class {
1485
1507
  try {
1486
1508
  let result = await iterator.next();
1487
1509
  while (!result.done) {
1488
- if ((_F = mergedGenerationSettings.abortSignal) == null ? void 0 : _F.aborted) {
1510
+ if ((_G = mergedGenerationSettings.abortSignal) == null ? void 0 : _G.aborted) {
1489
1511
  wasAborted = true;
1490
1512
  if (options.onAbort) {
1491
1513
  await options.onAbort({ steps });
@@ -1617,12 +1639,12 @@ var WorkflowAgent = class {
1617
1639
  const messages2 = iterMessages;
1618
1640
  const lastStep2 = steps[steps.length - 1];
1619
1641
  const totalUsage2 = aggregateUsage(steps);
1620
- const finishReason2 = (_G = lastStep2 == null ? void 0 : lastStep2.finishReason) != null ? _G : "other";
1642
+ const finishReason2 = (_H = lastStep2 == null ? void 0 : lastStep2.finishReason) != null ? _H : "other";
1621
1643
  if (mergedOnEnd && !wasAborted) {
1622
1644
  await mergedOnEnd({
1623
1645
  steps,
1624
1646
  messages: messages2,
1625
- text: (_H = lastStep2 == null ? void 0 : lastStep2.text) != null ? _H : "",
1647
+ text: (_I = lastStep2 == null ? void 0 : lastStep2.text) != null ? _I : "",
1626
1648
  finishReason: finishReason2,
1627
1649
  usage: totalUsage2,
1628
1650
  totalUsage: totalUsage2,
@@ -1634,7 +1656,7 @@ var WorkflowAgent = class {
1634
1656
  if (!wasAborted && steps.length > 0) {
1635
1657
  const telemetrySteps = steps.map(normalizeStepForTelemetry2);
1636
1658
  const lastTelemetryStep = telemetrySteps[telemetrySteps.length - 1];
1637
- await ((_I = telemetryDispatcher.onEnd) == null ? void 0 : _I.call(telemetryDispatcher, {
1659
+ await ((_J = telemetryDispatcher.onEnd) == null ? void 0 : _J.call(telemetryDispatcher, {
1638
1660
  ...lastTelemetryStep,
1639
1661
  steps: telemetrySteps,
1640
1662
  usage: totalUsage2,
@@ -1652,18 +1674,29 @@ var WorkflowAgent = class {
1652
1674
  return approvalNeeded[tcIndex];
1653
1675
  });
1654
1676
  if (approvalToolCalls.length > 0) {
1655
- await writeApprovalRequests(
1656
- options.writable,
1657
- approvalToolCalls.map((tc) => ({
1658
- toolCallId: tc.toolCallId,
1659
- toolName: tc.toolName
1660
- }))
1677
+ const approvalRequests = await Promise.all(
1678
+ approvalToolCalls.map(async (tc) => {
1679
+ const approvalId = `approval-${tc.toolCallId}`;
1680
+ const signature = effectiveToolApprovalSecret == null ? void 0 : await signWorkflowToolApproval({
1681
+ secret: effectiveToolApprovalSecret,
1682
+ approvalId,
1683
+ toolCallId: tc.toolCallId,
1684
+ toolName: tc.toolName,
1685
+ input: tc.input
1686
+ });
1687
+ return {
1688
+ approvalId,
1689
+ toolCallId: tc.toolCallId,
1690
+ ...signature != null ? { signature } : {}
1691
+ };
1692
+ })
1661
1693
  );
1694
+ await writeApprovalRequests(options.writable, approvalRequests);
1662
1695
  }
1663
1696
  }
1664
1697
  if (options.writable) {
1665
- const sendFinish = (_J = options.sendFinish) != null ? _J : true;
1666
- const preventClose = (_K = options.preventClose) != null ? _K : false;
1698
+ const sendFinish = (_K = options.sendFinish) != null ? _K : true;
1699
+ const preventClose = (_L = options.preventClose) != null ? _L : false;
1667
1700
  if (sendFinish || !preventClose) {
1668
1701
  await closeStream(options.writable, preventClose, sendFinish);
1669
1702
  }
@@ -1803,16 +1836,16 @@ var WorkflowAgent = class {
1803
1836
  } else if (options.onError) {
1804
1837
  await options.onError({ error });
1805
1838
  }
1806
- await ((_L = telemetryDispatcher.onError) == null ? void 0 : _L.call(telemetryDispatcher, error));
1839
+ await ((_M = telemetryDispatcher.onError) == null ? void 0 : _M.call(telemetryDispatcher, error));
1807
1840
  }
1808
1841
  if (hasTerminalError) {
1809
1842
  if (options.onError) {
1810
1843
  await options.onError({ error: terminalError });
1811
1844
  }
1812
- await ((_M = telemetryDispatcher.onError) == null ? void 0 : _M.call(telemetryDispatcher, terminalError));
1845
+ await ((_N = telemetryDispatcher.onError) == null ? void 0 : _N.call(telemetryDispatcher, terminalError));
1813
1846
  }
1814
1847
  const messages = finalMessages != null ? finalMessages : prompt.messages;
1815
- const effectiveOutput = (_N = options.output) != null ? _N : this.output;
1848
+ const effectiveOutput = (_O = options.output) != null ? _O : this.output;
1816
1849
  let experimentalOutput = void 0;
1817
1850
  if (effectiveOutput && steps.length > 0) {
1818
1851
  const lastStep2 = steps[steps.length - 1];
@@ -1837,12 +1870,12 @@ var WorkflowAgent = class {
1837
1870
  }
1838
1871
  const lastStep = steps[steps.length - 1];
1839
1872
  const totalUsage = aggregateUsage(steps);
1840
- const finishReason = (_O = lastStep == null ? void 0 : lastStep.finishReason) != null ? _O : "other";
1873
+ const finishReason = (_P = lastStep == null ? void 0 : lastStep.finishReason) != null ? _P : "other";
1841
1874
  if (mergedOnEnd && !wasAborted) {
1842
1875
  await mergedOnEnd({
1843
1876
  steps,
1844
1877
  messages,
1845
- text: (_P = lastStep == null ? void 0 : lastStep.text) != null ? _P : "",
1878
+ text: (_Q = lastStep == null ? void 0 : lastStep.text) != null ? _Q : "",
1846
1879
  finishReason,
1847
1880
  usage: totalUsage,
1848
1881
  totalUsage,
@@ -1854,7 +1887,7 @@ var WorkflowAgent = class {
1854
1887
  if (!wasAborted && steps.length > 0) {
1855
1888
  const telemetrySteps = steps.map(normalizeStepForTelemetry2);
1856
1889
  const lastTelemetryStep = telemetrySteps[telemetrySteps.length - 1];
1857
- await ((_Q = telemetryDispatcher.onEnd) == null ? void 0 : _Q.call(telemetryDispatcher, {
1890
+ await ((_R = telemetryDispatcher.onEnd) == null ? void 0 : _R.call(telemetryDispatcher, {
1858
1891
  ...lastTelemetryStep,
1859
1892
  steps: telemetrySteps,
1860
1893
  usage: totalUsage,
@@ -1863,8 +1896,8 @@ var WorkflowAgent = class {
1863
1896
  }
1864
1897
  if (hasEncounteredError) {
1865
1898
  if (options.writable) {
1866
- const sendFinish = (_R = options.sendFinish) != null ? _R : true;
1867
- const preventClose = (_S = options.preventClose) != null ? _S : false;
1899
+ const sendFinish = (_S = options.sendFinish) != null ? _S : true;
1900
+ const preventClose = (_T = options.preventClose) != null ? _T : false;
1868
1901
  if (sendFinish || !preventClose) {
1869
1902
  await closeStream(options.writable, preventClose, sendFinish);
1870
1903
  }
@@ -1872,8 +1905,8 @@ var WorkflowAgent = class {
1872
1905
  throw encounteredError;
1873
1906
  }
1874
1907
  if (options.writable) {
1875
- const sendFinish = (_T = options.sendFinish) != null ? _T : true;
1876
- const preventClose = (_U = options.preventClose) != null ? _U : false;
1908
+ const sendFinish = (_U = options.sendFinish) != null ? _U : true;
1909
+ const preventClose = (_V = options.preventClose) != null ? _V : false;
1877
1910
  if (sendFinish || !preventClose) {
1878
1911
  await closeStream(options.writable, preventClose, sendFinish);
1879
1912
  }
@@ -1915,21 +1948,101 @@ async function closeStream(writable, preventClose, sendFinish) {
1915
1948
  await writable.close();
1916
1949
  }
1917
1950
  }
1918
- async function writeApprovalRequests(writable, toolCalls) {
1951
+ async function writeApprovalRequests(writable, approvalRequests) {
1919
1952
  "use step";
1920
1953
  const writer = writable.getWriter();
1921
1954
  try {
1922
- for (const tc of toolCalls) {
1955
+ for (const request of approvalRequests) {
1923
1956
  await writer.write({
1924
1957
  type: "tool-approval-request",
1925
- approvalId: `approval-${tc.toolCallId}`,
1926
- toolCallId: tc.toolCallId
1958
+ approvalId: request.approvalId,
1959
+ toolCallId: request.toolCallId,
1960
+ ...request.signature != null ? { signature: request.signature } : {}
1927
1961
  });
1928
1962
  }
1929
1963
  } finally {
1930
1964
  writer.releaseLock();
1931
1965
  }
1932
1966
  }
1967
+ async function signWorkflowToolApproval({
1968
+ secret,
1969
+ approvalId,
1970
+ toolCallId,
1971
+ toolName,
1972
+ input
1973
+ }) {
1974
+ "use step";
1975
+ return signToolApproval({
1976
+ secret: getWorkflowToolApprovalSecret(secret),
1977
+ approvalId,
1978
+ toolCallId,
1979
+ toolName,
1980
+ input
1981
+ });
1982
+ }
1983
+ async function verifyWorkflowToolApprovalSignature({
1984
+ secret,
1985
+ signature,
1986
+ approvalId,
1987
+ toolCallId,
1988
+ toolName,
1989
+ input
1990
+ }) {
1991
+ "use step";
1992
+ return verifyToolApprovalSignature({
1993
+ secret: getWorkflowToolApprovalSecret(secret),
1994
+ signature,
1995
+ approvalId,
1996
+ toolCallId,
1997
+ toolName,
1998
+ input
1999
+ });
2000
+ }
2001
+ async function validateWorkflowToolApprovalSignature({
2002
+ secret,
2003
+ signature,
2004
+ approvalId,
2005
+ toolCallId,
2006
+ toolName,
2007
+ input
2008
+ }) {
2009
+ if (secret == null) {
2010
+ return;
2011
+ }
2012
+ if (signature == null) {
2013
+ throw new InvalidToolApprovalSignatureError({
2014
+ approvalId,
2015
+ toolCallId,
2016
+ reason: "missing signature"
2017
+ });
2018
+ }
2019
+ const valid = await verifyWorkflowToolApprovalSignature({
2020
+ secret,
2021
+ signature,
2022
+ approvalId,
2023
+ toolCallId,
2024
+ toolName,
2025
+ input
2026
+ });
2027
+ if (!valid) {
2028
+ throw new InvalidToolApprovalSignatureError({
2029
+ approvalId,
2030
+ toolCallId,
2031
+ reason: "invalid signature"
2032
+ });
2033
+ }
2034
+ }
2035
+ function getWorkflowToolApprovalSecret({
2036
+ environmentVariable
2037
+ }) {
2038
+ const secret = process.env[environmentVariable];
2039
+ if (secret == null) {
2040
+ throw new Error(
2041
+ `Tool approval secret environment variable "${environmentVariable}" is not set`
2042
+ );
2043
+ }
2044
+ return secret;
2045
+ }
1933
2046
  async function writeToolResults(writable, results, writeStepBoundary = false) {
1934
2047
  "use step";
1935
2048
  const writer = writable.getWriter();
@@ -2260,15 +2373,15 @@ function toUIMessageChunk(part) {
2260
2373
  case "model-call-end":
2261
2374
  case "raw":
2262
2375
  return void 0;
2376
+ case "tool-approval-request":
2377
+ return {
2378
+ type: "tool-approval-request",
2379
+ approvalId: part.approvalId,
2380
+ toolCallId: "toolCallId" in part ? part.toolCallId : part.toolCall.toolCallId,
2381
+ ...part.signature != null ? { signature: part.signature } : {}
2382
+ };
2263
2383
  default: {
2264
2384
  const passthroughPart = part;
2265
- if (passthroughPart.type === "tool-approval-request") {
2266
- return {
2267
- type: "tool-approval-request",
2268
- approvalId: passthroughPart.approvalId,
2269
- toolCallId: passthroughPart.toolCallId
2270
- };
2271
- }
2272
2385
  if (passthroughPart.type === "finish-step" || passthroughPart.type === "start-step" || passthroughPart.type === "tool-output-denied") {
2273
2386
  return passthroughPart;
2274
2387
  }