@raindrop-ai/ai-sdk 0.0.17 → 0.0.19-beta.1

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.
@@ -1,4 +1,4 @@
1
- // ../core/dist/chunk-FTBZHS25.js
1
+ // ../core/dist/chunk-FOHDGBT5.js
2
2
  function getCrypto() {
3
3
  const c = globalThis.crypto;
4
4
  return c;
@@ -269,6 +269,7 @@ var EventShipper = class {
269
269
  console.log(`${this.prefix} queue patch`, {
270
270
  eventId,
271
271
  userId: patch.userId,
272
+ convoId: patch.convoId,
272
273
  eventName: patch.eventName,
273
274
  hasInput: typeof patch.input === "string" && patch.input.length > 0,
274
275
  hasOutput: typeof patch.output === "string" && patch.output.length > 0,
@@ -397,16 +398,18 @@ var EventShipper = class {
397
398
  return;
398
399
  }
399
400
  const { wizardSession, ...restProperties } = (_e = accumulated.properties) != null ? _e : {};
401
+ const convoId = (_f = accumulated.convoId) != null ? _f : sticky.convoId;
402
+ const isPending = (_h = (_g = accumulated.isPending) != null ? _g : sticky.isPending) != null ? _h : true;
400
403
  const payload = {
401
404
  event_id: eventId,
402
405
  user_id: userId,
403
406
  event: eventName,
404
- timestamp: (_f = accumulated.timestamp) != null ? _f : (/* @__PURE__ */ new Date()).toISOString(),
407
+ timestamp: (_i = accumulated.timestamp) != null ? _i : (/* @__PURE__ */ new Date()).toISOString(),
405
408
  ai_data: {
406
409
  input: accumulated.input,
407
410
  output: accumulated.output,
408
411
  model: accumulated.model,
409
- convo_id: (_g = accumulated.convoId) != null ? _g : sticky.convoId
412
+ convo_id: convoId
410
413
  },
411
414
  properties: {
412
415
  ...restProperties,
@@ -414,7 +417,7 @@ var EventShipper = class {
414
417
  $context: this.context
415
418
  },
416
419
  attachments: accumulated.attachments,
417
- is_pending: ((_i = (_h = accumulated.isPending) != null ? _h : sticky.isPending) != null ? _i : true) !== false
420
+ is_pending: isPending
418
421
  };
419
422
  const url = `${this.baseUrl}events/track_partial`;
420
423
  if (this.debug) {
@@ -422,7 +425,8 @@ var EventShipper = class {
422
425
  eventId,
423
426
  eventName,
424
427
  userId,
425
- isPending: payload.is_pending,
428
+ convoId,
429
+ isPending,
426
430
  inputPreview: typeof accumulated.input === "string" ? accumulated.input.slice(0, 120) : void 0,
427
431
  outputPreview: typeof accumulated.output === "string" ? accumulated.output.slice(0, 120) : void 0,
428
432
  attachments: (_k = (_j = accumulated.attachments) == null ? void 0 : _j.length) != null ? _k : 0,
@@ -454,7 +458,6 @@ var EventShipper = class {
454
458
  } finally {
455
459
  this.inFlight.delete(p);
456
460
  }
457
- const isPending = payload.is_pending;
458
461
  if (!isPending) {
459
462
  this.sticky.delete(eventId);
460
463
  }
@@ -782,7 +785,7 @@ async function* asyncGeneratorWithCurrent(span, gen) {
782
785
  // package.json
783
786
  var package_default = {
784
787
  name: "@raindrop-ai/ai-sdk",
785
- version: "0.0.17"};
788
+ version: "0.0.19-beta.1"};
786
789
 
787
790
  // src/internal/version.ts
788
791
  var libraryName = package_default.name;
@@ -801,19 +804,6 @@ var EventShipper2 = class extends EventShipper {
801
804
  }
802
805
  };
803
806
 
804
- // src/internal/traces.ts
805
- var TraceShipper2 = class extends TraceShipper {
806
- constructor(opts) {
807
- var _a, _b, _c;
808
- super({
809
- ...opts,
810
- sdkName: (_a = opts.sdkName) != null ? _a : "ai-sdk",
811
- serviceName: (_b = opts.serviceName) != null ? _b : "raindrop.ai-sdk",
812
- serviceVersion: (_c = opts.serviceVersion) != null ? _c : libraryVersion
813
- });
814
- }
815
- };
816
-
817
807
  // src/internal/wrap/helpers.ts
818
808
  function isRecord(value) {
819
809
  return typeof value === "object" && value !== null;
@@ -1168,6 +1158,145 @@ function extractResponseMessages(result) {
1168
1158
  }
1169
1159
  return [];
1170
1160
  }
1161
+ function buildToolCallMatchKey(info) {
1162
+ if (typeof info.toolCallId === "string" && info.toolCallId.length > 0) {
1163
+ return `id:${info.toolCallId}`;
1164
+ }
1165
+ if (typeof info.toolName === "string" && info.toolName.length > 0) {
1166
+ const inputJson = safeJsonWithUint8(info.input);
1167
+ return inputJson !== void 0 ? `name:${info.toolName}|input:${inputJson}` : `name:${info.toolName}`;
1168
+ }
1169
+ return void 0;
1170
+ }
1171
+ function isTranscriptToolResultError(part, result) {
1172
+ if (part["isError"] === true || part["type"] === "tool-error") {
1173
+ return true;
1174
+ }
1175
+ if (isRecord(result) && typeof result["type"] === "string") {
1176
+ return result["type"].startsWith("error") || result["type"] === "execution-denied";
1177
+ }
1178
+ return false;
1179
+ }
1180
+ function getTranscriptToolErrorMessage(result) {
1181
+ if (typeof result === "string" && result.length > 0) {
1182
+ return result;
1183
+ }
1184
+ if (isRecord(result)) {
1185
+ if (typeof result["value"] === "string" && result["value"].length > 0) {
1186
+ return result["value"];
1187
+ }
1188
+ if (typeof result["reason"] === "string" && result["reason"].length > 0) {
1189
+ return result["reason"];
1190
+ }
1191
+ if (typeof result["message"] === "string" && result["message"].length > 0) {
1192
+ return result["message"];
1193
+ }
1194
+ }
1195
+ return safeJsonWithUint8(result);
1196
+ }
1197
+ function getTranscriptMessageParts(message) {
1198
+ if (!isRecord(message)) return [];
1199
+ const content = message["content"];
1200
+ if (Array.isArray(content)) {
1201
+ return content.filter(isRecord);
1202
+ }
1203
+ return isRecord(content) ? [content] : [];
1204
+ }
1205
+ function getTranscriptToolCallInput(part) {
1206
+ return "input" in part ? part["input"] : "args" in part ? part["args"] : void 0;
1207
+ }
1208
+ function getTranscriptToolCallId(part) {
1209
+ const toolCallId = part["toolCallId"];
1210
+ return typeof toolCallId === "string" && toolCallId.length > 0 ? toolCallId : void 0;
1211
+ }
1212
+ function getTranscriptToolResultValue(part) {
1213
+ if ("output" in part) return part["output"];
1214
+ if ("result" in part) return part["result"];
1215
+ return part["error"];
1216
+ }
1217
+ function rememberPendingTranscriptToolCallKey(pendingKeysByToolName, toolName, key) {
1218
+ var _a;
1219
+ if (!toolName) return;
1220
+ const pendingKeys = (_a = pendingKeysByToolName.get(toolName)) != null ? _a : [];
1221
+ if (pendingKeys.includes(key)) return;
1222
+ pendingKeys.push(key);
1223
+ pendingKeysByToolName.set(toolName, pendingKeys);
1224
+ }
1225
+ function takePendingTranscriptToolCallKey(pendingKeysByToolName, toolName) {
1226
+ if (!toolName) return void 0;
1227
+ const pendingKeys = pendingKeysByToolName.get(toolName);
1228
+ if (!pendingKeys || pendingKeys.length === 0) return void 0;
1229
+ const key = pendingKeys.shift();
1230
+ if (key === void 0) return void 0;
1231
+ if (pendingKeys.length === 0) {
1232
+ pendingKeysByToolName.delete(toolName);
1233
+ }
1234
+ return key;
1235
+ }
1236
+ function mergeTranscriptToolCallPart(params) {
1237
+ var _a, _b, _c, _d;
1238
+ const { spans, pendingKeysByToolName, part } = params;
1239
+ const toolCallId = getTranscriptToolCallId(part);
1240
+ const toolName = typeof part["toolName"] === "string" ? part["toolName"] : void 0;
1241
+ const input = getTranscriptToolCallInput(part);
1242
+ const key = buildToolCallMatchKey({ toolCallId, toolName, input });
1243
+ if (!key) return;
1244
+ const placeholderKey = toolCallId == null ? buildToolCallMatchKey({ toolCallId: void 0, toolName, input: void 0 }) : void 0;
1245
+ const placeholder = placeholderKey && placeholderKey !== key ? spans.get(placeholderKey) : void 0;
1246
+ const existing = (_a = spans.get(key)) != null ? _a : placeholder;
1247
+ spans.set(key, {
1248
+ key,
1249
+ toolCallId: (_b = existing == null ? void 0 : existing.toolCallId) != null ? _b : toolCallId,
1250
+ toolName: (_c = existing == null ? void 0 : existing.toolName) != null ? _c : toolName,
1251
+ input: (_d = existing == null ? void 0 : existing.input) != null ? _d : input,
1252
+ result: existing == null ? void 0 : existing.result,
1253
+ status: existing == null ? void 0 : existing.status,
1254
+ errorMessage: existing == null ? void 0 : existing.errorMessage
1255
+ });
1256
+ if (placeholderKey && placeholderKey !== key) {
1257
+ spans.delete(placeholderKey);
1258
+ }
1259
+ if (!toolCallId && (existing == null ? void 0 : existing.result) === void 0) {
1260
+ rememberPendingTranscriptToolCallKey(pendingKeysByToolName, toolName, key);
1261
+ }
1262
+ }
1263
+ function mergeTranscriptToolResultPart(params) {
1264
+ var _a, _b, _c;
1265
+ const { spans, pendingKeysByToolName, part } = params;
1266
+ const toolCallId = getTranscriptToolCallId(part);
1267
+ const toolName = typeof part["toolName"] === "string" ? part["toolName"] : void 0;
1268
+ const result = getTranscriptToolResultValue(part);
1269
+ const fallbackKey = buildToolCallMatchKey({ toolCallId, toolName, input: void 0 });
1270
+ const key = toolCallId != null ? fallbackKey : (_a = takePendingTranscriptToolCallKey(pendingKeysByToolName, toolName)) != null ? _a : fallbackKey;
1271
+ if (!key) return;
1272
+ const existing = spans.get(key);
1273
+ const isError = isTranscriptToolResultError(part, result);
1274
+ spans.set(key, {
1275
+ key,
1276
+ toolCallId: (_b = existing == null ? void 0 : existing.toolCallId) != null ? _b : toolCallId,
1277
+ toolName: (_c = existing == null ? void 0 : existing.toolName) != null ? _c : toolName,
1278
+ input: existing == null ? void 0 : existing.input,
1279
+ result,
1280
+ status: isError ? "ERROR" : "OK",
1281
+ errorMessage: isError ? getTranscriptToolErrorMessage(result) : void 0
1282
+ });
1283
+ }
1284
+ function extractToolSpansFromMessages(messages) {
1285
+ const spans = /* @__PURE__ */ new Map();
1286
+ const pendingKeysByToolName = /* @__PURE__ */ new Map();
1287
+ for (const message of messages) {
1288
+ for (const part of getTranscriptMessageParts(message)) {
1289
+ if (part["type"] === "tool-call") {
1290
+ mergeTranscriptToolCallPart({ spans, pendingKeysByToolName, part });
1291
+ continue;
1292
+ }
1293
+ if (part["type"] === "tool-result" || part["type"] === "tool-error") {
1294
+ mergeTranscriptToolResultPart({ spans, pendingKeysByToolName, part });
1295
+ }
1296
+ }
1297
+ }
1298
+ return [...spans.values()];
1299
+ }
1171
1300
  function extractTextFromLmContent(content) {
1172
1301
  if (!Array.isArray(content)) return void 0;
1173
1302
  let result = "";
@@ -1183,7 +1312,7 @@ function extractToolCallsFromLmContent(content) {
1183
1312
  const calls = [];
1184
1313
  for (const part of content) {
1185
1314
  if (!isRecord(part) || part["type"] !== "tool-call") continue;
1186
- const toolCallId = typeof part["toolCallId"] === "string" ? part["toolCallId"] : void 0;
1315
+ const toolCallId = getTranscriptToolCallId(part);
1187
1316
  const toolName = typeof part["toolName"] === "string" ? part["toolName"] : void 0;
1188
1317
  if (toolCallId || toolName) {
1189
1318
  calls.push({ toolCallId, toolName, input: part["input"] });
@@ -1222,7 +1351,7 @@ function toOtlpAttr(key, value) {
1222
1351
  }
1223
1352
  function attrsFromTelemetryMetadata(metadata) {
1224
1353
  if (!metadata) return [];
1225
- return Object.entries(metadata).map(([k, v]) => {
1354
+ return Object.entries(metadata).filter(([k]) => !k.startsWith("raindrop.internal.")).map(([k, v]) => {
1226
1355
  const key = k === "raindrop.userId" ? "raindrop.ai.userId" : k;
1227
1356
  return toOtlpAttr(`ai.telemetry.metadata.${key}`, v);
1228
1357
  });
@@ -1290,6 +1419,538 @@ function attrsFromGenAiRequest(options) {
1290
1419
  ];
1291
1420
  }
1292
1421
 
1422
+ // src/internal/raindrop-telemetry-integration.ts
1423
+ var RaindropTelemetryIntegration = class {
1424
+ constructor(opts) {
1425
+ this.callStates = /* @__PURE__ */ new Map();
1426
+ // ── onStart ─────────────────────────────────────────────────────────────
1427
+ this.onStart = (event) => {
1428
+ var _a, _b, _c;
1429
+ if (event.isEnabled !== true) return;
1430
+ const isEmbed = event.operationId === "ai.embed" || event.operationId === "ai.embedMany";
1431
+ const recordInputs = event.recordInputs !== false;
1432
+ const recordOutputs = event.recordOutputs !== false;
1433
+ const functionId = event.functionId;
1434
+ const metadata = event.metadata;
1435
+ const callMeta = this.extractRaindropMetadata(metadata);
1436
+ const eventId = (_c = (_b = callMeta.eventId) != null ? _b : (_a = this.defaultContext) == null ? void 0 : _a.eventId) != null ? _c : randomUUID();
1437
+ const inherited = getContextManager().getParentSpanIds();
1438
+ const inheritedParent = inherited && inherited.eventId === eventId ? { traceIdB64: inherited.traceIdB64, spanIdB64: inherited.spanIdB64 } : void 0;
1439
+ const { operationName, resourceName } = opName(
1440
+ event.operationId,
1441
+ functionId
1442
+ );
1443
+ let rootSpan;
1444
+ if (this.sendTraces) {
1445
+ const promptAttrs = !isEmbed && recordInputs ? [
1446
+ attrString(
1447
+ "ai.prompt",
1448
+ safeJsonWithUint8({
1449
+ system: event.system,
1450
+ prompt: event.prompt,
1451
+ messages: event.messages
1452
+ })
1453
+ )
1454
+ ] : [];
1455
+ const embedAttrs = isEmbed && recordInputs ? event.operationId === "ai.embedMany" ? [
1456
+ attrString(
1457
+ "ai.values",
1458
+ safeJsonWithUint8(event.value)
1459
+ )
1460
+ ] : [attrString("ai.value", safeJsonWithUint8(event.value))] : [];
1461
+ rootSpan = this.traceShipper.startSpan({
1462
+ name: event.operationId,
1463
+ parent: inheritedParent,
1464
+ eventId,
1465
+ operationId: event.operationId,
1466
+ attributes: [
1467
+ attrString("operation.name", operationName),
1468
+ attrString("resource.name", resourceName),
1469
+ attrString("ai.telemetry.functionId", functionId),
1470
+ attrString("ai.model.provider", event.provider),
1471
+ attrString("ai.model.id", event.modelId),
1472
+ ...attrsFromTelemetryMetadata(metadata),
1473
+ ...promptAttrs,
1474
+ ...embedAttrs
1475
+ ]
1476
+ });
1477
+ }
1478
+ this.callStates.set(event.callId, {
1479
+ operationId: event.operationId,
1480
+ eventId,
1481
+ rootSpan,
1482
+ rootParent: rootSpan ? this.spanParentRef(rootSpan) : inheritedParent,
1483
+ stepSpan: void 0,
1484
+ stepParent: void 0,
1485
+ toolSpans: /* @__PURE__ */ new Map(),
1486
+ embedSpans: /* @__PURE__ */ new Map(),
1487
+ recordInputs,
1488
+ recordOutputs,
1489
+ functionId,
1490
+ metadata,
1491
+ accumulatedText: "",
1492
+ inputText: isEmbed ? void 0 : this.extractInputText(event),
1493
+ toolCallCount: 0
1494
+ });
1495
+ };
1496
+ // ── onStepStart ─────────────────────────────────────────────────────────
1497
+ this.onStepStart = (event) => {
1498
+ const state = this.getState(event.callId);
1499
+ if (!(state == null ? void 0 : state.rootSpan) || !state.rootParent) return;
1500
+ const isStream = state.operationId === "ai.streamText" || state.operationId === "ai.streamObject";
1501
+ const stepOperationId = isStream ? `${state.operationId}.doStream` : `${state.operationId}.doGenerate`;
1502
+ const { operationName, resourceName } = opName(
1503
+ stepOperationId,
1504
+ state.functionId
1505
+ );
1506
+ const inputAttrs = [];
1507
+ if (state.recordInputs) {
1508
+ if (event.promptMessages) {
1509
+ inputAttrs.push(
1510
+ attrString(
1511
+ "ai.prompt.messages",
1512
+ safeJsonWithUint8(event.promptMessages)
1513
+ )
1514
+ );
1515
+ }
1516
+ if (event.stepTools) {
1517
+ inputAttrs.push(
1518
+ attrStringArray(
1519
+ "ai.prompt.tools",
1520
+ event.stepTools.map((t) => JSON.stringify(t))
1521
+ )
1522
+ );
1523
+ }
1524
+ if (event.stepToolChoice != null) {
1525
+ inputAttrs.push(
1526
+ attrString(
1527
+ "ai.prompt.toolChoice",
1528
+ JSON.stringify(event.stepToolChoice)
1529
+ )
1530
+ );
1531
+ }
1532
+ }
1533
+ const stepSpan = this.traceShipper.startSpan({
1534
+ name: stepOperationId,
1535
+ parent: state.rootParent,
1536
+ eventId: state.eventId,
1537
+ operationId: stepOperationId,
1538
+ attributes: [
1539
+ attrString("operation.name", operationName),
1540
+ attrString("resource.name", resourceName),
1541
+ attrString("ai.telemetry.functionId", state.functionId),
1542
+ attrString("ai.model.provider", event.provider),
1543
+ attrString("ai.model.id", event.modelId),
1544
+ attrString("gen_ai.system", event.provider),
1545
+ attrString("gen_ai.request.model", event.modelId),
1546
+ ...inputAttrs
1547
+ ]
1548
+ });
1549
+ state.stepSpan = stepSpan;
1550
+ state.stepParent = this.spanParentRef(stepSpan);
1551
+ };
1552
+ // ── onToolCallStart ─────────────────────────────────────────────────────
1553
+ this.onToolCallStart = (event) => {
1554
+ const state = this.getState(event.callId);
1555
+ if (!(state == null ? void 0 : state.stepParent)) return;
1556
+ const { toolCall } = event;
1557
+ const { operationName, resourceName } = opName(
1558
+ "ai.toolCall",
1559
+ state.functionId
1560
+ );
1561
+ const inputAttrs = state.recordInputs ? [attrString("ai.toolCall.args", safeJsonWithUint8(toolCall.input))] : [];
1562
+ const toolSpan = this.traceShipper.startSpan({
1563
+ name: "ai.toolCall",
1564
+ parent: state.stepParent,
1565
+ eventId: state.eventId,
1566
+ operationId: "ai.toolCall",
1567
+ attributes: [
1568
+ attrString("operation.name", operationName),
1569
+ attrString("resource.name", resourceName),
1570
+ attrString("ai.telemetry.functionId", state.functionId),
1571
+ attrString("ai.toolCall.name", toolCall.toolName),
1572
+ attrString("ai.toolCall.id", toolCall.toolCallId),
1573
+ ...inputAttrs
1574
+ ]
1575
+ });
1576
+ state.toolSpans.set(toolCall.toolCallId, toolSpan);
1577
+ };
1578
+ // ── onToolCallFinish ────────────────────────────────────────────────────
1579
+ this.onToolCallFinish = (event) => {
1580
+ const state = this.getState(event.callId);
1581
+ if (!state) return;
1582
+ const toolSpan = state.toolSpans.get(event.toolCall.toolCallId);
1583
+ if (!toolSpan) return;
1584
+ state.toolCallCount += 1;
1585
+ if (event.success) {
1586
+ const outputAttrs = state.recordOutputs ? [attrString("ai.toolCall.result", safeJsonWithUint8(event.output))] : [];
1587
+ this.traceShipper.endSpan(toolSpan, { attributes: outputAttrs });
1588
+ } else {
1589
+ this.traceShipper.endSpan(toolSpan, { error: event.error });
1590
+ }
1591
+ state.toolSpans.delete(event.toolCall.toolCallId);
1592
+ };
1593
+ // ── onChunk (streaming) ─────────────────────────────────────────────────
1594
+ this.onChunk = (event) => {
1595
+ var _a, _b, _c;
1596
+ const callId = (_b = event.callId) != null ? _b : (_a = event.chunk) == null ? void 0 : _a.callId;
1597
+ if (!callId) return;
1598
+ const state = this.getState(callId);
1599
+ if (!state) return;
1600
+ const chunk = event.chunk;
1601
+ if (!chunk || typeof chunk !== "object") return;
1602
+ if (chunk.type === "text-delta") {
1603
+ const delta = (_c = chunk.textDelta) != null ? _c : chunk.delta;
1604
+ if (typeof delta === "string") {
1605
+ state.accumulatedText += delta;
1606
+ }
1607
+ }
1608
+ };
1609
+ // ── onStepFinish ────────────────────────────────────────────────────────
1610
+ this.onStepFinish = (event) => {
1611
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
1612
+ const state = this.getState(event.callId);
1613
+ if (!(state == null ? void 0 : state.stepSpan)) return;
1614
+ const outputAttrs = [];
1615
+ if (state.recordOutputs) {
1616
+ outputAttrs.push(
1617
+ attrString("ai.response.finishReason", event.finishReason),
1618
+ attrString("ai.response.text", (_a = event.text) != null ? _a : void 0),
1619
+ attrString("ai.response.id", (_b = event.response) == null ? void 0 : _b.id),
1620
+ attrString("ai.response.model", (_c = event.response) == null ? void 0 : _c.modelId),
1621
+ attrString(
1622
+ "ai.response.timestamp",
1623
+ ((_d = event.response) == null ? void 0 : _d.timestamp) instanceof Date ? event.response.timestamp.toISOString() : (_e = event.response) == null ? void 0 : _e.timestamp
1624
+ ),
1625
+ attrString(
1626
+ "ai.response.providerMetadata",
1627
+ event.providerMetadata ? safeJsonWithUint8(event.providerMetadata) : void 0
1628
+ )
1629
+ );
1630
+ if (((_f = event.toolCalls) == null ? void 0 : _f.length) > 0) {
1631
+ outputAttrs.push(
1632
+ attrString(
1633
+ "ai.response.toolCalls",
1634
+ JSON.stringify(
1635
+ event.toolCalls.map((tc) => ({
1636
+ toolCallId: tc.toolCallId,
1637
+ toolName: tc.toolName,
1638
+ input: tc.input
1639
+ }))
1640
+ )
1641
+ )
1642
+ );
1643
+ }
1644
+ if (((_g = event.reasoning) == null ? void 0 : _g.length) > 0) {
1645
+ const reasoningText = event.reasoning.filter((part) => "text" in part).map((part) => part.text).join("\n");
1646
+ if (reasoningText) {
1647
+ outputAttrs.push(attrString("ai.response.reasoning", reasoningText));
1648
+ }
1649
+ }
1650
+ }
1651
+ outputAttrs.push(
1652
+ attrStringArray("gen_ai.response.finish_reasons", [event.finishReason]),
1653
+ attrString("gen_ai.response.id", (_h = event.response) == null ? void 0 : _h.id),
1654
+ attrString("gen_ai.response.model", (_i = event.response) == null ? void 0 : _i.modelId)
1655
+ );
1656
+ const usage = event.usage;
1657
+ if (usage) {
1658
+ outputAttrs.push(
1659
+ attrInt("ai.usage.inputTokens", usage.inputTokens),
1660
+ attrInt("ai.usage.outputTokens", usage.outputTokens),
1661
+ attrInt("ai.usage.totalTokens", usage.totalTokens),
1662
+ attrInt("ai.usage.reasoningTokens", usage.reasoningTokens),
1663
+ attrInt("ai.usage.cachedInputTokens", usage.cachedInputTokens),
1664
+ attrInt("gen_ai.usage.input_tokens", usage.inputTokens),
1665
+ attrInt("gen_ai.usage.output_tokens", usage.outputTokens)
1666
+ );
1667
+ }
1668
+ this.traceShipper.endSpan(state.stepSpan, { attributes: outputAttrs });
1669
+ state.stepSpan = void 0;
1670
+ state.stepParent = void 0;
1671
+ };
1672
+ // ── onEmbedStart ────────────────────────────────────────────────────────
1673
+ this.onEmbedStart = (event) => {
1674
+ const state = this.getState(event.callId);
1675
+ if (!(state == null ? void 0 : state.rootSpan) || !state.rootParent) return;
1676
+ const { operationName, resourceName } = opName(
1677
+ event.operationId,
1678
+ state.functionId
1679
+ );
1680
+ const inputAttrs = state.recordInputs ? [
1681
+ attrString(
1682
+ "ai.values",
1683
+ safeJsonWithUint8(event.values)
1684
+ )
1685
+ ] : [];
1686
+ const embedSpan = this.traceShipper.startSpan({
1687
+ name: event.operationId,
1688
+ parent: state.rootParent,
1689
+ eventId: state.eventId,
1690
+ operationId: event.operationId,
1691
+ attributes: [
1692
+ attrString("operation.name", operationName),
1693
+ attrString("resource.name", resourceName),
1694
+ attrString("ai.telemetry.functionId", state.functionId),
1695
+ ...inputAttrs
1696
+ ]
1697
+ });
1698
+ state.embedSpans.set(event.embedCallId, embedSpan);
1699
+ };
1700
+ // ── onEmbedFinish ───────────────────────────────────────────────────────
1701
+ this.onEmbedFinish = (event) => {
1702
+ var _a;
1703
+ const state = this.getState(event.callId);
1704
+ if (!state) return;
1705
+ const embedSpan = state.embedSpans.get(event.embedCallId);
1706
+ if (!embedSpan) return;
1707
+ const outputAttrs = [];
1708
+ if (state.recordOutputs) {
1709
+ outputAttrs.push(
1710
+ attrString(
1711
+ "ai.embeddings",
1712
+ safeJsonWithUint8(event.embeddings)
1713
+ )
1714
+ );
1715
+ }
1716
+ if (((_a = event.usage) == null ? void 0 : _a.tokens) != null) {
1717
+ outputAttrs.push(attrInt("ai.usage.tokens", event.usage.tokens));
1718
+ }
1719
+ this.traceShipper.endSpan(embedSpan, { attributes: outputAttrs });
1720
+ state.embedSpans.delete(event.embedCallId);
1721
+ };
1722
+ // ── onFinish ────────────────────────────────────────────────────────────
1723
+ this.onFinish = (event) => {
1724
+ const state = this.getState(event.callId);
1725
+ if (!state) return;
1726
+ const isEmbed = state.operationId === "ai.embed" || state.operationId === "ai.embedMany";
1727
+ if (isEmbed) {
1728
+ this.finishEmbed(event, state);
1729
+ } else {
1730
+ this.finishGenerate(event, state);
1731
+ }
1732
+ this.cleanup(event.callId);
1733
+ };
1734
+ // ── onError ─────────────────────────────────────────────────────────────
1735
+ this.onError = (error) => {
1736
+ var _a;
1737
+ const event = error;
1738
+ if (!(event == null ? void 0 : event.callId)) return;
1739
+ const state = this.getState(event.callId);
1740
+ if (!state) return;
1741
+ const actualError = (_a = event.error) != null ? _a : error;
1742
+ if (state.stepSpan) {
1743
+ this.traceShipper.endSpan(state.stepSpan, { error: actualError });
1744
+ }
1745
+ for (const embedSpan of state.embedSpans.values()) {
1746
+ this.traceShipper.endSpan(embedSpan, { error: actualError });
1747
+ }
1748
+ state.embedSpans.clear();
1749
+ for (const toolSpan of state.toolSpans.values()) {
1750
+ this.traceShipper.endSpan(toolSpan, { error: actualError });
1751
+ }
1752
+ state.toolSpans.clear();
1753
+ if (state.rootSpan) {
1754
+ this.traceShipper.endSpan(state.rootSpan, { error: actualError });
1755
+ }
1756
+ this.cleanup(event.callId);
1757
+ };
1758
+ // ── executeTool ─────────────────────────────────────────────────────────
1759
+ this.executeTool = async ({
1760
+ callId,
1761
+ toolCallId,
1762
+ execute
1763
+ }) => {
1764
+ const state = this.getState(callId);
1765
+ const toolSpan = state == null ? void 0 : state.toolSpans.get(toolCallId);
1766
+ if (!toolSpan) return execute();
1767
+ return runWithParentSpanContext(
1768
+ {
1769
+ traceIdB64: toolSpan.ids.traceIdB64,
1770
+ spanIdB64: toolSpan.ids.spanIdB64,
1771
+ eventId: state.eventId
1772
+ },
1773
+ () => execute()
1774
+ );
1775
+ };
1776
+ this.traceShipper = opts.traceShipper;
1777
+ this.eventShipper = opts.eventShipper;
1778
+ this.sendTraces = opts.sendTraces !== false;
1779
+ this.sendEvents = opts.sendEvents !== false;
1780
+ this.debug = opts.debug === true;
1781
+ this.defaultContext = opts.context;
1782
+ }
1783
+ // ── helpers ──────────────────────────────────────────────────────────────
1784
+ getState(callId) {
1785
+ return this.callStates.get(callId);
1786
+ }
1787
+ cleanup(callId) {
1788
+ this.callStates.delete(callId);
1789
+ }
1790
+ spanParentRef(span) {
1791
+ return { traceIdB64: span.ids.traceIdB64, spanIdB64: span.ids.spanIdB64 };
1792
+ }
1793
+ extractRaindropMetadata(metadata) {
1794
+ if (!metadata) return {};
1795
+ const result = {};
1796
+ const userId = metadata["raindrop.userId"];
1797
+ if (typeof userId === "string" && userId) result.userId = userId;
1798
+ const eventId = metadata["raindrop.eventId"];
1799
+ if (typeof eventId === "string" && eventId) result.eventId = eventId;
1800
+ const convoId = metadata["raindrop.convoId"];
1801
+ if (typeof convoId === "string" && convoId) result.convoId = convoId;
1802
+ const eventName = metadata["raindrop.eventName"];
1803
+ if (typeof eventName === "string" && eventName) result.eventName = eventName;
1804
+ const properties = metadata["raindrop.properties"];
1805
+ if (typeof properties === "string") {
1806
+ try {
1807
+ result.properties = JSON.parse(properties);
1808
+ } catch (e) {
1809
+ }
1810
+ } else if (properties && typeof properties === "object") {
1811
+ result.properties = properties;
1812
+ }
1813
+ return result;
1814
+ }
1815
+ /**
1816
+ * Extract the user-facing input text from an onStart event.
1817
+ * Mirrors the logic in the v4-v6 Proxy path (lastUserMessageTextFromArgs / extractInputFromArgs).
1818
+ */
1819
+ extractInputText(event) {
1820
+ if (typeof event.prompt === "string") return event.prompt;
1821
+ if (Array.isArray(event.messages)) {
1822
+ for (let i = event.messages.length - 1; i >= 0; i--) {
1823
+ const msg = event.messages[i];
1824
+ if ((msg == null ? void 0 : msg.role) === "user") {
1825
+ if (typeof msg.content === "string") return msg.content;
1826
+ if (Array.isArray(msg.content)) {
1827
+ const textPart = msg.content.find(
1828
+ (p) => (p == null ? void 0 : p.type) === "text" && typeof p.text === "string"
1829
+ );
1830
+ if (textPart) return textPart.text;
1831
+ }
1832
+ }
1833
+ }
1834
+ }
1835
+ return void 0;
1836
+ }
1837
+ finishGenerate(event, state) {
1838
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
1839
+ if (state.rootSpan) {
1840
+ const outputAttrs = [];
1841
+ if (state.recordOutputs) {
1842
+ outputAttrs.push(
1843
+ attrString("ai.response.finishReason", event.finishReason),
1844
+ attrString("ai.response.text", (_a = event.text) != null ? _a : void 0),
1845
+ attrString(
1846
+ "ai.response.providerMetadata",
1847
+ event.providerMetadata ? safeJsonWithUint8(event.providerMetadata) : void 0
1848
+ )
1849
+ );
1850
+ if (((_b = event.toolCalls) == null ? void 0 : _b.length) > 0) {
1851
+ outputAttrs.push(
1852
+ attrString(
1853
+ "ai.response.toolCalls",
1854
+ JSON.stringify(
1855
+ event.toolCalls.map((tc) => ({
1856
+ toolCallId: tc.toolCallId,
1857
+ toolName: tc.toolName,
1858
+ input: tc.input
1859
+ }))
1860
+ )
1861
+ )
1862
+ );
1863
+ }
1864
+ if (((_c = event.reasoning) == null ? void 0 : _c.length) > 0) {
1865
+ const reasoningText = event.reasoning.filter((part) => "text" in part).map((part) => part.text).join("\n");
1866
+ if (reasoningText) {
1867
+ outputAttrs.push(attrString("ai.response.reasoning", reasoningText));
1868
+ }
1869
+ }
1870
+ }
1871
+ const usage = (_d = event.totalUsage) != null ? _d : event.usage;
1872
+ if (usage) {
1873
+ outputAttrs.push(
1874
+ attrInt("ai.usage.inputTokens", usage.inputTokens),
1875
+ attrInt("ai.usage.outputTokens", usage.outputTokens),
1876
+ attrInt("ai.usage.totalTokens", usage.totalTokens),
1877
+ attrInt("ai.usage.reasoningTokens", usage.reasoningTokens),
1878
+ attrInt("ai.usage.cachedInputTokens", usage.cachedInputTokens)
1879
+ );
1880
+ }
1881
+ outputAttrs.push(
1882
+ attrInt("ai.toolCall.count", state.toolCallCount)
1883
+ );
1884
+ this.traceShipper.endSpan(state.rootSpan, { attributes: outputAttrs });
1885
+ }
1886
+ if (this.sendEvents) {
1887
+ const callMeta = this.extractRaindropMetadata(state.metadata);
1888
+ const userId = (_f = callMeta.userId) != null ? _f : (_e = this.defaultContext) == null ? void 0 : _e.userId;
1889
+ if (userId) {
1890
+ const eventName = (_i = (_h = callMeta.eventName) != null ? _h : (_g = this.defaultContext) == null ? void 0 : _g.eventName) != null ? _i : state.operationId;
1891
+ const output = (_j = event.text) != null ? _j : state.accumulatedText || void 0;
1892
+ const input = state.inputText;
1893
+ const model = (_k = event.response) == null ? void 0 : _k.modelId;
1894
+ const properties = {
1895
+ ...(_l = this.defaultContext) == null ? void 0 : _l.properties,
1896
+ ...callMeta.properties
1897
+ };
1898
+ const convoId = (_n = callMeta.convoId) != null ? _n : (_m = this.defaultContext) == null ? void 0 : _m.convoId;
1899
+ void this.eventShipper.patch(state.eventId, {
1900
+ eventName,
1901
+ userId,
1902
+ convoId,
1903
+ input,
1904
+ output,
1905
+ model,
1906
+ properties: Object.keys(properties).length > 0 ? properties : void 0,
1907
+ isPending: false
1908
+ }).catch((err) => {
1909
+ if (this.debug) {
1910
+ console.warn(
1911
+ `[raindrop-ai/ai-sdk] event patch failed: ${err instanceof Error ? err.message : err}`
1912
+ );
1913
+ }
1914
+ });
1915
+ }
1916
+ }
1917
+ }
1918
+ finishEmbed(event, state) {
1919
+ var _a;
1920
+ if (!state.rootSpan) return;
1921
+ const outputAttrs = [];
1922
+ const isMany = state.operationId === "ai.embedMany";
1923
+ if (state.recordOutputs) {
1924
+ if (isMany) {
1925
+ outputAttrs.push(
1926
+ attrString("ai.embeddings", safeJsonWithUint8(event.embedding))
1927
+ );
1928
+ } else {
1929
+ outputAttrs.push(
1930
+ attrString("ai.embedding", safeJsonWithUint8(event.embedding))
1931
+ );
1932
+ }
1933
+ }
1934
+ if (((_a = event.usage) == null ? void 0 : _a.tokens) != null) {
1935
+ outputAttrs.push(attrInt("ai.usage.tokens", event.usage.tokens));
1936
+ }
1937
+ this.traceShipper.endSpan(state.rootSpan, { attributes: outputAttrs });
1938
+ }
1939
+ };
1940
+
1941
+ // src/internal/traces.ts
1942
+ var TraceShipper2 = class extends TraceShipper {
1943
+ constructor(opts) {
1944
+ var _a, _b, _c;
1945
+ super({
1946
+ ...opts,
1947
+ sdkName: (_a = opts.sdkName) != null ? _a : "ai-sdk",
1948
+ serviceName: (_b = opts.serviceName) != null ? _b : "raindrop.ai-sdk",
1949
+ serviceVersion: (_c = opts.serviceVersion) != null ? _c : libraryVersion
1950
+ });
1951
+ }
1952
+ };
1953
+
1293
1954
  // src/internal/wrap/wrapAISDK.ts
1294
1955
  var AGENT_REPORTING_TOOL_NAME_DEFAULT = "__raindrop_report";
1295
1956
  var AGENT_REPORTING_SIGNALS_DEFAULT = {
@@ -1311,6 +1972,50 @@ var AGENT_REPORTING_SIGNALS_DEFAULT = {
1311
1972
  }
1312
1973
  };
1313
1974
  var AGENT_REPORTING_TOOL_PREAMBLE = "You have a diagnostic tool for flagging serious failures for developer review. Only call this when you hit a significant, unrecoverable problem \u2014 not for minor hiccups or routine clarifications. If you can still help the user, do that instead of calling this tool. This tool is invisible to the user \u2014 never mention it or its output.";
1975
+ var pendingStoresByShipper = /* @__PURE__ */ new WeakMap();
1976
+ var PendingToolSpanStore = class _PendingToolSpanStore {
1977
+ constructor() {
1978
+ this.spans = /* @__PURE__ */ new Map();
1979
+ }
1980
+ static for(traceShipper, eventId) {
1981
+ let byEvent = pendingStoresByShipper.get(traceShipper);
1982
+ if (!byEvent) {
1983
+ byEvent = /* @__PURE__ */ new Map();
1984
+ pendingStoresByShipper.set(traceShipper, byEvent);
1985
+ }
1986
+ let store = byEvent.get(eventId);
1987
+ if (!store) {
1988
+ store = new _PendingToolSpanStore();
1989
+ byEvent.set(eventId, store);
1990
+ }
1991
+ return store;
1992
+ }
1993
+ resolve(resolvedToolSpans, ctx) {
1994
+ for (const [key, span] of this.spans) {
1995
+ const toolCall = resolvedToolSpans.get(key);
1996
+ if (!toolCall) continue;
1997
+ finishToolSpan(toolCall, span, ctx, span.startTimeUnixNano);
1998
+ this.spans.delete(key);
1999
+ }
2000
+ }
2001
+ remember(toolCall, rootSpan, ctx, startTimeUnixNano) {
2002
+ if (this.spans.has(toolCall.key)) return;
2003
+ this.spans.set(toolCall.key, startToolSpan(toolCall, rootSpan, ctx, startTimeUnixNano));
2004
+ }
2005
+ closeAll(traceShipper) {
2006
+ for (const [, span] of this.spans) {
2007
+ traceShipper.endSpan(span, { endTimeUnixNano: span.startTimeUnixNano });
2008
+ }
2009
+ this.spans.clear();
2010
+ }
2011
+ cleanup(traceShipper, eventId) {
2012
+ if (this.spans.size > 0) return;
2013
+ const byEvent = pendingStoresByShipper.get(traceShipper);
2014
+ if (!byEvent) return;
2015
+ byEvent.delete(eventId);
2016
+ if (byEvent.size === 0) pendingStoresByShipper.delete(traceShipper);
2017
+ }
2018
+ };
1314
2019
  var warnedMissingUserId = false;
1315
2020
  function warnMissingUserIdOnce() {
1316
2021
  if (warnedMissingUserId) return;
@@ -1337,6 +2042,10 @@ function extractRaindropMetadata(metadata) {
1337
2042
  if (typeof userId === "string" && userId) result.userId = userId;
1338
2043
  const eventId = metadata["raindrop.eventId"];
1339
2044
  if (typeof eventId === "string" && eventId) result.eventId = eventId;
2045
+ const eventIdGenerated = metadata["raindrop.internal.eventIdGenerated"];
2046
+ if (eventIdGenerated === true || eventIdGenerated === "true" || eventIdGenerated === "1") {
2047
+ result.eventIdGenerated = true;
2048
+ }
1340
2049
  const convoId = metadata["raindrop.convoId"];
1341
2050
  if (typeof convoId === "string" && convoId) result.convoId = convoId;
1342
2051
  const eventName = metadata["raindrop.eventName"];
@@ -1451,6 +2160,9 @@ function detectAISDKVersion(aiSDK) {
1451
2160
  if (isFunction(aiSDK["tool"])) return "5";
1452
2161
  return "4";
1453
2162
  }
2163
+ function hasStructuredTelemetryEvents(aiSDK) {
2164
+ return isRecord(aiSDK) && isFunction(aiSDK["registerTelemetryIntegration"]) && isFunction(aiSDK["experimental_streamModelCall"]);
2165
+ }
1454
2166
  function asVercelSchema(jsonSchemaObj) {
1455
2167
  const validatorSymbol = /* @__PURE__ */ Symbol.for("vercel.ai.validator");
1456
2168
  const schemaSymbol = /* @__PURE__ */ Symbol.for("vercel.ai.schema");
@@ -1619,6 +2331,10 @@ function logFinalizeError(debug, err) {
1619
2331
  );
1620
2332
  }
1621
2333
  }
2334
+ function shouldKeepEventPending(params) {
2335
+ if (params.error != null || !params.canKeepEventPending) return false;
2336
+ return params.finishReason === "tool-calls" || params.finishReason === "tool_calls";
2337
+ }
1622
2338
  async function safeFinalize(finalize, debug, result, error) {
1623
2339
  try {
1624
2340
  await finalize(result, error);
@@ -1672,7 +2388,9 @@ function setupOperation(params) {
1672
2388
  const callTimeCtx = extractRaindropMetadata(telemetry == null ? void 0 : telemetry.metadata);
1673
2389
  const mergedCtx = mergeContexts(wrapTimeCtx, callTimeCtx);
1674
2390
  if (!mergedCtx.userId) warnMissingUserIdOnce();
1675
- const eventId = (_c = (_b = (_a = callTimeCtx.eventId) != null ? _a : mergedCtx.eventId) != null ? _b : inherited == null ? void 0 : inherited.eventId) != null ? _c : randomUUID();
2391
+ const hasCallTimeEventId = callTimeCtx.eventId != null;
2392
+ const hasWrapTimeEventId = wrapTimeCtx.eventId != null;
2393
+ const eventId = (_c = (_b = (_a = callTimeCtx.eventId) != null ? _a : wrapTimeCtx.eventId) != null ? _b : inherited == null ? void 0 : inherited.eventId) != null ? _c : randomUUID();
1676
2394
  const ctx = { ...mergedCtx, eventId };
1677
2395
  const inheritedParent = inherited && inherited.eventId === eventId ? { traceIdB64: inherited.traceIdB64, spanIdB64: inherited.spanIdB64 } : void 0;
1678
2396
  const outerOperationId = `ai.${operation}`;
@@ -1724,6 +2442,7 @@ function setupOperation(params) {
1724
2442
  return {
1725
2443
  eventId,
1726
2444
  ctx,
2445
+ canKeepEventPending: hasCallTimeEventId ? callTimeCtx.eventIdGenerated !== true : hasWrapTimeEventId,
1727
2446
  telemetry,
1728
2447
  rootSpan,
1729
2448
  wrappedArgs,
@@ -1746,6 +2465,12 @@ function createFinalize(params) {
1746
2465
  var _a, _b, _c, _d;
1747
2466
  const usage = extractUsageMetrics(result);
1748
2467
  const model = extractModel(result);
2468
+ const finishReason = extractFinishReason(result);
2469
+ const keepEventPending = shouldKeepEventPending({
2470
+ finishReason,
2471
+ error,
2472
+ canKeepEventPending: setup.canKeepEventPending
2473
+ });
1749
2474
  const inputAttachments = autoAttachmentEnabled ? extractInputAttachmentsFromArgs(arg) : void 0;
1750
2475
  const outputAttachments = autoAttachmentEnabled ? await extractOutputAttachmentsFromResult(result) : void 0;
1751
2476
  const baseMessages = coerceMessagesFromArgs(arg);
@@ -1767,7 +2492,18 @@ function createFinalize(params) {
1767
2492
  const output = patch.output;
1768
2493
  const finalModel = (_c = patch.model) != null ? _c : model;
1769
2494
  if (setup.rootSpan) {
1770
- const finishReason = extractFinishReason(result);
2495
+ const spanEndTimeUnixNano = nowUnixNanoString();
2496
+ const syntheticToolCallCount = emitTranscriptToolCallSpans({
2497
+ baseMessages,
2498
+ responseMessages,
2499
+ rootSpan: setup.rootSpan,
2500
+ eventId: setup.eventId,
2501
+ telemetry: setup.telemetry,
2502
+ toolCalls: setup.toolCalls,
2503
+ traceShipper,
2504
+ endTimeUnixNano: spanEndTimeUnixNano,
2505
+ keepEventPending
2506
+ });
1771
2507
  const providerMetadata = isRecord(result) ? result["providerMetadata"] : void 0;
1772
2508
  const resultToolCalls = isRecord(result) && Array.isArray(result["toolCalls"]) ? safeJsonWithUint8(result["toolCalls"]) : setup.toolCalls.length ? safeJsonWithUint8(setup.toolCalls) : void 0;
1773
2509
  traceShipper.endSpan(setup.rootSpan, {
@@ -1785,10 +2521,11 @@ function createFinalize(params) {
1785
2521
  attrInt("ai.usage.totalTokens", usage == null ? void 0 : usage.totalTokens),
1786
2522
  attrInt("ai.usage.reasoningTokens", usage == null ? void 0 : usage.reasoningTokens),
1787
2523
  attrInt("ai.usage.cachedInputTokens", usage == null ? void 0 : usage.cachedInputTokens),
1788
- attrInt("ai.toolCall.count", setup.toolCalls.length),
2524
+ attrInt("ai.toolCall.count", setup.toolCalls.length + syntheticToolCallCount),
1789
2525
  ...error ? [attrString("error.message", error instanceof Error ? error.message : String(error))] : []
1790
2526
  ],
1791
- error
2527
+ error,
2528
+ endTimeUnixNano: spanEndTimeUnixNano
1792
2529
  });
1793
2530
  }
1794
2531
  if (sendEvents) {
@@ -1801,7 +2538,7 @@ function createFinalize(params) {
1801
2538
  model: finalModel,
1802
2539
  properties: patch.properties,
1803
2540
  attachments: patch.attachments,
1804
- isPending: false
2541
+ isPending: keepEventPending
1805
2542
  }).catch((err) => {
1806
2543
  if (debug) {
1807
2544
  console.warn(
@@ -1812,6 +2549,89 @@ function createFinalize(params) {
1812
2549
  }
1813
2550
  };
1814
2551
  }
2552
+ function hasToolResult(toolCall) {
2553
+ return toolCall.result !== void 0 || toolCall.status === "ERROR";
2554
+ }
2555
+ function getExecutedToolCallKeys(toolCalls) {
2556
+ return new Set(
2557
+ toolCalls.map((tc) => buildToolCallMatchKey({ toolCallId: tc.id, toolName: tc.name, input: tc.args })).filter((key) => typeof key === "string" && key.length > 0)
2558
+ );
2559
+ }
2560
+ function getResolvedToolSpans(messages, executedKeys) {
2561
+ return new Map(
2562
+ extractToolSpansFromMessages(messages).filter((tc) => hasToolResult(tc) && !executedKeys.has(tc.key)).map((tc) => [tc.key, tc])
2563
+ );
2564
+ }
2565
+ function startToolSpan(toolCall, rootSpan, ctx, startTimeUnixNano) {
2566
+ var _a, _b, _c;
2567
+ const { operationName, resourceName } = opName("ai.toolCall", (_a = ctx.telemetry) == null ? void 0 : _a.functionId);
2568
+ return ctx.traceShipper.startSpan({
2569
+ name: "ai.toolCall",
2570
+ parent: { traceIdB64: rootSpan.ids.traceIdB64, spanIdB64: rootSpan.ids.spanIdB64 },
2571
+ eventId: ctx.eventId,
2572
+ operationId: "ai.toolCall",
2573
+ attributes: [
2574
+ attrString("operation.name", operationName),
2575
+ attrString("resource.name", resourceName),
2576
+ attrString("ai.telemetry.functionId", (_b = ctx.telemetry) == null ? void 0 : _b.functionId),
2577
+ attrString("ai.toolCall.name", toolCall.toolName),
2578
+ attrString("ai.toolCall.id", toolCall.toolCallId),
2579
+ ...((_c = ctx.telemetry) == null ? void 0 : _c.recordInputs) === false ? [] : [attrString("ai.toolCall.args", safeJsonWithUint8(toolCall.input))]
2580
+ ],
2581
+ startTimeUnixNano
2582
+ });
2583
+ }
2584
+ function finishToolSpan(toolCall, span, ctx, endTimeUnixNano) {
2585
+ var _a, _b, _c;
2586
+ const endAttributes = toolCall.status === "ERROR" ? [attrString("error.message", (_a = toolCall.errorMessage) != null ? _a : "Tool call failed")] : ((_b = ctx.telemetry) == null ? void 0 : _b.recordOutputs) === false ? [] : [attrString("ai.toolCall.result", safeJsonWithUint8(toolCall.result))];
2587
+ ctx.traceShipper.endSpan(span, {
2588
+ attributes: endAttributes,
2589
+ ...toolCall.status === "ERROR" ? { error: new Error((_c = toolCall.errorMessage) != null ? _c : "Tool call failed") } : {},
2590
+ endTimeUnixNano
2591
+ });
2592
+ }
2593
+ function emitToolSpan(toolCall, rootSpan, ctx, timeUnixNano) {
2594
+ const span = startToolSpan(toolCall, rootSpan, ctx, timeUnixNano);
2595
+ finishToolSpan(toolCall, span, ctx, timeUnixNano);
2596
+ }
2597
+ function emitTranscriptToolCallSpans(params) {
2598
+ const store = PendingToolSpanStore.for(params.traceShipper, params.eventId);
2599
+ const responseToolSpans = extractToolSpansFromMessages(params.responseMessages);
2600
+ if (responseToolSpans.length === 0 && params.baseMessages.length === 0) {
2601
+ if (!params.keepEventPending) {
2602
+ store.closeAll(params.traceShipper);
2603
+ }
2604
+ store.cleanup(params.traceShipper, params.eventId);
2605
+ return 0;
2606
+ }
2607
+ const ctx = {
2608
+ eventId: params.eventId,
2609
+ telemetry: params.telemetry,
2610
+ traceShipper: params.traceShipper
2611
+ };
2612
+ const executedKeys = getExecutedToolCallKeys(params.toolCalls);
2613
+ const resolvedSpans = getResolvedToolSpans(
2614
+ [...params.baseMessages, ...params.responseMessages],
2615
+ executedKeys
2616
+ );
2617
+ store.resolve(resolvedSpans, ctx);
2618
+ let syntheticToolCallCount = 0;
2619
+ for (const toolCall of responseToolSpans) {
2620
+ if (executedKeys.has(toolCall.key)) continue;
2621
+ executedKeys.add(toolCall.key);
2622
+ syntheticToolCallCount += 1;
2623
+ if (hasToolResult(toolCall) || !params.keepEventPending) {
2624
+ emitToolSpan(toolCall, params.rootSpan, ctx, params.endTimeUnixNano);
2625
+ } else {
2626
+ store.remember(toolCall, params.rootSpan, ctx, params.endTimeUnixNano);
2627
+ }
2628
+ }
2629
+ if (!params.keepEventPending) {
2630
+ store.closeAll(params.traceShipper);
2631
+ }
2632
+ store.cleanup(params.traceShipper, params.eventId);
2633
+ return syntheticToolCallCount;
2634
+ }
1815
2635
  function executeStreamingOperation(params) {
1816
2636
  const {
1817
2637
  operation,
@@ -1925,8 +2745,93 @@ async function executeNonStreamingOperation(params) {
1925
2745
  }
1926
2746
  }
1927
2747
  function wrapAISDK(aiSDK, deps) {
1928
- var _a, _b;
2748
+ var _a, _b, _c, _d;
1929
2749
  const debug = deps.eventShipper.isDebugEnabled() || deps.traceShipper.isDebugEnabled();
2750
+ if (deps.options.nativeTelemetry === true) {
2751
+ if (!hasStructuredTelemetryEvents(aiSDK)) {
2752
+ throw new Error(
2753
+ "[raindrop-ai/ai-sdk] nativeTelemetry requires AI SDK v7+. The AI SDK module passed to wrap() does not support structured telemetry events. Remove nativeTelemetry or upgrade to AI SDK v7."
2754
+ );
2755
+ }
2756
+ }
2757
+ const useNative = deps.options.nativeTelemetry === true;
2758
+ if (useNative) {
2759
+ const wrapTimeCtx = resolveContext(deps.options.context, { operation: "wrap", args: void 0 });
2760
+ const integration = new RaindropTelemetryIntegration({
2761
+ traceShipper: deps.traceShipper,
2762
+ eventShipper: deps.eventShipper,
2763
+ sendTraces: ((_a = deps.options.send) == null ? void 0 : _a.traces) !== false,
2764
+ sendEvents: ((_b = deps.options.send) == null ? void 0 : _b.events) !== false,
2765
+ debug,
2766
+ context: {
2767
+ userId: wrapTimeCtx.userId,
2768
+ eventId: wrapTimeCtx.eventId,
2769
+ eventName: wrapTimeCtx.eventName,
2770
+ convoId: wrapTimeCtx.convoId,
2771
+ properties: wrapTimeCtx.properties
2772
+ }
2773
+ });
2774
+ const registerFn = aiSDK["registerTelemetryIntegration"];
2775
+ if (isFunction(registerFn)) {
2776
+ registerFn(integration);
2777
+ }
2778
+ if (debug) {
2779
+ console.log("[raindrop-ai/ai-sdk] nativeTelemetry: registered RaindropTelemetryIntegration (no Proxy)");
2780
+ }
2781
+ const selfDiagnostics2 = normalizeSelfDiagnosticsConfig(deps.options.selfDiagnostics);
2782
+ if (selfDiagnostics2) {
2783
+ const textOps = /* @__PURE__ */ new Set(["generateText", "streamText"]);
2784
+ const jsonSchemaFactory = resolveJsonSchemaFactory(aiSDK);
2785
+ const proxyTarget2 = isModuleNamespace(aiSDK) ? Object.setPrototypeOf({}, aiSDK) : aiSDK;
2786
+ return new Proxy(proxyTarget2, {
2787
+ get(target, prop, receiver) {
2788
+ const original = Reflect.get(target, prop, receiver);
2789
+ if (typeof prop !== "string" || !textOps.has(prop) || !isFunction(original)) {
2790
+ return original;
2791
+ }
2792
+ return (...callArgs) => {
2793
+ var _a2, _b2;
2794
+ const arg = callArgs[0];
2795
+ if (!isRecord(arg)) return original.call(aiSDK, ...callArgs);
2796
+ const telemetry = extractExperimentalTelemetry(arg);
2797
+ const callMeta = (telemetry == null ? void 0 : telemetry.metadata) ? extractRaindropMetadata(telemetry.metadata) : {};
2798
+ const perCallEventId = (_b2 = (_a2 = callMeta.eventId) != null ? _a2 : wrapTimeCtx.eventId) != null ? _b2 : randomUUID();
2799
+ const perCallCtx = {
2800
+ eventId: perCallEventId,
2801
+ telemetry,
2802
+ sendTraces: false,
2803
+ debug,
2804
+ eventShipper: deps.eventShipper,
2805
+ traceShipper: deps.traceShipper,
2806
+ rootParentForChildren: void 0,
2807
+ jsonSchemaFactory,
2808
+ selfDiagnostics: selfDiagnostics2,
2809
+ aiSDKVersion: "7"
2810
+ };
2811
+ const tools = isRecord(arg["tools"]) ? { ...arg["tools"] } : {};
2812
+ const toolName = selfDiagnostics2.toolName;
2813
+ if (!(toolName in tools)) {
2814
+ const reportTool = createSelfDiagnosticsTool(perCallCtx);
2815
+ if (reportTool) tools[toolName] = reportTool;
2816
+ }
2817
+ const existingTelemetry = isRecord(arg["experimental_telemetry"]) ? arg["experimental_telemetry"] : {};
2818
+ const existingMetadata = isRecord(existingTelemetry["metadata"]) ? existingTelemetry["metadata"] : {};
2819
+ const mergedMetadata = existingMetadata["raindrop.eventId"] ? existingMetadata : { ...existingMetadata, "raindrop.eventId": perCallEventId };
2820
+ callArgs[0] = {
2821
+ ...arg,
2822
+ tools,
2823
+ experimental_telemetry: {
2824
+ ...existingTelemetry,
2825
+ metadata: mergedMetadata
2826
+ }
2827
+ };
2828
+ return original.call(aiSDK, ...callArgs);
2829
+ };
2830
+ }
2831
+ });
2832
+ }
2833
+ return aiSDK;
2834
+ }
1930
2835
  const instrumentedOps = /* @__PURE__ */ new Set([
1931
2836
  "generateText",
1932
2837
  "streamText",
@@ -1934,8 +2839,8 @@ function wrapAISDK(aiSDK, deps) {
1934
2839
  "streamObject"
1935
2840
  ]);
1936
2841
  const agentClasses = /* @__PURE__ */ new Set(["Agent", "Experimental_Agent", "ToolLoopAgent"]);
1937
- const sendEvents = ((_a = deps.options.send) == null ? void 0 : _a.events) !== false;
1938
- const sendTraces = ((_b = deps.options.send) == null ? void 0 : _b.traces) !== false;
2842
+ const sendEvents = ((_c = deps.options.send) == null ? void 0 : _c.events) !== false;
2843
+ const sendTraces = ((_d = deps.options.send) == null ? void 0 : _d.traces) !== false;
1939
2844
  const autoAttachmentEnabled = deps.options.autoAttachment !== false;
1940
2845
  const selfDiagnostics = normalizeSelfDiagnosticsConfig(deps.options.selfDiagnostics);
1941
2846
  const proxyTarget = isModuleNamespace(aiSDK) ? Object.setPrototypeOf({}, aiSDK) : aiSDK;
@@ -2119,6 +3024,18 @@ function wrapAgentGenerate(generate, instance, agentSettings, className, aiSDK,
2119
3024
  const output = patch.output;
2120
3025
  const finalModel = (_c2 = patch.model) != null ? _c2 : model;
2121
3026
  if (rootSpan) {
3027
+ const spanEndTimeUnixNano = nowUnixNanoString();
3028
+ const syntheticToolCallCount = emitTranscriptToolCallSpans({
3029
+ baseMessages,
3030
+ responseMessages,
3031
+ rootSpan,
3032
+ eventId,
3033
+ telemetry,
3034
+ toolCalls,
3035
+ traceShipper: deps.traceShipper,
3036
+ endTimeUnixNano: spanEndTimeUnixNano,
3037
+ keepEventPending: false
3038
+ });
2122
3039
  const finishReason = extractFinishReason(result);
2123
3040
  const providerMetadata = isRecord(result) ? result["providerMetadata"] : void 0;
2124
3041
  const resultToolCalls = isRecord(result) && Array.isArray(result["toolCalls"]) ? safeJsonWithUint8(result["toolCalls"]) : toolCalls.length ? safeJsonWithUint8(toolCalls) : void 0;
@@ -2137,7 +3054,7 @@ function wrapAgentGenerate(generate, instance, agentSettings, className, aiSDK,
2137
3054
  attrInt("ai.usage.totalTokens", usage == null ? void 0 : usage.totalTokens),
2138
3055
  attrInt("ai.usage.reasoningTokens", usage == null ? void 0 : usage.reasoningTokens),
2139
3056
  attrInt("ai.usage.cachedInputTokens", usage == null ? void 0 : usage.cachedInputTokens),
2140
- attrInt("ai.toolCall.count", toolCalls.length),
3057
+ attrInt("ai.toolCall.count", toolCalls.length + syntheticToolCallCount),
2141
3058
  ...error ? [
2142
3059
  attrString(
2143
3060
  "error.message",
@@ -2145,7 +3062,8 @@ function wrapAgentGenerate(generate, instance, agentSettings, className, aiSDK,
2145
3062
  )
2146
3063
  ] : []
2147
3064
  ],
2148
- error
3065
+ error,
3066
+ endTimeUnixNano: spanEndTimeUnixNano
2149
3067
  });
2150
3068
  }
2151
3069
  if (sendEvents) {
@@ -2313,6 +3231,18 @@ function wrapAgentStream(stream, instance, agentSettings, className, aiSDK, deps
2313
3231
  const output = patch.output;
2314
3232
  const finalModel = (_c2 = patch.model) != null ? _c2 : model;
2315
3233
  if (rootSpan) {
3234
+ const spanEndTimeUnixNano = nowUnixNanoString();
3235
+ const syntheticToolCallCount = emitTranscriptToolCallSpans({
3236
+ baseMessages,
3237
+ responseMessages,
3238
+ rootSpan,
3239
+ eventId,
3240
+ telemetry,
3241
+ toolCalls,
3242
+ traceShipper: deps.traceShipper,
3243
+ endTimeUnixNano: spanEndTimeUnixNano,
3244
+ keepEventPending: false
3245
+ });
2316
3246
  const finishReason = extractFinishReason(result);
2317
3247
  const providerMetadata = isRecord(result) ? result["providerMetadata"] : void 0;
2318
3248
  const resultToolCalls = isRecord(result) && Array.isArray(result["toolCalls"]) ? safeJsonWithUint8(result["toolCalls"]) : toolCalls.length ? safeJsonWithUint8(toolCalls) : void 0;
@@ -2331,7 +3261,7 @@ function wrapAgentStream(stream, instance, agentSettings, className, aiSDK, deps
2331
3261
  attrInt("ai.usage.totalTokens", usage == null ? void 0 : usage.totalTokens),
2332
3262
  attrInt("ai.usage.reasoningTokens", usage == null ? void 0 : usage.reasoningTokens),
2333
3263
  attrInt("ai.usage.cachedInputTokens", usage == null ? void 0 : usage.cachedInputTokens),
2334
- attrInt("ai.toolCall.count", toolCalls.length),
3264
+ attrInt("ai.toolCall.count", toolCalls.length + syntheticToolCallCount),
2335
3265
  ...error ? [
2336
3266
  attrString(
2337
3267
  "error.message",
@@ -2339,7 +3269,8 @@ function wrapAgentStream(stream, instance, agentSettings, className, aiSDK, deps
2339
3269
  )
2340
3270
  ] : []
2341
3271
  ],
2342
- error
3272
+ error,
3273
+ endTimeUnixNano: spanEndTimeUnixNano
2343
3274
  });
2344
3275
  }
2345
3276
  if (sendEvents) {
@@ -2509,10 +3440,10 @@ function wrapToolExecute(name, tool, ctx, toolCalls) {
2509
3440
  lastValue = value;
2510
3441
  yield value;
2511
3442
  }
2512
- toolCalls.push({ name, args: toolArgs, result: lastValue, status: "OK" });
3443
+ toolCalls.push({ id: toolCallId, name, args: toolArgs, result: lastValue, status: "OK" });
2513
3444
  endToolSpan(toolSpan, lastValue);
2514
3445
  } catch (error) {
2515
- toolCalls.push({ name, args: toolArgs, status: "ERROR" });
3446
+ toolCalls.push({ id: toolCallId, name, args: toolArgs, status: "ERROR" });
2516
3447
  endToolSpan(toolSpan, void 0, error);
2517
3448
  throw error;
2518
3449
  }
@@ -2525,11 +3456,17 @@ function wrapToolExecute(name, tool, ctx, toolCalls) {
2525
3456
  const run = async () => {
2526
3457
  try {
2527
3458
  const awaitedResult = await result;
2528
- toolCalls.push({ name, args: toolArgs, result: awaitedResult, status: "OK" });
3459
+ toolCalls.push({
3460
+ id: toolCallId,
3461
+ name,
3462
+ args: toolArgs,
3463
+ result: awaitedResult,
3464
+ status: "OK"
3465
+ });
2529
3466
  endToolSpan(toolSpan, awaitedResult);
2530
3467
  return awaitedResult;
2531
3468
  } catch (error) {
2532
- toolCalls.push({ name, args: toolArgs, status: "ERROR" });
3469
+ toolCalls.push({ id: toolCallId, name, args: toolArgs, status: "ERROR" });
2533
3470
  endToolSpan(toolSpan, void 0, error);
2534
3471
  throw error;
2535
3472
  }
@@ -2915,15 +3852,44 @@ function extractNestedTokens(usage, key) {
2915
3852
 
2916
3853
  // src/index.ts
2917
3854
  function eventMetadata(options) {
2918
- var _a;
2919
3855
  const result = {};
2920
- result["raindrop.eventId"] = (_a = options.eventId) != null ? _a : randomUUID();
3856
+ if (options.eventId) {
3857
+ result["raindrop.eventId"] = options.eventId;
3858
+ } else {
3859
+ result["raindrop.eventId"] = randomUUID();
3860
+ result["raindrop.internal.eventIdGenerated"] = "true";
3861
+ }
2921
3862
  if (options.userId) result["raindrop.userId"] = options.userId;
2922
3863
  if (options.convoId) result["raindrop.convoId"] = options.convoId;
2923
3864
  if (options.eventName) result["raindrop.eventName"] = options.eventName;
2924
3865
  if (options.properties) result["raindrop.properties"] = JSON.stringify(options.properties);
2925
3866
  return result;
2926
3867
  }
3868
+ function deriveChatTurnMessageId(request) {
3869
+ const messages = Array.isArray(request.messages) ? request.messages : [];
3870
+ for (let i = messages.length - 1; i >= 0; i--) {
3871
+ const message = messages[i];
3872
+ if ((message == null ? void 0 : message.role) === "user" && typeof message.id === "string" && message.id.length > 0) {
3873
+ return message.id;
3874
+ }
3875
+ }
3876
+ if (typeof request.messageId === "string" && request.messageId.length > 0) {
3877
+ return request.messageId;
3878
+ }
3879
+ return void 0;
3880
+ }
3881
+ function eventMetadataFromChatRequest(options) {
3882
+ var _a, _b;
3883
+ const { request, ...rest } = options;
3884
+ const convoId = (_a = rest.convoId) != null ? _a : typeof request.id === "string" && request.id.length > 0 ? request.id : void 0;
3885
+ const turnMessageId = deriveChatTurnMessageId(request);
3886
+ const eventId = (_b = rest.eventId) != null ? _b : turnMessageId ? convoId ? `chat:${convoId}:${turnMessageId}` : `chat:${turnMessageId}` : void 0;
3887
+ return eventMetadata({
3888
+ ...rest,
3889
+ ...convoId ? { convoId } : {},
3890
+ ...eventId ? { eventId } : {}
3891
+ });
3892
+ }
2927
3893
  function envDebugEnabled() {
2928
3894
  var _a;
2929
3895
  if (typeof process === "undefined") return false;
@@ -2968,6 +3934,16 @@ function createRaindropAISDK(opts) {
2968
3934
  traceShipper
2969
3935
  });
2970
3936
  },
3937
+ createTelemetryIntegration(context) {
3938
+ return new RaindropTelemetryIntegration({
3939
+ traceShipper,
3940
+ eventShipper,
3941
+ sendTraces: tracesEnabled,
3942
+ sendEvents: eventsEnabled,
3943
+ debug: envDebug,
3944
+ context
3945
+ });
3946
+ },
2971
3947
  events: {
2972
3948
  async patch(eventId, patch) {
2973
3949
  await eventShipper.patch(eventId, patch);
@@ -3001,4 +3977,4 @@ function createRaindropAISDK(opts) {
3001
3977
  };
3002
3978
  }
3003
3979
 
3004
- export { _resetWarnedMissingUserId, createRaindropAISDK, currentSpan, eventMetadata, getContextManager, withCurrent };
3980
+ export { RaindropTelemetryIntegration, _resetWarnedMissingUserId, createRaindropAISDK, currentSpan, eventMetadata, eventMetadataFromChatRequest, getContextManager, withCurrent };