@raindrop-ai/ai-sdk 0.0.21 → 0.0.23

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
@@ -192,6 +192,135 @@ v7 additionally runs:
192
192
  - **E2E native telemetry** - Real AI SDK v7 with MSW-intercepted payloads
193
193
  - **Subagent nesting** - Span hierarchy for nested generateText inside tool execution
194
194
 
195
+ ## Manual Traces
196
+
197
+ Create trace spans manually alongside (or instead of) auto-instrumented ones. Useful for custom operations, DSL command extraction, or building trace trees for custom agent loops.
198
+
199
+ Spans share the same trace tree as auto-instrumented spans when you pass matching `eventId` values.
200
+
201
+ All three methods are available on every entrypoint (`.`, `./workers`, `./browser`).
202
+
203
+ ### One-shot spans
204
+
205
+ Use `createSpan` when the operation is already complete and you know the duration:
206
+
207
+ ```ts
208
+ raindrop.traces.createSpan({
209
+ name: "SET theme=dark",
210
+ eventId: "evt_123",
211
+ operationId: "ai.toolCall", // appears as a tool call in the dashboard
212
+ input: "SET theme=dark",
213
+ output: "OK",
214
+ durationMs: 12,
215
+ });
216
+
217
+ // Failed span
218
+ raindrop.traces.createSpan({
219
+ name: "SET layout=invalid",
220
+ eventId: "evt_123",
221
+ operationId: "ai.toolCall",
222
+ input: "SET layout=invalid",
223
+ error: "Invalid layout value",
224
+ durationMs: 8,
225
+ });
226
+ ```
227
+
228
+ ### Lifecycle spans
229
+
230
+ Use `startSpan` / `endSpan` to time an operation in real time:
231
+
232
+ ```ts
233
+ const span = raindrop.traces.startSpan({
234
+ name: "database_query",
235
+ eventId: "evt_123",
236
+ operationId: "ai.toolCall",
237
+ });
238
+
239
+ try {
240
+ const result = await db.query("SELECT ...");
241
+ raindrop.traces.endSpan(span);
242
+ } catch (err) {
243
+ raindrop.traces.endSpan(span, { error: err });
244
+ }
245
+ ```
246
+
247
+ ### Nested spans
248
+
249
+ Pass a span as `parent` to build a trace tree:
250
+
251
+ ```ts
252
+ const eventId = "evt_456";
253
+
254
+ const agentTurn = raindrop.traces.startSpan({ name: "agent_turn", eventId });
255
+
256
+ const subagent = raindrop.traces.startSpan({
257
+ name: "search_subagent",
258
+ eventId,
259
+ parent: agentTurn,
260
+ });
261
+
262
+ raindrop.traces.createSpan({
263
+ name: "grep_search",
264
+ eventId,
265
+ parent: subagent,
266
+ operationId: "ai.toolCall",
267
+ input: { pattern: "execute" },
268
+ output: { matches: 12 },
269
+ durationMs: 120,
270
+ });
271
+
272
+ raindrop.traces.endSpan(subagent);
273
+ raindrop.traces.endSpan(agentTurn);
274
+
275
+ await raindrop.flush();
276
+ ```
277
+
278
+ ### Mixing with auto-instrumented spans
279
+
280
+ Use the same `eventId` for both `wrap()` calls and manual spans — they appear in the same trace tree:
281
+
282
+ ```ts
283
+ const eventId = crypto.randomUUID();
284
+ const { generateText } = raindrop.wrap(ai, {
285
+ context: { userId: "user_123" },
286
+ });
287
+
288
+ await generateText({
289
+ model: openai("gpt-4o"),
290
+ prompt: "Analyze this data",
291
+ experimental_telemetry: {
292
+ isEnabled: true,
293
+ metadata: eventMetadata({ eventId }),
294
+ },
295
+ });
296
+
297
+ raindrop.traces.createSpan({
298
+ name: "post_processing",
299
+ eventId,
300
+ input: "raw",
301
+ output: "processed",
302
+ durationMs: 50,
303
+ });
304
+
305
+ await raindrop.flush();
306
+ ```
307
+
308
+ ### API reference
309
+
310
+ | Method | Description |
311
+ |--------|-------------|
312
+ | `raindrop.traces.createSpan(args)` | One-shot span with known duration |
313
+ | `raindrop.traces.startSpan(args)` | Start a span, returns a `TraceSpan` handle |
314
+ | `raindrop.traces.endSpan(span, extra?)` | Close a span opened with `startSpan` |
315
+
316
+ **`createSpan` args:** `name`, `eventId`, `operationId?`, `parent?`, `input?`, `output?`, `durationMs`, `error?`
317
+
318
+ **`startSpan` args:** `name`, `eventId`, `operationId?`, `parent?`
319
+
320
+ **`endSpan` extra:** `error?` (`Error | string`)
321
+
322
+ Set `operationId: "ai.toolCall"` to make spans appear as tool calls in the Raindrop dashboard.
323
+
195
324
  ## Notes
196
325
 
197
326
  - Spans include `ai.telemetry.metadata.raindrop.eventId` for correlation, and **omit** `ai.telemetry.metadata.raindrop.userId` to prevent duplicate span→event creation server-side.
@@ -160,6 +160,9 @@ function createSpanIds(parent) {
160
160
  function nowUnixNanoString() {
161
161
  return Date.now().toString() + "000000";
162
162
  }
163
+ function unixMsToNanoString(ms) {
164
+ return String(Math.floor(ms)) + "000000";
165
+ }
163
166
  function attrString(key, value) {
164
167
  if (value === void 0) return void 0;
165
168
  return { key, value: { stringValue: value } };
@@ -4004,7 +4007,7 @@ function extractNestedTokens(usage, key) {
4004
4007
  // package.json
4005
4008
  var package_default = {
4006
4009
  name: "@raindrop-ai/ai-sdk",
4007
- version: "0.0.21"};
4010
+ version: "0.0.23"};
4008
4011
 
4009
4012
  // src/internal/version.ts
4010
4013
  var libraryName = package_default.name;
@@ -4076,6 +4079,14 @@ function eventMetadataFromChatRequest(options) {
4076
4079
  ...eventId ? { eventId } : {}
4077
4080
  });
4078
4081
  }
4082
+ function stringify(v) {
4083
+ if (typeof v === "string") return v;
4084
+ return JSON.stringify(v);
4085
+ }
4086
+ function userAttrsToOtlp(attrs) {
4087
+ if (!attrs) return [];
4088
+ return Object.entries(attrs).map(([key, value]) => attrString(key, value));
4089
+ }
4079
4090
  function envDebugEnabled() {
4080
4091
  var _a;
4081
4092
  if (typeof process === "undefined") return false;
@@ -4144,6 +4155,76 @@ function createRaindropAISDK(opts) {
4144
4155
  await eventShipper.finish(eventId, patch);
4145
4156
  }
4146
4157
  },
4158
+ traces: /* @__PURE__ */ (() => {
4159
+ const openSpans = /* @__PURE__ */ new Map();
4160
+ function toTraceSpan(internal) {
4161
+ return { traceId: internal.ids.traceIdB64, spanId: internal.ids.spanIdB64 };
4162
+ }
4163
+ return {
4164
+ startSpan(args) {
4165
+ const parent = args.parent ? { traceIdB64: args.parent.traceId, spanIdB64: args.parent.spanId } : void 0;
4166
+ const attrs = userAttrsToOtlp(args.attributes);
4167
+ if (args.operationId === "ai.toolCall") {
4168
+ attrs.push(attrString("ai.toolCall.name", args.name));
4169
+ }
4170
+ const internal = traceShipper.startSpan({
4171
+ name: args.name,
4172
+ eventId: args.eventId,
4173
+ parent,
4174
+ operationId: args.operationId,
4175
+ attributes: attrs
4176
+ });
4177
+ const handle = toTraceSpan(internal);
4178
+ openSpans.set(handle.spanId, internal);
4179
+ return handle;
4180
+ },
4181
+ endSpan(span, extra) {
4182
+ const internal = openSpans.get(span.spanId);
4183
+ if (!internal) return;
4184
+ openSpans.delete(span.spanId);
4185
+ const errorValue = extra == null ? void 0 : extra.error;
4186
+ const error = errorValue instanceof Error ? errorValue : typeof errorValue === "string" ? new Error(errorValue) : void 0;
4187
+ traceShipper.endSpan(internal, {
4188
+ attributes: userAttrsToOtlp(extra == null ? void 0 : extra.attributes),
4189
+ error
4190
+ });
4191
+ },
4192
+ createSpan(args) {
4193
+ var _a2;
4194
+ const parent = args.parent ? { traceIdB64: args.parent.traceId, spanIdB64: args.parent.spanId } : void 0;
4195
+ const startMs = (_a2 = args.startTime) != null ? _a2 : Date.now() - args.durationMs;
4196
+ const startAttrs = [...userAttrsToOtlp(args.attributes)];
4197
+ if (args.operationId === "ai.toolCall") {
4198
+ startAttrs.push(attrString("ai.toolCall.name", args.name));
4199
+ }
4200
+ if (args.input !== void 0) startAttrs.push(attrString("traceloop.entity.input", stringify(args.input)));
4201
+ if (args.operationId === "ai.toolCall" && args.input !== void 0) {
4202
+ startAttrs.push(attrString("ai.toolCall.args", stringify(args.input)));
4203
+ }
4204
+ const internal = traceShipper.startSpan({
4205
+ name: args.name,
4206
+ eventId: args.eventId,
4207
+ parent,
4208
+ operationId: args.operationId,
4209
+ attributes: startAttrs,
4210
+ startTimeUnixNano: unixMsToNanoString(startMs)
4211
+ });
4212
+ const endAttrs = [];
4213
+ if (args.output !== void 0) endAttrs.push(attrString("traceloop.entity.output", stringify(args.output)));
4214
+ if (args.operationId === "ai.toolCall" && args.output !== void 0) {
4215
+ endAttrs.push(attrString("ai.toolCall.result", stringify(args.output)));
4216
+ }
4217
+ const errorValue = args.error;
4218
+ const error = errorValue instanceof Error ? errorValue : typeof errorValue === "string" ? new Error(errorValue) : void 0;
4219
+ traceShipper.endSpan(internal, {
4220
+ attributes: endAttrs,
4221
+ error,
4222
+ endTimeUnixNano: unixMsToNanoString(startMs + args.durationMs)
4223
+ });
4224
+ return toTraceSpan(internal);
4225
+ }
4226
+ };
4227
+ })(),
4147
4228
  users: {
4148
4229
  async identify(users) {
4149
4230
  await eventShipper.identify(users);
@@ -551,6 +551,53 @@ type WrapAISDKOptions = {
551
551
  */
552
552
  nativeTelemetry?: boolean;
553
553
  };
554
+ /**
555
+ * Opaque handle for a trace span. Pass as `parent` when creating child spans.
556
+ */
557
+ type TraceSpan = {
558
+ readonly traceId: string;
559
+ readonly spanId: string;
560
+ };
561
+ type StartSpanArgs = {
562
+ /** Span name (e.g. "web_search", "finder_subagent"). */
563
+ name: string;
564
+ /** Raindrop event ID this span belongs to. */
565
+ eventId: string;
566
+ /** Parent span for nesting. Omit for root spans. */
567
+ parent?: TraceSpan;
568
+ /** AI SDK operation ID (e.g. "ai.toolCall", "ai.generateText"). Helps classify the span. */
569
+ operationId?: string;
570
+ /** Arbitrary string attributes. */
571
+ attributes?: Record<string, string>;
572
+ };
573
+ type EndSpanArgs = {
574
+ /** Additional attributes to add when ending. */
575
+ attributes?: Record<string, string>;
576
+ /** Mark the span as failed. */
577
+ error?: Error | string;
578
+ };
579
+ type CreateSpanArgs = {
580
+ /** Span name (e.g. "SET theme=dark", "grep_search"). */
581
+ name: string;
582
+ /** Raindrop event ID this span belongs to. */
583
+ eventId: string;
584
+ /** Parent span for nesting. Omit for root spans. */
585
+ parent?: TraceSpan;
586
+ /** AI SDK operation ID (e.g. "ai.toolCall"). Helps classify the span. */
587
+ operationId?: string;
588
+ /** Input data (will be JSON stringified if object). */
589
+ input?: unknown;
590
+ /** Output data (will be JSON stringified if object). */
591
+ output?: unknown;
592
+ /** Duration in milliseconds. */
593
+ durationMs: number;
594
+ /** Start time as epoch ms. Defaults to `Date.now() - durationMs`. */
595
+ startTime?: number;
596
+ /** Mark the span as failed. */
597
+ error?: Error | string;
598
+ /** Arbitrary string attributes. */
599
+ attributes?: Record<string, string>;
600
+ };
554
601
  type EventPatch = {
555
602
  eventName?: string;
556
603
  userId?: string;
@@ -580,6 +627,46 @@ type RaindropAISDKClient = {
580
627
  properties?: Record<string, unknown>;
581
628
  }): Promise<void>;
582
629
  };
630
+ /**
631
+ * Manually create trace spans alongside (or instead of) auto-instrumented ones.
632
+ *
633
+ * Use `startSpan` / `endSpan` for spans with manual lifecycle control, or
634
+ * `createSpan` for one-shot spans where timing is already known.
635
+ *
636
+ * Spans share the same trace tree as auto-instrumented spans when you pass
637
+ * matching `eventId` values. Use `parent` to nest spans arbitrarily.
638
+ *
639
+ * @example
640
+ * ```typescript
641
+ * // One-shot span for a DSL command extracted from agent output
642
+ * raindrop.traces.createSpan({
643
+ * name: "SET theme=dark",
644
+ * eventId: "evt_123",
645
+ * operationId: "ai.toolCall",
646
+ * input: "SET theme=dark",
647
+ * output: "OK",
648
+ * durationMs: 12,
649
+ * });
650
+ *
651
+ * // Manual lifecycle for a subagent
652
+ * const agent = raindrop.traces.startSpan({
653
+ * name: "finder_subagent",
654
+ * eventId: "evt_456",
655
+ * });
656
+ * const tool = raindrop.traces.startSpan({
657
+ * name: "grep_search",
658
+ * eventId: "evt_456",
659
+ * parent: agent,
660
+ * });
661
+ * raindrop.traces.endSpan(tool);
662
+ * raindrop.traces.endSpan(agent);
663
+ * ```
664
+ */
665
+ traces: {
666
+ startSpan(args: StartSpanArgs): TraceSpan;
667
+ endSpan(span: TraceSpan, extra?: EndSpanArgs): void;
668
+ createSpan(args: CreateSpanArgs): TraceSpan;
669
+ };
583
670
  users: {
584
671
  identify(users: IdentifyInput | IdentifyInput[]): Promise<void>;
585
672
  };
@@ -601,4 +688,4 @@ type RaindropAISDKClient = {
601
688
  };
602
689
  declare function createRaindropAISDK(opts: RaindropAISDKOptions): RaindropAISDKClient;
603
690
 
604
- export { type AISDKChatRequestLike as A, type BuildEventPatch as B, ContextManager as C, type EventBuilder as E, type IdentifyInput as I, type RaindropAISDKClient as R, type SelfDiagnosticsOptions as S, 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 EventMetadataOptions as g, type RaindropAISDKContext as h, type RaindropAISDKOptions as i, RaindropTelemetryIntegration as j, type RaindropTelemetryIntegrationOptions as k, type SelfDiagnosticsSignalDefinition as l, type SelfDiagnosticsSignalDefinitions as m, type WrappedAI as n, type WrappedAISDK as o, createRaindropAISDK as p, currentSpan as q, eventMetadata as r, eventMetadataFromChatRequest as s, getContextManager as t, withCurrent as w };
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 };
@@ -551,6 +551,53 @@ type WrapAISDKOptions = {
551
551
  */
552
552
  nativeTelemetry?: boolean;
553
553
  };
554
+ /**
555
+ * Opaque handle for a trace span. Pass as `parent` when creating child spans.
556
+ */
557
+ type TraceSpan = {
558
+ readonly traceId: string;
559
+ readonly spanId: string;
560
+ };
561
+ type StartSpanArgs = {
562
+ /** Span name (e.g. "web_search", "finder_subagent"). */
563
+ name: string;
564
+ /** Raindrop event ID this span belongs to. */
565
+ eventId: string;
566
+ /** Parent span for nesting. Omit for root spans. */
567
+ parent?: TraceSpan;
568
+ /** AI SDK operation ID (e.g. "ai.toolCall", "ai.generateText"). Helps classify the span. */
569
+ operationId?: string;
570
+ /** Arbitrary string attributes. */
571
+ attributes?: Record<string, string>;
572
+ };
573
+ type EndSpanArgs = {
574
+ /** Additional attributes to add when ending. */
575
+ attributes?: Record<string, string>;
576
+ /** Mark the span as failed. */
577
+ error?: Error | string;
578
+ };
579
+ type CreateSpanArgs = {
580
+ /** Span name (e.g. "SET theme=dark", "grep_search"). */
581
+ name: string;
582
+ /** Raindrop event ID this span belongs to. */
583
+ eventId: string;
584
+ /** Parent span for nesting. Omit for root spans. */
585
+ parent?: TraceSpan;
586
+ /** AI SDK operation ID (e.g. "ai.toolCall"). Helps classify the span. */
587
+ operationId?: string;
588
+ /** Input data (will be JSON stringified if object). */
589
+ input?: unknown;
590
+ /** Output data (will be JSON stringified if object). */
591
+ output?: unknown;
592
+ /** Duration in milliseconds. */
593
+ durationMs: number;
594
+ /** Start time as epoch ms. Defaults to `Date.now() - durationMs`. */
595
+ startTime?: number;
596
+ /** Mark the span as failed. */
597
+ error?: Error | string;
598
+ /** Arbitrary string attributes. */
599
+ attributes?: Record<string, string>;
600
+ };
554
601
  type EventPatch = {
555
602
  eventName?: string;
556
603
  userId?: string;
@@ -580,6 +627,46 @@ type RaindropAISDKClient = {
580
627
  properties?: Record<string, unknown>;
581
628
  }): Promise<void>;
582
629
  };
630
+ /**
631
+ * Manually create trace spans alongside (or instead of) auto-instrumented ones.
632
+ *
633
+ * Use `startSpan` / `endSpan` for spans with manual lifecycle control, or
634
+ * `createSpan` for one-shot spans where timing is already known.
635
+ *
636
+ * Spans share the same trace tree as auto-instrumented spans when you pass
637
+ * matching `eventId` values. Use `parent` to nest spans arbitrarily.
638
+ *
639
+ * @example
640
+ * ```typescript
641
+ * // One-shot span for a DSL command extracted from agent output
642
+ * raindrop.traces.createSpan({
643
+ * name: "SET theme=dark",
644
+ * eventId: "evt_123",
645
+ * operationId: "ai.toolCall",
646
+ * input: "SET theme=dark",
647
+ * output: "OK",
648
+ * durationMs: 12,
649
+ * });
650
+ *
651
+ * // Manual lifecycle for a subagent
652
+ * const agent = raindrop.traces.startSpan({
653
+ * name: "finder_subagent",
654
+ * eventId: "evt_456",
655
+ * });
656
+ * const tool = raindrop.traces.startSpan({
657
+ * name: "grep_search",
658
+ * eventId: "evt_456",
659
+ * parent: agent,
660
+ * });
661
+ * raindrop.traces.endSpan(tool);
662
+ * raindrop.traces.endSpan(agent);
663
+ * ```
664
+ */
665
+ traces: {
666
+ startSpan(args: StartSpanArgs): TraceSpan;
667
+ endSpan(span: TraceSpan, extra?: EndSpanArgs): void;
668
+ createSpan(args: CreateSpanArgs): TraceSpan;
669
+ };
583
670
  users: {
584
671
  identify(users: IdentifyInput | IdentifyInput[]): Promise<void>;
585
672
  };
@@ -601,4 +688,4 @@ type RaindropAISDKClient = {
601
688
  };
602
689
  declare function createRaindropAISDK(opts: RaindropAISDKOptions): RaindropAISDKClient;
603
690
 
604
- export { type AISDKChatRequestLike as A, type BuildEventPatch as B, ContextManager as C, type EventBuilder as E, type IdentifyInput as I, type RaindropAISDKClient as R, type SelfDiagnosticsOptions as S, 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 EventMetadataOptions as g, type RaindropAISDKContext as h, type RaindropAISDKOptions as i, RaindropTelemetryIntegration as j, type RaindropTelemetryIntegrationOptions as k, type SelfDiagnosticsSignalDefinition as l, type SelfDiagnosticsSignalDefinitions as m, type WrappedAI as n, type WrappedAISDK as o, createRaindropAISDK as p, currentSpan as q, eventMetadata as r, eventMetadataFromChatRequest as s, getContextManager as t, withCurrent as w };
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 };
@@ -551,6 +551,53 @@ type WrapAISDKOptions = {
551
551
  */
552
552
  nativeTelemetry?: boolean;
553
553
  };
554
+ /**
555
+ * Opaque handle for a trace span. Pass as `parent` when creating child spans.
556
+ */
557
+ type TraceSpan = {
558
+ readonly traceId: string;
559
+ readonly spanId: string;
560
+ };
561
+ type StartSpanArgs = {
562
+ /** Span name (e.g. "web_search", "finder_subagent"). */
563
+ name: string;
564
+ /** Raindrop event ID this span belongs to. */
565
+ eventId: string;
566
+ /** Parent span for nesting. Omit for root spans. */
567
+ parent?: TraceSpan;
568
+ /** AI SDK operation ID (e.g. "ai.toolCall", "ai.generateText"). Helps classify the span. */
569
+ operationId?: string;
570
+ /** Arbitrary string attributes. */
571
+ attributes?: Record<string, string>;
572
+ };
573
+ type EndSpanArgs = {
574
+ /** Additional attributes to add when ending. */
575
+ attributes?: Record<string, string>;
576
+ /** Mark the span as failed. */
577
+ error?: Error | string;
578
+ };
579
+ type CreateSpanArgs = {
580
+ /** Span name (e.g. "SET theme=dark", "grep_search"). */
581
+ name: string;
582
+ /** Raindrop event ID this span belongs to. */
583
+ eventId: string;
584
+ /** Parent span for nesting. Omit for root spans. */
585
+ parent?: TraceSpan;
586
+ /** AI SDK operation ID (e.g. "ai.toolCall"). Helps classify the span. */
587
+ operationId?: string;
588
+ /** Input data (will be JSON stringified if object). */
589
+ input?: unknown;
590
+ /** Output data (will be JSON stringified if object). */
591
+ output?: unknown;
592
+ /** Duration in milliseconds. */
593
+ durationMs: number;
594
+ /** Start time as epoch ms. Defaults to `Date.now() - durationMs`. */
595
+ startTime?: number;
596
+ /** Mark the span as failed. */
597
+ error?: Error | string;
598
+ /** Arbitrary string attributes. */
599
+ attributes?: Record<string, string>;
600
+ };
554
601
  type EventPatch = {
555
602
  eventName?: string;
556
603
  userId?: string;
@@ -580,6 +627,46 @@ type RaindropAISDKClient = {
580
627
  properties?: Record<string, unknown>;
581
628
  }): Promise<void>;
582
629
  };
630
+ /**
631
+ * Manually create trace spans alongside (or instead of) auto-instrumented ones.
632
+ *
633
+ * Use `startSpan` / `endSpan` for spans with manual lifecycle control, or
634
+ * `createSpan` for one-shot spans where timing is already known.
635
+ *
636
+ * Spans share the same trace tree as auto-instrumented spans when you pass
637
+ * matching `eventId` values. Use `parent` to nest spans arbitrarily.
638
+ *
639
+ * @example
640
+ * ```typescript
641
+ * // One-shot span for a DSL command extracted from agent output
642
+ * raindrop.traces.createSpan({
643
+ * name: "SET theme=dark",
644
+ * eventId: "evt_123",
645
+ * operationId: "ai.toolCall",
646
+ * input: "SET theme=dark",
647
+ * output: "OK",
648
+ * durationMs: 12,
649
+ * });
650
+ *
651
+ * // Manual lifecycle for a subagent
652
+ * const agent = raindrop.traces.startSpan({
653
+ * name: "finder_subagent",
654
+ * eventId: "evt_456",
655
+ * });
656
+ * const tool = raindrop.traces.startSpan({
657
+ * name: "grep_search",
658
+ * eventId: "evt_456",
659
+ * parent: agent,
660
+ * });
661
+ * raindrop.traces.endSpan(tool);
662
+ * raindrop.traces.endSpan(agent);
663
+ * ```
664
+ */
665
+ traces: {
666
+ startSpan(args: StartSpanArgs): TraceSpan;
667
+ endSpan(span: TraceSpan, extra?: EndSpanArgs): void;
668
+ createSpan(args: CreateSpanArgs): TraceSpan;
669
+ };
583
670
  users: {
584
671
  identify(users: IdentifyInput | IdentifyInput[]): Promise<void>;
585
672
  };
@@ -601,4 +688,4 @@ type RaindropAISDKClient = {
601
688
  };
602
689
  declare function createRaindropAISDK(opts: RaindropAISDKOptions): RaindropAISDKClient;
603
690
 
604
- export { type AISDKChatRequestLike, type AISDKChatRequestMessageLike, type AISDKMessage, type AgentCallMetadata, type AgentWithMetadata, type Attachment, type BuildEventPatch, ContextManager, type ContextSpan, type EventBuilder, type EventMetadataOptions, type IdentifyInput, type RaindropAISDKClient, type RaindropAISDKContext, type RaindropAISDKOptions, RaindropTelemetryIntegration, type RaindropTelemetryIntegrationOptions, type SelfDiagnosticsOptions, type SelfDiagnosticsSignalDefinition, type SelfDiagnosticsSignalDefinitions, type WrapAISDKOptions, type WrappedAI, type WrappedAISDK, _resetWarnedMissingUserId, createRaindropAISDK, currentSpan, eventMetadata, eventMetadataFromChatRequest, getContextManager, withCurrent };
691
+ export { type AISDKChatRequestLike, type AISDKChatRequestMessageLike, type AISDKMessage, type AgentCallMetadata, type AgentWithMetadata, type Attachment, type BuildEventPatch, ContextManager, type ContextSpan, type CreateSpanArgs, type EndSpanArgs, type EventBuilder, type EventMetadataOptions, type IdentifyInput, type RaindropAISDKClient, type RaindropAISDKContext, type RaindropAISDKOptions, RaindropTelemetryIntegration, type RaindropTelemetryIntegrationOptions, type SelfDiagnosticsOptions, type SelfDiagnosticsSignalDefinition, type SelfDiagnosticsSignalDefinitions, type StartSpanArgs, type TraceSpan, type WrapAISDKOptions, type WrappedAI, type WrappedAISDK, _resetWarnedMissingUserId, createRaindropAISDK, currentSpan, eventMetadata, eventMetadataFromChatRequest, getContextManager, withCurrent };
@@ -551,6 +551,53 @@ type WrapAISDKOptions = {
551
551
  */
552
552
  nativeTelemetry?: boolean;
553
553
  };
554
+ /**
555
+ * Opaque handle for a trace span. Pass as `parent` when creating child spans.
556
+ */
557
+ type TraceSpan = {
558
+ readonly traceId: string;
559
+ readonly spanId: string;
560
+ };
561
+ type StartSpanArgs = {
562
+ /** Span name (e.g. "web_search", "finder_subagent"). */
563
+ name: string;
564
+ /** Raindrop event ID this span belongs to. */
565
+ eventId: string;
566
+ /** Parent span for nesting. Omit for root spans. */
567
+ parent?: TraceSpan;
568
+ /** AI SDK operation ID (e.g. "ai.toolCall", "ai.generateText"). Helps classify the span. */
569
+ operationId?: string;
570
+ /** Arbitrary string attributes. */
571
+ attributes?: Record<string, string>;
572
+ };
573
+ type EndSpanArgs = {
574
+ /** Additional attributes to add when ending. */
575
+ attributes?: Record<string, string>;
576
+ /** Mark the span as failed. */
577
+ error?: Error | string;
578
+ };
579
+ type CreateSpanArgs = {
580
+ /** Span name (e.g. "SET theme=dark", "grep_search"). */
581
+ name: string;
582
+ /** Raindrop event ID this span belongs to. */
583
+ eventId: string;
584
+ /** Parent span for nesting. Omit for root spans. */
585
+ parent?: TraceSpan;
586
+ /** AI SDK operation ID (e.g. "ai.toolCall"). Helps classify the span. */
587
+ operationId?: string;
588
+ /** Input data (will be JSON stringified if object). */
589
+ input?: unknown;
590
+ /** Output data (will be JSON stringified if object). */
591
+ output?: unknown;
592
+ /** Duration in milliseconds. */
593
+ durationMs: number;
594
+ /** Start time as epoch ms. Defaults to `Date.now() - durationMs`. */
595
+ startTime?: number;
596
+ /** Mark the span as failed. */
597
+ error?: Error | string;
598
+ /** Arbitrary string attributes. */
599
+ attributes?: Record<string, string>;
600
+ };
554
601
  type EventPatch = {
555
602
  eventName?: string;
556
603
  userId?: string;
@@ -580,6 +627,46 @@ type RaindropAISDKClient = {
580
627
  properties?: Record<string, unknown>;
581
628
  }): Promise<void>;
582
629
  };
630
+ /**
631
+ * Manually create trace spans alongside (or instead of) auto-instrumented ones.
632
+ *
633
+ * Use `startSpan` / `endSpan` for spans with manual lifecycle control, or
634
+ * `createSpan` for one-shot spans where timing is already known.
635
+ *
636
+ * Spans share the same trace tree as auto-instrumented spans when you pass
637
+ * matching `eventId` values. Use `parent` to nest spans arbitrarily.
638
+ *
639
+ * @example
640
+ * ```typescript
641
+ * // One-shot span for a DSL command extracted from agent output
642
+ * raindrop.traces.createSpan({
643
+ * name: "SET theme=dark",
644
+ * eventId: "evt_123",
645
+ * operationId: "ai.toolCall",
646
+ * input: "SET theme=dark",
647
+ * output: "OK",
648
+ * durationMs: 12,
649
+ * });
650
+ *
651
+ * // Manual lifecycle for a subagent
652
+ * const agent = raindrop.traces.startSpan({
653
+ * name: "finder_subagent",
654
+ * eventId: "evt_456",
655
+ * });
656
+ * const tool = raindrop.traces.startSpan({
657
+ * name: "grep_search",
658
+ * eventId: "evt_456",
659
+ * parent: agent,
660
+ * });
661
+ * raindrop.traces.endSpan(tool);
662
+ * raindrop.traces.endSpan(agent);
663
+ * ```
664
+ */
665
+ traces: {
666
+ startSpan(args: StartSpanArgs): TraceSpan;
667
+ endSpan(span: TraceSpan, extra?: EndSpanArgs): void;
668
+ createSpan(args: CreateSpanArgs): TraceSpan;
669
+ };
583
670
  users: {
584
671
  identify(users: IdentifyInput | IdentifyInput[]): Promise<void>;
585
672
  };
@@ -601,4 +688,4 @@ type RaindropAISDKClient = {
601
688
  };
602
689
  declare function createRaindropAISDK(opts: RaindropAISDKOptions): RaindropAISDKClient;
603
690
 
604
- export { type AISDKChatRequestLike, type AISDKChatRequestMessageLike, type AISDKMessage, type AgentCallMetadata, type AgentWithMetadata, type Attachment, type BuildEventPatch, ContextManager, type ContextSpan, type EventBuilder, type EventMetadataOptions, type IdentifyInput, type RaindropAISDKClient, type RaindropAISDKContext, type RaindropAISDKOptions, RaindropTelemetryIntegration, type RaindropTelemetryIntegrationOptions, type SelfDiagnosticsOptions, type SelfDiagnosticsSignalDefinition, type SelfDiagnosticsSignalDefinitions, type WrapAISDKOptions, type WrappedAI, type WrappedAISDK, _resetWarnedMissingUserId, createRaindropAISDK, currentSpan, eventMetadata, eventMetadataFromChatRequest, getContextManager, withCurrent };
691
+ export { type AISDKChatRequestLike, type AISDKChatRequestMessageLike, type AISDKMessage, type AgentCallMetadata, type AgentWithMetadata, type Attachment, type BuildEventPatch, ContextManager, type ContextSpan, type CreateSpanArgs, type EndSpanArgs, type EventBuilder, type EventMetadataOptions, type IdentifyInput, type RaindropAISDKClient, type RaindropAISDKContext, type RaindropAISDKOptions, RaindropTelemetryIntegration, type RaindropTelemetryIntegrationOptions, type SelfDiagnosticsOptions, type SelfDiagnosticsSignalDefinition, type SelfDiagnosticsSignalDefinitions, type StartSpanArgs, type TraceSpan, type WrapAISDKOptions, type WrappedAI, type WrappedAISDK, _resetWarnedMissingUserId, createRaindropAISDK, currentSpan, eventMetadata, eventMetadataFromChatRequest, getContextManager, withCurrent };
@@ -160,6 +160,9 @@ function createSpanIds(parent) {
160
160
  function nowUnixNanoString() {
161
161
  return Date.now().toString() + "000000";
162
162
  }
163
+ function unixMsToNanoString(ms) {
164
+ return String(Math.floor(ms)) + "000000";
165
+ }
163
166
  function attrString(key, value) {
164
167
  if (value === void 0) return void 0;
165
168
  return { key, value: { stringValue: value } };
@@ -829,7 +832,7 @@ async function* asyncGeneratorWithCurrent(span, gen) {
829
832
  // package.json
830
833
  var package_default = {
831
834
  name: "@raindrop-ai/ai-sdk",
832
- version: "0.0.21"};
835
+ version: "0.0.23"};
833
836
 
834
837
  // src/internal/version.ts
835
838
  var libraryName = package_default.name;
@@ -4075,6 +4078,14 @@ function eventMetadataFromChatRequest(options) {
4075
4078
  ...eventId ? { eventId } : {}
4076
4079
  });
4077
4080
  }
4081
+ function stringify(v) {
4082
+ if (typeof v === "string") return v;
4083
+ return JSON.stringify(v);
4084
+ }
4085
+ function userAttrsToOtlp(attrs) {
4086
+ if (!attrs) return [];
4087
+ return Object.entries(attrs).map(([key, value]) => attrString(key, value));
4088
+ }
4078
4089
  function envDebugEnabled() {
4079
4090
  var _a;
4080
4091
  if (typeof process === "undefined") return false;
@@ -4143,6 +4154,76 @@ function createRaindropAISDK(opts) {
4143
4154
  await eventShipper.finish(eventId, patch);
4144
4155
  }
4145
4156
  },
4157
+ traces: /* @__PURE__ */ (() => {
4158
+ const openSpans = /* @__PURE__ */ new Map();
4159
+ function toTraceSpan(internal) {
4160
+ return { traceId: internal.ids.traceIdB64, spanId: internal.ids.spanIdB64 };
4161
+ }
4162
+ return {
4163
+ startSpan(args) {
4164
+ const parent = args.parent ? { traceIdB64: args.parent.traceId, spanIdB64: args.parent.spanId } : void 0;
4165
+ const attrs = userAttrsToOtlp(args.attributes);
4166
+ if (args.operationId === "ai.toolCall") {
4167
+ attrs.push(attrString("ai.toolCall.name", args.name));
4168
+ }
4169
+ const internal = traceShipper.startSpan({
4170
+ name: args.name,
4171
+ eventId: args.eventId,
4172
+ parent,
4173
+ operationId: args.operationId,
4174
+ attributes: attrs
4175
+ });
4176
+ const handle = toTraceSpan(internal);
4177
+ openSpans.set(handle.spanId, internal);
4178
+ return handle;
4179
+ },
4180
+ endSpan(span, extra) {
4181
+ const internal = openSpans.get(span.spanId);
4182
+ if (!internal) return;
4183
+ openSpans.delete(span.spanId);
4184
+ const errorValue = extra == null ? void 0 : extra.error;
4185
+ const error = errorValue instanceof Error ? errorValue : typeof errorValue === "string" ? new Error(errorValue) : void 0;
4186
+ traceShipper.endSpan(internal, {
4187
+ attributes: userAttrsToOtlp(extra == null ? void 0 : extra.attributes),
4188
+ error
4189
+ });
4190
+ },
4191
+ createSpan(args) {
4192
+ var _a2;
4193
+ const parent = args.parent ? { traceIdB64: args.parent.traceId, spanIdB64: args.parent.spanId } : void 0;
4194
+ const startMs = (_a2 = args.startTime) != null ? _a2 : Date.now() - args.durationMs;
4195
+ const startAttrs = [...userAttrsToOtlp(args.attributes)];
4196
+ if (args.operationId === "ai.toolCall") {
4197
+ startAttrs.push(attrString("ai.toolCall.name", args.name));
4198
+ }
4199
+ if (args.input !== void 0) startAttrs.push(attrString("traceloop.entity.input", stringify(args.input)));
4200
+ if (args.operationId === "ai.toolCall" && args.input !== void 0) {
4201
+ startAttrs.push(attrString("ai.toolCall.args", stringify(args.input)));
4202
+ }
4203
+ const internal = traceShipper.startSpan({
4204
+ name: args.name,
4205
+ eventId: args.eventId,
4206
+ parent,
4207
+ operationId: args.operationId,
4208
+ attributes: startAttrs,
4209
+ startTimeUnixNano: unixMsToNanoString(startMs)
4210
+ });
4211
+ const endAttrs = [];
4212
+ if (args.output !== void 0) endAttrs.push(attrString("traceloop.entity.output", stringify(args.output)));
4213
+ if (args.operationId === "ai.toolCall" && args.output !== void 0) {
4214
+ endAttrs.push(attrString("ai.toolCall.result", stringify(args.output)));
4215
+ }
4216
+ const errorValue = args.error;
4217
+ const error = errorValue instanceof Error ? errorValue : typeof errorValue === "string" ? new Error(errorValue) : void 0;
4218
+ traceShipper.endSpan(internal, {
4219
+ attributes: endAttrs,
4220
+ error,
4221
+ endTimeUnixNano: unixMsToNanoString(startMs + args.durationMs)
4222
+ });
4223
+ return toTraceSpan(internal);
4224
+ }
4225
+ };
4226
+ })(),
4146
4227
  users: {
4147
4228
  async identify(users) {
4148
4229
  await eventShipper.identify(users);
@@ -158,6 +158,9 @@ function createSpanIds(parent) {
158
158
  function nowUnixNanoString() {
159
159
  return Date.now().toString() + "000000";
160
160
  }
161
+ function unixMsToNanoString(ms) {
162
+ return String(Math.floor(ms)) + "000000";
163
+ }
161
164
  function attrString(key, value) {
162
165
  if (value === void 0) return void 0;
163
166
  return { key, value: { stringValue: value } };
@@ -827,7 +830,7 @@ async function* asyncGeneratorWithCurrent(span, gen) {
827
830
  // package.json
828
831
  var package_default = {
829
832
  name: "@raindrop-ai/ai-sdk",
830
- version: "0.0.21"};
833
+ version: "0.0.23"};
831
834
 
832
835
  // src/internal/version.ts
833
836
  var libraryName = package_default.name;
@@ -4073,6 +4076,14 @@ function eventMetadataFromChatRequest(options) {
4073
4076
  ...eventId ? { eventId } : {}
4074
4077
  });
4075
4078
  }
4079
+ function stringify(v) {
4080
+ if (typeof v === "string") return v;
4081
+ return JSON.stringify(v);
4082
+ }
4083
+ function userAttrsToOtlp(attrs) {
4084
+ if (!attrs) return [];
4085
+ return Object.entries(attrs).map(([key, value]) => attrString(key, value));
4086
+ }
4076
4087
  function envDebugEnabled() {
4077
4088
  var _a;
4078
4089
  if (typeof process === "undefined") return false;
@@ -4141,6 +4152,76 @@ function createRaindropAISDK(opts) {
4141
4152
  await eventShipper.finish(eventId, patch);
4142
4153
  }
4143
4154
  },
4155
+ traces: /* @__PURE__ */ (() => {
4156
+ const openSpans = /* @__PURE__ */ new Map();
4157
+ function toTraceSpan(internal) {
4158
+ return { traceId: internal.ids.traceIdB64, spanId: internal.ids.spanIdB64 };
4159
+ }
4160
+ return {
4161
+ startSpan(args) {
4162
+ const parent = args.parent ? { traceIdB64: args.parent.traceId, spanIdB64: args.parent.spanId } : void 0;
4163
+ const attrs = userAttrsToOtlp(args.attributes);
4164
+ if (args.operationId === "ai.toolCall") {
4165
+ attrs.push(attrString("ai.toolCall.name", args.name));
4166
+ }
4167
+ const internal = traceShipper.startSpan({
4168
+ name: args.name,
4169
+ eventId: args.eventId,
4170
+ parent,
4171
+ operationId: args.operationId,
4172
+ attributes: attrs
4173
+ });
4174
+ const handle = toTraceSpan(internal);
4175
+ openSpans.set(handle.spanId, internal);
4176
+ return handle;
4177
+ },
4178
+ endSpan(span, extra) {
4179
+ const internal = openSpans.get(span.spanId);
4180
+ if (!internal) return;
4181
+ openSpans.delete(span.spanId);
4182
+ const errorValue = extra == null ? void 0 : extra.error;
4183
+ const error = errorValue instanceof Error ? errorValue : typeof errorValue === "string" ? new Error(errorValue) : void 0;
4184
+ traceShipper.endSpan(internal, {
4185
+ attributes: userAttrsToOtlp(extra == null ? void 0 : extra.attributes),
4186
+ error
4187
+ });
4188
+ },
4189
+ createSpan(args) {
4190
+ var _a2;
4191
+ const parent = args.parent ? { traceIdB64: args.parent.traceId, spanIdB64: args.parent.spanId } : void 0;
4192
+ const startMs = (_a2 = args.startTime) != null ? _a2 : Date.now() - args.durationMs;
4193
+ const startAttrs = [...userAttrsToOtlp(args.attributes)];
4194
+ if (args.operationId === "ai.toolCall") {
4195
+ startAttrs.push(attrString("ai.toolCall.name", args.name));
4196
+ }
4197
+ if (args.input !== void 0) startAttrs.push(attrString("traceloop.entity.input", stringify(args.input)));
4198
+ if (args.operationId === "ai.toolCall" && args.input !== void 0) {
4199
+ startAttrs.push(attrString("ai.toolCall.args", stringify(args.input)));
4200
+ }
4201
+ const internal = traceShipper.startSpan({
4202
+ name: args.name,
4203
+ eventId: args.eventId,
4204
+ parent,
4205
+ operationId: args.operationId,
4206
+ attributes: startAttrs,
4207
+ startTimeUnixNano: unixMsToNanoString(startMs)
4208
+ });
4209
+ const endAttrs = [];
4210
+ if (args.output !== void 0) endAttrs.push(attrString("traceloop.entity.output", stringify(args.output)));
4211
+ if (args.operationId === "ai.toolCall" && args.output !== void 0) {
4212
+ endAttrs.push(attrString("ai.toolCall.result", stringify(args.output)));
4213
+ }
4214
+ const errorValue = args.error;
4215
+ const error = errorValue instanceof Error ? errorValue : typeof errorValue === "string" ? new Error(errorValue) : void 0;
4216
+ traceShipper.endSpan(internal, {
4217
+ attributes: endAttrs,
4218
+ error,
4219
+ endTimeUnixNano: unixMsToNanoString(startMs + args.durationMs)
4220
+ });
4221
+ return toTraceSpan(internal);
4222
+ }
4223
+ };
4224
+ })(),
4144
4225
  users: {
4145
4226
  async identify(users) {
4146
4227
  await eventShipper.identify(users);
@@ -1,4 +1,4 @@
1
- export { A as AISDKChatRequestLike, a as AISDKChatRequestMessageLike, b as AISDKMessage, c as AgentCallMetadata, d as AgentWithMetadata, e as Attachment, B as BuildEventPatch, C as ContextManager, f as ContextSpan, E as EventBuilder, g as EventMetadataOptions, I as IdentifyInput, R as RaindropAISDKClient, h as RaindropAISDKContext, i as RaindropAISDKOptions, j as RaindropTelemetryIntegration, k as RaindropTelemetryIntegrationOptions, S as SelfDiagnosticsOptions, l as SelfDiagnosticsSignalDefinition, m as SelfDiagnosticsSignalDefinitions, W as WrapAISDKOptions, n as WrappedAI, o as WrappedAISDK, _ as _resetWarnedMissingUserId, p as createRaindropAISDK, q as currentSpan, r as eventMetadata, s as eventMetadataFromChatRequest, t as getContextManager, w as withCurrent } from './index-CPArLupC.mjs';
1
+ export { A as AISDKChatRequestLike, a as AISDKChatRequestMessageLike, b as AISDKMessage, c as AgentCallMetadata, d as AgentWithMetadata, e as Attachment, B as BuildEventPatch, C as ContextManager, f as ContextSpan, g as CreateSpanArgs, E as EndSpanArgs, h as EventBuilder, i as EventMetadataOptions, I as IdentifyInput, R as RaindropAISDKClient, j as RaindropAISDKContext, k as RaindropAISDKOptions, l as RaindropTelemetryIntegration, m as RaindropTelemetryIntegrationOptions, S as SelfDiagnosticsOptions, n as SelfDiagnosticsSignalDefinition, o as SelfDiagnosticsSignalDefinitions, p as StartSpanArgs, T as TraceSpan, W as WrapAISDKOptions, q as WrappedAI, r as WrappedAISDK, _ as _resetWarnedMissingUserId, s as createRaindropAISDK, t as currentSpan, u as eventMetadata, v as eventMetadataFromChatRequest, w as getContextManager, x as withCurrent } from './index-sxjvhkYW.mjs';
2
2
 
3
3
  declare global {
4
4
  var RAINDROP_ASYNC_LOCAL_STORAGE: (new <T>() => {
@@ -1,4 +1,4 @@
1
- export { A as AISDKChatRequestLike, a as AISDKChatRequestMessageLike, b as AISDKMessage, c as AgentCallMetadata, d as AgentWithMetadata, e as Attachment, B as BuildEventPatch, C as ContextManager, f as ContextSpan, E as EventBuilder, g as EventMetadataOptions, I as IdentifyInput, R as RaindropAISDKClient, h as RaindropAISDKContext, i as RaindropAISDKOptions, j as RaindropTelemetryIntegration, k as RaindropTelemetryIntegrationOptions, S as SelfDiagnosticsOptions, l as SelfDiagnosticsSignalDefinition, m as SelfDiagnosticsSignalDefinitions, W as WrapAISDKOptions, n as WrappedAI, o as WrappedAISDK, _ as _resetWarnedMissingUserId, p as createRaindropAISDK, q as currentSpan, r as eventMetadata, s as eventMetadataFromChatRequest, t as getContextManager, w as withCurrent } from './index-CPArLupC.js';
1
+ export { A as AISDKChatRequestLike, a as AISDKChatRequestMessageLike, b as AISDKMessage, c as AgentCallMetadata, d as AgentWithMetadata, e as Attachment, B as BuildEventPatch, C as ContextManager, f as ContextSpan, g as CreateSpanArgs, E as EndSpanArgs, h as EventBuilder, i as EventMetadataOptions, I as IdentifyInput, R as RaindropAISDKClient, j as RaindropAISDKContext, k as RaindropAISDKOptions, l as RaindropTelemetryIntegration, m as RaindropTelemetryIntegrationOptions, S as SelfDiagnosticsOptions, n as SelfDiagnosticsSignalDefinition, o as SelfDiagnosticsSignalDefinitions, p as StartSpanArgs, T as TraceSpan, W as WrapAISDKOptions, q as WrappedAI, r as WrappedAISDK, _ as _resetWarnedMissingUserId, s as createRaindropAISDK, t as currentSpan, u as eventMetadata, v as eventMetadataFromChatRequest, w as getContextManager, x as withCurrent } from './index-sxjvhkYW.js';
2
2
 
3
3
  declare global {
4
4
  var RAINDROP_ASYNC_LOCAL_STORAGE: (new <T>() => {
@@ -164,6 +164,9 @@ function createSpanIds(parent) {
164
164
  function nowUnixNanoString() {
165
165
  return Date.now().toString() + "000000";
166
166
  }
167
+ function unixMsToNanoString(ms) {
168
+ return String(Math.floor(ms)) + "000000";
169
+ }
167
170
  function attrString(key, value) {
168
171
  if (value === void 0) return void 0;
169
172
  return { key, value: { stringValue: value } };
@@ -834,7 +837,7 @@ globalThis.RAINDROP_ASYNC_LOCAL_STORAGE = async_hooks.AsyncLocalStorage;
834
837
  // package.json
835
838
  var package_default = {
836
839
  name: "@raindrop-ai/ai-sdk",
837
- version: "0.0.21"};
840
+ version: "0.0.23"};
838
841
 
839
842
  // src/internal/version.ts
840
843
  var libraryName = package_default.name;
@@ -4080,6 +4083,14 @@ function eventMetadataFromChatRequest(options) {
4080
4083
  ...eventId ? { eventId } : {}
4081
4084
  });
4082
4085
  }
4086
+ function stringify(v) {
4087
+ if (typeof v === "string") return v;
4088
+ return JSON.stringify(v);
4089
+ }
4090
+ function userAttrsToOtlp(attrs) {
4091
+ if (!attrs) return [];
4092
+ return Object.entries(attrs).map(([key, value]) => attrString(key, value));
4093
+ }
4083
4094
  function envDebugEnabled() {
4084
4095
  var _a;
4085
4096
  if (typeof process === "undefined") return false;
@@ -4148,6 +4159,76 @@ function createRaindropAISDK(opts) {
4148
4159
  await eventShipper.finish(eventId, patch);
4149
4160
  }
4150
4161
  },
4162
+ traces: /* @__PURE__ */ (() => {
4163
+ const openSpans = /* @__PURE__ */ new Map();
4164
+ function toTraceSpan(internal) {
4165
+ return { traceId: internal.ids.traceIdB64, spanId: internal.ids.spanIdB64 };
4166
+ }
4167
+ return {
4168
+ startSpan(args) {
4169
+ const parent = args.parent ? { traceIdB64: args.parent.traceId, spanIdB64: args.parent.spanId } : void 0;
4170
+ const attrs = userAttrsToOtlp(args.attributes);
4171
+ if (args.operationId === "ai.toolCall") {
4172
+ attrs.push(attrString("ai.toolCall.name", args.name));
4173
+ }
4174
+ const internal = traceShipper.startSpan({
4175
+ name: args.name,
4176
+ eventId: args.eventId,
4177
+ parent,
4178
+ operationId: args.operationId,
4179
+ attributes: attrs
4180
+ });
4181
+ const handle = toTraceSpan(internal);
4182
+ openSpans.set(handle.spanId, internal);
4183
+ return handle;
4184
+ },
4185
+ endSpan(span, extra) {
4186
+ const internal = openSpans.get(span.spanId);
4187
+ if (!internal) return;
4188
+ openSpans.delete(span.spanId);
4189
+ const errorValue = extra == null ? void 0 : extra.error;
4190
+ const error = errorValue instanceof Error ? errorValue : typeof errorValue === "string" ? new Error(errorValue) : void 0;
4191
+ traceShipper.endSpan(internal, {
4192
+ attributes: userAttrsToOtlp(extra == null ? void 0 : extra.attributes),
4193
+ error
4194
+ });
4195
+ },
4196
+ createSpan(args) {
4197
+ var _a2;
4198
+ const parent = args.parent ? { traceIdB64: args.parent.traceId, spanIdB64: args.parent.spanId } : void 0;
4199
+ const startMs = (_a2 = args.startTime) != null ? _a2 : Date.now() - args.durationMs;
4200
+ const startAttrs = [...userAttrsToOtlp(args.attributes)];
4201
+ if (args.operationId === "ai.toolCall") {
4202
+ startAttrs.push(attrString("ai.toolCall.name", args.name));
4203
+ }
4204
+ if (args.input !== void 0) startAttrs.push(attrString("traceloop.entity.input", stringify(args.input)));
4205
+ if (args.operationId === "ai.toolCall" && args.input !== void 0) {
4206
+ startAttrs.push(attrString("ai.toolCall.args", stringify(args.input)));
4207
+ }
4208
+ const internal = traceShipper.startSpan({
4209
+ name: args.name,
4210
+ eventId: args.eventId,
4211
+ parent,
4212
+ operationId: args.operationId,
4213
+ attributes: startAttrs,
4214
+ startTimeUnixNano: unixMsToNanoString(startMs)
4215
+ });
4216
+ const endAttrs = [];
4217
+ if (args.output !== void 0) endAttrs.push(attrString("traceloop.entity.output", stringify(args.output)));
4218
+ if (args.operationId === "ai.toolCall" && args.output !== void 0) {
4219
+ endAttrs.push(attrString("ai.toolCall.result", stringify(args.output)));
4220
+ }
4221
+ const errorValue = args.error;
4222
+ const error = errorValue instanceof Error ? errorValue : typeof errorValue === "string" ? new Error(errorValue) : void 0;
4223
+ traceShipper.endSpan(internal, {
4224
+ attributes: endAttrs,
4225
+ error,
4226
+ endTimeUnixNano: unixMsToNanoString(startMs + args.durationMs)
4227
+ });
4228
+ return toTraceSpan(internal);
4229
+ }
4230
+ };
4231
+ })(),
4151
4232
  users: {
4152
4233
  async identify(users) {
4153
4234
  await eventShipper.identify(users);
@@ -1,4 +1,4 @@
1
- export { RaindropTelemetryIntegration, _resetWarnedMissingUserId, createRaindropAISDK, currentSpan, eventMetadata, eventMetadataFromChatRequest, getContextManager, withCurrent } from './chunk-BTNDCDA3.mjs';
1
+ export { RaindropTelemetryIntegration, _resetWarnedMissingUserId, createRaindropAISDK, currentSpan, eventMetadata, eventMetadataFromChatRequest, getContextManager, withCurrent } from './chunk-VQZMQSBQ.mjs';
2
2
  import { AsyncLocalStorage } from 'async_hooks';
3
3
 
4
4
  globalThis.RAINDROP_ASYNC_LOCAL_STORAGE = AsyncLocalStorage;
@@ -1,4 +1,4 @@
1
- export { A as AISDKChatRequestLike, a as AISDKChatRequestMessageLike, b as AISDKMessage, c as AgentCallMetadata, d as AgentWithMetadata, e as Attachment, B as BuildEventPatch, C as ContextManager, f as ContextSpan, E as EventBuilder, g as EventMetadataOptions, I as IdentifyInput, R as RaindropAISDKClient, h as RaindropAISDKContext, i as RaindropAISDKOptions, j as RaindropTelemetryIntegration, k as RaindropTelemetryIntegrationOptions, S as SelfDiagnosticsOptions, l as SelfDiagnosticsSignalDefinition, m as SelfDiagnosticsSignalDefinitions, W as WrapAISDKOptions, n as WrappedAI, o as WrappedAISDK, _ as _resetWarnedMissingUserId, p as createRaindropAISDK, q as currentSpan, r as eventMetadata, s as eventMetadataFromChatRequest, t as getContextManager, w as withCurrent } from './index-CPArLupC.mjs';
1
+ export { A as AISDKChatRequestLike, a as AISDKChatRequestMessageLike, b as AISDKMessage, c as AgentCallMetadata, d as AgentWithMetadata, e as Attachment, B as BuildEventPatch, C as ContextManager, f as ContextSpan, g as CreateSpanArgs, E as EndSpanArgs, h as EventBuilder, i as EventMetadataOptions, I as IdentifyInput, R as RaindropAISDKClient, j as RaindropAISDKContext, k as RaindropAISDKOptions, l as RaindropTelemetryIntegration, m as RaindropTelemetryIntegrationOptions, S as SelfDiagnosticsOptions, n as SelfDiagnosticsSignalDefinition, o as SelfDiagnosticsSignalDefinitions, p as StartSpanArgs, T as TraceSpan, W as WrapAISDKOptions, q as WrappedAI, r as WrappedAISDK, _ as _resetWarnedMissingUserId, s as createRaindropAISDK, t as currentSpan, u as eventMetadata, v as eventMetadataFromChatRequest, w as getContextManager, x as withCurrent } from './index-sxjvhkYW.mjs';
2
2
 
3
3
  declare global {
4
4
  var RAINDROP_ASYNC_LOCAL_STORAGE: (new <T>() => {
@@ -1,4 +1,4 @@
1
- export { A as AISDKChatRequestLike, a as AISDKChatRequestMessageLike, b as AISDKMessage, c as AgentCallMetadata, d as AgentWithMetadata, e as Attachment, B as BuildEventPatch, C as ContextManager, f as ContextSpan, E as EventBuilder, g as EventMetadataOptions, I as IdentifyInput, R as RaindropAISDKClient, h as RaindropAISDKContext, i as RaindropAISDKOptions, j as RaindropTelemetryIntegration, k as RaindropTelemetryIntegrationOptions, S as SelfDiagnosticsOptions, l as SelfDiagnosticsSignalDefinition, m as SelfDiagnosticsSignalDefinitions, W as WrapAISDKOptions, n as WrappedAI, o as WrappedAISDK, _ as _resetWarnedMissingUserId, p as createRaindropAISDK, q as currentSpan, r as eventMetadata, s as eventMetadataFromChatRequest, t as getContextManager, w as withCurrent } from './index-CPArLupC.js';
1
+ export { A as AISDKChatRequestLike, a as AISDKChatRequestMessageLike, b as AISDKMessage, c as AgentCallMetadata, d as AgentWithMetadata, e as Attachment, B as BuildEventPatch, C as ContextManager, f as ContextSpan, g as CreateSpanArgs, E as EndSpanArgs, h as EventBuilder, i as EventMetadataOptions, I as IdentifyInput, R as RaindropAISDKClient, j as RaindropAISDKContext, k as RaindropAISDKOptions, l as RaindropTelemetryIntegration, m as RaindropTelemetryIntegrationOptions, S as SelfDiagnosticsOptions, n as SelfDiagnosticsSignalDefinition, o as SelfDiagnosticsSignalDefinitions, p as StartSpanArgs, T as TraceSpan, W as WrapAISDKOptions, q as WrappedAI, r as WrappedAISDK, _ as _resetWarnedMissingUserId, s as createRaindropAISDK, t as currentSpan, u as eventMetadata, v as eventMetadataFromChatRequest, w as getContextManager, x as withCurrent } from './index-sxjvhkYW.js';
2
2
 
3
3
  declare global {
4
4
  var RAINDROP_ASYNC_LOCAL_STORAGE: (new <T>() => {
@@ -164,6 +164,9 @@ function createSpanIds(parent) {
164
164
  function nowUnixNanoString() {
165
165
  return Date.now().toString() + "000000";
166
166
  }
167
+ function unixMsToNanoString(ms) {
168
+ return String(Math.floor(ms)) + "000000";
169
+ }
167
170
  function attrString(key, value) {
168
171
  if (value === void 0) return void 0;
169
172
  return { key, value: { stringValue: value } };
@@ -834,7 +837,7 @@ globalThis.RAINDROP_ASYNC_LOCAL_STORAGE = async_hooks.AsyncLocalStorage;
834
837
  // package.json
835
838
  var package_default = {
836
839
  name: "@raindrop-ai/ai-sdk",
837
- version: "0.0.21"};
840
+ version: "0.0.23"};
838
841
 
839
842
  // src/internal/version.ts
840
843
  var libraryName = package_default.name;
@@ -4080,6 +4083,14 @@ function eventMetadataFromChatRequest(options) {
4080
4083
  ...eventId ? { eventId } : {}
4081
4084
  });
4082
4085
  }
4086
+ function stringify(v) {
4087
+ if (typeof v === "string") return v;
4088
+ return JSON.stringify(v);
4089
+ }
4090
+ function userAttrsToOtlp(attrs) {
4091
+ if (!attrs) return [];
4092
+ return Object.entries(attrs).map(([key, value]) => attrString(key, value));
4093
+ }
4083
4094
  function envDebugEnabled() {
4084
4095
  var _a;
4085
4096
  if (typeof process === "undefined") return false;
@@ -4148,6 +4159,76 @@ function createRaindropAISDK(opts) {
4148
4159
  await eventShipper.finish(eventId, patch);
4149
4160
  }
4150
4161
  },
4162
+ traces: /* @__PURE__ */ (() => {
4163
+ const openSpans = /* @__PURE__ */ new Map();
4164
+ function toTraceSpan(internal) {
4165
+ return { traceId: internal.ids.traceIdB64, spanId: internal.ids.spanIdB64 };
4166
+ }
4167
+ return {
4168
+ startSpan(args) {
4169
+ const parent = args.parent ? { traceIdB64: args.parent.traceId, spanIdB64: args.parent.spanId } : void 0;
4170
+ const attrs = userAttrsToOtlp(args.attributes);
4171
+ if (args.operationId === "ai.toolCall") {
4172
+ attrs.push(attrString("ai.toolCall.name", args.name));
4173
+ }
4174
+ const internal = traceShipper.startSpan({
4175
+ name: args.name,
4176
+ eventId: args.eventId,
4177
+ parent,
4178
+ operationId: args.operationId,
4179
+ attributes: attrs
4180
+ });
4181
+ const handle = toTraceSpan(internal);
4182
+ openSpans.set(handle.spanId, internal);
4183
+ return handle;
4184
+ },
4185
+ endSpan(span, extra) {
4186
+ const internal = openSpans.get(span.spanId);
4187
+ if (!internal) return;
4188
+ openSpans.delete(span.spanId);
4189
+ const errorValue = extra == null ? void 0 : extra.error;
4190
+ const error = errorValue instanceof Error ? errorValue : typeof errorValue === "string" ? new Error(errorValue) : void 0;
4191
+ traceShipper.endSpan(internal, {
4192
+ attributes: userAttrsToOtlp(extra == null ? void 0 : extra.attributes),
4193
+ error
4194
+ });
4195
+ },
4196
+ createSpan(args) {
4197
+ var _a2;
4198
+ const parent = args.parent ? { traceIdB64: args.parent.traceId, spanIdB64: args.parent.spanId } : void 0;
4199
+ const startMs = (_a2 = args.startTime) != null ? _a2 : Date.now() - args.durationMs;
4200
+ const startAttrs = [...userAttrsToOtlp(args.attributes)];
4201
+ if (args.operationId === "ai.toolCall") {
4202
+ startAttrs.push(attrString("ai.toolCall.name", args.name));
4203
+ }
4204
+ if (args.input !== void 0) startAttrs.push(attrString("traceloop.entity.input", stringify(args.input)));
4205
+ if (args.operationId === "ai.toolCall" && args.input !== void 0) {
4206
+ startAttrs.push(attrString("ai.toolCall.args", stringify(args.input)));
4207
+ }
4208
+ const internal = traceShipper.startSpan({
4209
+ name: args.name,
4210
+ eventId: args.eventId,
4211
+ parent,
4212
+ operationId: args.operationId,
4213
+ attributes: startAttrs,
4214
+ startTimeUnixNano: unixMsToNanoString(startMs)
4215
+ });
4216
+ const endAttrs = [];
4217
+ if (args.output !== void 0) endAttrs.push(attrString("traceloop.entity.output", stringify(args.output)));
4218
+ if (args.operationId === "ai.toolCall" && args.output !== void 0) {
4219
+ endAttrs.push(attrString("ai.toolCall.result", stringify(args.output)));
4220
+ }
4221
+ const errorValue = args.error;
4222
+ const error = errorValue instanceof Error ? errorValue : typeof errorValue === "string" ? new Error(errorValue) : void 0;
4223
+ traceShipper.endSpan(internal, {
4224
+ attributes: endAttrs,
4225
+ error,
4226
+ endTimeUnixNano: unixMsToNanoString(startMs + args.durationMs)
4227
+ });
4228
+ return toTraceSpan(internal);
4229
+ }
4230
+ };
4231
+ })(),
4151
4232
  users: {
4152
4233
  async identify(users) {
4153
4234
  await eventShipper.identify(users);
@@ -1,4 +1,4 @@
1
- export { RaindropTelemetryIntegration, _resetWarnedMissingUserId, createRaindropAISDK, currentSpan, eventMetadata, eventMetadataFromChatRequest, getContextManager, withCurrent } from './chunk-BTNDCDA3.mjs';
1
+ export { RaindropTelemetryIntegration, _resetWarnedMissingUserId, createRaindropAISDK, currentSpan, eventMetadata, eventMetadataFromChatRequest, getContextManager, withCurrent } from './chunk-VQZMQSBQ.mjs';
2
2
  import { AsyncLocalStorage } from 'async_hooks';
3
3
 
4
4
  if (!globalThis.RAINDROP_ASYNC_LOCAL_STORAGE) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raindrop-ai/ai-sdk",
3
- "version": "0.0.21",
3
+ "version": "0.0.23",
4
4
  "description": "Standalone Vercel AI SDK integration for Raindrop (events + OTLP/HTTP JSON traces, no OTEL runtime)",
5
5
  "main": "dist/index.node.js",
6
6
  "module": "dist/index.node.mjs",