@raindrop-ai/ai-sdk 0.0.25 → 0.0.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -117,7 +117,7 @@ await raindrop.flush();
117
117
 
118
118
  ### AI SDK v7+ native telemetry (opt-in)
119
119
 
120
- On AI SDK v7+, you can use the native `TelemetryIntegration` callback interface instead of Proxy wrapping. This avoids Proxy overhead and works with all AI SDK entry points (including `ToolLoopAgent`).
120
+ On AI SDK v7+, you can use the native `Telemetry` callback interface (formerly `TelemetryIntegration` before beta.111) instead of Proxy wrapping. This avoids Proxy overhead and works with all AI SDK entry points (including `ToolLoopAgent`).
121
121
 
122
122
  ```ts
123
123
  // Option A: wrap() with nativeTelemetry flag
@@ -127,15 +127,41 @@ const { generateText } = raindrop.wrap(ai, {
127
127
  });
128
128
 
129
129
  // Option B: direct registration (no wrap needed)
130
- import { registerTelemetryIntegration } from "ai";
130
+ // - registerTelemetry on AI SDK v7 beta.111+
131
+ // - registerTelemetryIntegration on older v7 betas
132
+ import { registerTelemetry } from "ai";
131
133
 
132
- registerTelemetryIntegration(
134
+ registerTelemetry(
133
135
  raindrop.createTelemetryIntegration({ userId: "user_123" })
134
136
  );
135
137
  ```
136
138
 
137
139
  Setting `nativeTelemetry: true` on pre-v7 throws a clear error. The Proxy path remains the default and supports features not yet available on the native path (`buildEvent`, output attachment extraction).
138
140
 
141
+ #### Per-call routing on AI SDK v7 beta.94+
142
+
143
+ `eventMetadata()` keeps working on every published v7 beta:
144
+
145
+ ```ts
146
+ const result = await generateText({
147
+ model,
148
+ prompt,
149
+ experimental_telemetry: {
150
+ isEnabled: true,
151
+ metadata: eventMetadata({
152
+ userId: "u_42",
153
+ eventName: "chat-turn",
154
+ eventId: "evt_abc",
155
+ convoId: "conv_xyz",
156
+ }),
157
+ },
158
+ });
159
+ ```
160
+
161
+ AI SDK v7 beta.94 (vercel/ai #14503) removed the `metadata` field from `TelemetryOptions`, and integration callbacks no longer receive it via `event.metadata`. Going through `wrap({ nativeTelemetry: true })` still routes per-call `userId` / `eventName` / `eventId` / `convoId` / `properties` correctly: the wrapper extracts them from the call's `experimental_telemetry.metadata` (or `telemetry.metadata`) before delegating, and exposes them to the integration via an `AsyncLocalStorage` slot.
162
+
163
+ If you are bypassing `wrap()` and registering an integration manually, use the helpers exported from this package (`runWithRaindropCallMetadata`, `readRaindropCallMetadataFromArgs`, `getCurrentRaindropCallMetadata`) to plumb per-call metadata through your own call sites.
164
+
139
165
  If `userId` is missing from both `wrap()` context and `eventMetadata()`, the SDK logs a warning (once) and skips sending events.
140
166
 
141
167
  ## Runtime support
@@ -188,7 +214,7 @@ This package is tested against multiple Vercel AI SDK versions:
188
214
  | v4.x | ✅ Supported | Proxy |
189
215
  | v5.x | ✅ Supported | Proxy |
190
216
  | v6.x | ✅ Supported | Proxy |
191
- | v7.x (beta) | ✅ Supported | Proxy (default) or native `TelemetryIntegration` (opt-in) |
217
+ | v7.x (beta) | ✅ Supported | Proxy (default) or native `Telemetry` (opt-in, formerly `TelemetryIntegration` pre-beta.111). Verified against beta.116. |
192
218
 
193
219
  ### Version Differences Handled
194
220
 
@@ -1,6 +1,6 @@
1
1
  import { AsyncLocalStorage } from 'async_hooks';
2
2
 
3
- // ../core/dist/chunk-4UCYIEH4.js
3
+ // ../core/dist/chunk-Y7SM66SW.js
4
4
  function getCrypto() {
5
5
  const c = globalThis.crypto;
6
6
  return c;
@@ -478,21 +478,6 @@ function resolveLocalDebuggerBaseUrl(baseUrl) {
478
478
  function localDebuggerEnabled(baseUrl) {
479
479
  return resolveLocalDebuggerBaseUrl(baseUrl) !== null;
480
480
  }
481
- function normalizeLocalDebuggerLiveEventType(type) {
482
- switch (type) {
483
- case "text-delta":
484
- return "text_delta";
485
- case "reasoning":
486
- case "reasoning-delta":
487
- return "reasoning_delta";
488
- case "tool-call":
489
- return "tool_start";
490
- case "tool-result":
491
- return "tool_result";
492
- default:
493
- return type;
494
- }
495
- }
496
481
  function mirrorTraceExportToLocalDebugger(body, options = {}) {
497
482
  var _a;
498
483
  const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
@@ -512,7 +497,7 @@ function sendLocalDebuggerLiveEvent(event, options = {}) {
512
497
  `${baseUrl}live`,
513
498
  {
514
499
  ...event,
515
- type: normalizeLocalDebuggerLiveEventType(event.type),
500
+ type: event.type,
516
501
  timestamp: (_a = event.timestamp) != null ? _a : Date.now()
517
502
  },
518
503
  {},
@@ -1451,6 +1436,77 @@ function attrsFromGenAiRequest(options) {
1451
1436
  ];
1452
1437
  }
1453
1438
 
1439
+ // src/internal/call-metadata.ts
1440
+ var SyncFallbackStorage = class {
1441
+ constructor() {
1442
+ this._stack = [];
1443
+ }
1444
+ getStore() {
1445
+ return this._stack[this._stack.length - 1];
1446
+ }
1447
+ run(store, callback) {
1448
+ this._stack.push(store);
1449
+ try {
1450
+ return callback();
1451
+ } finally {
1452
+ this._stack.pop();
1453
+ }
1454
+ }
1455
+ };
1456
+ var _storage = null;
1457
+ function getStorage() {
1458
+ if (_storage) return _storage;
1459
+ const Ctor = globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
1460
+ _storage = Ctor ? new Ctor() : new SyncFallbackStorage();
1461
+ return _storage;
1462
+ }
1463
+ function _resetRaindropCallMetadataStorage() {
1464
+ _storage = null;
1465
+ }
1466
+ function getCurrentRaindropCallMetadata() {
1467
+ return getStorage().getStore();
1468
+ }
1469
+ function runWithRaindropCallMetadata(metadata, fn) {
1470
+ return getStorage().run(metadata, fn);
1471
+ }
1472
+ function readRaindropCallMetadataFromArgs(args) {
1473
+ var _a;
1474
+ if (args.length === 0) return void 0;
1475
+ const first = args[0];
1476
+ if (!isRecord(first)) return void 0;
1477
+ const topLevel = isRecord(first["metadata"]) ? first["metadata"] : void 0;
1478
+ const stable = isRecord(first["telemetry"]) ? first["telemetry"]["metadata"] : void 0;
1479
+ const stableMetadata = isRecord(stable) ? stable : void 0;
1480
+ const exp = extractExperimentalTelemetry(first);
1481
+ const expMetadata = (exp == null ? void 0 : exp.metadata) && typeof exp.metadata === "object" ? exp.metadata : void 0;
1482
+ const raw = (_a = topLevel != null ? topLevel : stableMetadata) != null ? _a : expMetadata;
1483
+ if (!raw) return void 0;
1484
+ const meta = { rawMetadata: raw };
1485
+ const userId = raw["raindrop.userId"];
1486
+ if (typeof userId === "string" && userId) meta.userId = userId;
1487
+ const eventId = raw["raindrop.eventId"];
1488
+ if (typeof eventId === "string" && eventId) meta.eventId = eventId;
1489
+ const eventIdGenerated = raw["raindrop.internal.eventIdGenerated"];
1490
+ if (eventIdGenerated === true || eventIdGenerated === "true" || eventIdGenerated === "1") {
1491
+ meta.eventIdGenerated = true;
1492
+ }
1493
+ const convoId = raw["raindrop.convoId"];
1494
+ if (typeof convoId === "string" && convoId) meta.convoId = convoId;
1495
+ const eventName = raw["raindrop.eventName"];
1496
+ if (typeof eventName === "string" && eventName) meta.eventName = eventName;
1497
+ const properties = raw["raindrop.properties"];
1498
+ if (typeof properties === "string") {
1499
+ try {
1500
+ const parsed = JSON.parse(properties);
1501
+ if (parsed && typeof parsed === "object") meta.properties = parsed;
1502
+ } catch (e) {
1503
+ }
1504
+ } else if (properties && typeof properties === "object") {
1505
+ meta.properties = properties;
1506
+ }
1507
+ return meta;
1508
+ }
1509
+
1454
1510
  // src/internal/raindrop-telemetry-integration.ts
1455
1511
  var RaindropTelemetryIntegration = class {
1456
1512
  constructor(opts) {
@@ -1458,15 +1514,17 @@ var RaindropTelemetryIntegration = class {
1458
1514
  // ── onStart ─────────────────────────────────────────────────────────────
1459
1515
  this.onStart = (event) => {
1460
1516
  var _a, _b, _c, _d;
1461
- if (event.isEnabled !== true) return;
1517
+ if (event.isEnabled === false) return;
1462
1518
  const isEmbed = event.operationId === "ai.embed" || event.operationId === "ai.embedMany";
1463
1519
  const recordInputs = event.recordInputs !== false;
1464
1520
  const recordOutputs = event.recordOutputs !== false;
1465
1521
  const functionId = event.functionId;
1466
- const metadata = event.metadata;
1522
+ const eventMetadata2 = event.metadata;
1523
+ const callContextMetadata = getCurrentRaindropCallMetadata();
1524
+ const metadata = eventMetadata2 != null ? eventMetadata2 : callContextMetadata == null ? void 0 : callContextMetadata.rawMetadata;
1467
1525
  const callMeta = this.extractRaindropMetadata(metadata);
1468
1526
  const inherited = getContextManager().getParentSpanIds();
1469
- const eventIdGenerated = (metadata == null ? void 0 : metadata["raindrop.internal.eventIdGenerated"]) === "true" || (metadata == null ? void 0 : metadata["raindrop.internal.eventIdGenerated"]) === true;
1527
+ const eventIdGenerated = (metadata == null ? void 0 : metadata["raindrop.internal.eventIdGenerated"]) === "true" || (metadata == null ? void 0 : metadata["raindrop.internal.eventIdGenerated"]) === true || (callContextMetadata == null ? void 0 : callContextMetadata.eventIdGenerated) === true;
1470
1528
  const explicitEventId = callMeta.eventId && !eventIdGenerated ? callMeta.eventId : void 0;
1471
1529
  const eventId = (_d = (_c = (_b = explicitEventId != null ? explicitEventId : (_a = this.defaultContext) == null ? void 0 : _a.eventId) != null ? _b : inherited == null ? void 0 : inherited.eventId) != null ? _c : callMeta.eventId) != null ? _d : randomUUID();
1472
1530
  const inheritedParent = inherited && inherited.eventId === eventId ? { traceIdB64: inherited.traceIdB64, spanIdB64: inherited.spanIdB64 } : void 0;
@@ -1592,48 +1650,25 @@ var RaindropTelemetryIntegration = class {
1592
1650
  state.stepSpan = stepSpan;
1593
1651
  state.stepParent = this.spanParentRef(stepSpan);
1594
1652
  };
1595
- // ── onToolCallStart ─────────────────────────────────────────────────────
1596
- this.onToolCallStart = (event) => {
1597
- const state = this.getState(event.callId);
1598
- if (!(state == null ? void 0 : state.stepParent)) return;
1599
- const { toolCall } = event;
1600
- const { operationName, resourceName } = opName(
1601
- "ai.toolCall",
1602
- state.functionId
1603
- );
1604
- const inputAttrs = state.recordInputs ? [attrString("ai.toolCall.args", safeJsonWithUint8(toolCall.input))] : [];
1605
- const toolSpan = this.traceShipper.startSpan({
1606
- name: "ai.toolCall",
1607
- parent: state.stepParent,
1608
- eventId: state.eventId,
1609
- operationId: "ai.toolCall",
1610
- attributes: [
1611
- attrString("operation.name", operationName),
1612
- attrString("resource.name", resourceName),
1613
- attrString("ai.telemetry.functionId", state.functionId),
1614
- attrString("ai.toolCall.name", toolCall.toolName),
1615
- attrString("ai.toolCall.id", toolCall.toolCallId),
1616
- ...inputAttrs
1617
- ]
1618
- });
1619
- state.toolSpans.set(toolCall.toolCallId, toolSpan);
1620
- this.emitLive(state, "tool_start", toolCall.toolName, { args: toolCall.input });
1653
+ this.onToolExecutionStart = (event) => this.toolExecutionStart(event);
1654
+ this.onToolExecutionEnd = (event) => this.toolExecutionEnd(event);
1655
+ // Older v7 betas (< beta.111) emit these names. Kept as thin aliases so
1656
+ // applications pinned to those betas continue to work.
1657
+ this.onToolCallStart = (event) => this.toolExecutionStart(event);
1658
+ this.onToolCallFinish = (event) => this.toolExecutionEnd(event);
1659
+ // ── language-model call (v7 beta.111+) ─────────────────────────────────
1660
+ //
1661
+ // `onLanguageModelCallStart` / `onLanguageModelCallEnd` are scoped to the
1662
+ // model invocation only and exclude later client-side tool execution.
1663
+ // Raindrop already spans at the operation + step level, so these are
1664
+ // intentional no-ops — declared so the dispatcher's `mergeCallbacks` sees
1665
+ // them and so we don't accidentally rely on them later.
1666
+ //
1667
+ // Defined as no-ops rather than omitted so adding logic here later is a
1668
+ // strictly additive change.
1669
+ this.onLanguageModelCallStart = (_event) => {
1621
1670
  };
1622
- // ── onToolCallFinish ────────────────────────────────────────────────────
1623
- this.onToolCallFinish = (event) => {
1624
- const state = this.getState(event.callId);
1625
- if (!state) return;
1626
- const toolSpan = state.toolSpans.get(event.toolCall.toolCallId);
1627
- if (!toolSpan) return;
1628
- state.toolCallCount += 1;
1629
- if (event.success) {
1630
- const outputAttrs = state.recordOutputs ? [attrString("ai.toolCall.result", safeJsonWithUint8(event.output))] : [];
1631
- this.traceShipper.endSpan(toolSpan, { attributes: outputAttrs });
1632
- } else {
1633
- this.traceShipper.endSpan(toolSpan, { error: event.error });
1634
- }
1635
- this.emitLive(state, "tool_result", event.toolCall.toolName);
1636
- state.toolSpans.delete(event.toolCall.toolCallId);
1671
+ this.onLanguageModelCallEnd = (_event) => {
1637
1672
  };
1638
1673
  // ── onChunk (streaming) ─────────────────────────────────────────────────
1639
1674
  this.onChunk = (event) => {
@@ -1902,6 +1937,53 @@ var RaindropTelemetryIntegration = class {
1902
1937
  }
1903
1938
  return void 0;
1904
1939
  }
1940
+ // ── tool execution start / end ──────────────────────────────────────────
1941
+ //
1942
+ // v7 < beta.111 dispatched `onToolCallStart` / `onToolCallFinish`.
1943
+ // v7 >= beta.111 renamed them to `onToolExecutionStart` / `onToolExecutionEnd`
1944
+ // (see https://github.com/vercel/ai/pull/14589). Event shape is identical.
1945
+ // Both names are exposed and forward to a single implementation.
1946
+ toolExecutionStart(event) {
1947
+ const state = this.getState(event.callId);
1948
+ if (!(state == null ? void 0 : state.stepParent)) return;
1949
+ const { toolCall } = event;
1950
+ const { operationName, resourceName } = opName(
1951
+ "ai.toolCall",
1952
+ state.functionId
1953
+ );
1954
+ const inputAttrs = state.recordInputs ? [attrString("ai.toolCall.args", safeJsonWithUint8(toolCall.input))] : [];
1955
+ const toolSpan = this.traceShipper.startSpan({
1956
+ name: "ai.toolCall",
1957
+ parent: state.stepParent,
1958
+ eventId: state.eventId,
1959
+ operationId: "ai.toolCall",
1960
+ attributes: [
1961
+ attrString("operation.name", operationName),
1962
+ attrString("resource.name", resourceName),
1963
+ attrString("ai.telemetry.functionId", state.functionId),
1964
+ attrString("ai.toolCall.name", toolCall.toolName),
1965
+ attrString("ai.toolCall.id", toolCall.toolCallId),
1966
+ ...inputAttrs
1967
+ ]
1968
+ });
1969
+ state.toolSpans.set(toolCall.toolCallId, toolSpan);
1970
+ this.emitLive(state, "tool_start", toolCall.toolName, { args: toolCall.input });
1971
+ }
1972
+ toolExecutionEnd(event) {
1973
+ const state = this.getState(event.callId);
1974
+ if (!state) return;
1975
+ const toolSpan = state.toolSpans.get(event.toolCall.toolCallId);
1976
+ if (!toolSpan) return;
1977
+ state.toolCallCount += 1;
1978
+ if (event.success) {
1979
+ const outputAttrs = state.recordOutputs ? [attrString("ai.toolCall.result", safeJsonWithUint8(event.output))] : [];
1980
+ this.traceShipper.endSpan(toolSpan, { attributes: outputAttrs });
1981
+ } else {
1982
+ this.traceShipper.endSpan(toolSpan, { error: event.error });
1983
+ }
1984
+ this.emitLive(state, "tool_result", event.toolCall.toolName);
1985
+ state.toolSpans.delete(event.toolCall.toolCallId);
1986
+ }
1905
1987
  finishGenerate(event, state) {
1906
1988
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
1907
1989
  if (state.rootSpan) {
@@ -2216,7 +2298,16 @@ function detectAISDKVersion(aiSDK) {
2216
2298
  return "4";
2217
2299
  }
2218
2300
  function hasStructuredTelemetryEvents(aiSDK) {
2219
- return isRecord(aiSDK) && isFunction(aiSDK["registerTelemetryIntegration"]) && isFunction(aiSDK["experimental_streamModelCall"]);
2301
+ if (!isRecord(aiSDK)) return false;
2302
+ const hasRegister = isFunction(aiSDK["registerTelemetry"]) || isFunction(aiSDK["registerTelemetryIntegration"]);
2303
+ const hasV7Marker = isFunction(aiSDK["experimental_streamLanguageModelCall"]) || isFunction(aiSDK["experimental_streamModelCall"]);
2304
+ return hasRegister && hasV7Marker;
2305
+ }
2306
+ function resolveRegisterTelemetry(aiSDK) {
2307
+ var _a;
2308
+ if (!isRecord(aiSDK)) return void 0;
2309
+ const fn = (_a = aiSDK["registerTelemetry"]) != null ? _a : aiSDK["registerTelemetryIntegration"];
2310
+ return isFunction(fn) ? fn : void 0;
2220
2311
  }
2221
2312
  function asVercelSchema(jsonSchemaObj) {
2222
2313
  const validatorSymbol = /* @__PURE__ */ Symbol.for("vercel.ai.validator");
@@ -2857,31 +2948,44 @@ function wrapAISDK(aiSDK, deps) {
2857
2948
  properties: wrapTimeCtx.properties
2858
2949
  }
2859
2950
  });
2860
- const registerFn = aiSDK["registerTelemetryIntegration"];
2861
- if (isFunction(registerFn)) {
2951
+ const registerFn = resolveRegisterTelemetry(aiSDK);
2952
+ if (registerFn) {
2862
2953
  registerFn(integration);
2863
2954
  }
2864
2955
  if (debug) {
2865
- console.log("[raindrop-ai/ai-sdk] nativeTelemetry: registered RaindropTelemetryIntegration (no Proxy)");
2956
+ console.log(
2957
+ "[raindrop-ai/ai-sdk] nativeTelemetry: registered RaindropTelemetryIntegration (Proxy installed for per-call metadata propagation)"
2958
+ );
2866
2959
  }
2867
2960
  const selfDiagnostics2 = normalizeSelfDiagnosticsConfig(deps.options.selfDiagnostics);
2868
- if (selfDiagnostics2) {
2869
- const textOps = /* @__PURE__ */ new Set(["generateText", "streamText"]);
2870
- const jsonSchemaFactory = resolveJsonSchemaFactory(aiSDK);
2871
- const proxyTarget2 = isModuleNamespace(aiSDK) ? Object.setPrototypeOf({}, aiSDK) : aiSDK;
2872
- return new Proxy(proxyTarget2, {
2873
- get(target, prop, receiver) {
2874
- const original = Reflect.get(target, prop, receiver);
2875
- if (typeof prop !== "string" || !textOps.has(prop) || !isFunction(original)) {
2876
- return original;
2877
- }
2878
- return (...callArgs) => {
2879
- var _a2;
2880
- const arg = callArgs[0];
2881
- if (!isRecord(arg)) return original.call(aiSDK, ...callArgs);
2961
+ const jsonSchemaFactory = selfDiagnostics2 ? resolveJsonSchemaFactory(aiSDK) : void 0;
2962
+ const metadataAwareOps = /* @__PURE__ */ new Set([
2963
+ "generateText",
2964
+ "streamText",
2965
+ "generateObject",
2966
+ "streamObject",
2967
+ "embed",
2968
+ "embedMany",
2969
+ "rerank"
2970
+ ]);
2971
+ const selfDiagnosticsOps = /* @__PURE__ */ new Set(["generateText", "streamText"]);
2972
+ const proxyTarget2 = isModuleNamespace(aiSDK) ? Object.setPrototypeOf({}, aiSDK) : aiSDK;
2973
+ return new Proxy(proxyTarget2, {
2974
+ get(target, prop, receiver) {
2975
+ const original = Reflect.get(target, prop, receiver);
2976
+ if (typeof prop !== "string" || !metadataAwareOps.has(prop) || !isFunction(original)) {
2977
+ return original;
2978
+ }
2979
+ const propName = prop;
2980
+ return (...callArgs) => {
2981
+ var _a2, _b2, _c2;
2982
+ const arg = callArgs[0];
2983
+ const callMetadata = readRaindropCallMetadataFromArgs(callArgs);
2984
+ const callOriginal = () => original.call(aiSDK, ...callArgs);
2985
+ if (selfDiagnostics2 && selfDiagnosticsOps.has(propName) && isRecord(arg)) {
2882
2986
  const telemetry = extractExperimentalTelemetry(arg);
2883
2987
  const callMeta = (telemetry == null ? void 0 : telemetry.metadata) ? extractRaindropMetadata(telemetry.metadata) : {};
2884
- const perCallEventIdExplicit = (_a2 = callMeta.eventId) != null ? _a2 : wrapTimeCtx.eventId;
2988
+ const perCallEventIdExplicit = (_b2 = (_a2 = callMetadata == null ? void 0 : callMetadata.eventId) != null ? _a2 : callMeta.eventId) != null ? _b2 : wrapTimeCtx.eventId;
2885
2989
  const perCallEventId = perCallEventIdExplicit != null ? perCallEventIdExplicit : randomUUID();
2886
2990
  const perCallEventIdGenerated = !perCallEventIdExplicit;
2887
2991
  const perCallCtx = {
@@ -2918,12 +3022,25 @@ function wrapAISDK(aiSDK, deps) {
2918
3022
  metadata: mergedMetadata
2919
3023
  }
2920
3024
  };
2921
- return original.call(aiSDK, ...callArgs);
2922
- };
2923
- }
2924
- });
2925
- }
2926
- return aiSDK;
3025
+ const mergedAlsMetadata = {
3026
+ ...callMetadata != null ? callMetadata : {},
3027
+ eventId: perCallEventId,
3028
+ eventIdGenerated: perCallEventIdGenerated || (callMetadata == null ? void 0 : callMetadata.eventIdGenerated),
3029
+ rawMetadata: {
3030
+ ...(_c2 = callMetadata == null ? void 0 : callMetadata.rawMetadata) != null ? _c2 : {},
3031
+ "raindrop.eventId": perCallEventId,
3032
+ ...perCallEventIdGenerated ? { "raindrop.internal.eventIdGenerated": "true" } : {}
3033
+ }
3034
+ };
3035
+ return runWithRaindropCallMetadata(mergedAlsMetadata, callOriginal);
3036
+ }
3037
+ if (callMetadata) {
3038
+ return runWithRaindropCallMetadata(callMetadata, callOriginal);
3039
+ }
3040
+ return callOriginal();
3041
+ };
3042
+ }
3043
+ });
2927
3044
  }
2928
3045
  const instrumentedOps = /* @__PURE__ */ new Set([
2929
3046
  "generateText",
@@ -4007,7 +4124,7 @@ function extractNestedTokens(usage, key) {
4007
4124
  // package.json
4008
4125
  var package_default = {
4009
4126
  name: "@raindrop-ai/ai-sdk",
4010
- version: "0.0.25"};
4127
+ version: "0.0.26"};
4011
4128
 
4012
4129
  // src/internal/version.ts
4013
4130
  var libraryName = package_default.name;
@@ -4244,4 +4361,4 @@ function createRaindropAISDK(opts) {
4244
4361
  };
4245
4362
  }
4246
4363
 
4247
- export { RaindropTelemetryIntegration, _resetWarnedMissingUserId, createRaindropAISDK, currentSpan, eventMetadata, eventMetadataFromChatRequest, getContextManager, withCurrent };
4364
+ export { RaindropTelemetryIntegration, _resetRaindropCallMetadataStorage, _resetWarnedMissingUserId, createRaindropAISDK, currentSpan, eventMetadata, eventMetadataFromChatRequest, getContextManager, getCurrentRaindropCallMetadata, readRaindropCallMetadataFromArgs, runWithRaindropCallMetadata, withCurrent };
@@ -224,22 +224,16 @@ declare class TraceShipper extends TraceShipper$1 {
224
224
  constructor(opts: ConstructorParameters<typeof TraceShipper$1>[0]);
225
225
  }
226
226
 
227
- /**
228
- * Raindrop TelemetryIntegration for AI SDK v7+
229
- *
230
- * Implements the AI SDK's TelemetryIntegration interface to capture traces and
231
- * events natively, replacing the Proxy-based wrapping used for v4-v6.
232
- *
233
- * Modeled after the upstream OpenTelemetryIntegration but uses Raindrop's
234
- * TraceShipper (OTLP/HTTP) + EventShipper instead of the OTel Tracer API.
235
- */
236
-
237
227
  type Listener<T> = (event: T) => PromiseLike<void> | void;
238
228
  interface TelemetryIntegration {
239
229
  onStart?: Listener<any>;
240
230
  onStepStart?: Listener<any>;
231
+ onToolExecutionStart?: Listener<any>;
232
+ onToolExecutionEnd?: Listener<any>;
241
233
  onToolCallStart?: Listener<any>;
242
234
  onToolCallFinish?: Listener<any>;
235
+ onLanguageModelCallStart?: Listener<any>;
236
+ onLanguageModelCallEnd?: Listener<any>;
243
237
  onChunk?: Listener<any>;
244
238
  onStepFinish?: Listener<any>;
245
239
  onEmbedStart?: Listener<any>;
@@ -287,8 +281,14 @@ declare class RaindropTelemetryIntegration implements TelemetryIntegration {
287
281
  private extractInputText;
288
282
  onStart: (event: any) => void;
289
283
  onStepStart: (event: any) => void;
284
+ private toolExecutionStart;
285
+ private toolExecutionEnd;
286
+ onToolExecutionStart: (event: any) => void;
287
+ onToolExecutionEnd: (event: any) => void;
290
288
  onToolCallStart: (event: any) => void;
291
289
  onToolCallFinish: (event: any) => void;
290
+ onLanguageModelCallStart: (_event: any) => void;
291
+ onLanguageModelCallEnd: (_event: any) => void;
292
292
  onChunk: (event: any) => void;
293
293
  onStepFinish: (event: any) => void;
294
294
  onEmbedStart: (event: any) => void;
@@ -309,6 +309,65 @@ type IdentifyInput = {
309
309
  traits?: Record<string, unknown>;
310
310
  };
311
311
 
312
+ type RaindropCallMetadata = {
313
+ userId?: string;
314
+ eventId?: string;
315
+ /** True when the eventId was auto-generated by `eventMetadata()` rather than user-provided. */
316
+ eventIdGenerated?: boolean;
317
+ convoId?: string;
318
+ eventName?: string;
319
+ properties?: Record<string, unknown>;
320
+ /**
321
+ * Raw `metadata` record, preserved so the integration can write the
322
+ * full set of `raindrop.*` keys onto root spans (the trace shipper
323
+ * relies on this to surface metadata in the dashboard span attributes).
324
+ */
325
+ rawMetadata?: Record<string, unknown>;
326
+ };
327
+ declare global {
328
+ var RAINDROP_ASYNC_LOCAL_STORAGE: (new <T>() => {
329
+ getStore(): T | undefined;
330
+ run<R>(store: T, callback: () => R): R;
331
+ enterWith?(store: T): void;
332
+ }) | undefined;
333
+ }
334
+ /** Test helper — allow tests to drop a stale fallback storage between runs. */
335
+ declare function _resetRaindropCallMetadataStorage(): void;
336
+ /**
337
+ * Returns the active per-call Raindrop metadata, or `undefined` if no
338
+ * call is currently in scope. Safe to call from any telemetry callback.
339
+ */
340
+ declare function getCurrentRaindropCallMetadata(): RaindropCallMetadata | undefined;
341
+ /**
342
+ * Runs `fn` with `metadata` bound as the active per-call Raindrop metadata.
343
+ * Visible to nested async work via `AsyncLocalStorage` when available.
344
+ */
345
+ declare function runWithRaindropCallMetadata<R>(metadata: RaindropCallMetadata, fn: () => R): R;
346
+ /**
347
+ * Inspect the first argument to an AI SDK function call (the call
348
+ * options object) and pull out any Raindrop metadata routed via one of:
349
+ *
350
+ * 1. top-level `metadata` — convention inherited from the v4-v6 Proxy
351
+ * path (`extractRaindropCallOptions` in `wrap/wrapAISDK.ts`). Some
352
+ * callers route `eventMetadata()` here to bypass framework-specific
353
+ * `experimental_telemetry` typings;
354
+ * 2. `telemetry.metadata` — the v7 beta.111+ stable name (anticipated;
355
+ * the v7 dispatcher does not currently forward `metadata`, but the
356
+ * shape is what users will pass once it lands);
357
+ * 3. `experimental_telemetry.metadata` — the documented and currently
358
+ * working channel for v6 + every published v7 beta.
359
+ *
360
+ * Priority is `(1) > (2) > (3)` to stay consistent with the v4-v6 path's
361
+ * `extractRaindropCallOptions`. If you ever change this order, the
362
+ * self-diagnostics injection in `wrapAISDK.ts` (which mutates the v3
363
+ * source only) becomes a re-read hazard — see the comment by
364
+ * `mergedAlsMetadata` in that file.
365
+ *
366
+ * Returns `undefined` when there is no Raindrop metadata to propagate,
367
+ * so callers can skip the ALS push entirely.
368
+ */
369
+ declare function readRaindropCallMetadataFromArgs(args: readonly unknown[]): RaindropCallMetadata | undefined;
370
+
312
371
  declare function _resetWarnedMissingUserId(): void;
313
372
 
314
373
  /**
@@ -688,4 +747,4 @@ type RaindropAISDKClient = {
688
747
  };
689
748
  declare function createRaindropAISDK(opts: RaindropAISDKOptions): RaindropAISDKClient;
690
749
 
691
- export { type AISDKChatRequestLike as A, type BuildEventPatch as B, ContextManager as C, type EndSpanArgs as E, type IdentifyInput as I, type RaindropAISDKClient as R, type SelfDiagnosticsOptions as S, type TraceSpan as T, type WrapAISDKOptions as W, _resetWarnedMissingUserId as _, type AISDKChatRequestMessageLike as a, type AISDKMessage as b, type AgentCallMetadata as c, type AgentWithMetadata as d, type Attachment as e, type ContextSpan as f, type CreateSpanArgs as g, type EventBuilder as h, type EventMetadataOptions as i, type RaindropAISDKContext as j, type RaindropAISDKOptions as k, RaindropTelemetryIntegration as l, type RaindropTelemetryIntegrationOptions as m, type SelfDiagnosticsSignalDefinition as n, type SelfDiagnosticsSignalDefinitions as o, type StartSpanArgs as p, type WrappedAI as q, type WrappedAISDK as r, createRaindropAISDK as s, currentSpan as t, eventMetadata as u, eventMetadataFromChatRequest as v, getContextManager as w, withCurrent as x };
750
+ export { type AISDKChatRequestLike as A, type BuildEventPatch as B, ContextManager as C, readRaindropCallMetadataFromArgs as D, type EndSpanArgs as E, runWithRaindropCallMetadata as F, withCurrent as G, type IdentifyInput as I, type RaindropAISDKClient as R, type SelfDiagnosticsOptions as S, type TraceSpan as T, type WrapAISDKOptions as W, _resetRaindropCallMetadataStorage as _, type AISDKChatRequestMessageLike as a, type AISDKMessage as b, type AgentCallMetadata as c, type AgentWithMetadata as d, type Attachment as e, type ContextSpan as f, type CreateSpanArgs as g, type EventBuilder as h, type EventMetadataOptions as i, type RaindropAISDKContext as j, type RaindropAISDKOptions as k, type RaindropCallMetadata as l, RaindropTelemetryIntegration as m, type RaindropTelemetryIntegrationOptions as n, type SelfDiagnosticsSignalDefinition as o, type SelfDiagnosticsSignalDefinitions as p, type StartSpanArgs as q, type WrappedAI as r, type WrappedAISDK as s, _resetWarnedMissingUserId as t, createRaindropAISDK as u, currentSpan as v, eventMetadata as w, eventMetadataFromChatRequest as x, getContextManager as y, getCurrentRaindropCallMetadata as z };