ai 6.0.91 → 6.0.93

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai",
3
- "version": "6.0.91",
3
+ "version": "6.0.93",
4
4
  "description": "AI SDK by Vercel - The AI Toolkit for TypeScript and JavaScript",
5
5
  "license": "Apache-2.0",
6
6
  "sideEffects": false,
@@ -45,7 +45,7 @@
45
45
  },
46
46
  "dependencies": {
47
47
  "@opentelemetry/api": "1.9.0",
48
- "@ai-sdk/gateway": "3.0.50",
48
+ "@ai-sdk/gateway": "3.0.51",
49
49
  "@ai-sdk/provider": "3.0.8",
50
50
  "@ai-sdk/provider-utils": "4.0.15"
51
51
  },
@@ -4,12 +4,28 @@ import { assembleOperationName } from '../telemetry/assemble-operation-name';
4
4
  import { recordErrorOnSpan, recordSpan } from '../telemetry/record-span';
5
5
  import { selectTelemetryAttributes } from '../telemetry/select-telemetry-attributes';
6
6
  import { TelemetrySettings } from '../telemetry/telemetry-settings';
7
+ import { now } from '../util/now';
8
+ import {
9
+ GenerateTextOnToolCallFinishCallback,
10
+ GenerateTextOnToolCallStartCallback,
11
+ } from './generate-text';
7
12
  import { TypedToolCall } from './tool-call';
8
13
  import { ToolOutput } from './tool-output';
9
14
  import { ToolSet } from './tool-set';
10
15
  import { TypedToolResult } from './tool-result';
11
16
  import { TypedToolError } from './tool-error';
12
17
 
18
+ /**
19
+ * Executes a single tool call and manages its lifecycle callbacks.
20
+ *
21
+ * This function handles the complete tool execution flow:
22
+ * 1. Invokes `onToolCallStart` callback before execution
23
+ * 2. Executes the tool's `execute` function with proper context
24
+ * 3. Handles streaming outputs via `onPreliminaryToolResult`
25
+ * 4. Invokes `onToolCallFinish` callback with success or error result
26
+ *
27
+ * @returns The tool output (result or error), or undefined if the tool has no execute function.
28
+ */
13
29
  export async function executeToolCall<TOOLS extends ToolSet>({
14
30
  toolCall,
15
31
  tools,
@@ -18,7 +34,11 @@ export async function executeToolCall<TOOLS extends ToolSet>({
18
34
  messages,
19
35
  abortSignal,
20
36
  experimental_context,
37
+ stepNumber,
38
+ model,
21
39
  onPreliminaryToolResult,
40
+ onToolCallStart,
41
+ onToolCallFinish,
22
42
  }: {
23
43
  toolCall: TypedToolCall<TOOLS>;
24
44
  tools: TOOLS | undefined;
@@ -27,7 +47,11 @@ export async function executeToolCall<TOOLS extends ToolSet>({
27
47
  messages: ModelMessage[];
28
48
  abortSignal: AbortSignal | undefined;
29
49
  experimental_context: unknown;
50
+ stepNumber?: number;
51
+ model?: { provider: string; modelId: string };
30
52
  onPreliminaryToolResult?: (result: TypedToolResult<TOOLS>) => void;
53
+ onToolCallStart?: GenerateTextOnToolCallStartCallback<TOOLS>;
54
+ onToolCallFinish?: GenerateTextOnToolCallFinishCallback<TOOLS>;
31
55
  }): Promise<ToolOutput<TOOLS> | undefined> {
32
56
  const { toolName, toolCallId, input } = toolCall;
33
57
  const tool = tools?.[toolName];
@@ -56,6 +80,23 @@ export async function executeToolCall<TOOLS extends ToolSet>({
56
80
  fn: async span => {
57
81
  let output: unknown;
58
82
 
83
+ try {
84
+ await onToolCallStart?.({
85
+ stepNumber,
86
+ model,
87
+ toolCall,
88
+ messages,
89
+ abortSignal,
90
+ functionId: telemetry?.functionId,
91
+ metadata: telemetry?.metadata as Record<string, unknown> | undefined,
92
+ experimental_context,
93
+ });
94
+ } catch (_ignored) {
95
+ // Errors in callbacks should not break the generation flow.
96
+ }
97
+
98
+ const startTime = now();
99
+
59
100
  try {
60
101
  const stream = executeTool({
61
102
  execute: tool.execute!.bind(tool),
@@ -81,6 +122,28 @@ export async function executeToolCall<TOOLS extends ToolSet>({
81
122
  }
82
123
  }
83
124
  } catch (error) {
125
+ const durationMs = now() - startTime;
126
+
127
+ try {
128
+ await onToolCallFinish?.({
129
+ stepNumber,
130
+ model,
131
+ toolCall,
132
+ messages,
133
+ abortSignal,
134
+ success: false,
135
+ error,
136
+ durationMs,
137
+ functionId: telemetry?.functionId,
138
+ metadata: telemetry?.metadata as
139
+ | Record<string, unknown>
140
+ | undefined,
141
+ experimental_context,
142
+ });
143
+ } catch (_ignored) {
144
+ // Errors in callbacks should not break the generation flow.
145
+ }
146
+
84
147
  recordErrorOnSpan(span, error);
85
148
  return {
86
149
  type: 'tool-error',
@@ -95,6 +158,26 @@ export async function executeToolCall<TOOLS extends ToolSet>({
95
158
  } as TypedToolError<TOOLS>;
96
159
  }
97
160
 
161
+ const durationMs = now() - startTime;
162
+
163
+ try {
164
+ await onToolCallFinish?.({
165
+ stepNumber,
166
+ model,
167
+ toolCall,
168
+ messages,
169
+ abortSignal,
170
+ success: true,
171
+ output,
172
+ durationMs,
173
+ functionId: telemetry?.functionId,
174
+ metadata: telemetry?.metadata as Record<string, unknown> | undefined,
175
+ experimental_context,
176
+ });
177
+ } catch (_ignored) {
178
+ // Errors in callbacks should not break the generation flow.
179
+ }
180
+
98
181
  try {
99
182
  span.setAttributes(
100
183
  await selectTelemetryAttributes({