@raindrop-ai/ai-sdk 0.0.20 → 0.0.21

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
@@ -5,6 +5,7 @@ Standalone Vercel AI SDK integration for Raindrop:
5
5
  - **Events**: sends a `track_partial` payload to `POST /v1/events/track_partial` when the model finishes
6
6
  - **Standalone traces**: ships spans directly to `POST /v1/traces` as **OTLP/HTTP JSON**
7
7
  - **No OpenTelemetry SDK init**: avoids global OTEL registration conflicts
8
+ - **Native v7 telemetry**: opt-in callback-based integration via AI SDK v7's `TelemetryIntegration` interface (no Proxy wrapping)
8
9
 
9
10
  ## Install
10
11
 
@@ -54,6 +55,27 @@ await raindrop.users.identify({
54
55
  await raindrop.flush();
55
56
  ```
56
57
 
58
+ ### AI SDK v7+ native telemetry (opt-in)
59
+
60
+ 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`).
61
+
62
+ ```ts
63
+ // Option A: wrap() with nativeTelemetry flag
64
+ const { generateText } = raindrop.wrap(ai, {
65
+ context: { userId: "user_123" },
66
+ nativeTelemetry: true,
67
+ });
68
+
69
+ // Option B: direct registration (no wrap needed)
70
+ import { registerTelemetryIntegration } from "ai";
71
+
72
+ registerTelemetryIntegration(
73
+ raindrop.createTelemetryIntegration({ userId: "user_123" })
74
+ );
75
+ ```
76
+
77
+ 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).
78
+
57
79
  If `userId` is missing from both `wrap()` context and `eventMetadata()`, the SDK logs a warning (once) and skips sending events.
58
80
 
59
81
  ## Runtime support
@@ -101,11 +123,12 @@ but it uses the same synchronous fallback described above rather than real
101
123
 
102
124
  This package is tested against multiple Vercel AI SDK versions:
103
125
 
104
- | Version | Status |
105
- |---------|--------|
106
- | v4.x | ✅ Supported |
107
- | v5.x | ✅ Supported |
108
- | v6.x | ✅ Supported |
126
+ | Version | Status | Integration |
127
+ |---------|--------|-------------|
128
+ | v4.x | ✅ Supported | Proxy |
129
+ | v5.x | ✅ Supported | Proxy |
130
+ | v6.x | ✅ Supported | Proxy |
131
+ | v7.x (beta) | ✅ Supported | Proxy (default) or native `TelemetryIntegration` (opt-in) |
109
132
 
110
133
  ### Version Differences Handled
111
134
 
@@ -130,10 +153,15 @@ packages/ai-sdk/
130
153
  │ │ ├── ai-sdk.v5.test.ts
131
154
  │ │ ├── wrapper.test.ts
132
155
  │ │ └── http-payloads.test.ts
133
- └── v6/ # AI SDK v6 (pins ai@^6.0.0)
134
- ├── ai-sdk.v6.test.ts
135
- ├── wrapper.test.ts
136
- └── http-payloads.test.ts
156
+ ├── v6/ # AI SDK v6 (pins ai@^6.0.0)
157
+ ├── ai-sdk.v6.test.ts
158
+ ├── wrapper.test.ts
159
+ └── http-payloads.test.ts
160
+ │ └── v7/ # AI SDK v7 beta (native telemetry + proxy)
161
+ │ ├── telemetry-integration.test.ts # Unit tests for all callbacks
162
+ │ ├── e2e-native-telemetry.test.ts # E2E with real AI SDK + MSW
163
+ │ ├── e2e-subagent-nesting.test.ts # Subagent span hierarchy
164
+ │ └── wrapper.test.ts
137
165
  ```
138
166
 
139
167
  ### Running Tests
@@ -146,6 +174,7 @@ pnpm test
146
174
  pnpm test:v4
147
175
  pnpm test:v5
148
176
  pnpm test:v6
177
+ pnpm test:v7
149
178
 
150
179
  # Quick smoke test (real LLM calls, single version)
151
180
  pnpm smoke:min
@@ -158,6 +187,11 @@ Each version runs:
158
187
  - **HTTP payload tests** - MSW-based payload validation for each spec version
159
188
  - **Version-specific tests** - API differences (finishReason format, usage naming)
160
189
 
190
+ v7 additionally runs:
191
+ - **Telemetry integration tests** - All callback lifecycles with mock shippers
192
+ - **E2E native telemetry** - Real AI SDK v7 with MSW-intercepted payloads
193
+ - **Subagent nesting** - Span hierarchy for nested generateText inside tool execution
194
+
161
195
  ## Notes
162
196
 
163
197
  - Spans include `ai.telemetry.metadata.raindrop.eventId` for correlation, and **omit** `ai.telemetry.metadata.raindrop.userId` to prevent duplicate span→event creation server-side.
@@ -1,6 +1,6 @@
1
1
  import { AsyncLocalStorage } from 'async_hooks';
2
2
 
3
- // ../core/dist/chunk-H6VSZSLN.js
3
+ // ../core/dist/chunk-4UCYIEH4.js
4
4
  function getCrypto() {
5
5
  const c = globalThis.crypto;
6
6
  return c;
@@ -145,6 +145,7 @@ async function postJson(url, body, headers, opts) {
145
145
  );
146
146
  }
147
147
  var SpanStatusCode = {
148
+ UNSET: 0,
148
149
  ERROR: 2
149
150
  };
150
151
  function createSpanIds(parent) {
@@ -465,11 +466,66 @@ var EventShipper = class {
465
466
  }
466
467
  }
467
468
  };
469
+ var LOCAL_DEBUGGER_ENV_VAR = "RAINDROP_LOCAL_DEBUGGER";
470
+ function resolveLocalDebuggerBaseUrl(baseUrl) {
471
+ var _a, _b, _c;
472
+ const resolved = (_b = baseUrl != null ? baseUrl : typeof process !== "undefined" ? (_a = process.env) == null ? void 0 : _a[LOCAL_DEBUGGER_ENV_VAR] : void 0) != null ? _b : null;
473
+ return resolved ? (_c = formatEndpoint(resolved)) != null ? _c : null : null;
474
+ }
475
+ function localDebuggerEnabled(baseUrl) {
476
+ return resolveLocalDebuggerBaseUrl(baseUrl) !== null;
477
+ }
478
+ function normalizeLocalDebuggerLiveEventType(type) {
479
+ switch (type) {
480
+ case "text-delta":
481
+ return "text_delta";
482
+ case "reasoning":
483
+ case "reasoning-delta":
484
+ return "reasoning_delta";
485
+ case "tool-call":
486
+ return "tool_start";
487
+ case "tool-result":
488
+ return "tool_result";
489
+ default:
490
+ return type;
491
+ }
492
+ }
493
+ function mirrorTraceExportToLocalDebugger(body, options = {}) {
494
+ var _a;
495
+ const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
496
+ if (!baseUrl) return;
497
+ void postJson(`${baseUrl}traces`, body, {}, {
498
+ maxAttempts: 1,
499
+ debug: (_a = options.debug) != null ? _a : false,
500
+ sdkName: options.sdkName
501
+ }).catch(() => {
502
+ });
503
+ }
504
+ function sendLocalDebuggerLiveEvent(event, options = {}) {
505
+ var _a, _b;
506
+ const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
507
+ if (!baseUrl) return;
508
+ void postJson(
509
+ `${baseUrl}live`,
510
+ {
511
+ ...event,
512
+ type: normalizeLocalDebuggerLiveEventType(event.type),
513
+ timestamp: (_a = event.timestamp) != null ? _a : Date.now()
514
+ },
515
+ {},
516
+ {
517
+ maxAttempts: 1,
518
+ debug: (_b = options.debug) != null ? _b : false,
519
+ sdkName: options.sdkName
520
+ }
521
+ ).catch(() => {
522
+ });
523
+ }
468
524
  var TraceShipper = class {
469
525
  constructor(opts) {
470
526
  this.queue = [];
471
527
  this.inFlight = /* @__PURE__ */ new Set();
472
- var _a, _b, _c, _d, _e, _f, _g, _h;
528
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
473
529
  this.writeKey = (_a = opts.writeKey) == null ? void 0 : _a.trim();
474
530
  this.baseUrl = (_b = formatEndpoint(opts.endpoint)) != null ? _b : "https://api.raindrop.ai/v1/";
475
531
  this.enabled = opts.enabled !== false;
@@ -482,6 +538,13 @@ var TraceShipper = class {
482
538
  this.prefix = `[raindrop-ai/${this.sdkName}]`;
483
539
  this.serviceName = (_g = opts.serviceName) != null ? _g : "raindrop.core";
484
540
  this.serviceVersion = (_h = opts.serviceVersion) != null ? _h : "0.0.0";
541
+ const localDebugger = typeof process !== "undefined" ? (_i = process.env) == null ? void 0 : _i.RAINDROP_LOCAL_DEBUGGER : void 0;
542
+ if (localDebugger) {
543
+ this.localDebuggerUrl = (_j = resolveLocalDebuggerBaseUrl(localDebugger)) != null ? _j : void 0;
544
+ if (this.debug) {
545
+ console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
546
+ }
547
+ }
485
548
  }
486
549
  isDebugEnabled() {
487
550
  return this.debug;
@@ -498,7 +561,25 @@ var TraceShipper = class {
498
561
  attrString("ai.operationId", args.operationId)
499
562
  ];
500
563
  if ((_b = args.attributes) == null ? void 0 : _b.length) attrs.push(...args.attributes);
501
- return { ids, name: args.name, startTimeUnixNano: started, attributes: attrs };
564
+ const span = { ids, name: args.name, startTimeUnixNano: started, attributes: attrs };
565
+ if (this.localDebuggerUrl) {
566
+ const openSpan = buildOtlpSpan({
567
+ ids: span.ids,
568
+ name: span.name,
569
+ startTimeUnixNano: span.startTimeUnixNano,
570
+ endTimeUnixNano: span.startTimeUnixNano,
571
+ // placeholder — will be updated on endSpan
572
+ attributes: span.attributes,
573
+ status: { code: SpanStatusCode.UNSET }
574
+ });
575
+ const body = buildExportTraceServiceRequest([openSpan], this.serviceName, this.serviceVersion);
576
+ mirrorTraceExportToLocalDebugger(body, {
577
+ baseUrl: this.localDebuggerUrl,
578
+ debug: false,
579
+ sdkName: this.sdkName
580
+ });
581
+ }
582
+ return span;
502
583
  }
503
584
  endSpan(span, extra) {
504
585
  var _a, _b;
@@ -521,6 +602,14 @@ var TraceShipper = class {
521
602
  status
522
603
  });
523
604
  this.enqueue(otlp);
605
+ if (this.localDebuggerUrl) {
606
+ const body = buildExportTraceServiceRequest([otlp], this.serviceName, this.serviceVersion);
607
+ mirrorTraceExportToLocalDebugger(body, {
608
+ baseUrl: this.localDebuggerUrl,
609
+ debug: false,
610
+ sdkName: this.sdkName
611
+ });
612
+ }
524
613
  }
525
614
  createSpan(args) {
526
615
  var _a;
@@ -538,6 +627,14 @@ var TraceShipper = class {
538
627
  status: args.status
539
628
  });
540
629
  this.enqueue(otlp);
630
+ if (this.localDebuggerUrl) {
631
+ const body = buildExportTraceServiceRequest([otlp], this.serviceName, this.serviceVersion);
632
+ mirrorTraceExportToLocalDebugger(body, {
633
+ baseUrl: this.localDebuggerUrl,
634
+ debug: false,
635
+ sdkName: this.sdkName
636
+ });
637
+ }
541
638
  }
542
639
  enqueue(span) {
543
640
  if (!this.enabled) return;
@@ -1517,6 +1614,7 @@ var RaindropTelemetryIntegration = class {
1517
1614
  ]
1518
1615
  });
1519
1616
  state.toolSpans.set(toolCall.toolCallId, toolSpan);
1617
+ this.emitLive(state, "tool_start", toolCall.toolName, { args: toolCall.input });
1520
1618
  };
1521
1619
  // ── onToolCallFinish ────────────────────────────────────────────────────
1522
1620
  this.onToolCallFinish = (event) => {
@@ -1531,11 +1629,12 @@ var RaindropTelemetryIntegration = class {
1531
1629
  } else {
1532
1630
  this.traceShipper.endSpan(toolSpan, { error: event.error });
1533
1631
  }
1632
+ this.emitLive(state, "tool_result", event.toolCall.toolName);
1534
1633
  state.toolSpans.delete(event.toolCall.toolCallId);
1535
1634
  };
1536
1635
  // ── onChunk (streaming) ─────────────────────────────────────────────────
1537
1636
  this.onChunk = (event) => {
1538
- var _a, _b, _c;
1637
+ var _a, _b, _c, _d, _e;
1539
1638
  const callId = (_b = event.callId) != null ? _b : (_a = event.chunk) == null ? void 0 : _a.callId;
1540
1639
  if (!callId) return;
1541
1640
  const state = this.getState(callId);
@@ -1546,6 +1645,12 @@ var RaindropTelemetryIntegration = class {
1546
1645
  const delta = (_c = chunk.textDelta) != null ? _c : chunk.delta;
1547
1646
  if (typeof delta === "string") {
1548
1647
  state.accumulatedText += delta;
1648
+ this.emitLive(state, "text_delta", delta);
1649
+ }
1650
+ } else if (chunk.type === "reasoning" || chunk.type === "reasoning-delta") {
1651
+ const text = (_e = (_d = chunk.textDelta) != null ? _d : chunk.text) != null ? _e : chunk.delta;
1652
+ if (typeof text === "string") {
1653
+ this.emitLive(state, "reasoning_delta", text);
1549
1654
  }
1550
1655
  }
1551
1656
  };
@@ -1733,6 +1838,23 @@ var RaindropTelemetryIntegration = class {
1733
1838
  spanParentRef(span) {
1734
1839
  return { traceIdB64: span.ids.traceIdB64, spanIdB64: span.ids.spanIdB64 };
1735
1840
  }
1841
+ emitLive(state, type, content, extra) {
1842
+ var _a, _b, _c, _d, _e, _f;
1843
+ if (!localDebuggerEnabled() || !state.rootSpan) return;
1844
+ const callMeta = this.extractRaindropMetadata(state.metadata);
1845
+ sendLocalDebuggerLiveEvent({
1846
+ traceId: state.rootSpan.ids.traceIdB64,
1847
+ type,
1848
+ content,
1849
+ metadata: {
1850
+ userId: (_b = callMeta.userId) != null ? _b : (_a = this.defaultContext) == null ? void 0 : _a.userId,
1851
+ convoId: (_d = callMeta.convoId) != null ? _d : (_c = this.defaultContext) == null ? void 0 : _c.convoId,
1852
+ eventName: (_f = callMeta.eventName) != null ? _f : (_e = this.defaultContext) == null ? void 0 : _e.eventName,
1853
+ eventId: state.eventId,
1854
+ ...extra
1855
+ }
1856
+ });
1857
+ }
1736
1858
  extractRaindropMetadata(metadata) {
1737
1859
  if (!metadata) return {};
1738
1860
  const result = {};
@@ -2265,6 +2387,36 @@ function shouldKeepEventPending(params) {
2265
2387
  if (params.error != null || !params.canKeepEventPending) return false;
2266
2388
  return params.finishReason === "tool-calls" || params.finishReason === "tool_calls";
2267
2389
  }
2390
+ function normalizePromptAttr(arg) {
2391
+ if (!isRecord(arg)) return arg;
2392
+ const system = arg["system"];
2393
+ const prompt = arg["prompt"];
2394
+ const messages = arg["messages"];
2395
+ if (Array.isArray(messages)) {
2396
+ if (system) {
2397
+ const sysContent = typeof system === "string" ? system : JSON.stringify(system);
2398
+ return [{ role: "system", content: sysContent }, ...messages];
2399
+ }
2400
+ return messages;
2401
+ }
2402
+ if (typeof prompt === "string") {
2403
+ const msgs = [];
2404
+ if (system) {
2405
+ msgs.push({ role: "system", content: typeof system === "string" ? system : JSON.stringify(system) });
2406
+ }
2407
+ msgs.push({ role: "user", content: prompt });
2408
+ return msgs;
2409
+ }
2410
+ return { system, prompt, messages };
2411
+ }
2412
+ function getLocalDebuggerMetadata(ctx) {
2413
+ return {
2414
+ eventId: ctx.eventId,
2415
+ ...ctx.eventName ? { eventName: ctx.eventName } : {},
2416
+ ...ctx.userId ? { userId: ctx.userId } : {},
2417
+ ...ctx.convoId ? { convoId: ctx.convoId } : {}
2418
+ };
2419
+ }
2268
2420
  async function safeFinalize(finalize, debug, result, error) {
2269
2421
  try {
2270
2422
  await finalize(result, error);
@@ -2337,17 +2489,17 @@ function setupOperation(params) {
2337
2489
  attrString("ai.telemetry.functionId", telemetry == null ? void 0 : telemetry.functionId),
2338
2490
  attrString("ai.model.provider", modelInfoFromArgs.provider),
2339
2491
  attrString("ai.model.id", modelInfoFromArgs.modelId),
2492
+ attrString("ai.telemetry.metadata.raindrop.eventId", eventId),
2493
+ attrString("ai.telemetry.metadata.raindrop.eventName", mergedCtx.eventName),
2494
+ attrString("ai.telemetry.metadata.raindrop.userId", mergedCtx.userId),
2495
+ attrString("ai.telemetry.metadata.raindrop.convoId", mergedCtx.convoId),
2340
2496
  ...attrsFromTelemetryMetadata(telemetry == null ? void 0 : telemetry.metadata),
2341
2497
  ...attrsFromHeaders(isRecord(arg) ? arg["headers"] : void 0),
2342
2498
  ...attrsFromSettings(arg),
2343
2499
  ...(telemetry == null ? void 0 : telemetry.recordInputs) === false ? [] : [
2344
2500
  attrString(
2345
2501
  "ai.prompt",
2346
- safeJsonWithUint8({
2347
- system: isRecord(arg) ? arg["system"] : void 0,
2348
- prompt: isRecord(arg) ? arg["prompt"] : void 0,
2349
- messages: isRecord(arg) ? arg["messages"] : void 0
2350
- })
2502
+ safeJsonWithUint8(normalizePromptAttr(arg))
2351
2503
  )
2352
2504
  ]
2353
2505
  ]
@@ -2356,6 +2508,7 @@ function setupOperation(params) {
2356
2508
  const operationSelfDiagnostics = isObjectOperation(operation) ? void 0 : selfDiagnostics;
2357
2509
  const wrapCtx = {
2358
2510
  eventId,
2511
+ context: mergedCtx,
2359
2512
  telemetry,
2360
2513
  sendTraces,
2361
2514
  debug,
@@ -2730,6 +2883,7 @@ function wrapAISDK(aiSDK, deps) {
2730
2883
  const perCallEventIdGenerated = !perCallEventIdExplicit;
2731
2884
  const perCallCtx = {
2732
2885
  eventId: perCallEventId,
2886
+ context: wrapTimeCtx,
2733
2887
  telemetry,
2734
2888
  sendTraces: false,
2735
2889
  debug,
@@ -2884,7 +3038,7 @@ function wrapAgentGenerate(generate, instance, agentSettings, className, aiSDK,
2884
3038
  if (!mergedCtx.userId) warnMissingUserIdOnce();
2885
3039
  const inherited = await getCurrentParentSpanContext();
2886
3040
  const eventId = (_c = (_b2 = (_a2 = callTimeCtx.eventId) != null ? _a2 : mergedCtx.eventId) != null ? _b2 : inherited == null ? void 0 : inherited.eventId) != null ? _c : randomUUID();
2887
- const ctx = { ...mergedCtx};
3041
+ const ctx = { ...mergedCtx, eventId };
2888
3042
  const inheritedParent = inherited && inherited.eventId === eventId ? { traceIdB64: inherited.traceIdB64, spanIdB64: inherited.spanIdB64 } : void 0;
2889
3043
  const outerOperationId = `ai.${operation}`;
2890
3044
  const { operationName, resourceName } = opName(outerOperationId, telemetry == null ? void 0 : telemetry.functionId);
@@ -2900,17 +3054,17 @@ function wrapAgentGenerate(generate, instance, agentSettings, className, aiSDK,
2900
3054
  attrString("ai.telemetry.functionId", telemetry == null ? void 0 : telemetry.functionId),
2901
3055
  attrString("ai.model.provider", modelInfoFromArgs.provider),
2902
3056
  attrString("ai.model.id", modelInfoFromArgs.modelId),
3057
+ attrString("ai.telemetry.metadata.raindrop.eventId", eventId),
3058
+ attrString("ai.telemetry.metadata.raindrop.eventName", ctx.eventName),
3059
+ attrString("ai.telemetry.metadata.raindrop.userId", ctx.userId),
3060
+ attrString("ai.telemetry.metadata.raindrop.convoId", ctx.convoId),
2903
3061
  ...attrsFromTelemetryMetadata(telemetry == null ? void 0 : telemetry.metadata),
2904
3062
  ...attrsFromHeaders(mergedArgs["headers"]),
2905
3063
  ...attrsFromSettings(mergedArgs),
2906
3064
  ...(telemetry == null ? void 0 : telemetry.recordInputs) === false ? [] : [
2907
3065
  attrString(
2908
3066
  "ai.prompt",
2909
- safeJsonWithUint8({
2910
- system: (_d = mergedArgs["system"]) != null ? _d : mergedArgs["instructions"],
2911
- prompt: mergedArgs["prompt"],
2912
- messages: mergedArgs["messages"]
2913
- })
3067
+ safeJsonWithUint8(normalizePromptAttr({ system: (_d = mergedArgs["system"]) != null ? _d : mergedArgs["instructions"], prompt: mergedArgs["prompt"], messages: mergedArgs["messages"] }))
2914
3068
  )
2915
3069
  ]
2916
3070
  ]
@@ -2918,6 +3072,7 @@ function wrapAgentGenerate(generate, instance, agentSettings, className, aiSDK,
2918
3072
  const rootParentForChildren = rootSpan ? { traceIdB64: rootSpan.ids.traceIdB64, spanIdB64: rootSpan.ids.spanIdB64 } : inheritedParent;
2919
3073
  const wrapCtx = {
2920
3074
  eventId,
3075
+ context: ctx,
2921
3076
  telemetry,
2922
3077
  sendTraces,
2923
3078
  debug,
@@ -3091,7 +3246,7 @@ function wrapAgentStream(stream, instance, agentSettings, className, aiSDK, deps
3091
3246
  if (!mergedCtx.userId) warnMissingUserIdOnce();
3092
3247
  const inherited = await getCurrentParentSpanContext();
3093
3248
  const eventId = (_c = (_b2 = (_a2 = callTimeCtx.eventId) != null ? _a2 : mergedCtx.eventId) != null ? _b2 : inherited == null ? void 0 : inherited.eventId) != null ? _c : randomUUID();
3094
- const ctx = { ...mergedCtx};
3249
+ const ctx = { ...mergedCtx, eventId };
3095
3250
  const inheritedParent = inherited && inherited.eventId === eventId ? { traceIdB64: inherited.traceIdB64, spanIdB64: inherited.spanIdB64 } : void 0;
3096
3251
  const outerOperationId = `ai.${operation}`;
3097
3252
  const { operationName, resourceName } = opName(outerOperationId, telemetry == null ? void 0 : telemetry.functionId);
@@ -3107,17 +3262,17 @@ function wrapAgentStream(stream, instance, agentSettings, className, aiSDK, deps
3107
3262
  attrString("ai.telemetry.functionId", telemetry == null ? void 0 : telemetry.functionId),
3108
3263
  attrString("ai.model.provider", modelInfoFromArgs.provider),
3109
3264
  attrString("ai.model.id", modelInfoFromArgs.modelId),
3265
+ attrString("ai.telemetry.metadata.raindrop.eventId", eventId),
3266
+ attrString("ai.telemetry.metadata.raindrop.eventName", ctx.eventName),
3267
+ attrString("ai.telemetry.metadata.raindrop.userId", ctx.userId),
3268
+ attrString("ai.telemetry.metadata.raindrop.convoId", ctx.convoId),
3110
3269
  ...attrsFromTelemetryMetadata(telemetry == null ? void 0 : telemetry.metadata),
3111
3270
  ...attrsFromHeaders(mergedArgs["headers"]),
3112
3271
  ...attrsFromSettings(mergedArgs),
3113
3272
  ...(telemetry == null ? void 0 : telemetry.recordInputs) === false ? [] : [
3114
3273
  attrString(
3115
3274
  "ai.prompt",
3116
- safeJsonWithUint8({
3117
- system: (_d = mergedArgs["system"]) != null ? _d : mergedArgs["instructions"],
3118
- prompt: mergedArgs["prompt"],
3119
- messages: mergedArgs["messages"]
3120
- })
3275
+ safeJsonWithUint8(normalizePromptAttr({ system: (_d = mergedArgs["system"]) != null ? _d : mergedArgs["instructions"], prompt: mergedArgs["prompt"], messages: mergedArgs["messages"] }))
3121
3276
  )
3122
3277
  ]
3123
3278
  ]
@@ -3125,6 +3280,7 @@ function wrapAgentStream(stream, instance, agentSettings, className, aiSDK, deps
3125
3280
  const rootParentForChildren = rootSpan ? { traceIdB64: rootSpan.ids.traceIdB64, spanIdB64: rootSpan.ids.spanIdB64 } : inheritedParent;
3126
3281
  const wrapCtx = {
3127
3282
  eventId,
3283
+ context: ctx,
3128
3284
  telemetry,
3129
3285
  sendTraces,
3130
3286
  debug,
@@ -3348,6 +3504,21 @@ function wrapToolExecute(name, tool, ctx, toolCalls) {
3348
3504
  });
3349
3505
  }
3350
3506
  };
3507
+ const sendToolLiveEvent = (parent, type, metadata) => {
3508
+ if (!localDebuggerEnabled() || !parent) return;
3509
+ sendLocalDebuggerLiveEvent({
3510
+ traceId: parent.traceIdB64,
3511
+ type,
3512
+ content: name,
3513
+ metadata: {
3514
+ ...getLocalDebuggerMetadata({
3515
+ ...ctx.context,
3516
+ eventId: ctx.eventId
3517
+ }),
3518
+ ...metadata
3519
+ }
3520
+ });
3521
+ };
3351
3522
  const createContextSpan = (span) => ({
3352
3523
  traceIdB64: span.ids.traceIdB64,
3353
3524
  spanIdB64: span.ids.spanIdB64,
@@ -3363,6 +3534,7 @@ function wrapToolExecute(name, tool, ctx, toolCalls) {
3363
3534
  const parentCtx = await getCurrentParentSpanContext();
3364
3535
  const parent = parentCtx && parentCtx.eventId === ctx.eventId ? { traceIdB64: parentCtx.traceIdB64, spanIdB64: parentCtx.spanIdB64 } : ctx.rootParentForChildren;
3365
3536
  const toolSpan = createToolSpan(toolCallId, toolArgs, parent);
3537
+ sendToolLiveEvent(parent, "tool_start", { args: toolArgs });
3366
3538
  try {
3367
3539
  let lastValue;
3368
3540
  const iterator = result[Symbol.asyncIterator]();
@@ -3378,9 +3550,13 @@ function wrapToolExecute(name, tool, ctx, toolCalls) {
3378
3550
  }
3379
3551
  toolCalls.push({ id: toolCallId, name, args: toolArgs, result: lastValue, status: "OK" });
3380
3552
  endToolSpan(toolSpan, lastValue);
3553
+ sendToolLiveEvent(parent, "tool_result", { result: lastValue });
3381
3554
  } catch (error) {
3382
3555
  toolCalls.push({ id: toolCallId, name, args: toolArgs, status: "ERROR" });
3383
3556
  endToolSpan(toolSpan, void 0, error);
3557
+ sendToolLiveEvent(parent, "tool_result", {
3558
+ error: error instanceof Error ? error.message : String(error)
3559
+ });
3384
3560
  throw error;
3385
3561
  }
3386
3562
  })();
@@ -3389,6 +3565,7 @@ function wrapToolExecute(name, tool, ctx, toolCalls) {
3389
3565
  const parentCtx = await getCurrentParentSpanContext();
3390
3566
  const parent = parentCtx && parentCtx.eventId === ctx.eventId ? { traceIdB64: parentCtx.traceIdB64, spanIdB64: parentCtx.spanIdB64 } : ctx.rootParentForChildren;
3391
3567
  const toolSpan = createToolSpan(toolCallId, toolArgs, parent);
3568
+ sendToolLiveEvent(parent, "tool_start", { args: toolArgs });
3392
3569
  const run = async () => {
3393
3570
  try {
3394
3571
  const awaitedResult = await result;
@@ -3400,10 +3577,14 @@ function wrapToolExecute(name, tool, ctx, toolCalls) {
3400
3577
  status: "OK"
3401
3578
  });
3402
3579
  endToolSpan(toolSpan, awaitedResult);
3580
+ sendToolLiveEvent(parent, "tool_result", { result: awaitedResult });
3403
3581
  return awaitedResult;
3404
3582
  } catch (error) {
3405
3583
  toolCalls.push({ id: toolCallId, name, args: toolArgs, status: "ERROR" });
3406
3584
  endToolSpan(toolSpan, void 0, error);
3585
+ sendToolLiveEvent(parent, "tool_result", {
3586
+ error: error instanceof Error ? error.message : String(error)
3587
+ });
3407
3588
  throw error;
3408
3589
  }
3409
3590
  };
@@ -3443,6 +3624,7 @@ function wrapModel(args, aiSDK, outerOperationId, ctx) {
3443
3624
  const original = Reflect.get(target, prop, receiver);
3444
3625
  if (prop === "doGenerate" && isFunction(original)) {
3445
3626
  return async (...callArgs) => {
3627
+ var _a, _b;
3446
3628
  const options = callArgs[0];
3447
3629
  const parentCtx = await getCurrentParentSpanContext();
3448
3630
  const parent = parentCtx && parentCtx.eventId === ctx.eventId ? { traceIdB64: parentCtx.traceIdB64, spanIdB64: parentCtx.spanIdB64 } : ctx.rootParentForChildren;
@@ -3450,6 +3632,22 @@ function wrapModel(args, aiSDK, outerOperationId, ctx) {
3450
3632
  try {
3451
3633
  const result = await original.apply(target, callArgs);
3452
3634
  if (span) endDoGenerateSpan(span, result, modelInfo, ctx);
3635
+ if (localDebuggerEnabled() && ctx.rootParentForChildren && isRecord(result)) {
3636
+ const traceId = ctx.rootParentForChildren.traceIdB64;
3637
+ const liveMeta = getLocalDebuggerMetadata({ ...ctx.context, eventId: ctx.eventId });
3638
+ const content = result["content"];
3639
+ if (Array.isArray(content)) {
3640
+ for (const part of content) {
3641
+ if (isRecord(part)) {
3642
+ if ((part["type"] === "reasoning" || part["type"] === "thinking") && typeof ((_a = part["text"]) != null ? _a : part["thinking"]) === "string") {
3643
+ sendLocalDebuggerLiveEvent({ traceId, type: "reasoning_delta", content: (_b = part["text"]) != null ? _b : part["thinking"], metadata: liveMeta });
3644
+ } else if (part["type"] === "text" && typeof part["text"] === "string") {
3645
+ sendLocalDebuggerLiveEvent({ traceId, type: "text_delta", content: part["text"], metadata: liveMeta });
3646
+ }
3647
+ }
3648
+ }
3649
+ }
3650
+ }
3453
3651
  return result;
3454
3652
  } catch (error) {
3455
3653
  if (span)
@@ -3589,6 +3787,23 @@ function wrapModel(args, aiSDK, outerOperationId, ctx) {
3589
3787
  }
3590
3788
  if ("usage" in value) usage = value["usage"];
3591
3789
  if ("providerMetadata" in value) providerMetadata = value["providerMetadata"];
3790
+ if (localDebuggerEnabled() && ctx.rootParentForChildren) {
3791
+ const traceId = ctx.rootParentForChildren.traceIdB64;
3792
+ const liveMeta = getLocalDebuggerMetadata({ ...ctx.context, eventId: ctx.eventId });
3793
+ if (type === "text-delta") {
3794
+ const text = typeof value["delta"] === "string" ? value["delta"] : typeof value["textDelta"] === "string" ? value["textDelta"] : typeof value["text"] === "string" ? value["text"] : void 0;
3795
+ if (typeof text === "string" && text) sendLocalDebuggerLiveEvent({ traceId, type: "text_delta", content: text, metadata: liveMeta });
3796
+ } else if (type === "reasoning" || type === "reasoning-delta") {
3797
+ const text = typeof value["delta"] === "string" ? value["delta"] : typeof value["text"] === "string" ? value["text"] : typeof value["thinking"] === "string" ? value["thinking"] : void 0;
3798
+ if (typeof text === "string" && text) sendLocalDebuggerLiveEvent({ traceId, type: "reasoning_delta", content: text, metadata: liveMeta });
3799
+ } else if (type === "tool-call") {
3800
+ const toolName = typeof value["toolName"] === "string" ? value["toolName"] : "tool";
3801
+ sendLocalDebuggerLiveEvent({ traceId, type: "tool_start", content: toolName, metadata: { ...liveMeta, args: value["args"] } });
3802
+ } else if (type === "tool-result") {
3803
+ const toolName = typeof value["toolName"] === "string" ? value["toolName"] : "tool";
3804
+ sendLocalDebuggerLiveEvent({ traceId, type: "tool_result", content: toolName, metadata: { ...liveMeta, result: value["result"] } });
3805
+ }
3806
+ }
3592
3807
  }
3593
3808
  controller.enqueue(value);
3594
3809
  } catch (error) {
@@ -3789,7 +4004,7 @@ function extractNestedTokens(usage, key) {
3789
4004
  // package.json
3790
4005
  var package_default = {
3791
4006
  name: "@raindrop-ai/ai-sdk",
3792
- version: "0.0.20"};
4007
+ version: "0.0.21"};
3793
4008
 
3794
4009
  // src/internal/version.ts
3795
4010
  var libraryName = package_default.name;
@@ -147,6 +147,8 @@ declare class TraceShipper$1 {
147
147
  private queue;
148
148
  private timer;
149
149
  private inFlight;
150
+ /** URL of the local debugger (from RAINDROP_LOCAL_DEBUGGER env var). */
151
+ private localDebuggerUrl;
150
152
  constructor(opts: TraceShipperOptions);
151
153
  isDebugEnabled(): boolean;
152
154
  private authHeaders;
@@ -276,6 +278,7 @@ declare class RaindropTelemetryIntegration implements TelemetryIntegration {
276
278
  private getState;
277
279
  private cleanup;
278
280
  private spanParentRef;
281
+ private emitLive;
279
282
  private extractRaindropMetadata;
280
283
  /**
281
284
  * Extract the user-facing input text from an onStart event.
@@ -147,6 +147,8 @@ declare class TraceShipper$1 {
147
147
  private queue;
148
148
  private timer;
149
149
  private inFlight;
150
+ /** URL of the local debugger (from RAINDROP_LOCAL_DEBUGGER env var). */
151
+ private localDebuggerUrl;
150
152
  constructor(opts: TraceShipperOptions);
151
153
  isDebugEnabled(): boolean;
152
154
  private authHeaders;
@@ -276,6 +278,7 @@ declare class RaindropTelemetryIntegration implements TelemetryIntegration {
276
278
  private getState;
277
279
  private cleanup;
278
280
  private spanParentRef;
281
+ private emitLive;
279
282
  private extractRaindropMetadata;
280
283
  /**
281
284
  * Extract the user-facing input text from an onStart event.
@@ -147,6 +147,8 @@ declare class TraceShipper$1 {
147
147
  private queue;
148
148
  private timer;
149
149
  private inFlight;
150
+ /** URL of the local debugger (from RAINDROP_LOCAL_DEBUGGER env var). */
151
+ private localDebuggerUrl;
150
152
  constructor(opts: TraceShipperOptions);
151
153
  isDebugEnabled(): boolean;
152
154
  private authHeaders;
@@ -276,6 +278,7 @@ declare class RaindropTelemetryIntegration implements TelemetryIntegration {
276
278
  private getState;
277
279
  private cleanup;
278
280
  private spanParentRef;
281
+ private emitLive;
279
282
  private extractRaindropMetadata;
280
283
  /**
281
284
  * Extract the user-facing input text from an onStart event.
@@ -147,6 +147,8 @@ declare class TraceShipper$1 {
147
147
  private queue;
148
148
  private timer;
149
149
  private inFlight;
150
+ /** URL of the local debugger (from RAINDROP_LOCAL_DEBUGGER env var). */
151
+ private localDebuggerUrl;
150
152
  constructor(opts: TraceShipperOptions);
151
153
  isDebugEnabled(): boolean;
152
154
  private authHeaders;
@@ -276,6 +278,7 @@ declare class RaindropTelemetryIntegration implements TelemetryIntegration {
276
278
  private getState;
277
279
  private cleanup;
278
280
  private spanParentRef;
281
+ private emitLive;
279
282
  private extractRaindropMetadata;
280
283
  /**
281
284
  * Extract the user-facing input text from an onStart event.