ai 6.0.99 → 6.0.101
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 +12 -0
- package/dist/index.js +114 -99
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +114 -99
- package/dist/index.mjs.map +1 -1
- package/dist/internal/index.js +1 -1
- package/dist/internal/index.js.map +1 -1
- package/dist/internal/index.mjs +1 -1
- package/dist/internal/index.mjs.map +1 -1
- package/docs/03-agents/01-overview.mdx +5 -5
- package/docs/03-agents/02-building-agents.mdx +3 -3
- package/docs/03-agents/index.mdx +2 -2
- package/docs/03-ai-sdk-core/65-event-listeners.mdx +915 -0
- package/package.json +1 -1
- package/src/generate-text/execute-tool-call.ts +14 -19
- package/src/generate-text/generate-text.ts +43 -40
- package/src/generate-text/stream-text.ts +43 -40
- package/src/ui/process-ui-message-stream.ts +12 -1
- package/src/util/notify.ts +18 -0
package/package.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { executeTool, ModelMessage } from '@ai-sdk/provider-utils';
|
|
2
2
|
import { Tracer } from '@opentelemetry/api';
|
|
3
|
+
import { notify } from '../util/notify';
|
|
3
4
|
import { assembleOperationName } from '../telemetry/assemble-operation-name';
|
|
4
5
|
import { recordErrorOnSpan, recordSpan } from '../telemetry/record-span';
|
|
5
6
|
import { selectTelemetryAttributes } from '../telemetry/select-telemetry-attributes';
|
|
@@ -91,11 +92,7 @@ export async function executeToolCall<TOOLS extends ToolSet>({
|
|
|
91
92
|
fn: async span => {
|
|
92
93
|
let output: unknown;
|
|
93
94
|
|
|
94
|
-
|
|
95
|
-
await onToolCallStart?.(baseCallbackEvent);
|
|
96
|
-
} catch (_ignored) {
|
|
97
|
-
// Errors in callbacks should not break the generation flow.
|
|
98
|
-
}
|
|
95
|
+
await notify({ event: baseCallbackEvent, callbacks: onToolCallStart });
|
|
99
96
|
|
|
100
97
|
const startTime = now();
|
|
101
98
|
|
|
@@ -126,16 +123,15 @@ export async function executeToolCall<TOOLS extends ToolSet>({
|
|
|
126
123
|
} catch (error) {
|
|
127
124
|
const durationMs = now() - startTime;
|
|
128
125
|
|
|
129
|
-
|
|
130
|
-
|
|
126
|
+
await notify({
|
|
127
|
+
event: {
|
|
131
128
|
...baseCallbackEvent,
|
|
132
|
-
success: false,
|
|
129
|
+
success: false as const,
|
|
133
130
|
error,
|
|
134
131
|
durationMs,
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
132
|
+
},
|
|
133
|
+
callbacks: onToolCallFinish,
|
|
134
|
+
});
|
|
139
135
|
|
|
140
136
|
recordErrorOnSpan(span, error);
|
|
141
137
|
return {
|
|
@@ -153,16 +149,15 @@ export async function executeToolCall<TOOLS extends ToolSet>({
|
|
|
153
149
|
|
|
154
150
|
const durationMs = now() - startTime;
|
|
155
151
|
|
|
156
|
-
|
|
157
|
-
|
|
152
|
+
await notify({
|
|
153
|
+
event: {
|
|
158
154
|
...baseCallbackEvent,
|
|
159
|
-
success: true,
|
|
155
|
+
success: true as const,
|
|
160
156
|
output,
|
|
161
157
|
durationMs,
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}
|
|
158
|
+
},
|
|
159
|
+
callbacks: onToolCallFinish,
|
|
160
|
+
});
|
|
166
161
|
|
|
167
162
|
try {
|
|
168
163
|
span.setAttributes(
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
} from '@ai-sdk/provider-utils';
|
|
16
16
|
import { Tracer } from '@opentelemetry/api';
|
|
17
17
|
import { NoOutputGeneratedError } from '../error';
|
|
18
|
+
import { notify } from '../util/notify';
|
|
18
19
|
import { logWarnings } from '../logger/log-warnings';
|
|
19
20
|
import { resolveLanguageModel } from '../model/resolve-model';
|
|
20
21
|
import { ModelMessage } from '../prompt';
|
|
@@ -479,8 +480,8 @@ export async function generateText<
|
|
|
479
480
|
messages,
|
|
480
481
|
} as Prompt);
|
|
481
482
|
|
|
482
|
-
|
|
483
|
-
|
|
483
|
+
await notify({
|
|
484
|
+
event: {
|
|
484
485
|
model: modelInfo,
|
|
485
486
|
system,
|
|
486
487
|
prompt,
|
|
@@ -507,10 +508,9 @@ export async function generateText<
|
|
|
507
508
|
functionId: telemetry?.functionId,
|
|
508
509
|
metadata: telemetry?.metadata as Record<string, unknown> | undefined,
|
|
509
510
|
experimental_context,
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
}
|
|
511
|
+
},
|
|
512
|
+
callbacks: onStart,
|
|
513
|
+
});
|
|
514
514
|
|
|
515
515
|
const tracer = getTracer(telemetry);
|
|
516
516
|
|
|
@@ -712,8 +712,8 @@ export async function generateText<
|
|
|
712
712
|
prepareStepResult?.providerOptions,
|
|
713
713
|
);
|
|
714
714
|
|
|
715
|
-
|
|
716
|
-
|
|
715
|
+
await notify({
|
|
716
|
+
event: {
|
|
717
717
|
stepNumber: steps.length,
|
|
718
718
|
model: stepModelInfo,
|
|
719
719
|
system: stepSystem,
|
|
@@ -734,10 +734,9 @@ export async function generateText<
|
|
|
734
734
|
| Record<string, unknown>
|
|
735
735
|
| undefined,
|
|
736
736
|
experimental_context,
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
}
|
|
737
|
+
},
|
|
738
|
+
callbacks: onStepStart,
|
|
739
|
+
});
|
|
741
740
|
|
|
742
741
|
currentModelResponse = await retry(() =>
|
|
743
742
|
recordSpan({
|
|
@@ -1056,7 +1055,8 @@ export async function generateText<
|
|
|
1056
1055
|
});
|
|
1057
1056
|
|
|
1058
1057
|
steps.push(currentStepResult);
|
|
1059
|
-
|
|
1058
|
+
|
|
1059
|
+
await notify({ event: currentStepResult, callbacks: onStepFinish });
|
|
1060
1060
|
} finally {
|
|
1061
1061
|
if (stepTimeoutId != null) {
|
|
1062
1062
|
clearTimeout(stepTimeoutId);
|
|
@@ -1123,33 +1123,36 @@ export async function generateText<
|
|
|
1123
1123
|
} as LanguageModelUsage,
|
|
1124
1124
|
);
|
|
1125
1125
|
|
|
1126
|
-
await
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1126
|
+
await notify({
|
|
1127
|
+
event: {
|
|
1128
|
+
stepNumber: lastStep.stepNumber,
|
|
1129
|
+
model: lastStep.model,
|
|
1130
|
+
functionId: lastStep.functionId,
|
|
1131
|
+
metadata: lastStep.metadata,
|
|
1132
|
+
experimental_context: lastStep.experimental_context,
|
|
1133
|
+
finishReason: lastStep.finishReason,
|
|
1134
|
+
rawFinishReason: lastStep.rawFinishReason,
|
|
1135
|
+
usage: lastStep.usage,
|
|
1136
|
+
content: lastStep.content,
|
|
1137
|
+
text: lastStep.text,
|
|
1138
|
+
reasoningText: lastStep.reasoningText,
|
|
1139
|
+
reasoning: lastStep.reasoning,
|
|
1140
|
+
files: lastStep.files,
|
|
1141
|
+
sources: lastStep.sources,
|
|
1142
|
+
toolCalls: lastStep.toolCalls,
|
|
1143
|
+
staticToolCalls: lastStep.staticToolCalls,
|
|
1144
|
+
dynamicToolCalls: lastStep.dynamicToolCalls,
|
|
1145
|
+
toolResults: lastStep.toolResults,
|
|
1146
|
+
staticToolResults: lastStep.staticToolResults,
|
|
1147
|
+
dynamicToolResults: lastStep.dynamicToolResults,
|
|
1148
|
+
request: lastStep.request,
|
|
1149
|
+
response: lastStep.response,
|
|
1150
|
+
warnings: lastStep.warnings,
|
|
1151
|
+
providerMetadata: lastStep.providerMetadata,
|
|
1152
|
+
steps,
|
|
1153
|
+
totalUsage,
|
|
1154
|
+
},
|
|
1155
|
+
callbacks: onFinish,
|
|
1153
1156
|
});
|
|
1154
1157
|
|
|
1155
1158
|
// parse output only if the last step was finished with "stop":
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
import { Span } from '@opentelemetry/api';
|
|
20
20
|
import { ServerResponse } from 'node:http';
|
|
21
21
|
import { NoOutputGeneratedError } from '../error';
|
|
22
|
+
import { notify } from '../util/notify';
|
|
22
23
|
import { logWarnings } from '../logger/log-warnings';
|
|
23
24
|
import { resolveLanguageModel } from '../model/resolve-model';
|
|
24
25
|
import {
|
|
@@ -1028,7 +1029,7 @@ class DefaultStreamTextResult<TOOLS extends ToolSet, OUTPUT extends Output>
|
|
|
1028
1029
|
providerMetadata: part.providerMetadata,
|
|
1029
1030
|
});
|
|
1030
1031
|
|
|
1031
|
-
await
|
|
1032
|
+
await notify({ event: currentStepResult, callbacks: onStepFinish });
|
|
1032
1033
|
|
|
1033
1034
|
logWarnings({
|
|
1034
1035
|
warnings: recordedWarnings,
|
|
@@ -1084,33 +1085,37 @@ class DefaultStreamTextResult<TOOLS extends ToolSet, OUTPUT extends Output>
|
|
|
1084
1085
|
|
|
1085
1086
|
// call onFinish callback:
|
|
1086
1087
|
const finalStep = recordedSteps[recordedSteps.length - 1];
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1088
|
+
|
|
1089
|
+
await notify({
|
|
1090
|
+
event: {
|
|
1091
|
+
stepNumber: finalStep.stepNumber,
|
|
1092
|
+
model: finalStep.model,
|
|
1093
|
+
functionId: finalStep.functionId,
|
|
1094
|
+
metadata: finalStep.metadata,
|
|
1095
|
+
experimental_context: finalStep.experimental_context,
|
|
1096
|
+
finishReason: finalStep.finishReason,
|
|
1097
|
+
rawFinishReason: finalStep.rawFinishReason,
|
|
1098
|
+
totalUsage,
|
|
1099
|
+
usage: finalStep.usage,
|
|
1100
|
+
content: finalStep.content,
|
|
1101
|
+
text: finalStep.text,
|
|
1102
|
+
reasoningText: finalStep.reasoningText,
|
|
1103
|
+
reasoning: finalStep.reasoning,
|
|
1104
|
+
files: finalStep.files,
|
|
1105
|
+
sources: finalStep.sources,
|
|
1106
|
+
toolCalls: finalStep.toolCalls,
|
|
1107
|
+
staticToolCalls: finalStep.staticToolCalls,
|
|
1108
|
+
dynamicToolCalls: finalStep.dynamicToolCalls,
|
|
1109
|
+
toolResults: finalStep.toolResults,
|
|
1110
|
+
staticToolResults: finalStep.staticToolResults,
|
|
1111
|
+
dynamicToolResults: finalStep.dynamicToolResults,
|
|
1112
|
+
request: finalStep.request,
|
|
1113
|
+
response: finalStep.response,
|
|
1114
|
+
warnings: finalStep.warnings,
|
|
1115
|
+
providerMetadata: finalStep.providerMetadata,
|
|
1116
|
+
steps: recordedSteps,
|
|
1117
|
+
},
|
|
1118
|
+
callbacks: onFinish,
|
|
1114
1119
|
});
|
|
1115
1120
|
|
|
1116
1121
|
// Add response information to the root span:
|
|
@@ -1271,8 +1276,8 @@ class DefaultStreamTextResult<TOOLS extends ToolSet, OUTPUT extends Output>
|
|
|
1271
1276
|
messages,
|
|
1272
1277
|
} as Prompt);
|
|
1273
1278
|
|
|
1274
|
-
|
|
1275
|
-
|
|
1279
|
+
await notify({
|
|
1280
|
+
event: {
|
|
1276
1281
|
model: modelInfo,
|
|
1277
1282
|
system,
|
|
1278
1283
|
prompt,
|
|
@@ -1298,10 +1303,9 @@ class DefaultStreamTextResult<TOOLS extends ToolSet, OUTPUT extends Output>
|
|
|
1298
1303
|
include,
|
|
1299
1304
|
...callbackTelemetryProps,
|
|
1300
1305
|
experimental_context,
|
|
1301
|
-
}
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
}
|
|
1306
|
+
},
|
|
1307
|
+
callbacks: onStart,
|
|
1308
|
+
});
|
|
1305
1309
|
|
|
1306
1310
|
const initialMessages = initialPrompt.messages;
|
|
1307
1311
|
const initialResponseMessages: Array<ResponseMessage> = [];
|
|
@@ -1549,8 +1553,8 @@ class DefaultStreamTextResult<TOOLS extends ToolSet, OUTPUT extends Output>
|
|
|
1549
1553
|
prepareStepResult?.providerOptions,
|
|
1550
1554
|
);
|
|
1551
1555
|
|
|
1552
|
-
|
|
1553
|
-
|
|
1556
|
+
await notify({
|
|
1557
|
+
event: {
|
|
1554
1558
|
stepNumber: recordedSteps.length,
|
|
1555
1559
|
model: stepModelInfo,
|
|
1556
1560
|
system: stepSystem,
|
|
@@ -1568,10 +1572,9 @@ class DefaultStreamTextResult<TOOLS extends ToolSet, OUTPUT extends Output>
|
|
|
1568
1572
|
include,
|
|
1569
1573
|
...callbackTelemetryProps,
|
|
1570
1574
|
experimental_context,
|
|
1571
|
-
}
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
}
|
|
1575
|
+
},
|
|
1576
|
+
callbacks: onStepStart,
|
|
1577
|
+
});
|
|
1575
1578
|
|
|
1576
1579
|
const {
|
|
1577
1580
|
result: { stream, response, request },
|
|
@@ -558,7 +558,18 @@ export function processUIMessageStream<UI_MESSAGE extends UIMessage>({
|
|
|
558
558
|
}
|
|
559
559
|
|
|
560
560
|
case 'tool-input-error': {
|
|
561
|
-
|
|
561
|
+
// When a part already exists for this toolCallId (e.g. from
|
|
562
|
+
// tool-input-start), honour its type so we update in place
|
|
563
|
+
// instead of creating a duplicate with a mismatched type.
|
|
564
|
+
const existingPart = state.message.parts
|
|
565
|
+
.filter(isToolUIPart)
|
|
566
|
+
.find(p => p.toolCallId === chunk.toolCallId);
|
|
567
|
+
const isDynamic =
|
|
568
|
+
existingPart != null
|
|
569
|
+
? existingPart.type === 'dynamic-tool'
|
|
570
|
+
: !!chunk.dynamic;
|
|
571
|
+
|
|
572
|
+
if (isDynamic) {
|
|
562
573
|
updateDynamicToolPart({
|
|
563
574
|
toolCallId: chunk.toolCallId,
|
|
564
575
|
toolName: chunk.toolName,
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { asArray } from './as-array';
|
|
2
|
+
|
|
3
|
+
export type Listener<EVENT> = (event: EVENT) => PromiseLike<void> | void;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Notifies all provided callbacks with the given event.
|
|
7
|
+
* Errors in callbacks do not break the generation flow.
|
|
8
|
+
*/
|
|
9
|
+
export async function notify<EVENT>(options: {
|
|
10
|
+
event: EVENT;
|
|
11
|
+
callbacks?: Listener<EVENT> | Array<Listener<EVENT>>;
|
|
12
|
+
}): Promise<void> {
|
|
13
|
+
for (const callback of asArray(options.callbacks)) {
|
|
14
|
+
try {
|
|
15
|
+
await callback(options.event);
|
|
16
|
+
} catch (_ignored) {}
|
|
17
|
+
}
|
|
18
|
+
}
|