ai 7.0.43 → 7.0.45

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,22 @@
1
1
  # ai
2
2
 
3
+ ## 7.0.45
4
+
5
+ ### Patch Changes
6
+
7
+ - d6ce0ee: feat(ai): support experimental_toolCallers in streamText
8
+ - fa95504: feat(ai): support experimental tool callers in ToolLoopAgent
9
+ - 349afe7: Warn when `generateText` receives streaming-only `firstChunkMs` or `chunkMs` timeout settings.
10
+ - Updated dependencies [fa95504]
11
+ - @ai-sdk/provider-utils@5.0.17
12
+ - @ai-sdk/gateway@4.0.34
13
+
14
+ ## 7.0.44
15
+
16
+ ### Patch Changes
17
+
18
+ - 015acb4: fix telemetry attribution for language model calls that resolve to a different response model
19
+
3
20
  ## 7.0.43
4
21
 
5
22
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ export { AISDKError, APICallError, EmptyResponseBodyError, InvalidPromptError, I
3
3
  import { GatewayModelId } from '@ai-sdk/gateway';
4
4
  export { GatewayModelId, createGateway, gateway } from '@ai-sdk/gateway';
5
5
  import * as _ai_sdk_provider_utils from '@ai-sdk/provider-utils';
6
- import { ModelMessage, AssistantModelMessage, ToolModelMessage, ProviderOptions, ToolSet, SystemModelMessage, UserModelMessage, DataContent, FlexibleSchema, InferSchema, Context, Arrayable, InferToolSetContext, InferToolInput, InferToolOutput, ReasoningPart, ReasoningFilePart, Experimental_SandboxSession, Tool, ToolCall, IdGenerator, ToolExecutionOptions, MaybePromiseLike, InferToolContext, HasRequiredKey, Experimental_ToolCallerTool, TextPart, FilePart, Resolvable, FetchFunction } from '@ai-sdk/provider-utils';
6
+ import { ModelMessage, AssistantModelMessage, ToolModelMessage, ProviderOptions, ToolSet, SystemModelMessage, UserModelMessage, DataContent, FlexibleSchema, InferSchema, Context, Arrayable, InferToolSetContext, InferToolInput, InferToolOutput, ReasoningPart, ReasoningFilePart, Experimental_SandboxSession, Tool, ToolCall, IdGenerator, ToolExecutionOptions, MaybePromiseLike, InferToolContext, Experimental_ToolCallerTool, HasRequiredKey, TextPart, FilePart, Resolvable, FetchFunction } from '@ai-sdk/provider-utils';
7
7
  export { AssistantContent, AssistantModelMessage, DataContent, DownloadError, Experimental_SandboxProcess, Experimental_SandboxSession, Experimental_ToolCallerTool, FilePart, FlexibleSchema, IdGenerator, ImagePart, InferSchema, InferToolInput, InferToolOutput, ModelMessage, Schema, SystemModelMessage, TextPart, Tool, ToolApprovalRequest, ToolApprovalResponse, ToolCallPart, ToolContent, ToolExecuteFunction, ToolExecutionOptions, ToolModelMessage, ToolResultPart, ToolSet, UserContent, UserModelMessage, asSchema, createIdGenerator, dynamicTool, experimental_toolCaller, generateId, jsonSchema, parseJsonEventStream, tool, zodSchema } from '@ai-sdk/provider-utils';
8
8
  import { ServerResponse } from 'node:http';
9
9
  import { ServerResponse as ServerResponse$1 } from 'http';
@@ -3019,6 +3019,21 @@ type ToolApprovalConfiguration<TOOLS extends ToolSet, RUNTIME_CONTEXT extends Co
3019
3019
  [key in keyof TOOLS]?: ToolApprovalStatus | SingleToolApprovalFunction<InferToolInput<TOOLS[key]>, InferToolContext<TOOLS[key]>, RUNTIME_CONTEXT>;
3020
3020
  };
3021
3021
 
3022
+ interface Experimental_ToolCallerReference<NAME extends string = string> {
3023
+ readonly toolName: NAME;
3024
+ }
3025
+ type ToolCallerName<TOOLS extends ToolSet> = {
3026
+ [NAME in keyof TOOLS]: TOOLS[NAME] extends Experimental_ToolCallerTool ? NAME : never;
3027
+ }[keyof TOOLS] & string;
3028
+ type ToolCallerReferenceUnion<TOOLS extends ToolSet> = {
3029
+ [NAME in ToolCallerName<TOOLS>]: Experimental_ToolCallerReference<NAME>;
3030
+ }[ToolCallerName<TOOLS>];
3031
+ type Experimental_ToolCallers<TOOLS extends ToolSet> = (callers: {
3032
+ [NAME in ToolCallerName<TOOLS>]: Experimental_ToolCallerReference<NAME>;
3033
+ }) => {
3034
+ [NAME in keyof TOOLS]?: ReadonlyArray<'direct' | ToolCallerReferenceUnion<TOOLS>>;
3035
+ };
3036
+
3022
3037
  declare const symbol$l: unique symbol;
3023
3038
  declare class InvalidToolInputError extends AISDKError {
3024
3039
  private readonly [symbol$l];
@@ -3373,7 +3388,7 @@ type StreamTextOnAbortCallback<TOOLS extends ToolSet, RUNTIME_CONTEXT extends Co
3373
3388
  * @returns
3374
3389
  * A result object for accessing different stream types and additional information.
3375
3390
  */
3376
- declare function streamText<TOOLS extends ToolSet, RUNTIME_CONTEXT extends Context = Context, OUTPUT extends Output = Output<string, string, never>>({ model, tools, toolChoice, instructions, system, prompt, messages, allowSystemInMessages, maxRetries, abortSignal, timeout, headers, stopWhen, experimental_sandbox: sandbox, output, toolApproval, experimental_toolApprovalSecret, experimental_telemetry, telemetry, prepareStep, providerOptions, activeTools, toolOrder, experimental_repairToolCall, repairToolCall, experimental_refineToolInput: refineToolInput, experimental_transform: transform, experimental_download: download, includeRawChunks, onChunk, onError, onFinish, onEnd, onAbort, onStepEnd, onStepFinish, onStart, experimental_onStart, onStepStart, experimental_onStepStart, onLanguageModelCallStart, experimental_onLanguageModelCallStart, onLanguageModelCallEnd, experimental_onLanguageModelCallEnd, onToolExecutionStart, onToolExecutionEnd, experimental_onToolCallStart, experimental_onToolCallFinish, runtimeContext, toolsContext, experimental_include, include, _internal: { now, generateId, generateCallId, }, ...settings }: LanguageModelCallOptions & RequestOptions<TOOLS> & Prompt & ToolsContextParameter<TOOLS> & {
3391
+ declare function streamText<TOOLS extends ToolSet, RUNTIME_CONTEXT extends Context = Context, OUTPUT extends Output = Output<string, string, never>>({ model, tools, toolChoice, instructions, system, prompt, messages, allowSystemInMessages, maxRetries, abortSignal, timeout, headers, stopWhen, experimental_sandbox: sandbox, output, toolApproval, experimental_toolCallers, experimental_toolApprovalSecret, experimental_telemetry, telemetry, prepareStep, providerOptions, activeTools, toolOrder, experimental_repairToolCall, repairToolCall, experimental_refineToolInput: refineToolInput, experimental_transform: transform, experimental_download: download, includeRawChunks, onChunk, onError, onFinish, onEnd, onAbort, onStepEnd, onStepFinish, onStart, experimental_onStart, onStepStart, experimental_onStepStart, onLanguageModelCallStart, experimental_onLanguageModelCallStart, onLanguageModelCallEnd, experimental_onLanguageModelCallEnd, onToolExecutionStart, onToolExecutionEnd, experimental_onToolCallStart, experimental_onToolCallFinish, runtimeContext, toolsContext, experimental_include, include, _internal: { now, generateId, generateCallId, }, ...settings }: LanguageModelCallOptions & RequestOptions<TOOLS> & Prompt & ToolsContextParameter<TOOLS> & {
3377
3392
  /**
3378
3393
  * The language model to use.
3379
3394
  */
@@ -3437,6 +3452,10 @@ declare function streamText<TOOLS extends ToolSet, RUNTIME_CONTEXT extends Conte
3437
3452
  * This configuration takes precedence over tool-defined approval settings.
3438
3453
  */
3439
3454
  toolApproval?: ToolApprovalConfiguration<TOOLS, RUNTIME_CONTEXT>;
3455
+ /**
3456
+ * Configures which caller tools may invoke each tool.
3457
+ */
3458
+ experimental_toolCallers?: Experimental_ToolCallers<NoInfer<TOOLS>>;
3440
3459
  /**
3441
3460
  * Secret for HMAC-signing tool approval requests. When set, the server
3442
3461
  * signs each approval request at issuance and verifies the signature when
@@ -4452,8 +4471,10 @@ interface GenerateTextResult<TOOLS extends ToolSet, RUNTIME_CONTEXT extends Cont
4452
4471
  */
4453
4472
  readonly finalStep: StepResult<TOOLS, RUNTIME_CONTEXT>;
4454
4473
  /**
4455
- * The generated structured output. It uses the `output` specification.
4474
+ * The generated output according to the `output` specification.
4456
4475
  *
4476
+ * @throws {NoOutputGeneratedError} When no output is available, for example
4477
+ * when the final step does not finish with a `stop` reason.
4457
4478
  */
4458
4479
  readonly output: InferCompleteOutput<OUTPUT>;
4459
4480
  }
@@ -4610,21 +4631,6 @@ interface Agent<CALL_OPTIONS = never, TOOLS extends ToolSet = {}, RUNTIME_CONTEX
4610
4631
  stream(options: AgentStreamParameters<CALL_OPTIONS, TOOLS, RUNTIME_CONTEXT>): PromiseLike<StreamTextResult<TOOLS, RUNTIME_CONTEXT, OUTPUT>>;
4611
4632
  }
4612
4633
 
4613
- interface Experimental_ToolCallerReference<NAME extends string = string> {
4614
- readonly toolName: NAME;
4615
- }
4616
- type ToolCallerName<TOOLS extends ToolSet> = {
4617
- [NAME in keyof TOOLS]: TOOLS[NAME] extends Experimental_ToolCallerTool ? NAME : never;
4618
- }[keyof TOOLS] & string;
4619
- type ToolCallerReferenceUnion<TOOLS extends ToolSet> = {
4620
- [NAME in ToolCallerName<TOOLS>]: Experimental_ToolCallerReference<NAME>;
4621
- }[ToolCallerName<TOOLS>];
4622
- type Experimental_ToolCallers<TOOLS extends ToolSet> = (callers: {
4623
- [NAME in ToolCallerName<TOOLS>]: Experimental_ToolCallerReference<NAME>;
4624
- }) => {
4625
- [NAME in keyof TOOLS]?: ReadonlyArray<'direct' | ToolCallerReferenceUnion<TOOLS>>;
4626
- };
4627
-
4628
4634
  type GenerateTextInclude = {
4629
4635
  /**
4630
4636
  * Whether to retain the request body in step results.
@@ -5002,6 +5008,10 @@ type ToolLoopAgentSettings<CALL_OPTIONS = never, TOOLS extends ToolSet = {}, RUN
5002
5008
  * This configuration takes precedence over tool-defined approval settings.
5003
5009
  */
5004
5010
  toolApproval?: ToolApprovalConfiguration<NoInfer<TOOLS>, RUNTIME_CONTEXT>;
5011
+ /**
5012
+ * Configures which caller tools may invoke each tool.
5013
+ */
5014
+ experimental_toolCallers?: Experimental_ToolCallers<NoInfer<TOOLS>>;
5005
5015
  /**
5006
5016
  * Optional function that you can use to provide different settings for a step.
5007
5017
  */
@@ -5118,9 +5128,9 @@ type ToolLoopAgentSettings<CALL_OPTIONS = never, TOOLS extends ToolSet = {}, RUN
5118
5128
  * }),
5119
5129
  * ```
5120
5130
  */
5121
- prepareCall?: (options: Omit<AgentCallParameters<CALL_OPTIONS, NoInfer<TOOLS>, NoInfer<RUNTIME_CONTEXT>>, 'onStepEnd' | 'onStepFinish'> & Pick<ToolLoopAgentSettings<CALL_OPTIONS, TOOLS, RUNTIME_CONTEXT, NoInfer<OUTPUT>>, 'model' | 'tools' | 'maxOutputTokens' | 'temperature' | 'topP' | 'topK' | 'presencePenalty' | 'frequencyPenalty' | 'stopSequences' | 'seed' | 'headers' | 'instructions' | 'allowSystemInMessages' | 'stopWhen' | 'telemetry' | 'experimental_telemetry' | 'activeTools' | 'toolOrder' | 'toolApproval' | 'providerOptions' | 'experimental_download' | 'experimental_refineToolInput' | 'include' | 'runtimeContext' | '_internal'> & {
5131
+ prepareCall?: (options: Omit<AgentCallParameters<CALL_OPTIONS, NoInfer<TOOLS>, NoInfer<RUNTIME_CONTEXT>>, 'onStepEnd' | 'onStepFinish'> & Pick<ToolLoopAgentSettings<CALL_OPTIONS, TOOLS, RUNTIME_CONTEXT, NoInfer<OUTPUT>>, 'model' | 'tools' | 'maxOutputTokens' | 'temperature' | 'topP' | 'topK' | 'presencePenalty' | 'frequencyPenalty' | 'stopSequences' | 'seed' | 'headers' | 'instructions' | 'allowSystemInMessages' | 'stopWhen' | 'telemetry' | 'experimental_telemetry' | 'activeTools' | 'toolOrder' | 'toolApproval' | 'experimental_toolCallers' | 'providerOptions' | 'experimental_download' | 'experimental_refineToolInput' | 'include' | 'runtimeContext' | '_internal'> & {
5122
5132
  toolsContext: InferToolSetContext<TOOLS>;
5123
- }) => MaybePromiseLike<Pick<ToolLoopAgentSettings<CALL_OPTIONS, TOOLS, RUNTIME_CONTEXT, NoInfer<OUTPUT>>, 'model' | 'tools' | 'maxOutputTokens' | 'temperature' | 'topP' | 'topK' | 'presencePenalty' | 'frequencyPenalty' | 'stopSequences' | 'seed' | 'headers' | 'instructions' | 'allowSystemInMessages' | 'stopWhen' | 'telemetry' | 'experimental_telemetry' | 'activeTools' | 'toolOrder' | 'toolApproval' | 'providerOptions' | 'experimental_download' | 'experimental_refineToolInput' | 'include' | 'runtimeContext' | '_internal'> & Omit<Prompt, 'system'> & {
5133
+ }) => MaybePromiseLike<Pick<ToolLoopAgentSettings<CALL_OPTIONS, TOOLS, RUNTIME_CONTEXT, NoInfer<OUTPUT>>, 'model' | 'tools' | 'maxOutputTokens' | 'temperature' | 'topP' | 'topK' | 'presencePenalty' | 'frequencyPenalty' | 'stopSequences' | 'seed' | 'headers' | 'instructions' | 'allowSystemInMessages' | 'stopWhen' | 'telemetry' | 'experimental_telemetry' | 'activeTools' | 'toolOrder' | 'toolApproval' | 'experimental_toolCallers' | 'providerOptions' | 'experimental_download' | 'experimental_refineToolInput' | 'include' | 'runtimeContext' | '_internal'> & Omit<Prompt, 'system'> & {
5124
5134
  toolsContext: InferToolSetContext<TOOLS>;
5125
5135
  }>;
5126
5136
  };
package/dist/index.js CHANGED
@@ -1143,7 +1143,7 @@ import {
1143
1143
  } from "@ai-sdk/provider-utils";
1144
1144
 
1145
1145
  // src/version.ts
1146
- var VERSION = true ? "7.0.43" : "0.0.0-test";
1146
+ var VERSION = true ? "7.0.45" : "0.0.0-test";
1147
1147
 
1148
1148
  // src/util/download/download.ts
1149
1149
  var download = async ({
@@ -5279,6 +5279,28 @@ async function generateText({
5279
5279
  const resolvedOnToolExecutionStart = onToolExecutionStart != null ? onToolExecutionStart : experimental_onToolCallStart;
5280
5280
  const resolvedOnToolExecutionEnd = onToolExecutionEnd != null ? onToolExecutionEnd : experimental_onToolCallFinish;
5281
5281
  const resolvedOnStepEnd = onStepEnd != null ? onStepEnd : onStepFinish;
5282
+ const unsupportedTimeoutWarnings = [];
5283
+ if (getFirstChunkTimeoutMs(timeout) != null) {
5284
+ unsupportedTimeoutWarnings.push({
5285
+ type: "unsupported",
5286
+ feature: "timeout.firstChunkMs",
5287
+ details: "The firstChunkMs timeout is only supported by streaming functions."
5288
+ });
5289
+ }
5290
+ if (getChunkTimeoutMs(timeout) != null) {
5291
+ unsupportedTimeoutWarnings.push({
5292
+ type: "unsupported",
5293
+ feature: "timeout.chunkMs",
5294
+ details: "The chunkMs timeout is only supported by streaming functions."
5295
+ });
5296
+ }
5297
+ if (unsupportedTimeoutWarnings.length > 0) {
5298
+ logWarnings({
5299
+ warnings: unsupportedTimeoutWarnings,
5300
+ provider: model.provider,
5301
+ model: model.modelId
5302
+ });
5303
+ }
5282
5304
  const totalTimeoutMs = getTotalTimeoutMs(timeout);
5283
5305
  const stepTimeoutMs = getStepTimeoutMs(timeout);
5284
5306
  const stepAbortController = stepTimeoutMs != null ? new AbortController() : void 0;
@@ -5642,7 +5664,7 @@ async function generateText({
5642
5664
  event: {
5643
5665
  callId,
5644
5666
  provider: stepModel.provider,
5645
- modelId: stepModel.modelId,
5667
+ modelId: currentModelResponse.response.modelId,
5646
5668
  finishReason: currentModelResponse.finishReason.unified,
5647
5669
  usage: stepUsage,
5648
5670
  content: modelCallContent,
@@ -8360,12 +8382,13 @@ function createLanguageModelV4StreamPartToLanguageModelStreamPartTransform({
8360
8382
  const textPartIndexes = /* @__PURE__ */ new Map();
8361
8383
  const reasoningPartIndexes = /* @__PURE__ */ new Map();
8362
8384
  let responseId = generateId2();
8385
+ let responseModelId = modelId;
8363
8386
  let timeToFirstOutputMs;
8364
8387
  let previousOutputChunkTimestampMs;
8365
8388
  const timeBetweenOutputChunksMs = [];
8366
8389
  return new TransformStream({
8367
8390
  async transform(chunk, controller) {
8368
- var _a23, _b;
8391
+ var _a23, _b, _c;
8369
8392
  if (isOutputChunk(chunk)) {
8370
8393
  const outputChunkTimestampMs = now2();
8371
8394
  if (timeToFirstOutputMs == null) {
@@ -8498,7 +8521,7 @@ function createLanguageModelV4StreamPartToLanguageModelStreamPartTransform({
8498
8521
  event: {
8499
8522
  callId,
8500
8523
  provider,
8501
- modelId,
8524
+ modelId: responseModelId,
8502
8525
  finishReason: chunk.finishReason.unified,
8503
8526
  usage,
8504
8527
  content: modelCallContent,
@@ -8618,6 +8641,7 @@ function createLanguageModelV4StreamPartToLanguageModelStreamPartTransform({
8618
8641
  }
8619
8642
  case "response-metadata": {
8620
8643
  responseId = (_b = chunk.id) != null ? _b : responseId;
8644
+ responseModelId = (_c = chunk.modelId) != null ? _c : responseModelId;
8621
8645
  controller.enqueue({
8622
8646
  type: "model-call-response-metadata",
8623
8647
  id: chunk.id,
@@ -8750,6 +8774,7 @@ function streamText({
8750
8774
  experimental_sandbox: sandbox,
8751
8775
  output,
8752
8776
  toolApproval,
8777
+ experimental_toolCallers,
8753
8778
  experimental_toolApprovalSecret,
8754
8779
  experimental_telemetry,
8755
8780
  telemetry = experimental_telemetry,
@@ -8847,6 +8872,7 @@ function streamText({
8847
8872
  stopConditions: asArray6(stopWhen),
8848
8873
  output,
8849
8874
  toolApproval,
8875
+ experimental_toolCallers,
8850
8876
  experimental_toolApprovalSecret,
8851
8877
  providerOptions,
8852
8878
  prepareStep,
@@ -8976,6 +9002,7 @@ var DefaultStreamTextResult = class {
8976
9002
  stopConditions,
8977
9003
  output,
8978
9004
  toolApproval,
9005
+ experimental_toolCallers,
8979
9006
  experimental_toolApprovalSecret,
8980
9007
  providerOptions,
8981
9008
  prepareStep,
@@ -9006,6 +9033,10 @@ var DefaultStreamTextResult = class {
9006
9033
  this._initialResponseMessages = new DelayedPromise();
9007
9034
  this.outputSpecification = output;
9008
9035
  this.tools = tools;
9036
+ const resolvedToolCallers = resolveToolCallerConfiguration({
9037
+ tools,
9038
+ toolCallers: experimental_toolCallers
9039
+ });
9009
9040
  const telemetryDispatcher = createRestrictedTelemetryDispatcher({
9010
9041
  telemetry,
9011
9042
  includeRuntimeContext: telemetry == null ? void 0 : telemetry.includeRuntimeContext,
@@ -9619,9 +9650,16 @@ var DefaultStreamTextResult = class {
9619
9650
  tools,
9620
9651
  activeTools: (_f = prepareStepResult == null ? void 0 : prepareStepResult.activeTools) != null ? _f : activeTools
9621
9652
  });
9653
+ const {
9654
+ executionTools: stepExecutionTools,
9655
+ modelTools: stepModelTools
9656
+ } = prepareToolsForToolCallers({
9657
+ tools: stepActiveTools,
9658
+ toolCallers: resolvedToolCallers
9659
+ });
9622
9660
  const stepToolOrder = (_g = prepareStepResult == null ? void 0 : prepareStepResult.toolOrder) != null ? _g : toolOrder;
9623
9661
  const stepTools = await prepareTools({
9624
- tools: stepActiveTools,
9662
+ tools: stepModelTools,
9625
9663
  toolOrder: stepToolOrder,
9626
9664
  // active tools context is a subset of the tools context, so we can cast to the unknown type
9627
9665
  toolsContext,
@@ -9654,7 +9692,7 @@ var DefaultStreamTextResult = class {
9654
9692
  var _a25, _b2;
9655
9693
  return streamLanguageModelCall({
9656
9694
  model: (_a25 = prepareStepResult == null ? void 0 : prepareStepResult.model) != null ? _a25 : model,
9657
- tools: stepActiveTools,
9695
+ tools: stepModelTools,
9658
9696
  toolOrder: stepToolOrder,
9659
9697
  toolChoice: (_b2 = prepareStepResult == null ? void 0 : prepareStepResult.toolChoice) != null ? _b2 : toolChoice,
9660
9698
  instructions: stepInstructions,
@@ -9717,7 +9755,7 @@ var DefaultStreamTextResult = class {
9717
9755
  startFirstChunkTimeout();
9718
9756
  const streamAfterToolCallbackInvocation = invokeToolCallbacksFromStream({
9719
9757
  stream: languageModelStream,
9720
- tools,
9758
+ tools: stepExecutionTools,
9721
9759
  stepInputMessages: stepMessages,
9722
9760
  abortSignal,
9723
9761
  runtimeContext
@@ -9727,7 +9765,7 @@ var DefaultStreamTextResult = class {
9727
9765
  );
9728
9766
  const streamWithToolResults = executeToolsFromStream({
9729
9767
  stream: streamAfterToolCallbackInvocation,
9730
- tools,
9768
+ tools: stepExecutionTools,
9731
9769
  callId,
9732
9770
  messages: stepMessages,
9733
9771
  abortSignal,
@@ -9937,7 +9975,7 @@ var DefaultStreamTextResult = class {
9937
9975
  for (const toolCall of stepToolCalls) {
9938
9976
  if (toolCall.providerExecuted !== true)
9939
9977
  continue;
9940
- const tool2 = getOwn(tools, toolCall.toolName);
9978
+ const tool2 = getOwn(stepExecutionTools, toolCall.toolName);
9941
9979
  if ((tool2 == null ? void 0 : tool2.type) === "provider" && tool2.supportsDeferredResults) {
9942
9980
  const hasResultInStep = stepToolOutputs.some(
9943
9981
  (output2) => (output2.type === "tool-result" || output2.type === "tool-error") && output2.toolCallId === toolCall.toolCallId