@raindrop-ai/ai-sdk 0.0.16 → 0.0.18

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.
@@ -4,7 +4,7 @@ var async_hooks = require('async_hooks');
4
4
 
5
5
  // src/index.node.ts
6
6
 
7
- // ../core/dist/chunk-FTBZHS25.js
7
+ // ../core/dist/chunk-FOHDGBT5.js
8
8
  function getCrypto() {
9
9
  const c = globalThis.crypto;
10
10
  return c;
@@ -275,6 +275,7 @@ var EventShipper = class {
275
275
  console.log(`${this.prefix} queue patch`, {
276
276
  eventId,
277
277
  userId: patch.userId,
278
+ convoId: patch.convoId,
278
279
  eventName: patch.eventName,
279
280
  hasInput: typeof patch.input === "string" && patch.input.length > 0,
280
281
  hasOutput: typeof patch.output === "string" && patch.output.length > 0,
@@ -403,16 +404,18 @@ var EventShipper = class {
403
404
  return;
404
405
  }
405
406
  const { wizardSession, ...restProperties } = (_e = accumulated.properties) != null ? _e : {};
407
+ const convoId = (_f = accumulated.convoId) != null ? _f : sticky.convoId;
408
+ const isPending = (_h = (_g = accumulated.isPending) != null ? _g : sticky.isPending) != null ? _h : true;
406
409
  const payload = {
407
410
  event_id: eventId,
408
411
  user_id: userId,
409
412
  event: eventName,
410
- timestamp: (_f = accumulated.timestamp) != null ? _f : (/* @__PURE__ */ new Date()).toISOString(),
413
+ timestamp: (_i = accumulated.timestamp) != null ? _i : (/* @__PURE__ */ new Date()).toISOString(),
411
414
  ai_data: {
412
415
  input: accumulated.input,
413
416
  output: accumulated.output,
414
417
  model: accumulated.model,
415
- convo_id: (_g = accumulated.convoId) != null ? _g : sticky.convoId
418
+ convo_id: convoId
416
419
  },
417
420
  properties: {
418
421
  ...restProperties,
@@ -420,7 +423,7 @@ var EventShipper = class {
420
423
  $context: this.context
421
424
  },
422
425
  attachments: accumulated.attachments,
423
- is_pending: ((_i = (_h = accumulated.isPending) != null ? _h : sticky.isPending) != null ? _i : true) !== false
426
+ is_pending: isPending
424
427
  };
425
428
  const url = `${this.baseUrl}events/track_partial`;
426
429
  if (this.debug) {
@@ -428,7 +431,8 @@ var EventShipper = class {
428
431
  eventId,
429
432
  eventName,
430
433
  userId,
431
- isPending: payload.is_pending,
434
+ convoId,
435
+ isPending,
432
436
  inputPreview: typeof accumulated.input === "string" ? accumulated.input.slice(0, 120) : void 0,
433
437
  outputPreview: typeof accumulated.output === "string" ? accumulated.output.slice(0, 120) : void 0,
434
438
  attachments: (_k = (_j = accumulated.attachments) == null ? void 0 : _j.length) != null ? _k : 0,
@@ -460,7 +464,6 @@ var EventShipper = class {
460
464
  } finally {
461
465
  this.inFlight.delete(p);
462
466
  }
463
- const isPending = payload.is_pending;
464
467
  if (!isPending) {
465
468
  this.sticky.delete(eventId);
466
469
  }
@@ -788,7 +791,7 @@ async function* asyncGeneratorWithCurrent(span, gen) {
788
791
  // package.json
789
792
  var package_default = {
790
793
  name: "@raindrop-ai/ai-sdk",
791
- version: "0.0.16"};
794
+ version: "0.0.18"};
792
795
 
793
796
  // src/internal/version.ts
794
797
  var libraryName = package_default.name;
@@ -1174,6 +1177,145 @@ function extractResponseMessages(result) {
1174
1177
  }
1175
1178
  return [];
1176
1179
  }
1180
+ function buildToolCallMatchKey(info) {
1181
+ if (typeof info.toolCallId === "string" && info.toolCallId.length > 0) {
1182
+ return `id:${info.toolCallId}`;
1183
+ }
1184
+ if (typeof info.toolName === "string" && info.toolName.length > 0) {
1185
+ const inputJson = safeJsonWithUint8(info.input);
1186
+ return inputJson !== void 0 ? `name:${info.toolName}|input:${inputJson}` : `name:${info.toolName}`;
1187
+ }
1188
+ return void 0;
1189
+ }
1190
+ function isTranscriptToolResultError(part, result) {
1191
+ if (part["isError"] === true || part["type"] === "tool-error") {
1192
+ return true;
1193
+ }
1194
+ if (isRecord(result) && typeof result["type"] === "string") {
1195
+ return result["type"].startsWith("error") || result["type"] === "execution-denied";
1196
+ }
1197
+ return false;
1198
+ }
1199
+ function getTranscriptToolErrorMessage(result) {
1200
+ if (typeof result === "string" && result.length > 0) {
1201
+ return result;
1202
+ }
1203
+ if (isRecord(result)) {
1204
+ if (typeof result["value"] === "string" && result["value"].length > 0) {
1205
+ return result["value"];
1206
+ }
1207
+ if (typeof result["reason"] === "string" && result["reason"].length > 0) {
1208
+ return result["reason"];
1209
+ }
1210
+ if (typeof result["message"] === "string" && result["message"].length > 0) {
1211
+ return result["message"];
1212
+ }
1213
+ }
1214
+ return safeJsonWithUint8(result);
1215
+ }
1216
+ function getTranscriptMessageParts(message) {
1217
+ if (!isRecord(message)) return [];
1218
+ const content = message["content"];
1219
+ if (Array.isArray(content)) {
1220
+ return content.filter(isRecord);
1221
+ }
1222
+ return isRecord(content) ? [content] : [];
1223
+ }
1224
+ function getTranscriptToolCallInput(part) {
1225
+ return "input" in part ? part["input"] : "args" in part ? part["args"] : void 0;
1226
+ }
1227
+ function getTranscriptToolCallId(part) {
1228
+ const toolCallId = part["toolCallId"];
1229
+ return typeof toolCallId === "string" && toolCallId.length > 0 ? toolCallId : void 0;
1230
+ }
1231
+ function getTranscriptToolResultValue(part) {
1232
+ if ("output" in part) return part["output"];
1233
+ if ("result" in part) return part["result"];
1234
+ return part["error"];
1235
+ }
1236
+ function rememberPendingTranscriptToolCallKey(pendingKeysByToolName, toolName, key) {
1237
+ var _a;
1238
+ if (!toolName) return;
1239
+ const pendingKeys = (_a = pendingKeysByToolName.get(toolName)) != null ? _a : [];
1240
+ if (pendingKeys.includes(key)) return;
1241
+ pendingKeys.push(key);
1242
+ pendingKeysByToolName.set(toolName, pendingKeys);
1243
+ }
1244
+ function takePendingTranscriptToolCallKey(pendingKeysByToolName, toolName) {
1245
+ if (!toolName) return void 0;
1246
+ const pendingKeys = pendingKeysByToolName.get(toolName);
1247
+ if (!pendingKeys || pendingKeys.length === 0) return void 0;
1248
+ const key = pendingKeys.shift();
1249
+ if (key === void 0) return void 0;
1250
+ if (pendingKeys.length === 0) {
1251
+ pendingKeysByToolName.delete(toolName);
1252
+ }
1253
+ return key;
1254
+ }
1255
+ function mergeTranscriptToolCallPart(params) {
1256
+ var _a, _b, _c, _d;
1257
+ const { spans, pendingKeysByToolName, part } = params;
1258
+ const toolCallId = getTranscriptToolCallId(part);
1259
+ const toolName = typeof part["toolName"] === "string" ? part["toolName"] : void 0;
1260
+ const input = getTranscriptToolCallInput(part);
1261
+ const key = buildToolCallMatchKey({ toolCallId, toolName, input });
1262
+ if (!key) return;
1263
+ const placeholderKey = toolCallId == null ? buildToolCallMatchKey({ toolCallId: void 0, toolName, input: void 0 }) : void 0;
1264
+ const placeholder = placeholderKey && placeholderKey !== key ? spans.get(placeholderKey) : void 0;
1265
+ const existing = (_a = spans.get(key)) != null ? _a : placeholder;
1266
+ spans.set(key, {
1267
+ key,
1268
+ toolCallId: (_b = existing == null ? void 0 : existing.toolCallId) != null ? _b : toolCallId,
1269
+ toolName: (_c = existing == null ? void 0 : existing.toolName) != null ? _c : toolName,
1270
+ input: (_d = existing == null ? void 0 : existing.input) != null ? _d : input,
1271
+ result: existing == null ? void 0 : existing.result,
1272
+ status: existing == null ? void 0 : existing.status,
1273
+ errorMessage: existing == null ? void 0 : existing.errorMessage
1274
+ });
1275
+ if (placeholderKey && placeholderKey !== key) {
1276
+ spans.delete(placeholderKey);
1277
+ }
1278
+ if (!toolCallId && (existing == null ? void 0 : existing.result) === void 0) {
1279
+ rememberPendingTranscriptToolCallKey(pendingKeysByToolName, toolName, key);
1280
+ }
1281
+ }
1282
+ function mergeTranscriptToolResultPart(params) {
1283
+ var _a, _b, _c;
1284
+ const { spans, pendingKeysByToolName, part } = params;
1285
+ const toolCallId = getTranscriptToolCallId(part);
1286
+ const toolName = typeof part["toolName"] === "string" ? part["toolName"] : void 0;
1287
+ const result = getTranscriptToolResultValue(part);
1288
+ const fallbackKey = buildToolCallMatchKey({ toolCallId, toolName, input: void 0 });
1289
+ const key = toolCallId != null ? fallbackKey : (_a = takePendingTranscriptToolCallKey(pendingKeysByToolName, toolName)) != null ? _a : fallbackKey;
1290
+ if (!key) return;
1291
+ const existing = spans.get(key);
1292
+ const isError = isTranscriptToolResultError(part, result);
1293
+ spans.set(key, {
1294
+ key,
1295
+ toolCallId: (_b = existing == null ? void 0 : existing.toolCallId) != null ? _b : toolCallId,
1296
+ toolName: (_c = existing == null ? void 0 : existing.toolName) != null ? _c : toolName,
1297
+ input: existing == null ? void 0 : existing.input,
1298
+ result,
1299
+ status: isError ? "ERROR" : "OK",
1300
+ errorMessage: isError ? getTranscriptToolErrorMessage(result) : void 0
1301
+ });
1302
+ }
1303
+ function extractToolSpansFromMessages(messages) {
1304
+ const spans = /* @__PURE__ */ new Map();
1305
+ const pendingKeysByToolName = /* @__PURE__ */ new Map();
1306
+ for (const message of messages) {
1307
+ for (const part of getTranscriptMessageParts(message)) {
1308
+ if (part["type"] === "tool-call") {
1309
+ mergeTranscriptToolCallPart({ spans, pendingKeysByToolName, part });
1310
+ continue;
1311
+ }
1312
+ if (part["type"] === "tool-result" || part["type"] === "tool-error") {
1313
+ mergeTranscriptToolResultPart({ spans, pendingKeysByToolName, part });
1314
+ }
1315
+ }
1316
+ }
1317
+ return [...spans.values()];
1318
+ }
1177
1319
  function extractTextFromLmContent(content) {
1178
1320
  if (!Array.isArray(content)) return void 0;
1179
1321
  let result = "";
@@ -1189,7 +1331,7 @@ function extractToolCallsFromLmContent(content) {
1189
1331
  const calls = [];
1190
1332
  for (const part of content) {
1191
1333
  if (!isRecord(part) || part["type"] !== "tool-call") continue;
1192
- const toolCallId = typeof part["toolCallId"] === "string" ? part["toolCallId"] : void 0;
1334
+ const toolCallId = getTranscriptToolCallId(part);
1193
1335
  const toolName = typeof part["toolName"] === "string" ? part["toolName"] : void 0;
1194
1336
  if (toolCallId || toolName) {
1195
1337
  calls.push({ toolCallId, toolName, input: part["input"] });
@@ -1228,7 +1370,7 @@ function toOtlpAttr(key, value) {
1228
1370
  }
1229
1371
  function attrsFromTelemetryMetadata(metadata) {
1230
1372
  if (!metadata) return [];
1231
- return Object.entries(metadata).map(([k, v]) => {
1373
+ return Object.entries(metadata).filter(([k]) => !k.startsWith("raindrop.internal.")).map(([k, v]) => {
1232
1374
  const key = k === "raindrop.userId" ? "raindrop.ai.userId" : k;
1233
1375
  return toOtlpAttr(`ai.telemetry.metadata.${key}`, v);
1234
1376
  });
@@ -1317,6 +1459,50 @@ var AGENT_REPORTING_SIGNALS_DEFAULT = {
1317
1459
  }
1318
1460
  };
1319
1461
  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.";
1462
+ var pendingStoresByShipper = /* @__PURE__ */ new WeakMap();
1463
+ var PendingToolSpanStore = class _PendingToolSpanStore {
1464
+ constructor() {
1465
+ this.spans = /* @__PURE__ */ new Map();
1466
+ }
1467
+ static for(traceShipper, eventId) {
1468
+ let byEvent = pendingStoresByShipper.get(traceShipper);
1469
+ if (!byEvent) {
1470
+ byEvent = /* @__PURE__ */ new Map();
1471
+ pendingStoresByShipper.set(traceShipper, byEvent);
1472
+ }
1473
+ let store = byEvent.get(eventId);
1474
+ if (!store) {
1475
+ store = new _PendingToolSpanStore();
1476
+ byEvent.set(eventId, store);
1477
+ }
1478
+ return store;
1479
+ }
1480
+ resolve(resolvedToolSpans, ctx) {
1481
+ for (const [key, span] of this.spans) {
1482
+ const toolCall = resolvedToolSpans.get(key);
1483
+ if (!toolCall) continue;
1484
+ finishToolSpan(toolCall, span, ctx, span.startTimeUnixNano);
1485
+ this.spans.delete(key);
1486
+ }
1487
+ }
1488
+ remember(toolCall, rootSpan, ctx, startTimeUnixNano) {
1489
+ if (this.spans.has(toolCall.key)) return;
1490
+ this.spans.set(toolCall.key, startToolSpan(toolCall, rootSpan, ctx, startTimeUnixNano));
1491
+ }
1492
+ closeAll(traceShipper) {
1493
+ for (const [, span] of this.spans) {
1494
+ traceShipper.endSpan(span, { endTimeUnixNano: span.startTimeUnixNano });
1495
+ }
1496
+ this.spans.clear();
1497
+ }
1498
+ cleanup(traceShipper, eventId) {
1499
+ if (this.spans.size > 0) return;
1500
+ const byEvent = pendingStoresByShipper.get(traceShipper);
1501
+ if (!byEvent) return;
1502
+ byEvent.delete(eventId);
1503
+ if (byEvent.size === 0) pendingStoresByShipper.delete(traceShipper);
1504
+ }
1505
+ };
1320
1506
  var warnedMissingUserId = false;
1321
1507
  function warnMissingUserIdOnce() {
1322
1508
  if (warnedMissingUserId) return;
@@ -1343,6 +1529,10 @@ function extractRaindropMetadata(metadata) {
1343
1529
  if (typeof userId === "string" && userId) result.userId = userId;
1344
1530
  const eventId = metadata["raindrop.eventId"];
1345
1531
  if (typeof eventId === "string" && eventId) result.eventId = eventId;
1532
+ const eventIdGenerated = metadata["raindrop.internal.eventIdGenerated"];
1533
+ if (eventIdGenerated === true || eventIdGenerated === "true" || eventIdGenerated === "1") {
1534
+ result.eventIdGenerated = true;
1535
+ }
1346
1536
  const convoId = metadata["raindrop.convoId"];
1347
1537
  if (typeof convoId === "string" && convoId) result.convoId = convoId;
1348
1538
  const eventName = metadata["raindrop.eventName"];
@@ -1625,6 +1815,10 @@ function logFinalizeError(debug, err) {
1625
1815
  );
1626
1816
  }
1627
1817
  }
1818
+ function shouldKeepEventPending(params) {
1819
+ if (params.error != null || !params.canKeepEventPending) return false;
1820
+ return params.finishReason === "tool-calls" || params.finishReason === "tool_calls";
1821
+ }
1628
1822
  async function safeFinalize(finalize, debug, result, error) {
1629
1823
  try {
1630
1824
  await finalize(result, error);
@@ -1678,7 +1872,9 @@ function setupOperation(params) {
1678
1872
  const callTimeCtx = extractRaindropMetadata(telemetry == null ? void 0 : telemetry.metadata);
1679
1873
  const mergedCtx = mergeContexts(wrapTimeCtx, callTimeCtx);
1680
1874
  if (!mergedCtx.userId) warnMissingUserIdOnce();
1681
- const eventId = (_c = (_b = (_a = callTimeCtx.eventId) != null ? _a : mergedCtx.eventId) != null ? _b : inherited == null ? void 0 : inherited.eventId) != null ? _c : randomUUID();
1875
+ const hasCallTimeEventId = callTimeCtx.eventId != null;
1876
+ const hasWrapTimeEventId = wrapTimeCtx.eventId != null;
1877
+ const eventId = (_c = (_b = (_a = callTimeCtx.eventId) != null ? _a : wrapTimeCtx.eventId) != null ? _b : inherited == null ? void 0 : inherited.eventId) != null ? _c : randomUUID();
1682
1878
  const ctx = { ...mergedCtx, eventId };
1683
1879
  const inheritedParent = inherited && inherited.eventId === eventId ? { traceIdB64: inherited.traceIdB64, spanIdB64: inherited.spanIdB64 } : void 0;
1684
1880
  const outerOperationId = `ai.${operation}`;
@@ -1730,6 +1926,7 @@ function setupOperation(params) {
1730
1926
  return {
1731
1927
  eventId,
1732
1928
  ctx,
1929
+ canKeepEventPending: hasCallTimeEventId ? callTimeCtx.eventIdGenerated !== true : hasWrapTimeEventId,
1733
1930
  telemetry,
1734
1931
  rootSpan,
1735
1932
  wrappedArgs,
@@ -1752,6 +1949,12 @@ function createFinalize(params) {
1752
1949
  var _a, _b, _c, _d;
1753
1950
  const usage = extractUsageMetrics(result);
1754
1951
  const model = extractModel(result);
1952
+ const finishReason = extractFinishReason(result);
1953
+ const keepEventPending = shouldKeepEventPending({
1954
+ finishReason,
1955
+ error,
1956
+ canKeepEventPending: setup.canKeepEventPending
1957
+ });
1755
1958
  const inputAttachments = autoAttachmentEnabled ? extractInputAttachmentsFromArgs(arg) : void 0;
1756
1959
  const outputAttachments = autoAttachmentEnabled ? await extractOutputAttachmentsFromResult(result) : void 0;
1757
1960
  const baseMessages = coerceMessagesFromArgs(arg);
@@ -1773,7 +1976,18 @@ function createFinalize(params) {
1773
1976
  const output = patch.output;
1774
1977
  const finalModel = (_c = patch.model) != null ? _c : model;
1775
1978
  if (setup.rootSpan) {
1776
- const finishReason = extractFinishReason(result);
1979
+ const spanEndTimeUnixNano = nowUnixNanoString();
1980
+ const syntheticToolCallCount = emitTranscriptToolCallSpans({
1981
+ baseMessages,
1982
+ responseMessages,
1983
+ rootSpan: setup.rootSpan,
1984
+ eventId: setup.eventId,
1985
+ telemetry: setup.telemetry,
1986
+ toolCalls: setup.toolCalls,
1987
+ traceShipper,
1988
+ endTimeUnixNano: spanEndTimeUnixNano,
1989
+ keepEventPending
1990
+ });
1777
1991
  const providerMetadata = isRecord(result) ? result["providerMetadata"] : void 0;
1778
1992
  const resultToolCalls = isRecord(result) && Array.isArray(result["toolCalls"]) ? safeJsonWithUint8(result["toolCalls"]) : setup.toolCalls.length ? safeJsonWithUint8(setup.toolCalls) : void 0;
1779
1993
  traceShipper.endSpan(setup.rootSpan, {
@@ -1791,10 +2005,11 @@ function createFinalize(params) {
1791
2005
  attrInt("ai.usage.totalTokens", usage == null ? void 0 : usage.totalTokens),
1792
2006
  attrInt("ai.usage.reasoningTokens", usage == null ? void 0 : usage.reasoningTokens),
1793
2007
  attrInt("ai.usage.cachedInputTokens", usage == null ? void 0 : usage.cachedInputTokens),
1794
- attrInt("ai.toolCall.count", setup.toolCalls.length),
2008
+ attrInt("ai.toolCall.count", setup.toolCalls.length + syntheticToolCallCount),
1795
2009
  ...error ? [attrString("error.message", error instanceof Error ? error.message : String(error))] : []
1796
2010
  ],
1797
- error
2011
+ error,
2012
+ endTimeUnixNano: spanEndTimeUnixNano
1798
2013
  });
1799
2014
  }
1800
2015
  if (sendEvents) {
@@ -1807,7 +2022,7 @@ function createFinalize(params) {
1807
2022
  model: finalModel,
1808
2023
  properties: patch.properties,
1809
2024
  attachments: patch.attachments,
1810
- isPending: false
2025
+ isPending: keepEventPending
1811
2026
  }).catch((err) => {
1812
2027
  if (debug) {
1813
2028
  console.warn(
@@ -1818,6 +2033,89 @@ function createFinalize(params) {
1818
2033
  }
1819
2034
  };
1820
2035
  }
2036
+ function hasToolResult(toolCall) {
2037
+ return toolCall.result !== void 0 || toolCall.status === "ERROR";
2038
+ }
2039
+ function getExecutedToolCallKeys(toolCalls) {
2040
+ return new Set(
2041
+ toolCalls.map((tc) => buildToolCallMatchKey({ toolCallId: tc.id, toolName: tc.name, input: tc.args })).filter((key) => typeof key === "string" && key.length > 0)
2042
+ );
2043
+ }
2044
+ function getResolvedToolSpans(messages, executedKeys) {
2045
+ return new Map(
2046
+ extractToolSpansFromMessages(messages).filter((tc) => hasToolResult(tc) && !executedKeys.has(tc.key)).map((tc) => [tc.key, tc])
2047
+ );
2048
+ }
2049
+ function startToolSpan(toolCall, rootSpan, ctx, startTimeUnixNano) {
2050
+ var _a, _b, _c;
2051
+ const { operationName, resourceName } = opName("ai.toolCall", (_a = ctx.telemetry) == null ? void 0 : _a.functionId);
2052
+ return ctx.traceShipper.startSpan({
2053
+ name: "ai.toolCall",
2054
+ parent: { traceIdB64: rootSpan.ids.traceIdB64, spanIdB64: rootSpan.ids.spanIdB64 },
2055
+ eventId: ctx.eventId,
2056
+ operationId: "ai.toolCall",
2057
+ attributes: [
2058
+ attrString("operation.name", operationName),
2059
+ attrString("resource.name", resourceName),
2060
+ attrString("ai.telemetry.functionId", (_b = ctx.telemetry) == null ? void 0 : _b.functionId),
2061
+ attrString("ai.toolCall.name", toolCall.toolName),
2062
+ attrString("ai.toolCall.id", toolCall.toolCallId),
2063
+ ...((_c = ctx.telemetry) == null ? void 0 : _c.recordInputs) === false ? [] : [attrString("ai.toolCall.args", safeJsonWithUint8(toolCall.input))]
2064
+ ],
2065
+ startTimeUnixNano
2066
+ });
2067
+ }
2068
+ function finishToolSpan(toolCall, span, ctx, endTimeUnixNano) {
2069
+ var _a, _b, _c;
2070
+ 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))];
2071
+ ctx.traceShipper.endSpan(span, {
2072
+ attributes: endAttributes,
2073
+ ...toolCall.status === "ERROR" ? { error: new Error((_c = toolCall.errorMessage) != null ? _c : "Tool call failed") } : {},
2074
+ endTimeUnixNano
2075
+ });
2076
+ }
2077
+ function emitToolSpan(toolCall, rootSpan, ctx, timeUnixNano) {
2078
+ const span = startToolSpan(toolCall, rootSpan, ctx, timeUnixNano);
2079
+ finishToolSpan(toolCall, span, ctx, timeUnixNano);
2080
+ }
2081
+ function emitTranscriptToolCallSpans(params) {
2082
+ const store = PendingToolSpanStore.for(params.traceShipper, params.eventId);
2083
+ const responseToolSpans = extractToolSpansFromMessages(params.responseMessages);
2084
+ if (responseToolSpans.length === 0 && params.baseMessages.length === 0) {
2085
+ if (!params.keepEventPending) {
2086
+ store.closeAll(params.traceShipper);
2087
+ }
2088
+ store.cleanup(params.traceShipper, params.eventId);
2089
+ return 0;
2090
+ }
2091
+ const ctx = {
2092
+ eventId: params.eventId,
2093
+ telemetry: params.telemetry,
2094
+ traceShipper: params.traceShipper
2095
+ };
2096
+ const executedKeys = getExecutedToolCallKeys(params.toolCalls);
2097
+ const resolvedSpans = getResolvedToolSpans(
2098
+ [...params.baseMessages, ...params.responseMessages],
2099
+ executedKeys
2100
+ );
2101
+ store.resolve(resolvedSpans, ctx);
2102
+ let syntheticToolCallCount = 0;
2103
+ for (const toolCall of responseToolSpans) {
2104
+ if (executedKeys.has(toolCall.key)) continue;
2105
+ executedKeys.add(toolCall.key);
2106
+ syntheticToolCallCount += 1;
2107
+ if (hasToolResult(toolCall) || !params.keepEventPending) {
2108
+ emitToolSpan(toolCall, params.rootSpan, ctx, params.endTimeUnixNano);
2109
+ } else {
2110
+ store.remember(toolCall, params.rootSpan, ctx, params.endTimeUnixNano);
2111
+ }
2112
+ }
2113
+ if (!params.keepEventPending) {
2114
+ store.closeAll(params.traceShipper);
2115
+ }
2116
+ store.cleanup(params.traceShipper, params.eventId);
2117
+ return syntheticToolCallCount;
2118
+ }
1821
2119
  function executeStreamingOperation(params) {
1822
2120
  const {
1823
2121
  operation,
@@ -1939,7 +2237,7 @@ function wrapAISDK(aiSDK, deps) {
1939
2237
  "generateObject",
1940
2238
  "streamObject"
1941
2239
  ]);
1942
- const agentClasses = /* @__PURE__ */ new Set(["ToolLoopAgent"]);
2240
+ const agentClasses = /* @__PURE__ */ new Set(["Agent", "Experimental_Agent", "ToolLoopAgent"]);
1943
2241
  const sendEvents = ((_a = deps.options.send) == null ? void 0 : _a.events) !== false;
1944
2242
  const sendTraces = ((_b = deps.options.send) == null ? void 0 : _b.traces) !== false;
1945
2243
  const autoAttachmentEnabled = deps.options.autoAttachment !== false;
@@ -2125,6 +2423,18 @@ function wrapAgentGenerate(generate, instance, agentSettings, className, aiSDK,
2125
2423
  const output = patch.output;
2126
2424
  const finalModel = (_c2 = patch.model) != null ? _c2 : model;
2127
2425
  if (rootSpan) {
2426
+ const spanEndTimeUnixNano = nowUnixNanoString();
2427
+ const syntheticToolCallCount = emitTranscriptToolCallSpans({
2428
+ baseMessages,
2429
+ responseMessages,
2430
+ rootSpan,
2431
+ eventId,
2432
+ telemetry,
2433
+ toolCalls,
2434
+ traceShipper: deps.traceShipper,
2435
+ endTimeUnixNano: spanEndTimeUnixNano,
2436
+ keepEventPending: false
2437
+ });
2128
2438
  const finishReason = extractFinishReason(result);
2129
2439
  const providerMetadata = isRecord(result) ? result["providerMetadata"] : void 0;
2130
2440
  const resultToolCalls = isRecord(result) && Array.isArray(result["toolCalls"]) ? safeJsonWithUint8(result["toolCalls"]) : toolCalls.length ? safeJsonWithUint8(toolCalls) : void 0;
@@ -2143,7 +2453,7 @@ function wrapAgentGenerate(generate, instance, agentSettings, className, aiSDK,
2143
2453
  attrInt("ai.usage.totalTokens", usage == null ? void 0 : usage.totalTokens),
2144
2454
  attrInt("ai.usage.reasoningTokens", usage == null ? void 0 : usage.reasoningTokens),
2145
2455
  attrInt("ai.usage.cachedInputTokens", usage == null ? void 0 : usage.cachedInputTokens),
2146
- attrInt("ai.toolCall.count", toolCalls.length),
2456
+ attrInt("ai.toolCall.count", toolCalls.length + syntheticToolCallCount),
2147
2457
  ...error ? [
2148
2458
  attrString(
2149
2459
  "error.message",
@@ -2151,7 +2461,8 @@ function wrapAgentGenerate(generate, instance, agentSettings, className, aiSDK,
2151
2461
  )
2152
2462
  ] : []
2153
2463
  ],
2154
- error
2464
+ error,
2465
+ endTimeUnixNano: spanEndTimeUnixNano
2155
2466
  });
2156
2467
  }
2157
2468
  if (sendEvents) {
@@ -2319,6 +2630,18 @@ function wrapAgentStream(stream, instance, agentSettings, className, aiSDK, deps
2319
2630
  const output = patch.output;
2320
2631
  const finalModel = (_c2 = patch.model) != null ? _c2 : model;
2321
2632
  if (rootSpan) {
2633
+ const spanEndTimeUnixNano = nowUnixNanoString();
2634
+ const syntheticToolCallCount = emitTranscriptToolCallSpans({
2635
+ baseMessages,
2636
+ responseMessages,
2637
+ rootSpan,
2638
+ eventId,
2639
+ telemetry,
2640
+ toolCalls,
2641
+ traceShipper: deps.traceShipper,
2642
+ endTimeUnixNano: spanEndTimeUnixNano,
2643
+ keepEventPending: false
2644
+ });
2322
2645
  const finishReason = extractFinishReason(result);
2323
2646
  const providerMetadata = isRecord(result) ? result["providerMetadata"] : void 0;
2324
2647
  const resultToolCalls = isRecord(result) && Array.isArray(result["toolCalls"]) ? safeJsonWithUint8(result["toolCalls"]) : toolCalls.length ? safeJsonWithUint8(toolCalls) : void 0;
@@ -2337,7 +2660,7 @@ function wrapAgentStream(stream, instance, agentSettings, className, aiSDK, deps
2337
2660
  attrInt("ai.usage.totalTokens", usage == null ? void 0 : usage.totalTokens),
2338
2661
  attrInt("ai.usage.reasoningTokens", usage == null ? void 0 : usage.reasoningTokens),
2339
2662
  attrInt("ai.usage.cachedInputTokens", usage == null ? void 0 : usage.cachedInputTokens),
2340
- attrInt("ai.toolCall.count", toolCalls.length),
2663
+ attrInt("ai.toolCall.count", toolCalls.length + syntheticToolCallCount),
2341
2664
  ...error ? [
2342
2665
  attrString(
2343
2666
  "error.message",
@@ -2345,7 +2668,8 @@ function wrapAgentStream(stream, instance, agentSettings, className, aiSDK, deps
2345
2668
  )
2346
2669
  ] : []
2347
2670
  ],
2348
- error
2671
+ error,
2672
+ endTimeUnixNano: spanEndTimeUnixNano
2349
2673
  });
2350
2674
  }
2351
2675
  if (sendEvents) {
@@ -2515,10 +2839,10 @@ function wrapToolExecute(name, tool, ctx, toolCalls) {
2515
2839
  lastValue = value;
2516
2840
  yield value;
2517
2841
  }
2518
- toolCalls.push({ name, args: toolArgs, result: lastValue, status: "OK" });
2842
+ toolCalls.push({ id: toolCallId, name, args: toolArgs, result: lastValue, status: "OK" });
2519
2843
  endToolSpan(toolSpan, lastValue);
2520
2844
  } catch (error) {
2521
- toolCalls.push({ name, args: toolArgs, status: "ERROR" });
2845
+ toolCalls.push({ id: toolCallId, name, args: toolArgs, status: "ERROR" });
2522
2846
  endToolSpan(toolSpan, void 0, error);
2523
2847
  throw error;
2524
2848
  }
@@ -2531,11 +2855,17 @@ function wrapToolExecute(name, tool, ctx, toolCalls) {
2531
2855
  const run = async () => {
2532
2856
  try {
2533
2857
  const awaitedResult = await result;
2534
- toolCalls.push({ name, args: toolArgs, result: awaitedResult, status: "OK" });
2858
+ toolCalls.push({
2859
+ id: toolCallId,
2860
+ name,
2861
+ args: toolArgs,
2862
+ result: awaitedResult,
2863
+ status: "OK"
2864
+ });
2535
2865
  endToolSpan(toolSpan, awaitedResult);
2536
2866
  return awaitedResult;
2537
2867
  } catch (error) {
2538
- toolCalls.push({ name, args: toolArgs, status: "ERROR" });
2868
+ toolCalls.push({ id: toolCallId, name, args: toolArgs, status: "ERROR" });
2539
2869
  endToolSpan(toolSpan, void 0, error);
2540
2870
  throw error;
2541
2871
  }
@@ -2699,10 +3029,16 @@ function wrapModel(args, aiSDK, outerOperationId, ctx) {
2699
3029
  if (firstChunkMs === void 0) firstChunkMs = Date.now();
2700
3030
  if (isRecord(value)) {
2701
3031
  const type = value["type"];
2702
- if (type === "text-delta" && typeof value["textDelta"] === "string")
2703
- activeText += value["textDelta"];
2704
- if (type === "finish" && typeof value["finishReason"] === "string")
2705
- finishReason = value["finishReason"];
3032
+ if (type === "text-delta") {
3033
+ let textDelta;
3034
+ if (typeof value["delta"] === "string") {
3035
+ textDelta = value["delta"];
3036
+ } else if (typeof value["textDelta"] === "string") {
3037
+ textDelta = value["textDelta"];
3038
+ }
3039
+ if (typeof textDelta === "string") activeText += textDelta;
3040
+ }
3041
+ if (type === "finish") finishReason = extractFinishReason(value);
2706
3042
  if (type === "tool-call") toolCallsLocal.push(value);
2707
3043
  if ("response" in value && isRecord(value["response"])) {
2708
3044
  const response = value["response"];
@@ -2915,15 +3251,44 @@ function extractNestedTokens(usage, key) {
2915
3251
 
2916
3252
  // src/index.ts
2917
3253
  function eventMetadata(options) {
2918
- var _a;
2919
3254
  const result = {};
2920
- result["raindrop.eventId"] = (_a = options.eventId) != null ? _a : randomUUID();
3255
+ if (options.eventId) {
3256
+ result["raindrop.eventId"] = options.eventId;
3257
+ } else {
3258
+ result["raindrop.eventId"] = randomUUID();
3259
+ result["raindrop.internal.eventIdGenerated"] = "true";
3260
+ }
2921
3261
  if (options.userId) result["raindrop.userId"] = options.userId;
2922
3262
  if (options.convoId) result["raindrop.convoId"] = options.convoId;
2923
3263
  if (options.eventName) result["raindrop.eventName"] = options.eventName;
2924
3264
  if (options.properties) result["raindrop.properties"] = JSON.stringify(options.properties);
2925
3265
  return result;
2926
3266
  }
3267
+ function deriveChatTurnMessageId(request) {
3268
+ const messages = Array.isArray(request.messages) ? request.messages : [];
3269
+ for (let i = messages.length - 1; i >= 0; i--) {
3270
+ const message = messages[i];
3271
+ if ((message == null ? void 0 : message.role) === "user" && typeof message.id === "string" && message.id.length > 0) {
3272
+ return message.id;
3273
+ }
3274
+ }
3275
+ if (typeof request.messageId === "string" && request.messageId.length > 0) {
3276
+ return request.messageId;
3277
+ }
3278
+ return void 0;
3279
+ }
3280
+ function eventMetadataFromChatRequest(options) {
3281
+ var _a, _b;
3282
+ const { request, ...rest } = options;
3283
+ const convoId = (_a = rest.convoId) != null ? _a : typeof request.id === "string" && request.id.length > 0 ? request.id : void 0;
3284
+ const turnMessageId = deriveChatTurnMessageId(request);
3285
+ const eventId = (_b = rest.eventId) != null ? _b : turnMessageId ? convoId ? `chat:${convoId}:${turnMessageId}` : `chat:${turnMessageId}` : void 0;
3286
+ return eventMetadata({
3287
+ ...rest,
3288
+ ...convoId ? { convoId } : {},
3289
+ ...eventId ? { eventId } : {}
3290
+ });
3291
+ }
2927
3292
  function envDebugEnabled() {
2928
3293
  var _a;
2929
3294
  if (typeof process === "undefined") return false;
@@ -3008,5 +3373,6 @@ exports._resetWarnedMissingUserId = _resetWarnedMissingUserId;
3008
3373
  exports.createRaindropAISDK = createRaindropAISDK;
3009
3374
  exports.currentSpan = currentSpan;
3010
3375
  exports.eventMetadata = eventMetadata;
3376
+ exports.eventMetadataFromChatRequest = eventMetadataFromChatRequest;
3011
3377
  exports.getContextManager = getContextManager;
3012
3378
  exports.withCurrent = withCurrent;
@@ -1,4 +1,4 @@
1
- export { _resetWarnedMissingUserId, createRaindropAISDK, currentSpan, eventMetadata, getContextManager, withCurrent } from './chunk-MYJCN2H7.mjs';
1
+ export { _resetWarnedMissingUserId, createRaindropAISDK, currentSpan, eventMetadata, eventMetadataFromChatRequest, getContextManager, withCurrent } from './chunk-4RNTOVBH.mjs';
2
2
  import { AsyncLocalStorage } from 'async_hooks';
3
3
 
4
4
  globalThis.RAINDROP_ASYNC_LOCAL_STORAGE = AsyncLocalStorage;
@@ -1,4 +1,4 @@
1
- export { AISDKMessage, AgentCallMetadata, AgentWithMetadata, Attachment, BuildEventPatch, ContextManager, ContextSpan, EventBuilder, EventMetadataOptions, IdentifyInput, RaindropAISDKClient, RaindropAISDKContext, RaindropAISDKOptions, SelfDiagnosticsOptions, SelfDiagnosticsSignalDefinition, SelfDiagnosticsSignalDefinitions, WrapAISDKOptions, WrappedAI, WrappedAISDK, _resetWarnedMissingUserId, createRaindropAISDK, currentSpan, eventMetadata, getContextManager, withCurrent } from './index.mjs';
1
+ export { AISDKChatRequestLike, AISDKChatRequestMessageLike, AISDKMessage, AgentCallMetadata, AgentWithMetadata, Attachment, BuildEventPatch, ContextManager, ContextSpan, EventBuilder, EventMetadataOptions, IdentifyInput, RaindropAISDKClient, RaindropAISDKContext, RaindropAISDKOptions, SelfDiagnosticsOptions, SelfDiagnosticsSignalDefinition, SelfDiagnosticsSignalDefinitions, WrapAISDKOptions, WrappedAI, WrappedAISDK, _resetWarnedMissingUserId, createRaindropAISDK, currentSpan, eventMetadata, eventMetadataFromChatRequest, getContextManager, withCurrent } from './index.mjs';
2
2
 
3
3
  declare global {
4
4
  var RAINDROP_ASYNC_LOCAL_STORAGE: (new <T>() => {
@@ -1,4 +1,4 @@
1
- export { AISDKMessage, AgentCallMetadata, AgentWithMetadata, Attachment, BuildEventPatch, ContextManager, ContextSpan, EventBuilder, EventMetadataOptions, IdentifyInput, RaindropAISDKClient, RaindropAISDKContext, RaindropAISDKOptions, SelfDiagnosticsOptions, SelfDiagnosticsSignalDefinition, SelfDiagnosticsSignalDefinitions, WrapAISDKOptions, WrappedAI, WrappedAISDK, _resetWarnedMissingUserId, createRaindropAISDK, currentSpan, eventMetadata, getContextManager, withCurrent } from './index.js';
1
+ export { AISDKChatRequestLike, AISDKChatRequestMessageLike, AISDKMessage, AgentCallMetadata, AgentWithMetadata, Attachment, BuildEventPatch, ContextManager, ContextSpan, EventBuilder, EventMetadataOptions, IdentifyInput, RaindropAISDKClient, RaindropAISDKContext, RaindropAISDKOptions, SelfDiagnosticsOptions, SelfDiagnosticsSignalDefinition, SelfDiagnosticsSignalDefinitions, WrapAISDKOptions, WrappedAI, WrappedAISDK, _resetWarnedMissingUserId, createRaindropAISDK, currentSpan, eventMetadata, eventMetadataFromChatRequest, getContextManager, withCurrent } from './index.js';
2
2
 
3
3
  declare global {
4
4
  var RAINDROP_ASYNC_LOCAL_STORAGE: (new <T>() => {