ai 3.2.18 → 3.2.20
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.d.mts +84 -30
- package/dist/index.d.ts +84 -30
- package/dist/index.js +480 -150
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +480 -150
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -8
- package/rsc/dist/index.d.ts +19 -19
- package/rsc/dist/rsc-server.d.mts +19 -19
- package/rsc/dist/rsc-server.mjs +10 -10
- package/rsc/dist/rsc-server.mjs.map +1 -1
package/dist/index.mjs
CHANGED
@@ -83,6 +83,7 @@ async function embed({
|
|
83
83
|
abortSignal,
|
84
84
|
headers
|
85
85
|
}) {
|
86
|
+
var _a;
|
86
87
|
const retry = retryWithExponentialBackoff({ maxRetries });
|
87
88
|
const modelResponse = await retry(
|
88
89
|
() => model.doEmbed({ values: [value], abortSignal, headers })
|
@@ -90,6 +91,7 @@ async function embed({
|
|
90
91
|
return new EmbedResult({
|
91
92
|
value,
|
92
93
|
embedding: modelResponse.embeddings[0],
|
94
|
+
usage: (_a = modelResponse.usage) != null ? _a : { tokens: NaN },
|
93
95
|
rawResponse: modelResponse.rawResponse
|
94
96
|
});
|
95
97
|
}
|
@@ -97,6 +99,7 @@ var EmbedResult = class {
|
|
97
99
|
constructor(options) {
|
98
100
|
this.value = options.value;
|
99
101
|
this.embedding = options.embedding;
|
102
|
+
this.usage = options.usage;
|
100
103
|
this.rawResponse = options.rawResponse;
|
101
104
|
}
|
102
105
|
};
|
@@ -121,6 +124,7 @@ async function embedMany({
|
|
121
124
|
abortSignal,
|
122
125
|
headers
|
123
126
|
}) {
|
127
|
+
var _a, _b, _c;
|
124
128
|
const retry = retryWithExponentialBackoff({ maxRetries });
|
125
129
|
const maxEmbeddingsPerCall = model.maxEmbeddingsPerCall;
|
126
130
|
if (maxEmbeddingsPerCall == null) {
|
@@ -129,23 +133,27 @@ async function embedMany({
|
|
129
133
|
);
|
130
134
|
return new EmbedManyResult({
|
131
135
|
values,
|
132
|
-
embeddings: modelResponse.embeddings
|
136
|
+
embeddings: modelResponse.embeddings,
|
137
|
+
usage: (_a = modelResponse.usage) != null ? _a : { tokens: NaN }
|
133
138
|
});
|
134
139
|
}
|
135
140
|
const valueChunks = splitArray(values, maxEmbeddingsPerCall);
|
136
141
|
const embeddings = [];
|
142
|
+
let tokens = 0;
|
137
143
|
for (const chunk of valueChunks) {
|
138
144
|
const modelResponse = await retry(
|
139
145
|
() => model.doEmbed({ values: chunk, abortSignal, headers })
|
140
146
|
);
|
141
147
|
embeddings.push(...modelResponse.embeddings);
|
148
|
+
tokens += (_c = (_b = modelResponse.usage) == null ? void 0 : _b.tokens) != null ? _c : NaN;
|
142
149
|
}
|
143
|
-
return new EmbedManyResult({ values, embeddings });
|
150
|
+
return new EmbedManyResult({ values, embeddings, usage: { tokens } });
|
144
151
|
}
|
145
152
|
var EmbedManyResult = class {
|
146
153
|
constructor(options) {
|
147
154
|
this.values = options.values;
|
148
155
|
this.embeddings = options.embeddings;
|
156
|
+
this.usage = options.usage;
|
149
157
|
}
|
150
158
|
};
|
151
159
|
|
@@ -153,15 +161,6 @@ var EmbedManyResult = class {
|
|
153
161
|
import { NoObjectGeneratedError } from "@ai-sdk/provider";
|
154
162
|
import { safeParseJSON } from "@ai-sdk/provider-utils";
|
155
163
|
|
156
|
-
// core/generate-text/token-usage.ts
|
157
|
-
function calculateTokenUsage(usage) {
|
158
|
-
return {
|
159
|
-
promptTokens: usage.promptTokens,
|
160
|
-
completionTokens: usage.completionTokens,
|
161
|
-
totalTokens: usage.promptTokens + usage.completionTokens
|
162
|
-
};
|
163
|
-
}
|
164
|
-
|
165
164
|
// core/util/detect-image-mimetype.ts
|
166
165
|
var mimeTypeSignatures = [
|
167
166
|
{ mimeType: "image/gif", bytes: [71, 73, 70] },
|
@@ -512,12 +511,31 @@ function prepareCallSettings({
|
|
512
511
|
};
|
513
512
|
}
|
514
513
|
|
514
|
+
// core/types/token-usage.ts
|
515
|
+
function calculateCompletionTokenUsage(usage) {
|
516
|
+
return {
|
517
|
+
promptTokens: usage.promptTokens,
|
518
|
+
completionTokens: usage.completionTokens,
|
519
|
+
totalTokens: usage.promptTokens + usage.completionTokens
|
520
|
+
};
|
521
|
+
}
|
522
|
+
|
515
523
|
// core/util/convert-zod-to-json-schema.ts
|
516
524
|
import zodToJsonSchema from "zod-to-json-schema";
|
517
525
|
function convertZodToJSONSchema(zodSchema) {
|
518
526
|
return zodToJsonSchema(zodSchema);
|
519
527
|
}
|
520
528
|
|
529
|
+
// core/util/prepare-response-headers.ts
|
530
|
+
function prepareResponseHeaders(init, { contentType }) {
|
531
|
+
var _a;
|
532
|
+
const headers = new Headers((_a = init == null ? void 0 : init.headers) != null ? _a : {});
|
533
|
+
if (!headers.has("Content-Type")) {
|
534
|
+
headers.set("Content-Type", contentType);
|
535
|
+
}
|
536
|
+
return headers;
|
537
|
+
}
|
538
|
+
|
521
539
|
// core/generate-object/inject-json-schema-into-system.ts
|
522
540
|
var DEFAULT_SCHEMA_PREFIX = "JSON schema:";
|
523
541
|
var DEFAULT_SCHEMA_SUFFIX = "You MUST answer with a JSON object that matches the JSON schema above.";
|
@@ -537,16 +555,6 @@ function injectJsonSchemaIntoSystem({
|
|
537
555
|
].filter((line) => line != null).join("\n");
|
538
556
|
}
|
539
557
|
|
540
|
-
// core/util/prepare-response-headers.ts
|
541
|
-
function prepareResponseHeaders(init, { contentType }) {
|
542
|
-
var _a;
|
543
|
-
const headers = new Headers((_a = init == null ? void 0 : init.headers) != null ? _a : {});
|
544
|
-
if (!headers.has("Content-Type")) {
|
545
|
-
headers.set("Content-Type", contentType);
|
546
|
-
}
|
547
|
-
return headers;
|
548
|
-
}
|
549
|
-
|
550
558
|
// core/generate-object/generate-object.ts
|
551
559
|
async function generateObject({
|
552
560
|
model,
|
@@ -676,7 +684,7 @@ async function generateObject({
|
|
676
684
|
return new GenerateObjectResult({
|
677
685
|
object: parseResult.value,
|
678
686
|
finishReason,
|
679
|
-
usage:
|
687
|
+
usage: calculateCompletionTokenUsage(usage),
|
680
688
|
warnings,
|
681
689
|
rawResponse,
|
682
690
|
logprobs
|
@@ -922,7 +930,7 @@ var StreamObjectResult = class {
|
|
922
930
|
textDelta: delta
|
923
931
|
});
|
924
932
|
}
|
925
|
-
usage =
|
933
|
+
usage = calculateCompletionTokenUsage(chunk.usage);
|
926
934
|
controller.enqueue({ ...chunk, usage });
|
927
935
|
resolveUsage(usage);
|
928
936
|
const validationResult = safeValidateTypes({
|
@@ -1105,6 +1113,157 @@ function prepareToolsAndToolChoice({
|
|
1105
1113
|
};
|
1106
1114
|
}
|
1107
1115
|
|
1116
|
+
// core/telemetry/get-base-telemetry-attributes.ts
|
1117
|
+
function getBaseTelemetryAttributes({
|
1118
|
+
operationName,
|
1119
|
+
model,
|
1120
|
+
settings,
|
1121
|
+
telemetry,
|
1122
|
+
headers
|
1123
|
+
}) {
|
1124
|
+
var _a;
|
1125
|
+
return {
|
1126
|
+
"ai.model.provider": model.provider,
|
1127
|
+
"ai.model.id": model.modelId,
|
1128
|
+
// settings:
|
1129
|
+
...Object.entries(settings).reduce((attributes, [key, value]) => {
|
1130
|
+
attributes[`ai.settings.${key}`] = value;
|
1131
|
+
return attributes;
|
1132
|
+
}, {}),
|
1133
|
+
// special telemetry information
|
1134
|
+
"operation.name": operationName,
|
1135
|
+
"resource.name": telemetry == null ? void 0 : telemetry.functionId,
|
1136
|
+
"ai.telemetry.functionId": telemetry == null ? void 0 : telemetry.functionId,
|
1137
|
+
// add metadata as attributes:
|
1138
|
+
...Object.entries((_a = telemetry == null ? void 0 : telemetry.metadata) != null ? _a : {}).reduce(
|
1139
|
+
(attributes, [key, value]) => {
|
1140
|
+
attributes[`ai.telemetry.metadata.${key}`] = value;
|
1141
|
+
return attributes;
|
1142
|
+
},
|
1143
|
+
{}
|
1144
|
+
),
|
1145
|
+
// request headers
|
1146
|
+
...Object.entries(headers != null ? headers : {}).reduce((attributes, [key, value]) => {
|
1147
|
+
if (value !== void 0) {
|
1148
|
+
attributes[`ai.request.headers.${key}`] = value;
|
1149
|
+
}
|
1150
|
+
return attributes;
|
1151
|
+
}, {})
|
1152
|
+
};
|
1153
|
+
}
|
1154
|
+
|
1155
|
+
// core/telemetry/get-tracer.ts
|
1156
|
+
import { trace } from "@opentelemetry/api";
|
1157
|
+
|
1158
|
+
// core/telemetry/noop-tracer.ts
|
1159
|
+
var noopTracer = {
|
1160
|
+
startSpan() {
|
1161
|
+
return noopSpan;
|
1162
|
+
},
|
1163
|
+
startActiveSpan(name, arg1, arg2, arg3) {
|
1164
|
+
if (typeof arg1 === "function") {
|
1165
|
+
return arg1(noopSpan);
|
1166
|
+
}
|
1167
|
+
if (typeof arg2 === "function") {
|
1168
|
+
return arg2(noopSpan);
|
1169
|
+
}
|
1170
|
+
if (typeof arg3 === "function") {
|
1171
|
+
return arg3(noopSpan);
|
1172
|
+
}
|
1173
|
+
}
|
1174
|
+
};
|
1175
|
+
var noopSpan = {
|
1176
|
+
spanContext() {
|
1177
|
+
return noopSpanContext;
|
1178
|
+
},
|
1179
|
+
setAttribute() {
|
1180
|
+
return this;
|
1181
|
+
},
|
1182
|
+
setAttributes() {
|
1183
|
+
return this;
|
1184
|
+
},
|
1185
|
+
addEvent() {
|
1186
|
+
return this;
|
1187
|
+
},
|
1188
|
+
addLink() {
|
1189
|
+
return this;
|
1190
|
+
},
|
1191
|
+
addLinks() {
|
1192
|
+
return this;
|
1193
|
+
},
|
1194
|
+
setStatus() {
|
1195
|
+
return this;
|
1196
|
+
},
|
1197
|
+
updateName() {
|
1198
|
+
return this;
|
1199
|
+
},
|
1200
|
+
end() {
|
1201
|
+
return this;
|
1202
|
+
},
|
1203
|
+
isRecording() {
|
1204
|
+
return false;
|
1205
|
+
},
|
1206
|
+
recordException() {
|
1207
|
+
return this;
|
1208
|
+
}
|
1209
|
+
};
|
1210
|
+
var noopSpanContext = {
|
1211
|
+
traceId: "",
|
1212
|
+
spanId: "",
|
1213
|
+
traceFlags: 0
|
1214
|
+
};
|
1215
|
+
|
1216
|
+
// core/telemetry/get-tracer.ts
|
1217
|
+
var testTracer = void 0;
|
1218
|
+
function getTracer({ isEnabled }) {
|
1219
|
+
if (!isEnabled) {
|
1220
|
+
return noopTracer;
|
1221
|
+
}
|
1222
|
+
if (testTracer) {
|
1223
|
+
return testTracer;
|
1224
|
+
}
|
1225
|
+
return trace.getTracer("ai");
|
1226
|
+
}
|
1227
|
+
|
1228
|
+
// core/telemetry/record-span.ts
|
1229
|
+
import { SpanStatusCode } from "@opentelemetry/api";
|
1230
|
+
function recordSpan({
|
1231
|
+
name,
|
1232
|
+
tracer,
|
1233
|
+
attributes,
|
1234
|
+
fn,
|
1235
|
+
endWhenDone = true
|
1236
|
+
}) {
|
1237
|
+
return tracer.startActiveSpan(name, { attributes }, async (span) => {
|
1238
|
+
try {
|
1239
|
+
const result = await fn(span);
|
1240
|
+
if (endWhenDone) {
|
1241
|
+
span.end();
|
1242
|
+
}
|
1243
|
+
return result;
|
1244
|
+
} catch (error) {
|
1245
|
+
try {
|
1246
|
+
if (error instanceof Error) {
|
1247
|
+
span.recordException({
|
1248
|
+
name: error.name,
|
1249
|
+
message: error.message,
|
1250
|
+
stack: error.stack
|
1251
|
+
});
|
1252
|
+
span.setStatus({
|
1253
|
+
code: SpanStatusCode.ERROR,
|
1254
|
+
message: error.message
|
1255
|
+
});
|
1256
|
+
} else {
|
1257
|
+
span.setStatus({ code: SpanStatusCode.ERROR });
|
1258
|
+
}
|
1259
|
+
} finally {
|
1260
|
+
span.end();
|
1261
|
+
}
|
1262
|
+
throw error;
|
1263
|
+
}
|
1264
|
+
});
|
1265
|
+
}
|
1266
|
+
|
1108
1267
|
// core/generate-text/tool-call.ts
|
1109
1268
|
import {
|
1110
1269
|
InvalidToolArgumentsError,
|
@@ -1158,71 +1317,128 @@ async function generateText({
|
|
1158
1317
|
headers,
|
1159
1318
|
maxAutomaticRoundtrips = 0,
|
1160
1319
|
maxToolRoundtrips = maxAutomaticRoundtrips,
|
1320
|
+
experimental_telemetry: telemetry,
|
1161
1321
|
...settings
|
1162
1322
|
}) {
|
1163
|
-
var _a
|
1164
|
-
const
|
1165
|
-
|
1166
|
-
|
1167
|
-
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
const
|
1172
|
-
|
1173
|
-
|
1174
|
-
|
1175
|
-
|
1176
|
-
|
1177
|
-
|
1178
|
-
|
1179
|
-
|
1180
|
-
|
1181
|
-
|
1182
|
-
|
1183
|
-
|
1184
|
-
|
1185
|
-
|
1186
|
-
|
1323
|
+
var _a;
|
1324
|
+
const baseTelemetryAttributes = getBaseTelemetryAttributes({
|
1325
|
+
operationName: "ai.generateText",
|
1326
|
+
model,
|
1327
|
+
telemetry,
|
1328
|
+
headers,
|
1329
|
+
settings: { ...settings, maxRetries }
|
1330
|
+
});
|
1331
|
+
const tracer = getTracer({ isEnabled: (_a = telemetry == null ? void 0 : telemetry.isEnabled) != null ? _a : false });
|
1332
|
+
return recordSpan({
|
1333
|
+
name: "ai.generateText",
|
1334
|
+
attributes: {
|
1335
|
+
...baseTelemetryAttributes,
|
1336
|
+
// specific settings that only make sense on the outer level:
|
1337
|
+
"ai.prompt": JSON.stringify({ system, prompt, messages }),
|
1338
|
+
"ai.settings.maxToolRoundtrips": maxToolRoundtrips
|
1339
|
+
},
|
1340
|
+
tracer,
|
1341
|
+
fn: async (span) => {
|
1342
|
+
var _a2, _b, _c;
|
1343
|
+
const retry = retryWithExponentialBackoff({ maxRetries });
|
1344
|
+
const validatedPrompt = getValidatedPrompt({
|
1345
|
+
system,
|
1346
|
+
prompt,
|
1347
|
+
messages
|
1187
1348
|
});
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1194
|
-
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
1198
|
-
|
1199
|
-
|
1200
|
-
|
1201
|
-
|
1202
|
-
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1349
|
+
const mode = {
|
1350
|
+
type: "regular",
|
1351
|
+
...prepareToolsAndToolChoice({ tools, toolChoice })
|
1352
|
+
};
|
1353
|
+
const callSettings = prepareCallSettings(settings);
|
1354
|
+
const promptMessages = convertToLanguageModelPrompt(validatedPrompt);
|
1355
|
+
let currentModelResponse;
|
1356
|
+
let currentToolCalls = [];
|
1357
|
+
let currentToolResults = [];
|
1358
|
+
let roundtrips = 0;
|
1359
|
+
const responseMessages = [];
|
1360
|
+
do {
|
1361
|
+
const currentInputFormat = roundtrips === 0 ? validatedPrompt.type : "messages";
|
1362
|
+
currentModelResponse = await retry(
|
1363
|
+
() => recordSpan({
|
1364
|
+
name: "ai.generateText.doGenerate",
|
1365
|
+
attributes: {
|
1366
|
+
...baseTelemetryAttributes,
|
1367
|
+
"ai.prompt.format": currentInputFormat,
|
1368
|
+
"ai.prompt.messages": JSON.stringify(promptMessages)
|
1369
|
+
},
|
1370
|
+
tracer,
|
1371
|
+
fn: async (span2) => {
|
1372
|
+
const result = await model.doGenerate({
|
1373
|
+
mode,
|
1374
|
+
...callSettings,
|
1375
|
+
inputFormat: currentInputFormat,
|
1376
|
+
prompt: promptMessages,
|
1377
|
+
abortSignal,
|
1378
|
+
headers
|
1379
|
+
});
|
1380
|
+
span2.setAttributes({
|
1381
|
+
"ai.finishReason": result.finishReason,
|
1382
|
+
"ai.usage.promptTokens": result.usage.promptTokens,
|
1383
|
+
"ai.usage.completionTokens": result.usage.completionTokens,
|
1384
|
+
"ai.result.text": result.text,
|
1385
|
+
"ai.result.toolCalls": JSON.stringify(result.toolCalls)
|
1386
|
+
});
|
1387
|
+
return result;
|
1388
|
+
}
|
1389
|
+
})
|
1390
|
+
);
|
1391
|
+
currentToolCalls = ((_a2 = currentModelResponse.toolCalls) != null ? _a2 : []).map(
|
1392
|
+
(modelToolCall) => parseToolCall({ toolCall: modelToolCall, tools })
|
1393
|
+
);
|
1394
|
+
currentToolResults = tools == null ? [] : await executeTools({
|
1395
|
+
toolCalls: currentToolCalls,
|
1396
|
+
tools,
|
1397
|
+
tracer
|
1398
|
+
});
|
1399
|
+
const newResponseMessages = toResponseMessages({
|
1400
|
+
text: (_b = currentModelResponse.text) != null ? _b : "",
|
1401
|
+
toolCalls: currentToolCalls,
|
1402
|
+
toolResults: currentToolResults
|
1403
|
+
});
|
1404
|
+
responseMessages.push(...newResponseMessages);
|
1405
|
+
promptMessages.push(
|
1406
|
+
...newResponseMessages.map(convertToLanguageModelMessage)
|
1407
|
+
);
|
1408
|
+
} while (
|
1409
|
+
// there are tool calls:
|
1410
|
+
currentToolCalls.length > 0 && // all current tool calls have results:
|
1411
|
+
currentToolResults.length === currentToolCalls.length && // the number of roundtrips is less than the maximum:
|
1412
|
+
roundtrips++ < maxToolRoundtrips
|
1413
|
+
);
|
1414
|
+
span.setAttributes({
|
1415
|
+
"ai.finishReason": currentModelResponse.finishReason,
|
1416
|
+
"ai.usage.promptTokens": currentModelResponse.usage.promptTokens,
|
1417
|
+
"ai.usage.completionTokens": currentModelResponse.usage.completionTokens,
|
1418
|
+
"ai.result.text": currentModelResponse.text,
|
1419
|
+
"ai.result.toolCalls": JSON.stringify(currentModelResponse.toolCalls)
|
1420
|
+
});
|
1421
|
+
return new GenerateTextResult({
|
1422
|
+
// Always return a string so that the caller doesn't have to check for undefined.
|
1423
|
+
// If they need to check if the model did not return any text,
|
1424
|
+
// they can check the length of the string:
|
1425
|
+
text: (_c = currentModelResponse.text) != null ? _c : "",
|
1426
|
+
toolCalls: currentToolCalls,
|
1427
|
+
toolResults: currentToolResults,
|
1428
|
+
finishReason: currentModelResponse.finishReason,
|
1429
|
+
usage: calculateCompletionTokenUsage(currentModelResponse.usage),
|
1430
|
+
warnings: currentModelResponse.warnings,
|
1431
|
+
rawResponse: currentModelResponse.rawResponse,
|
1432
|
+
logprobs: currentModelResponse.logprobs,
|
1433
|
+
responseMessages
|
1434
|
+
});
|
1435
|
+
}
|
1221
1436
|
});
|
1222
1437
|
}
|
1223
1438
|
async function executeTools({
|
1224
1439
|
toolCalls,
|
1225
|
-
tools
|
1440
|
+
tools,
|
1441
|
+
tracer
|
1226
1442
|
}) {
|
1227
1443
|
const toolResults = await Promise.all(
|
1228
1444
|
toolCalls.map(async (toolCall) => {
|
@@ -1230,7 +1446,25 @@ async function executeTools({
|
|
1230
1446
|
if ((tool2 == null ? void 0 : tool2.execute) == null) {
|
1231
1447
|
return void 0;
|
1232
1448
|
}
|
1233
|
-
const result = await
|
1449
|
+
const result = await recordSpan({
|
1450
|
+
name: "ai.toolCall",
|
1451
|
+
attributes: {
|
1452
|
+
"ai.toolCall.name": toolCall.toolName,
|
1453
|
+
"ai.toolCall.id": toolCall.toolCallId,
|
1454
|
+
"ai.toolCall.args": JSON.stringify(toolCall.args)
|
1455
|
+
},
|
1456
|
+
tracer,
|
1457
|
+
fn: async (span) => {
|
1458
|
+
const result2 = await tool2.execute(toolCall.args);
|
1459
|
+
try {
|
1460
|
+
span.setAttributes({
|
1461
|
+
"ai.toolCall.result": JSON.stringify(result2)
|
1462
|
+
});
|
1463
|
+
} catch (ignored) {
|
1464
|
+
}
|
1465
|
+
return result2;
|
1466
|
+
}
|
1467
|
+
});
|
1234
1468
|
return {
|
1235
1469
|
toolCallId: toolCall.toolCallId,
|
1236
1470
|
toolName: toolCall.toolName,
|
@@ -1286,7 +1520,8 @@ import { NoSuchToolError as NoSuchToolError2 } from "@ai-sdk/provider";
|
|
1286
1520
|
import { generateId } from "@ai-sdk/ui-utils";
|
1287
1521
|
function runToolsTransformation({
|
1288
1522
|
tools,
|
1289
|
-
generatorStream
|
1523
|
+
generatorStream,
|
1524
|
+
tracer
|
1290
1525
|
}) {
|
1291
1526
|
let canClose = false;
|
1292
1527
|
const outstandingToolCalls = /* @__PURE__ */ new Set();
|
@@ -1334,29 +1569,44 @@ function runToolsTransformation({
|
|
1334
1569
|
if (tool2.execute != null) {
|
1335
1570
|
const toolExecutionId = generateId();
|
1336
1571
|
outstandingToolCalls.add(toolExecutionId);
|
1337
|
-
|
1338
|
-
|
1339
|
-
|
1340
|
-
|
1341
|
-
|
1342
|
-
|
1343
|
-
});
|
1344
|
-
outstandingToolCalls.delete(toolExecutionId);
|
1345
|
-
if (canClose && outstandingToolCalls.size === 0) {
|
1346
|
-
toolResultsStreamController.close();
|
1347
|
-
}
|
1572
|
+
recordSpan({
|
1573
|
+
name: "ai.toolCall",
|
1574
|
+
attributes: {
|
1575
|
+
"ai.toolCall.name": toolCall.toolName,
|
1576
|
+
"ai.toolCall.id": toolCall.toolCallId,
|
1577
|
+
"ai.toolCall.args": JSON.stringify(toolCall.args)
|
1348
1578
|
},
|
1349
|
-
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1353
|
-
|
1354
|
-
|
1355
|
-
|
1356
|
-
|
1579
|
+
tracer,
|
1580
|
+
fn: async (span) => tool2.execute(toolCall.args).then(
|
1581
|
+
(result) => {
|
1582
|
+
toolResultsStreamController.enqueue({
|
1583
|
+
...toolCall,
|
1584
|
+
type: "tool-result",
|
1585
|
+
result
|
1586
|
+
});
|
1587
|
+
outstandingToolCalls.delete(toolExecutionId);
|
1588
|
+
if (canClose && outstandingToolCalls.size === 0) {
|
1589
|
+
toolResultsStreamController.close();
|
1590
|
+
}
|
1591
|
+
try {
|
1592
|
+
span.setAttributes({
|
1593
|
+
"ai.toolCall.result": JSON.stringify(result)
|
1594
|
+
});
|
1595
|
+
} catch (ignored) {
|
1596
|
+
}
|
1597
|
+
},
|
1598
|
+
(error) => {
|
1599
|
+
toolResultsStreamController.enqueue({
|
1600
|
+
type: "error",
|
1601
|
+
error
|
1602
|
+
});
|
1603
|
+
outstandingToolCalls.delete(toolExecutionId);
|
1604
|
+
if (canClose && outstandingToolCalls.size === 0) {
|
1605
|
+
toolResultsStreamController.close();
|
1606
|
+
}
|
1357
1607
|
}
|
1358
|
-
|
1359
|
-
);
|
1608
|
+
)
|
1609
|
+
});
|
1360
1610
|
}
|
1361
1611
|
} catch (error) {
|
1362
1612
|
toolResultsStreamController.enqueue({
|
@@ -1371,7 +1621,7 @@ function runToolsTransformation({
|
|
1371
1621
|
type: "finish",
|
1372
1622
|
finishReason: chunk.finishReason,
|
1373
1623
|
logprobs: chunk.logprobs,
|
1374
|
-
usage:
|
1624
|
+
usage: calculateCompletionTokenUsage(chunk.usage)
|
1375
1625
|
});
|
1376
1626
|
break;
|
1377
1627
|
}
|
@@ -1429,32 +1679,76 @@ async function streamText({
|
|
1429
1679
|
maxRetries,
|
1430
1680
|
abortSignal,
|
1431
1681
|
headers,
|
1682
|
+
experimental_telemetry: telemetry,
|
1432
1683
|
onFinish,
|
1433
1684
|
...settings
|
1434
1685
|
}) {
|
1435
|
-
|
1436
|
-
const
|
1437
|
-
|
1438
|
-
|
1439
|
-
|
1440
|
-
|
1441
|
-
|
1442
|
-
|
1443
|
-
|
1444
|
-
|
1445
|
-
|
1446
|
-
|
1447
|
-
|
1448
|
-
|
1449
|
-
|
1450
|
-
|
1451
|
-
|
1452
|
-
|
1453
|
-
|
1454
|
-
|
1455
|
-
|
1456
|
-
|
1457
|
-
|
1686
|
+
var _a;
|
1687
|
+
const baseTelemetryAttributes = getBaseTelemetryAttributes({
|
1688
|
+
operationName: "ai.streamText",
|
1689
|
+
model,
|
1690
|
+
telemetry,
|
1691
|
+
headers,
|
1692
|
+
settings: { ...settings, maxRetries }
|
1693
|
+
});
|
1694
|
+
const tracer = getTracer({ isEnabled: (_a = telemetry == null ? void 0 : telemetry.isEnabled) != null ? _a : false });
|
1695
|
+
return recordSpan({
|
1696
|
+
name: "ai.streamText",
|
1697
|
+
attributes: {
|
1698
|
+
...baseTelemetryAttributes,
|
1699
|
+
// specific settings that only make sense on the outer level:
|
1700
|
+
"ai.prompt": JSON.stringify({ system, prompt, messages })
|
1701
|
+
},
|
1702
|
+
tracer,
|
1703
|
+
endWhenDone: false,
|
1704
|
+
fn: async (rootSpan) => {
|
1705
|
+
const retry = retryWithExponentialBackoff({ maxRetries });
|
1706
|
+
const validatedPrompt = getValidatedPrompt({ system, prompt, messages });
|
1707
|
+
const promptMessages = convertToLanguageModelPrompt(validatedPrompt);
|
1708
|
+
const {
|
1709
|
+
result: { stream, warnings, rawResponse },
|
1710
|
+
doStreamSpan
|
1711
|
+
} = await retry(
|
1712
|
+
() => recordSpan({
|
1713
|
+
name: "ai.streamText.doStream",
|
1714
|
+
attributes: {
|
1715
|
+
...baseTelemetryAttributes,
|
1716
|
+
"ai.prompt.format": validatedPrompt.type,
|
1717
|
+
"ai.prompt.messages": JSON.stringify(promptMessages)
|
1718
|
+
},
|
1719
|
+
tracer,
|
1720
|
+
endWhenDone: false,
|
1721
|
+
fn: async (doStreamSpan2) => {
|
1722
|
+
return {
|
1723
|
+
result: await model.doStream({
|
1724
|
+
mode: {
|
1725
|
+
type: "regular",
|
1726
|
+
...prepareToolsAndToolChoice({ tools, toolChoice })
|
1727
|
+
},
|
1728
|
+
...prepareCallSettings(settings),
|
1729
|
+
inputFormat: validatedPrompt.type,
|
1730
|
+
prompt: promptMessages,
|
1731
|
+
abortSignal,
|
1732
|
+
headers
|
1733
|
+
}),
|
1734
|
+
doStreamSpan: doStreamSpan2
|
1735
|
+
};
|
1736
|
+
}
|
1737
|
+
})
|
1738
|
+
);
|
1739
|
+
return new StreamTextResult({
|
1740
|
+
stream: runToolsTransformation({
|
1741
|
+
tools,
|
1742
|
+
generatorStream: stream,
|
1743
|
+
tracer
|
1744
|
+
}),
|
1745
|
+
warnings,
|
1746
|
+
rawResponse,
|
1747
|
+
onFinish,
|
1748
|
+
rootSpan,
|
1749
|
+
doStreamSpan
|
1750
|
+
});
|
1751
|
+
}
|
1458
1752
|
});
|
1459
1753
|
}
|
1460
1754
|
var StreamTextResult = class {
|
@@ -1462,7 +1756,9 @@ var StreamTextResult = class {
|
|
1462
1756
|
stream,
|
1463
1757
|
warnings,
|
1464
1758
|
rawResponse,
|
1465
|
-
onFinish
|
1759
|
+
onFinish,
|
1760
|
+
rootSpan,
|
1761
|
+
doStreamSpan
|
1466
1762
|
}) {
|
1467
1763
|
this.warnings = warnings;
|
1468
1764
|
this.rawResponse = rawResponse;
|
@@ -1492,41 +1788,73 @@ var StreamTextResult = class {
|
|
1492
1788
|
let text = "";
|
1493
1789
|
const toolCalls = [];
|
1494
1790
|
const toolResults = [];
|
1791
|
+
let firstChunk = true;
|
1495
1792
|
const self = this;
|
1496
1793
|
this.originalStream = stream.pipeThrough(
|
1497
1794
|
new TransformStream({
|
1498
1795
|
async transform(chunk, controller) {
|
1499
1796
|
controller.enqueue(chunk);
|
1500
|
-
if (
|
1501
|
-
|
1797
|
+
if (firstChunk) {
|
1798
|
+
firstChunk = false;
|
1799
|
+
doStreamSpan.addEvent("ai.stream.firstChunk");
|
1502
1800
|
}
|
1503
|
-
|
1504
|
-
|
1505
|
-
|
1506
|
-
|
1507
|
-
|
1508
|
-
|
1509
|
-
|
1510
|
-
|
1511
|
-
|
1512
|
-
|
1513
|
-
|
1514
|
-
|
1515
|
-
|
1801
|
+
const chunkType = chunk.type;
|
1802
|
+
switch (chunkType) {
|
1803
|
+
case "text-delta":
|
1804
|
+
text += chunk.textDelta;
|
1805
|
+
break;
|
1806
|
+
case "tool-call":
|
1807
|
+
toolCalls.push(chunk);
|
1808
|
+
break;
|
1809
|
+
case "tool-result":
|
1810
|
+
toolResults.push(chunk);
|
1811
|
+
break;
|
1812
|
+
case "finish":
|
1813
|
+
usage = chunk.usage;
|
1814
|
+
finishReason = chunk.finishReason;
|
1815
|
+
resolveUsage(usage);
|
1816
|
+
resolveFinishReason(finishReason);
|
1817
|
+
resolveText(text);
|
1818
|
+
resolveToolCalls(toolCalls);
|
1819
|
+
break;
|
1820
|
+
case "error":
|
1821
|
+
break;
|
1822
|
+
default: {
|
1823
|
+
const exhaustiveCheck = chunkType;
|
1824
|
+
throw new Error(`Unknown chunk type: ${exhaustiveCheck}`);
|
1825
|
+
}
|
1516
1826
|
}
|
1517
1827
|
},
|
1518
1828
|
// invoke onFinish callback and resolve toolResults promise when the stream is about to close:
|
1519
1829
|
async flush(controller) {
|
1520
1830
|
var _a;
|
1521
1831
|
try {
|
1832
|
+
const finalUsage = usage != null ? usage : {
|
1833
|
+
promptTokens: NaN,
|
1834
|
+
completionTokens: NaN,
|
1835
|
+
totalTokens: NaN
|
1836
|
+
};
|
1837
|
+
const finalFinishReason = finishReason != null ? finishReason : "unknown";
|
1838
|
+
const telemetryToolCalls = toolCalls.length > 0 ? JSON.stringify(toolCalls) : void 0;
|
1839
|
+
doStreamSpan.setAttributes({
|
1840
|
+
"ai.finishReason": finalFinishReason,
|
1841
|
+
"ai.usage.promptTokens": finalUsage.promptTokens,
|
1842
|
+
"ai.usage.completionTokens": finalUsage.completionTokens,
|
1843
|
+
"ai.result.text": text,
|
1844
|
+
"ai.result.toolCalls": telemetryToolCalls
|
1845
|
+
});
|
1846
|
+
doStreamSpan.end();
|
1847
|
+
rootSpan.setAttributes({
|
1848
|
+
"ai.finishReason": finalFinishReason,
|
1849
|
+
"ai.usage.promptTokens": finalUsage.promptTokens,
|
1850
|
+
"ai.usage.completionTokens": finalUsage.completionTokens,
|
1851
|
+
"ai.result.text": text,
|
1852
|
+
"ai.result.toolCalls": telemetryToolCalls
|
1853
|
+
});
|
1522
1854
|
resolveToolResults(toolResults);
|
1523
1855
|
await ((_a = self.onFinish) == null ? void 0 : _a.call(self, {
|
1524
|
-
finishReason:
|
1525
|
-
usage:
|
1526
|
-
promptTokens: NaN,
|
1527
|
-
completionTokens: NaN,
|
1528
|
-
totalTokens: NaN
|
1529
|
-
},
|
1856
|
+
finishReason: finalFinishReason,
|
1857
|
+
usage: finalUsage,
|
1530
1858
|
text,
|
1531
1859
|
toolCalls,
|
1532
1860
|
// The tool results are inferred as a never[] type, because they are
|
@@ -1539,6 +1867,8 @@ var StreamTextResult = class {
|
|
1539
1867
|
}));
|
1540
1868
|
} catch (error) {
|
1541
1869
|
controller.error(error);
|
1870
|
+
} finally {
|
1871
|
+
rootSpan.end();
|
1542
1872
|
}
|
1543
1873
|
}
|
1544
1874
|
})
|