raindrop-ai 0.2.4 → 0.3.0

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.
@@ -0,0 +1,1457 @@
1
+ import * as _opentelemetry_instrumentation from '@opentelemetry/instrumentation';
2
+ import { Span } from '@opentelemetry/api';
3
+ import { z } from 'zod';
4
+ import { SpanProcessorOptions } from '@traceloop/node-server-sdk';
5
+
6
+ /** The reverse reference a detached child carries on its own spans. */
7
+ type DetachedChildLink = {
8
+ /** The caller's event id. */
9
+ parentEventId: string;
10
+ /** The dispatch span id, hex-encoded as the backend stores span ids. */
11
+ parentSpanId?: string;
12
+ name?: string;
13
+ };
14
+
15
+ /**
16
+ * Portable trace-context carrier for cross-process sub-agents.
17
+ *
18
+ * `toHeaders()` / `fromHeaders()` mirror LangSmith's
19
+ * `RunTree.toHeaders()` / `tracing_context(parent=headers)` so migrating from
20
+ * LangSmith is a rename rather than a redesign.
21
+ *
22
+ * Two carriers are understood:
23
+ *
24
+ * 1. Native — `x-raindrop-handoff`, plus W3C `traceparent` and a `baggage` of
25
+ * `raindrop-*` keys. The standard pair is what other readers understand;
26
+ * the Raindrop header is what survives an instrumented caller, and wins
27
+ * where they disagree. See {@link HANDOFF_HEADER}.
28
+ * 2. LangSmith — `langsmith-trace` (dotted order) plus LangSmith's `baggage`.
29
+ * Accepted on READ so a service already propagating LangSmith headers links
30
+ * correctly with no call-site change.
31
+ *
32
+ * ## Trust boundary
33
+ *
34
+ * A carrier names the event a child will be attributed to, so accepting one from
35
+ * an untrusted caller lets that caller write into another tenant's trace. Only
36
+ * accept carriers from services inside your own trust boundary — the same
37
+ * constraint LangSmith documents for distributed tracing. Never take a carrier
38
+ * off a public, unauthenticated request.
39
+ *
40
+ * Trace and span ids are hex here, as W3C `traceparent` and the Raindrop backend
41
+ * both represent them. Use `base64ToHex` when converting from the base64 ids
42
+ * used inside the trace shippers.
43
+ */
44
+ type TraceCarrier = {
45
+ /** Hex trace id (32 chars for a W3C-conformant id). */
46
+ traceId: string;
47
+ /** Hex span id of the dispatching span (16 chars for a W3C-conformant id). */
48
+ spanId: string;
49
+ /** Event the child should join (continuation) or reference (detached). */
50
+ eventId: string;
51
+ /** Set only for a detached hand-off: the child's OWN event id. */
52
+ childEventId?: string;
53
+ /** Sub-agent name, carried so the child can label its own run identically. */
54
+ name?: string;
55
+ convoId?: string;
56
+ userId?: string;
57
+ };
58
+ /**
59
+ * A header container that answers by name rather than by property.
60
+ *
61
+ * A WHATWG `Headers` — what fetch, Next.js route handlers, Hono, Remix and
62
+ * Cloudflare Workers all call `request.headers` — keeps its fields in an
63
+ * internal slot, so `headers["baggage"]` is `undefined` and `Object.entries()`
64
+ * on one yields nothing. Next.js's `headers()` returns a `ReadonlyHeaders`,
65
+ * which is that object sealed behind a Proxy. `get()` is the only way in, and it
66
+ * is also where the spec puts case-insensitivity and the joining of repeated
67
+ * fields — so the container does that work rather than {@link readHeader}
68
+ * reimplementing it.
69
+ */
70
+ type HeaderLookup = {
71
+ get(name: string): string | null | undefined;
72
+ };
73
+ type CarrierHeaders = Readonly<Record<string, string | string[] | undefined>> | HeaderLookup;
74
+ type LocalDebuggerLiveEventType = "text_delta" | "reasoning_delta" | "tool_start" | "tool_result" | "status";
75
+ type LocalDebuggerLiveEventInput$1 = {
76
+ traceId: string;
77
+ spanId?: string;
78
+ type: LocalDebuggerLiveEventType | (string & {});
79
+ content?: string;
80
+ timestamp?: number;
81
+ metadata?: Record<string, unknown>;
82
+ };
83
+
84
+ /**
85
+ * Run telemetry egress with OpenTelemetry tracing suppressed.
86
+ *
87
+ * Why this exists
88
+ * ---------------
89
+ * Raindrop integrations ship spans/events over HTTP with the global `fetch`
90
+ * (see {@link ../http.ts `postJson`}). When the host app also runs an OTel
91
+ * fetch/undici instrumentation — e.g. `@vercel/otel`'s `registerOTel`, which
92
+ * every Eve agent installs — that instrumentation wraps *our own* telemetry
93
+ * POSTs in a `fetch POST <endpoint>` span. Those spans are then handed to the
94
+ * very exporter that issued the request, so they get shipped right back to
95
+ * Raindrop and Workshop as standalone "runs" (and, because each export issues
96
+ * another fetch, they feed back on themselves). The result is a run list
97
+ * flooded with `fetch POST .../v1/traces`, `.../events/track_partial` and
98
+ * `.../live` entries that drown out the real agent turns — especially with
99
+ * sub-agents, where every sandbox runs its own instrumentation.
100
+ *
101
+ * The OTel-blessed fix is to mark the active context as "tracing suppressed"
102
+ * around the request; instrumentations check `isTracingSuppressed` and return
103
+ * a no-op span instead of recording one. We do this through a hook stashed on
104
+ * `globalThis` by the Node entrypoint ({@link ../index.node.ts}) so that:
105
+ * - `@opentelemetry/api` / `@opentelemetry/core` stay *optional* — core never
106
+ * hard-depends on them, and the hook is simply absent when they (and thus
107
+ * any instrumentation to suppress) are not installed; and
108
+ * - the browser bundle never pulls in `node:module`, mirroring how core
109
+ * injects `AsyncLocalStorage` via `RAINDROP_ASYNC_LOCAL_STORAGE`.
110
+ *
111
+ * When no hook is present the callback runs unchanged, so suppression is a
112
+ * best-effort no-op rather than a hard requirement.
113
+ */
114
+ /** Hook signature: run `fn` with OTel tracing suppressed, returning its value. */
115
+ type SuppressTracingHook = <T>(fn: () => T) => T;
116
+ declare global {
117
+ var RAINDROP_SUPPRESS_TRACING: SuppressTracingHook | undefined;
118
+ }
119
+
120
+ type ParentSpanContext = {
121
+ traceIdB64: string;
122
+ spanIdB64: string;
123
+ eventId: string;
124
+ };
125
+ interface ContextSpan {
126
+ readonly traceIdB64: string;
127
+ readonly spanIdB64: string;
128
+ readonly eventId: string;
129
+ log?(data: Record<string, unknown>): void;
130
+ }
131
+ interface AsyncLocalStorageLike<T> {
132
+ getStore(): T | undefined;
133
+ run<R>(store: T, callback: () => R): R;
134
+ enterWith?(store: T): void;
135
+ }
136
+ declare abstract class ContextManager {
137
+ abstract getParentSpanIds(): ParentSpanContext | undefined;
138
+ abstract runInContext<R>(span: ContextSpan, callback: () => R): R;
139
+ abstract getCurrentSpan(): ContextSpan | undefined;
140
+ abstract isReady(): boolean;
141
+ }
142
+ declare global {
143
+ var RAINDROP_CONTEXT_MANAGER: (new () => ContextManager) | undefined;
144
+ var RAINDROP_ASYNC_LOCAL_STORAGE: (new <T>() => AsyncLocalStorageLike<T>) | undefined;
145
+ }
146
+
147
+ /**
148
+ * Version-agnostic SpanProcessor interface.
149
+ *
150
+ * This interface avoids direct dependency on OTEL's Span and ReadableSpan types
151
+ * which can cause compatibility issues across minor OTEL versions. Using `any`
152
+ * allows the processor to work with any version of OTEL without type conflicts.
153
+ */
154
+ interface RaindropSpanProcessor {
155
+ forceFlush(): Promise<void>;
156
+ onStart(span: any, parentContext: any): void;
157
+ onEnd(span: any): void;
158
+ shutdown(): Promise<void>;
159
+ }
160
+ type BaseAttachment = {
161
+ attachment_id?: string;
162
+ name?: string;
163
+ value: string;
164
+ role: "input" | "output";
165
+ };
166
+ type CodeAttachment = BaseAttachment & {
167
+ type: "code";
168
+ language?: string;
169
+ };
170
+ type OtherAttachment = BaseAttachment & {
171
+ type: "text" | "image" | "iframe";
172
+ };
173
+ type Attachment = CodeAttachment | OtherAttachment;
174
+ type RaindropFeatureFlagValue = string | number | boolean;
175
+ type RaindropFeatureFlags = string[] | Record<string, RaindropFeatureFlagValue>;
176
+ type RaindropPropertyLeaf = string | boolean | number;
177
+ type RaindropPropertyValue = RaindropPropertyLeaf | RaindropPropertyValue[] | {
178
+ [key: string]: RaindropPropertyValue;
179
+ };
180
+ type RaindropProperties = Record<string, RaindropPropertyValue>;
181
+ /**
182
+ * Interface for tracking events.
183
+ *
184
+ * @param eventId - An optional event ID for the event.
185
+ * @param event - The name of the event.
186
+ * @param properties - An optional record of properties for the event.
187
+ * @param timestamp - An optional timestamp for the event.
188
+ * @param userId - The ID of the user. This is a required field.
189
+ * @param anonymousId - An optional anonymous ID for the user.
190
+ */
191
+ interface TrackEvent {
192
+ eventId?: string;
193
+ event: string;
194
+ properties?: RaindropProperties;
195
+ featureFlags?: RaindropFeatureFlags;
196
+ timestamp?: string;
197
+ userId: string;
198
+ }
199
+ type BasicSignal = {
200
+ eventId: string;
201
+ name: "thumbs_up" | "thumbs_down" | string;
202
+ sentiment?: "POSITIVE" | "NEGATIVE";
203
+ timestamp?: string;
204
+ properties?: {
205
+ [key: string]: any;
206
+ };
207
+ attachmentId?: string;
208
+ };
209
+ type DefaultSignal = BasicSignal & {
210
+ type?: "default" | "standard";
211
+ };
212
+ type FeedbackSignal = BasicSignal & {
213
+ type: "feedback";
214
+ comment?: string;
215
+ };
216
+ type EditSignal = BasicSignal & {
217
+ type: "edit";
218
+ after?: string;
219
+ };
220
+ type AgentSignal = BasicSignal & {
221
+ type: "agent" | "agent_internal";
222
+ };
223
+ type SignalEvent = DefaultSignal | FeedbackSignal | EditSignal | AgentSignal;
224
+ type SelfDiagnoseOptions = {
225
+ /** The interaction/event ID this diagnostic belongs to. */
226
+ eventId: string;
227
+ /** A human-readable description of the issue. */
228
+ description: string;
229
+ /** Optional category to group the diagnostic under (e.g. "missing_context", "capability_gap"). Defaults to "general". */
230
+ category?: string;
231
+ /** Optional source identifier (e.g. your agent or service name). */
232
+ source?: string;
233
+ /** Signal sentiment. Defaults to "NEGATIVE". */
234
+ sentiment?: "POSITIVE" | "NEGATIVE";
235
+ /** Additional custom properties to attach to the signal. */
236
+ properties?: Record<string, unknown>;
237
+ };
238
+ type SelfDiagnosticsSignalDefinition = {
239
+ description: string;
240
+ sentiment?: "POSITIVE" | "NEGATIVE";
241
+ };
242
+ type SelfDiagnosticsSignalDefinitions = Record<string, SelfDiagnosticsSignalDefinition>;
243
+ type SelfDiagnosticsToolInputSchema = {
244
+ type: "object";
245
+ additionalProperties: false;
246
+ properties: {
247
+ category: {
248
+ type: "string";
249
+ enum: string[];
250
+ description: string;
251
+ };
252
+ detail: {
253
+ type: "string";
254
+ description: string;
255
+ };
256
+ };
257
+ required: string[];
258
+ };
259
+ type SelfDiagnosticsExecuteContext = {
260
+ eventId?: string;
261
+ interaction?: {
262
+ getEventId(): string | undefined;
263
+ };
264
+ metadata?: Record<string, unknown>;
265
+ properties?: Record<string, unknown>;
266
+ source?: string;
267
+ };
268
+ type SelfDiagnosticsExecuteResult = {
269
+ acknowledged: boolean;
270
+ category: string;
271
+ eventId?: string;
272
+ reason?: "missing_event_id";
273
+ };
274
+ type SelfDiagnosticsToolOptions = {
275
+ eventId?: string;
276
+ getEventId?: () => string | undefined;
277
+ interaction?: {
278
+ getEventId(): string | undefined;
279
+ };
280
+ toolName?: string;
281
+ guidance?: string;
282
+ signals?: SelfDiagnosticsSignalDefinitions;
283
+ source?: string;
284
+ onMissingEventId?: "warn" | "ignore" | "throw";
285
+ };
286
+ type SelfDiagnosticsTool = {
287
+ name: string;
288
+ description: string;
289
+ inputSchema: SelfDiagnosticsToolInputSchema;
290
+ signalKeys: string[];
291
+ execute(input: unknown, context?: SelfDiagnosticsExecuteContext): Promise<SelfDiagnosticsExecuteResult>;
292
+ forVercelAI(): {
293
+ description: string;
294
+ parameters: SelfDiagnosticsToolInputSchema;
295
+ inputSchema: SelfDiagnosticsToolInputSchema;
296
+ execute: (input: unknown, context?: SelfDiagnosticsExecuteContext) => Promise<SelfDiagnosticsExecuteResult>;
297
+ };
298
+ forOpenAI(): {
299
+ type: "function";
300
+ function: {
301
+ name: string;
302
+ description: string;
303
+ parameters: SelfDiagnosticsToolInputSchema;
304
+ };
305
+ };
306
+ forAnthropic(): {
307
+ name: string;
308
+ description: string;
309
+ input_schema: SelfDiagnosticsToolInputSchema;
310
+ };
311
+ };
312
+ /**
313
+ * Interface for identifying events.
314
+ *
315
+ * @param userId - The ID of the user. This is a required field.
316
+ * @param traits - An optional object of traits for the user.
317
+ * @param anonymousId - An optional anonymous ID for the user.
318
+ * TODO: ensure at least one out of userId or anonymousId is present
319
+ */
320
+ interface IdentifyEvent {
321
+ userId: string;
322
+ traits?: object;
323
+ }
324
+ /**
325
+ * Type definition for AI tracking events.
326
+ * In addition to the properties of a TrackEvent, an AiTrackEvent may have a 'model' property.
327
+ * It must have at least one of 'input' or 'output' property.
328
+ *
329
+ * @property model - An optional model property for the even
330
+ * @property input - An optional input property for the event, required if output is not provided.
331
+ * @property output - An optional output property for the event, required if input is not provided.
332
+ */
333
+ type AiTrackEvent = Omit<TrackEvent, "type"> & {
334
+ model?: string;
335
+ convoId?: string;
336
+ attachments?: Attachment[];
337
+ featureFlags?: RaindropFeatureFlags;
338
+ } & ({
339
+ input: string;
340
+ output?: string;
341
+ } | {
342
+ input?: string;
343
+ output: string;
344
+ });
345
+ /**
346
+ * Type definition for partial AI tracking events used with trackAiPartial.
347
+ * Requires an eventId to correlate partial updates. All other fields are optional.
348
+ */
349
+ type PartialAiTrackEvent = Partial<AiTrackEvent> & {
350
+ eventId: string;
351
+ isPending?: boolean;
352
+ };
353
+ declare const AttachmentTypeSchema: z.ZodEnum<["code", "text", "image", "iframe"]>;
354
+ type AttachmentType = z.infer<typeof AttachmentTypeSchema>;
355
+ /**
356
+ * Configuration for initializing a trace interaction.
357
+ *
358
+ * This interface defines the context required to create and track an AI
359
+ * interaction through its lifecycle. It includes identifiers for the user
360
+ * and conversation, as well as input/output content and attachments.
361
+ *
362
+ * @property userId - Optional unique identifier for the user
363
+ * @property convoId - Optional unique identifier for the conversation
364
+ * @property eventId - Optional unique identifier for this specific interaction event
365
+ * @property input - Optional input text from the user
366
+ * @property attachments - Optional array of attachments associated with this interaction
367
+ * @property properties - Optional key-value pairs for additional custom metadata
368
+ */
369
+ interface TraceContext {
370
+ userId?: string;
371
+ convoId?: string;
372
+ eventId?: string;
373
+ input?: string;
374
+ event?: string;
375
+ attachments?: Attachment[];
376
+ properties?: Record<string, string>;
377
+ }
378
+ type BeginInteractionOptions = PartialAiTrackEvent & {
379
+ eventId: string;
380
+ };
381
+ type FinishInteractionOptions = Omit<PartialAiTrackEvent, "eventId"> & {
382
+ output: string;
383
+ eventId?: string;
384
+ };
385
+ /**
386
+ * Configuration for a traced workflow.
387
+ *
388
+ * Workflows represent higher-level operations that might contain multiple
389
+ * tasks. They help organize traces into logical units of work.
390
+ *
391
+ * @property name - Name of the workflow for identification in traces
392
+ * @property inputParameters - Optional array of input parameters for the workflow
393
+ * @property properties - Optional key-value pairs for additional metadata
394
+ */
395
+ interface WorkflowParams {
396
+ name: string;
397
+ inputParameters?: unknown[];
398
+ properties?: Record<string, string>;
399
+ }
400
+ /**
401
+ * Configuration for a traced task.
402
+ *
403
+ * Tasks represent individual operations within a workflow, such as an LLM call,
404
+ * a tool invocation, a retrieval operation, or internal processing.
405
+ *
406
+ * @property name - Name of the task for identification in traces
407
+ * @property kind - Category of the task (llm, tool, retrival, or internal)
408
+ * @property properties - Optional key-value pairs for additional metadata
409
+ * @property inputParameters - Optional array of input parameters for the task
410
+ * @property traceContent - Optional flag to control whether content is traced
411
+ * @property suppressTracing - Optional flag to suppress tracing for this task
412
+ */
413
+ interface SpanParams {
414
+ name: string;
415
+ properties?: Record<string, string>;
416
+ inputParameters?: unknown[];
417
+ traceContent?: boolean;
418
+ suppressTracing?: boolean;
419
+ }
420
+ /**
421
+ * Configuration for a traced tool.
422
+ *
423
+ * Tools represent external utilities or services that are invoked during an AI interaction,
424
+ * such as search engines, calculators, or other specialized functions.
425
+ *
426
+ * @property name - Name of the tool for identification in traces
427
+ * @property version - Optional version number of the tool
428
+ * @property properties - Optional key-value pairs for additional metadata
429
+ * @property inputParameters - Optional record of input parameters for the tool
430
+ * @property traceContent - Optional flag to control whether content is traced
431
+ * @property suppressTracing - Optional flag to suppress tracing for this tool invocation
432
+ */
433
+ interface ToolParams {
434
+ name: string;
435
+ version?: number;
436
+ properties?: Record<string, string>;
437
+ inputParameters?: Record<string, any>;
438
+ traceContent?: boolean;
439
+ suppressTracing?: boolean;
440
+ }
441
+ /**
442
+ * Parameters for directly logging a tool span without wrapping a function.
443
+ *
444
+ * Use this when you want to record a tool invocation that has already completed,
445
+ * rather than wrapping the tool call with withTool().
446
+ *
447
+ * @property name - Name of the tool for identification in traces
448
+ * @property input - The input provided to the tool (will be JSON stringified if object)
449
+ * @property output - The output returned by the tool (will be JSON stringified if object)
450
+ * @property durationMs - Duration of the tool execution in milliseconds
451
+ * @property startTime - Optional start time of the tool execution
452
+ * @property error - Optional error if the tool failed
453
+ * @property properties - Optional key-value pairs for additional metadata
454
+ * @property traceId - Optional W3C trace ID override for bypassOtelForTools mode
455
+ * @property parentSpanId - Optional W3C parent span ID override for bypassOtelForTools mode
456
+ */
457
+ interface TrackToolParams {
458
+ name: string;
459
+ input?: unknown;
460
+ output?: unknown;
461
+ durationMs?: number;
462
+ startTime?: Date | number;
463
+ error?: Error | string;
464
+ properties?: Record<string, string>;
465
+ traceId?: string;
466
+ parentSpanId?: string;
467
+ }
468
+ type LocalDebuggerLiveEventInput = Omit<LocalDebuggerLiveEventInput$1, "traceId"> & {
469
+ traceId?: string;
470
+ };
471
+ /**
472
+ * Arguments for {@link Interaction.subagent}.
473
+ *
474
+ * Deliberately absent: anything describing how the child is doing. The caller
475
+ * dispatched a job and moved on, so a status it wrote would be a guess that
476
+ * goes stale — readers derive status from the child's own event.
477
+ */
478
+ interface SubagentDispatchOptions {
479
+ /** Sub-agent name. The child labels its own run with the same value. */
480
+ name: string;
481
+ /** Launch arguments, recorded as the dispatch span's input. */
482
+ input?: unknown;
483
+ /**
484
+ * Reuse an id the caller already has (a queue job id, say) instead of
485
+ * minting one. Either way the id exists BEFORE dispatch, which is what makes
486
+ * the link resolvable while the child is still queued.
487
+ */
488
+ childEventId?: string;
489
+ /** Name of the dispatch span. Defaults to `launch_subagent`. */
490
+ toolName?: string;
491
+ /** Extra properties recorded on the dispatch span. */
492
+ properties?: RaindropProperties;
493
+ }
494
+ /** The record of one detached dispatch, returned by {@link Interaction.subagent}. */
495
+ interface SubagentDispatch {
496
+ /** The child's own event id — the job handle to pass to the worker. */
497
+ childEventId: string;
498
+ name: string;
499
+ /** The launching interaction's event id. */
500
+ parentEventId: string;
501
+ /** Hex id of the dispatch span, or `undefined` when none was recorded. */
502
+ dispatchSpanId?: string;
503
+ /**
504
+ * The carrier behind the headers, for transports that are not HTTP.
505
+ *
506
+ * `null` when no dispatch span could be recorded (tracing disabled). There is
507
+ * then no span for the child to reference, and `headers` is empty rather than
508
+ * naming one that does not exist — pass `childEventId` to the worker yourself
509
+ * if it must still report under that id.
510
+ */
511
+ carrier: TraceCarrier | null;
512
+ /**
513
+ * Native carrier headers: W3C `traceparent` + `raindrop-*` `baggage`, plus
514
+ * `x-raindrop-handoff` carrying the same fields under a name no propagator
515
+ * rewrites. Send all of them — instrumentation owns `traceparent` and the
516
+ * baggage propagator REPLACES `baggage`, so the standard pair alone can arrive
517
+ * emptied of every hand-off identity.
518
+ *
519
+ * TRUST BOUNDARY: send these only to services inside your own trust
520
+ * boundary — a carrier names the event the child will be attributed to.
521
+ */
522
+ headers: Record<string, string>;
523
+ /** The same carrier in LangSmith's header shape, for services that parse it. */
524
+ langsmithHeaders: Record<string, string>;
525
+ }
526
+ /**
527
+ * Fallbacks for a sub-agent run whose request carried no carrier, i.e. one
528
+ * invoked directly rather than dispatched.
529
+ *
530
+ * These do NOT override a carrier. Every identity field here names something
531
+ * the launcher already recorded, so a local value winning would strand the
532
+ * child outside the link it exists to complete.
533
+ */
534
+ interface SubagentResumeOptions {
535
+ /** Used when the carrier supplied no name. */
536
+ name?: string;
537
+ /** Used when the carrier supplied no child event id. */
538
+ eventId?: string;
539
+ userId?: string;
540
+ convoId?: string;
541
+ /** Event name for the child's own event. Defaults to `subagent.<name>`. */
542
+ event?: string;
543
+ input?: string;
544
+ model?: string;
545
+ properties?: RaindropProperties;
546
+ /** Pre-parsed carrier, for transports that are not HTTP. */
547
+ parent?: TraceCarrier | null;
548
+ }
549
+ /** How a detached sub-agent's run completes. */
550
+ type SubagentFinishOptions = Omit<FinishInteractionOptions, "eventId">;
551
+ /**
552
+ * A detached sub-agent's own run, as seen from inside the sub-agent.
553
+ *
554
+ * Wraps the child's own Raindrop event and keeps the reverse reference bound to
555
+ * the execution context, so every span the child emits while the run is open
556
+ * carries it.
557
+ */
558
+ interface SubagentRun {
559
+ /** The child's own Raindrop event. */
560
+ readonly interaction: Interaction;
561
+ /** The child's own event id, adopted from the carrier when it supplied one. */
562
+ readonly eventId: string;
563
+ readonly name: string;
564
+ /** The conversation this run reports into — the launcher's when linked. */
565
+ readonly convoId?: string;
566
+ /**
567
+ * The launching context, or `null` when the request carried no carrier.
568
+ *
569
+ * `null` is a legitimate state — the sub-agent was invoked directly rather
570
+ * than dispatched — and the run still reports as its own event, just without
571
+ * a link back.
572
+ */
573
+ readonly parent: DetachedChildLink | null;
574
+ readonly linked: boolean;
575
+ /** Complete the child's event with its result. */
576
+ finish(result: SubagentFinishOptions): Promise<void>;
577
+ /**
578
+ * Report that the run aborted: error the child's own span, and say why in
579
+ * the output.
580
+ *
581
+ * Both halves matter. The ERROR status is what makes the run read as
582
+ * *failed* — status is derived from the child's telemetry, and a run with
583
+ * output but no errored span is indistinguishable from one that succeeded.
584
+ * The output is what makes the run exist at all: an event needs non-empty
585
+ * output, so a child that closes empty leaves its launcher on `queued`
586
+ * forever.
587
+ */
588
+ fail(reason: unknown): Promise<void>;
589
+ /**
590
+ * Mark the run cancelled — the one state its telemetry cannot express.
591
+ *
592
+ * A cancelled run is span-for-span identical to a finished one (spans close,
593
+ * nothing errors, there is simply no answer), so it needs an explicit
594
+ * marker. Written by the child on itself, never by the caller. Deliberately
595
+ * does NOT error any span: error spans are what separate failed from
596
+ * cancelled.
597
+ */
598
+ cancel(reason?: unknown): Promise<void>;
599
+ }
600
+ /**
601
+ * A wrapper around an OpenTelemetry span for tool invocations.
602
+ *
603
+ * Provides a clean API for setting tool input, output, and error status
604
+ * without needing to know the internal traceloop attribute names.
605
+ *
606
+ * @example
607
+ * ```typescript
608
+ * const toolSpan = interaction.startToolSpan({ name: "web_search" });
609
+ * try {
610
+ * const result = await performSearch(query);
611
+ * toolSpan.setOutput(result);
612
+ * } catch (error) {
613
+ * toolSpan.setError(error);
614
+ * } finally {
615
+ * toolSpan.end();
616
+ * }
617
+ * ```
618
+ */
619
+ interface ToolSpan {
620
+ /**
621
+ * Sets the input for this tool span.
622
+ * @param input The input value (will be JSON stringified if object)
623
+ */
624
+ setInput(input: unknown): void;
625
+ /**
626
+ * Sets the output for this tool span.
627
+ * @param output The output value (will be JSON stringified if object)
628
+ */
629
+ setOutput(output: unknown): void;
630
+ /**
631
+ * Marks this tool span as failed with an error.
632
+ * @param error The error that occurred
633
+ */
634
+ setError(error: Error | string): void;
635
+ /**
636
+ * Ends this tool span. Must be called when the tool execution is complete.
637
+ */
638
+ end(): void;
639
+ }
640
+ /**
641
+ * Represents an active tracing interaction for tracking and analyzing AI interactions.
642
+ *
643
+ * An Interaction is the core entity for tracing and instrumenting AI operations,
644
+ * allowing you to organize your code into workflows and tasks while capturing
645
+ * important metadata and contextual information. Use the methods on this interface
646
+ * to record your AI interaction's lifecycle from input to output, and to add
647
+ * structured context about the operation.
648
+ *
649
+ * Interactions are typically created using the `tracing.begin()` method and ended
650
+ * with the `end()` method. Between these calls, you can add properties, attachments,
651
+ * and nested traced operations.
652
+ *
653
+ * @example
654
+ * // Basic usage pattern
655
+ * const interaction = tracing.begin({
656
+ * userId: "user-123",
657
+ * convoId: "conversation-456"
658
+ * });
659
+ *
660
+ * // Set the user's input
661
+ * interaction.setInput("Tell me a joke about AI");
662
+ *
663
+ * // Add context properties
664
+ * interaction.setProperty("intent", "entertainment");
665
+ *
666
+ * // Run a traced workflow
667
+ * const result = await interaction.withWorkflow("joke_generation", async () => {
668
+ * // Run a traced task for the LLM call
669
+ * return await interaction.withTask({
670
+ * name: "llm_completion",
671
+ * kind: "llm"
672
+ * }, async () => {
673
+ * const completion = await openai.chat.completions.create({
674
+ * model: "gpt-4",
675
+ * messages: [{ role: "user", content: "Tell me a joke about AI" }]
676
+ * });
677
+ * return completion.choices[0].message.content;
678
+ * });
679
+ * });
680
+ *
681
+ * // End the interaction with the result
682
+ * interaction.end(result);
683
+ */
684
+ type Interaction = {
685
+ /**
686
+ * Creates a traced task that executes the provided function.
687
+ *
688
+ * @param params TaskParams object with task configuration
689
+ * @returns A span that can be used to record a task
690
+ */
691
+ withSpan<T>(params: SpanParams, fn: (...args: any[]) => Promise<T> | T, thisArg?: any, ...args: any[]): Promise<T>;
692
+ /**
693
+ * Creates a traced tool that executes the provided function.
694
+ *
695
+ * Tools represent external utilities or services that are invoked during an AI interaction.
696
+ * This method wraps a function call with tracing to capture the tool's inputs and outputs.
697
+ *
698
+ * @param params ToolParams object with tool configuration
699
+ * @param fn Function to execute within the tool trace
700
+ * @param thisArg Optional 'this' context for the function
701
+ * @param args Optional arguments to pass to the function
702
+ * @returns A promise that resolves with the tool execution result
703
+ *
704
+ * @example
705
+ * // Basic tool usage
706
+ * const result = await interaction.withTool(
707
+ * { name: "search_tool" },
708
+ * async () => {
709
+ * // Call to external API or service
710
+ * return "Search results";
711
+ * }
712
+ * );
713
+ *
714
+ * @example
715
+ * // Basic tool usage
716
+ * const result = await interaction.withTool(
717
+ * {
718
+ * name: "calculator",
719
+ * properties: { operation: "multiply" },
720
+ * inputParameters: { a: 5, b: 10 }
721
+ * },
722
+ * async () => {
723
+ * // Tool implementation
724
+ * return "Result: 50";
725
+ * }
726
+ * );
727
+ */
728
+ withTool<T>(params: ToolParams, fn: (...args: any[]) => Promise<T> | T, thisArg?: any, ...args: any[]): Promise<T>;
729
+ /**
730
+ * Creates a task span that can be used to manually record a task.
731
+ *
732
+ * @param params TaskParams object with task configuration
733
+ * @returns A span that can be used to record a task
734
+ */
735
+ startSpan(params: SpanParams): Span;
736
+ /**
737
+ * Creates a tool span that can be used to manually record a tool invocation.
738
+ *
739
+ * Similar to startSpan but sets the span kind to "tool" instead of "task".
740
+ * Use this when you want manual control over the span lifecycle for tool calls.
741
+ * Returns a ToolSpan wrapper with convenient methods for setting input, output, and errors.
742
+ *
743
+ * @param params ToolParams object with tool configuration
744
+ * @returns A ToolSpan wrapper for recording the tool execution
745
+ *
746
+ * @example
747
+ * ```typescript
748
+ * const interaction = raindrop.begin({ userId: "user-123", event: "agent_run" });
749
+ *
750
+ * // Start a tool span with manual control
751
+ * const toolSpan = interaction.startToolSpan({ name: "web_search" });
752
+ * try {
753
+ * const result = await performSearch(query);
754
+ * toolSpan.setOutput(result);
755
+ * } catch (error) {
756
+ * toolSpan.setError(error);
757
+ * } finally {
758
+ * toolSpan.end();
759
+ * }
760
+ * ```
761
+ */
762
+ startToolSpan(params: ToolParams): ToolSpan;
763
+ /**
764
+ * Sets multiple properties on the interaction context.
765
+ *
766
+ * @param properties Object containing properties to set
767
+ */
768
+ setProperties(properties: RaindropProperties): void;
769
+ /**
770
+ * Sets a single property on the interaction context.
771
+ *
772
+ * @param key The property key
773
+ * @param value The property value
774
+ */
775
+ setProperty(key: string, value: RaindropPropertyValue): void;
776
+ /**
777
+ * Adds an attachment to the interaction.
778
+ *
779
+ * @param attachment The attachment to add
780
+ *
781
+ * @example
782
+ * // Adding various attachment types to an interaction
783
+ *
784
+ * // 1. Text attachment for context
785
+ * interaction.addAttachment([{
786
+ * type: "text",
787
+ * name: "Additional Info",
788
+ * value: "A very long document",
789
+ * role: "input",
790
+ * }]);
791
+ *
792
+ * // 2. Image attachment (output)
793
+ * interaction.addAttachment([{
794
+ * type: "image",
795
+ * value: "https://example.com/image.png",
796
+ * role: "output"
797
+ * }]);
798
+ *
799
+ * // 3. Iframe for embedded content
800
+ * interaction.addAttachment([{
801
+ * type: "iframe",
802
+ * name: "Generated UI",
803
+ * value: "https://newui.generated.com",
804
+ * role: "output",
805
+ * }]);
806
+ *
807
+ * // 4. Code snippet
808
+ * interaction.addAttachment([{
809
+ * type: "code",
810
+ * name: "Generated SQL Query",
811
+ * value: "SELECT * FROM users WHERE os_build = '17.1'",
812
+ * role: "output",
813
+ * language: "sql"
814
+ * }]);
815
+ *
816
+ * // All attachments are included when the interaction ends
817
+ * interaction.end("The weather is sunny and warm.");
818
+ */
819
+ addAttachments(attachments: Attachment[]): void;
820
+ /**
821
+ * Sets a single feature flag on the interaction.
822
+ * @param name The flag name
823
+ * @param value The flag value (defaults to "true")
824
+ */
825
+ setFeatureFlag(name: string, value?: RaindropFeatureFlagValue): void;
826
+ /**
827
+ * Sets multiple feature flags on the interaction.
828
+ * Accepts an array of flag names (all set to "true") or an object with explicit values.
829
+ * Merges with any previously set flags.
830
+ * @param flags The feature flags to set
831
+ */
832
+ setFeatureFlags(flags: RaindropFeatureFlags): void;
833
+ /**
834
+ * Sets the input for the interaction.
835
+ *
836
+ * @param input The input string
837
+ */
838
+ setInput(input: string): void;
839
+ /**
840
+ * Ends the interaction and sends analytics data.
841
+ *
842
+ * This method completes the interaction lifecycle by:
843
+ * 1. Setting the trace_id as a property (if available)
844
+ * 2. Sending analytics data including the event ID, conversation ID,
845
+ * user ID, input, output, attachments, and any custom properties
846
+ *
847
+ * @param output The final output string for this interaction
848
+ *
849
+ * @example
850
+ * // Start and end an interaction
851
+ * const interaction = tracing.begin({
852
+ * userId: "user-123",
853
+ * convoId: "convo-456"
854
+ * });
855
+ *
856
+ * interaction.setInput("What can you help me with today?");
857
+ * // ... process the request ...
858
+ *
859
+ * // End the interaction with the response
860
+ * interaction.end("I can help you with various tasks. Here are some examples...");
861
+ */
862
+ finish(resultEvent: FinishInteractionOptions): Promise<void>;
863
+ /**
864
+ * Returns metadata for Vercel AI SDK's experimental_telemetry option.
865
+ *
866
+ * Use this when making Vercel AI SDK calls outside of withSpan() to ensure
867
+ * the interaction's properties (userId, convoId, eventId) are attached to the spans.
868
+ *
869
+ * When using withSpan(), this is handled automatically via context propagation.
870
+ * This method is a fallback for cases where you can't use withSpan().
871
+ *
872
+ * @returns Metadata object with traceloop association properties
873
+ *
874
+ * @example
875
+ * ```typescript
876
+ * const interaction = raindrop.begin({ userId: "user-123", convoId: "convo-456" });
877
+ *
878
+ * // Option 1: Use withSpan (recommended - automatic context propagation)
879
+ * await interaction.withSpan("my-task", async () => {
880
+ * await generateText({ experimental_telemetry: { isEnabled: true }, ... });
881
+ * });
882
+ *
883
+ * // Option 2: Use vercelAiSdkMetadata (fallback when withSpan isn't possible)
884
+ * await generateText({
885
+ * experimental_telemetry: {
886
+ * isEnabled: true,
887
+ * metadata: interaction.vercelAiSdkMetadata(),
888
+ * },
889
+ * ...
890
+ * });
891
+ * ```
892
+ */
893
+ vercelAiSdkMetadata(): Record<string, string>;
894
+ /**
895
+ * Returns the interaction event ID used for event/signal correlation.
896
+ */
897
+ getEventId(): string | undefined;
898
+ /**
899
+ * Logs a tool span directly without wrapping a function.
900
+ *
901
+ * Use this when you want to record a tool invocation that has already completed,
902
+ * rather than wrapping the tool call with withTool(). This is useful for:
903
+ * - Recording tool calls from external systems
904
+ * - Logging tools that were executed outside of the tracing context
905
+ * - Retroactively adding tool spans with known input/output/duration
906
+ *
907
+ * @param params TrackToolParams object with tool execution details
908
+ *
909
+ * @example
910
+ * ```typescript
911
+ * const interaction = raindrop.begin({ userId: "user-123", event: "agent_run" });
912
+ *
913
+ * // Record a tool that was already executed
914
+ * interaction.trackTool({
915
+ * name: "web_search",
916
+ * input: { query: "weather in NYC" },
917
+ * output: { results: ["Sunny, 72°F"] },
918
+ * durationMs: 150,
919
+ * });
920
+ *
921
+ * // Record a failed tool
922
+ * interaction.trackTool({
923
+ * name: "database_query",
924
+ * input: { sql: "SELECT * FROM users" },
925
+ * error: new Error("Connection timeout"),
926
+ * durationMs: 5000,
927
+ * });
928
+ *
929
+ * interaction.finish({ output: "Here's the weather..." });
930
+ * ```
931
+ */
932
+ trackTool(params: TrackToolParams): void;
933
+ /**
934
+ * Emits a live event to the local debugger for this interaction's trace.
935
+ *
936
+ * Use this to surface streaming output or framework-specific progress from
937
+ * integrations that do not use `@raindrop-ai/ai-sdk`.
938
+ */
939
+ emitLiveEvent(event: LocalDebuggerLiveEventInput): void;
940
+ /**
941
+ * Records the launch of a **detached** sub-agent: one that runs in another
942
+ * process, does not block this interaction, and reports as its own Raindrop
943
+ * event with its own lifecycle.
944
+ *
945
+ * The child's event id is allocated BEFORE anything is dispatched, so this
946
+ * interaction can point at the child from the moment of launch — while the
947
+ * job is still queued and before the child has emitted anything. Send the
948
+ * returned headers with the job; the worker passes them to
949
+ * `raindrop.resumeSubagent()`.
950
+ *
951
+ * Nothing here waits for the child, and nothing here claims to know how it
952
+ * is doing.
953
+ *
954
+ * @example
955
+ * ```typescript
956
+ * const dispatch = interaction.subagent({
957
+ * name: "researcher",
958
+ * input: { task },
959
+ * });
960
+ * await queue.send({ task, headers: dispatch.headers });
961
+ * return { jobId: dispatch.childEventId, status: "accepted" };
962
+ * ```
963
+ */
964
+ subagent(options: SubagentDispatchOptions): SubagentDispatch;
965
+ };
966
+ type Tracer = {
967
+ /**
968
+ * Creates a traced task that executes the provided function.
969
+ *
970
+ * @param params TaskParams object with task configuration
971
+ * @returns A span that can be used to record a task
972
+ */
973
+ withSpan<T>(params: SpanParams, fn: (...args: any[]) => Promise<T> | T, thisArg?: any, ...args: any[]): Promise<T>;
974
+ /**
975
+ * Logs a tool span directly without wrapping a function.
976
+ *
977
+ * Use this when you want to record a tool invocation that has already completed,
978
+ * rather than wrapping the tool call. This is useful for batch jobs or
979
+ * non-interactive use-cases where you only care about tracing and token usage.
980
+ *
981
+ * @param params TrackToolParams object with tool execution details
982
+ *
983
+ * @example
984
+ * ```typescript
985
+ * const tracer = raindrop.tracer({ job_id: "batch-123" });
986
+ *
987
+ * // Record a tool that was already executed
988
+ * tracer.trackTool({
989
+ * name: "web_search",
990
+ * input: { query: "weather in NYC" },
991
+ * output: { results: ["Sunny, 72°F"] },
992
+ * durationMs: 150,
993
+ * });
994
+ * ```
995
+ */
996
+ trackTool(params: TrackToolParams): void;
997
+ /**
998
+ * Emits a live event to the local debugger using the current active trace.
999
+ */
1000
+ emitLiveEvent(event: LocalDebuggerLiveEventInput): void;
1001
+ };
1002
+
1003
+ declare global {
1004
+ var RAINDROP_ASYNC_LOCAL_STORAGE: (new <T>() => {
1005
+ getStore(): T | undefined;
1006
+ run<R>(store: T, callback: () => R): R;
1007
+ enterWith?(store: T): void;
1008
+ }) | undefined;
1009
+ }
1010
+
1011
+ interface AnalyticsConfig {
1012
+ wizardSession?: string;
1013
+ /**
1014
+ * Raindrop write key. When omitted (or empty), the SDK runs in local-only mode:
1015
+ * cloud requests are skipped and only the Workshop / local-debugger mirror fires
1016
+ * (when `localWorkshopUrl` resolves to a URL). Useful for local development where
1017
+ * you only want events to land in Workshop without provisioning a write key.
1018
+ */
1019
+ writeKey?: string;
1020
+ bufferSize?: number;
1021
+ bufferTimeout?: number;
1022
+ debugLogs?: boolean;
1023
+ endpoint?: string;
1024
+ redactPii?: boolean;
1025
+ /**
1026
+ * Per-field character cap applied to ai input/output and serialized
1027
+ * tool/span content BEFORE buffering or serialization, so oversized
1028
+ * payloads cost the cap — not the payload — on the calling code path
1029
+ * (`JSON.stringify` of a multi-MB payload blocks the event loop).
1030
+ * Truncated fields end with `...[truncated by raindrop]` and never exceed
1031
+ * the cap, marker included. Defaults to 1,000,000 (matching the Python SDK's
1032
+ * `max_text_field_chars`).
1033
+ */
1034
+ maxTextFieldChars?: number;
1035
+ /**
1036
+ * Force-enable (or opt out of) Workshop / local-debugger mirroring.
1037
+ *
1038
+ * - `string` — explicit Workshop URL (e.g. `"http://localhost:5899/v1/"`),
1039
+ * wins over env vars and runtime auto-detect.
1040
+ * - `false` (or `null`) — explicit opt-out, even on localhost / when
1041
+ * `NODE_ENV=development` / when `RAINDROP_WORKSHOP` is set.
1042
+ * - `undefined` (default) — fall through to `RAINDROP_LOCAL_DEBUGGER`,
1043
+ * `RAINDROP_WORKSHOP`, and runtime auto-detect (localhost-ish hostname
1044
+ * OR `NODE_ENV=development` enables the default `:5899` daemon).
1045
+ */
1046
+ localWorkshopUrl?: string | false | null;
1047
+ /**
1048
+ * Optional project slug. When set, every outbound cloud ingest request
1049
+ * (event POSTs and the direct trace shipper) carries an
1050
+ * `X-Raindrop-Project-Id: <projectId>` header so the backend routes the
1051
+ * data to that project. Empty / whitespace-only values are ignored and the
1052
+ * backend falls back to the account's default project. Slug format is
1053
+ * validated on construction but never throws — invalid values are warned
1054
+ * about (when `debugLogs` is true) and sent anyway (the backend returns
1055
+ * HTTP 400 if the value is actually unusable). Local Workshop mirror
1056
+ * requests deliberately skip this header (project routing is a cloud-only
1057
+ * concept), mirroring the `@raindrop-ai/core` convention.
1058
+ */
1059
+ projectId?: string;
1060
+ /**
1061
+ * @deprecated Renamed to `useExternalOtel`. Use that instead.
1062
+ * This option will be removed in a future version.
1063
+ */
1064
+ disableTracing?: boolean;
1065
+ /**
1066
+ * Set to true if you have your own OpenTelemetry setup (e.g., Sentry, Datadog).
1067
+ *
1068
+ * When true:
1069
+ * - Raindrop won't create its own NodeSDK (avoids conflicts)
1070
+ * - Use `raindrop.createSpanProcessor()` to get a processor for your NodeSDK
1071
+ * - Use `raindrop.getInstrumentations()` to get configured LLM instrumentations
1072
+ *
1073
+ * @example
1074
+ * ```ts
1075
+ * import { NodeSDK } from "@opentelemetry/sdk-node";
1076
+ * import Anthropic from "@anthropic-ai/sdk";
1077
+ *
1078
+ * const raindrop = new Raindrop({
1079
+ * writeKey: "xxx",
1080
+ * useExternalOtel: true,
1081
+ * instrumentModules: { anthropic: Anthropic },
1082
+ * });
1083
+ *
1084
+ * const sdk = new NodeSDK({
1085
+ * spanProcessors: [raindrop.createSpanProcessor(), yourSentryProcessor],
1086
+ * instrumentations: raindrop.getInstrumentations(),
1087
+ * });
1088
+ * sdk.start();
1089
+ * ```
1090
+ */
1091
+ useExternalOtel?: boolean;
1092
+ /**
1093
+ * false by default. If true, the SDK will not send any events or initialize tracing.
1094
+ * Useful for development/test environments.
1095
+ */
1096
+ disabled?: boolean;
1097
+ /**
1098
+ * Disable span batching for local development.
1099
+ * When true, spans are sent immediately instead of being batched.
1100
+ * Defaults to true in development (NODE_ENV !== 'production').
1101
+ */
1102
+ disableBatching?: boolean;
1103
+ /**
1104
+ * When true, all `trackTool()`, `withTool()`, and `startToolSpan()` calls bypass the OTEL
1105
+ * exporter pipeline and ship spans directly to the Raindrop API via HTTP POST.
1106
+ *
1107
+ * Spans still read the active OTEL context to inherit traceId
1108
+ * and parentSpanId — they still appear as children in the trace tree.
1109
+ * Only the shipping mechanism changes.
1110
+ *
1111
+ * This is useful when OTEL setup is fragile (e.g., conflicting providers,
1112
+ * broken exporters) but you still want tool spans to work reliably.
1113
+ *
1114
+ * @default false
1115
+ */
1116
+ bypassOtelForTools?: boolean;
1117
+ /**
1118
+ * Whether `interaction.finish()` should await the in-flight span/trace flush
1119
+ * (i.e. `forceFlush()`, which drains buffered OTLP/tool spans — a `/v1/traces`
1120
+ * POST with retries) before resolving. This await was added so a local
1121
+ * Workshop daemon doesn't race OTLP ingest; in cloud mode it only adds
1122
+ * request latency.
1123
+ *
1124
+ * Note this gates *only* the span flush. `finish()` always awaits the
1125
+ * terminal partial-event POST that records the run, and always orders it
1126
+ * after any earlier in-flight POST for the same eventId — to skip the
1127
+ * partial POST too, simply don't `await interaction.finish(...)`.
1128
+ *
1129
+ * - `true` / `undefined` (default) — await the span/trace flush, preserving
1130
+ * the historical guaranteed-flush-before-return behavior.
1131
+ * - `false` — don't await it; it drains in the background so the caller's
1132
+ * request isn't taxed by the round trip + retries. A local Workshop /
1133
+ * debugger still forces the await regardless (its read-after-write
1134
+ * guarantee depends on it).
1135
+ */
1136
+ awaitSpanFlush?: boolean;
1137
+ /**
1138
+ * Explicitly specify modules to instrument. Optional.
1139
+ *
1140
+ * Pass the module constructors/namespaces you want to instrument:
1141
+ * @example
1142
+ * ```ts
1143
+ * import OpenAI from "openai";
1144
+ * import Anthropic from "@anthropic-ai/sdk";
1145
+ *
1146
+ * const raindrop = new Raindrop({
1147
+ * writeKey: "xxx",
1148
+ * instrumentModules: {
1149
+ * openAI: OpenAI,
1150
+ * anthropic: Anthropic,
1151
+ * },
1152
+ * });
1153
+ * ```
1154
+ */
1155
+ instrumentModules?: {
1156
+ openAI?: unknown;
1157
+ anthropic?: unknown;
1158
+ cohere?: unknown;
1159
+ bedrock?: unknown;
1160
+ google_vertexai?: unknown;
1161
+ google_aiplatform?: unknown;
1162
+ pinecone?: unknown;
1163
+ together?: unknown;
1164
+ langchain?: boolean;
1165
+ llamaIndex?: unknown;
1166
+ chromadb?: unknown;
1167
+ qdrant?: unknown;
1168
+ mcp?: unknown;
1169
+ } & Record<string, unknown>;
1170
+ }
1171
+ declare const MAX_INGEST_SIZE_BYTES: number;
1172
+ /**
1173
+ * Resolve the effective `disableBatching` flag that decides whether tracing
1174
+ * uses `SimpleSpanProcessor` (immediate export) or `BatchSpanProcessor`.
1175
+ *
1176
+ * Precedence:
1177
+ * 1. An explicit `config.disableBatching` always wins, in both directions.
1178
+ * 2. Otherwise, batching is disabled when NOT in production (existing
1179
+ * behavior) OR when the local debugger (Workshop) is active — so spans
1180
+ * deliver immediately to Workshop even under `NODE_ENV=production`.
1181
+ *
1182
+ * Production behavior for consumers is unchanged: with no local debugger and
1183
+ * no explicit config, this returns `false` (i.e. batching stays on).
1184
+ */
1185
+ declare function resolveDisableBatching(explicit: boolean | undefined, signals: {
1186
+ isProduction: boolean;
1187
+ isLocalDebugger: boolean;
1188
+ }): boolean;
1189
+ declare class Raindrop {
1190
+ private wizardSession;
1191
+ private writeKey;
1192
+ private apiUrl;
1193
+ private buffer;
1194
+ private bufferSize;
1195
+ private bufferTimeout;
1196
+ private flushTimer;
1197
+ private redactPii;
1198
+ private disabled;
1199
+ private context;
1200
+ private _tracing;
1201
+ private localDebuggerUrlOpt;
1202
+ private awaitSpanFlushOpt;
1203
+ private partialEventBuffer;
1204
+ private partialEventTimeouts;
1205
+ private inFlightRequests;
1206
+ private inFlightByEvent;
1207
+ private maxTextFieldChars;
1208
+ private projectId;
1209
+ private authHint;
1210
+ /**
1211
+ * Epoch ms deadline while `close()` is draining; undefined otherwise.
1212
+ * Checked before every POST issued during the final flush so a dead or
1213
+ * slow network can never wedge process exit.
1214
+ */
1215
+ private shutdownDeadlineAt;
1216
+ /**
1217
+ * Set once `close()` begins and never cleared. Sends issued after the
1218
+ * drain window (stragglers, or flush work the deadline abandoned
1219
+ * mid-drain) run as a single short attempt instead of regaining the full
1220
+ * retry schedule.
1221
+ */
1222
+ private hasShutdown;
1223
+ debugLogs: boolean;
1224
+ constructor(config: AnalyticsConfig);
1225
+ private get localOnly();
1226
+ private formatEndpoint;
1227
+ /**
1228
+ * Begins a new interaction.
1229
+ *
1230
+ * The interaction's routing binding lives until `finish()` (which unbinds it
1231
+ * by identity, so it is removed even if `finish()` runs inside a nested
1232
+ * `withSpan`/`withTool`/`asCurrent` scope or a detached task). One exception:
1233
+ * calling `begin()` INSIDE an `asCurrent(fn)` scope pushes the binding within
1234
+ * that scope, so it dies when the scope exits (matching the Python SDK's
1235
+ * token-reset semantics) — start such interactions outside `asCurrent`, or
1236
+ * keep their work inside the same scope.
1237
+ *
1238
+ * @param traceContext - The trace context for the interaction.
1239
+ * @returns The interaction object.
1240
+ */
1241
+ begin(traceContext: PartialAiTrackEvent & {
1242
+ event: string;
1243
+ userId: string;
1244
+ }): Interaction;
1245
+ /**
1246
+ * Returns a tracer object that can be used to create spans and tools that aren't tied to any interaction.
1247
+ * For chat interaction use-case `begin` should be used.
1248
+ * This is meant for batch jobs or other non-interactive use-cases where you only care about tracing and token usage.
1249
+ *
1250
+ * @param globalProperties - Optional global properties to be associated with all spans and tools.
1251
+ * @returns The tracer object.
1252
+ */
1253
+ tracer(globalProperties?: Record<string, string>): Tracer;
1254
+ /**
1255
+ * Scope all spans created inside `fn` (and its awaited continuations) to this
1256
+ * client's project/key, without an interaction. Use it around auto-
1257
+ * instrumented calls (an LLM SDK call, a framework invocation) that aren't
1258
+ * wrapped by `begin()`/`finish()` so their spans route to this client's
1259
+ * project in a multi-client process. The binding lasts exactly the duration
1260
+ * of `fn` — it is removed when `fn` returns or throws.
1261
+ *
1262
+ * @example
1263
+ * ```ts
1264
+ * const answer = await raindrop.asCurrent(() => llm.chat({ ... }));
1265
+ * ```
1266
+ */
1267
+ asCurrent<T>(fn: () => T): T;
1268
+ createSpanProcessor(processorOptions?: SpanProcessorOptions): RaindropSpanProcessor;
1269
+ /**
1270
+ * Returns configured instrumentation instances based on instrumentModules.
1271
+ * Add these to your NodeSDK when using useExternalOtel: true.
1272
+ *
1273
+ * @example
1274
+ * ```ts
1275
+ * import { NodeSDK } from "@opentelemetry/sdk-node";
1276
+ * import Anthropic from "@anthropic-ai/sdk";
1277
+ *
1278
+ * const raindrop = new Raindrop({
1279
+ * writeKey: "xxx",
1280
+ * useExternalOtel: true,
1281
+ * instrumentModules: { anthropic: Anthropic },
1282
+ * });
1283
+ *
1284
+ * const sdk = new NodeSDK({
1285
+ * spanProcessors: [raindrop.createSpanProcessor()],
1286
+ * instrumentations: raindrop.getInstrumentations(),
1287
+ * });
1288
+ * sdk.start();
1289
+ * ```
1290
+ */
1291
+ getInstrumentations(): _opentelemetry_instrumentation.Instrumentation<_opentelemetry_instrumentation.InstrumentationConfig>[];
1292
+ /**
1293
+ * Resumes an existing interaction.
1294
+ *
1295
+ * @param eventId - The ID of the interaction to resume.
1296
+ * @returns The interaction object.
1297
+ */
1298
+ resumeInteraction(eventId: string): Interaction;
1299
+ /**
1300
+ * Opens the child's own event for a launched detached sub-agent.
1301
+ *
1302
+ * Sibling to {@link resumeInteraction}, and deliberately not the same thing:
1303
+ * a resumed interaction JOINS the caller's event, while a detached sub-agent
1304
+ * reports as its OWN event under the id the launcher minted, linked back only
1305
+ * by the hand-off attributes both sides write. Every span the run emits
1306
+ * carries the reverse reference until it reports a result.
1307
+ *
1308
+ * Pass the headers the request arrived with. A missing carrier is a
1309
+ * legitimate state — the sub-agent was invoked directly rather than
1310
+ * dispatched — so this always returns a usable run and leaves `parent` null;
1311
+ * call sites stay unconditional. A malformed carrier costs the link, never
1312
+ * the request.
1313
+ *
1314
+ * The carrier is authoritative for every identity field it supplies. The
1315
+ * options are fallbacks for the direct-invocation case, not overrides: each
1316
+ * field names something the launcher already recorded, so a locally minted
1317
+ * value winning would strand the child outside the link.
1318
+ *
1319
+ * > **Trust boundary.** A carrier names the event the child will be
1320
+ * > attributed to, so accepting one from an untrusted caller lets that caller
1321
+ * > write into another tenant's trace. Only read carriers that came from
1322
+ * > inside your own trust boundary.
1323
+ *
1324
+ * @example
1325
+ * ```typescript
1326
+ * const run = raindrop.resumeSubagent(request.headers);
1327
+ * try {
1328
+ * const answer = await doTheWork();
1329
+ * await run.finish({ output: answer });
1330
+ * } catch (error) {
1331
+ * await run.fail(error);
1332
+ * }
1333
+ * ```
1334
+ */
1335
+ resumeSubagent(headers: CarrierHeaders | TraceCarrier | null | undefined, options?: SubagentResumeOptions): SubagentRun;
1336
+ /**
1337
+ * Runs `fn` as a detached sub-agent and guarantees the run reports an
1338
+ * outcome, mirroring the Python SDK's `with rd.resume_subagent(...) as run:`.
1339
+ *
1340
+ * A run that returns without reporting output is closed with an abort reason,
1341
+ * and one that throws is failed with it. That is not cosmetic: an event is
1342
+ * created only from a run with non-empty output, so a child that dies
1343
+ * silently produces no event at all and its launcher stays on `queued`
1344
+ * forever — indistinguishable from a job that never started.
1345
+ *
1346
+ * @example
1347
+ * ```typescript
1348
+ * await raindrop.withSubagentRun(request.headers, async (run) => {
1349
+ * await run.finish({ output: await doTheWork() });
1350
+ * });
1351
+ * ```
1352
+ */
1353
+ withSubagentRun<T>(headers: CarrierHeaders | TraceCarrier | null | undefined, fn: (run: SubagentRun) => Promise<T> | T, options?: SubagentResumeOptions): Promise<T>;
1354
+ /**
1355
+ * Creates a framework-agnostic self-diagnostics tool definition.
1356
+ *
1357
+ * Use this when your agent framework does not support automatic tool injection.
1358
+ * The returned object includes adapters for Vercel AI SDK, OpenAI function tools,
1359
+ * and Anthropic tool definitions.
1360
+ */
1361
+ createSelfDiagnosticsTool(options?: SelfDiagnosticsToolOptions): SelfDiagnosticsTool;
1362
+ /**
1363
+ * Track AI events. In addiiton to normal event properties, you can provide an "input", "output", or "model" parameter.
1364
+ * It takes an AiTrackEvent as input and sends it to the /track-ai endpoint of the raindrop api.
1365
+ *
1366
+ * @param event - The AiTrackEvent (you must specify at least one of input/output properties)
1367
+ * @returns A Promise that resolves when the event has been successfully sent.
1368
+ *
1369
+ * Example usage:
1370
+ * ```typescript
1371
+ * raindrop.track_ai({
1372
+ * event: "chat", //name of the event
1373
+ * model: "claude", //optional
1374
+ * input: "what's up?", // input or output is required
1375
+ * output: "not much human, how are you?", //input or output is required
1376
+ * userId: "cn123456789",
1377
+ * });
1378
+ * ```
1379
+ */
1380
+ trackAi(event: AiTrackEvent | AiTrackEvent[]): string | Array<string | undefined> | undefined;
1381
+ setUserDetails(event: IdentifyEvent): void;
1382
+ /**
1383
+ * Report a self-diagnostic signal. This is a convenient shorthand for sending
1384
+ * signals that appear in the Self Diagnostics tab of the Raindrop dashboard.
1385
+ *
1386
+ * @param options - The diagnostic details.
1387
+ * @param options.eventId - The interaction/event ID this diagnostic belongs to.
1388
+ * @param options.description - A human-readable description of the issue.
1389
+ * @param options.category - Optional category (e.g. "missing_context"). Defaults to "general".
1390
+ * @param options.source - Optional source identifier. Defaults to "selfDiagnose".
1391
+ * @param options.sentiment - Signal sentiment. Defaults to "NEGATIVE".
1392
+ * @param options.properties - Additional custom properties.
1393
+ *
1394
+ * @example
1395
+ * ```typescript
1396
+ * raindrop.selfDiagnose({
1397
+ * eventId: "evt_123",
1398
+ * description: "User asked for production DB access but no credentials were provided.",
1399
+ * category: "missing_context",
1400
+ * });
1401
+ * ```
1402
+ */
1403
+ selfDiagnose(options: SelfDiagnoseOptions): void;
1404
+ trackSignal(signal: SignalEvent | SignalEvent[]): void | void[];
1405
+ private getSize;
1406
+ private saveToBuffer;
1407
+ private flush;
1408
+ private mirrorBatchToLocalDebugger;
1409
+ /**
1410
+ * Attempts/timeout budget for one POST, honoring the close() deadline.
1411
+ * Returns `null` when the shutdown budget is exhausted — the caller must
1412
+ * drop the payload instead of issuing a request that could outlive
1413
+ * process exit. Checked fresh on every send so a deadline that expires
1414
+ * mid-drain takes effect immediately.
1415
+ */
1416
+ private requestBudget;
1417
+ private warnShutdownDrop;
1418
+ private sendBatchToApi;
1419
+ private getContext;
1420
+ private formatZodError;
1421
+ /**
1422
+ * Deeply merges properties of the source object into the target object.
1423
+ * Modifies the target object in place. Handles nested plain objects.
1424
+ */
1425
+ private deepMergeObjects;
1426
+ /**
1427
+ * Internal method for tracking partial AI events. use .begin() to start an interaction instead.
1428
+ *
1429
+ * @param event - The PartialAiTrackEvent, requires eventId.
1430
+ */
1431
+ _trackAiPartial(event: PartialAiTrackEvent): Promise<void>;
1432
+ /**
1433
+ * Flushes a single accumulated partial event by its ID.
1434
+ * This is called internally by the timeout or by the close method.
1435
+ * @param eventId - The ID of the partial event to flush.
1436
+ */
1437
+ private flushPartialEvent;
1438
+ /**
1439
+ * Internal implementation of flushPartialEvent without request tracking.
1440
+ * @param eventId - The ID of the partial event to flush.
1441
+ */
1442
+ private _flushPartialEventInternal;
1443
+ /**
1444
+ * Sends a single prepared event object to the 'events/track_partial' endpoint.
1445
+ * @param event - The event data conforming to ClientAiTrack schema.
1446
+ */
1447
+ private sendPartialEvent;
1448
+ /**
1449
+ * Best-effort flush of in-flight OTel spans and pending partial-event POSTs.
1450
+ * Safe to call multiple times; never throws.
1451
+ */
1452
+ forceFlush(): Promise<void>;
1453
+ close(): Promise<void>;
1454
+ private closeWithinDeadline;
1455
+ }
1456
+
1457
+ export { type AiTrackEvent as A, type BeginInteractionOptions as B, type CarrierHeaders as C, type TraceContext as D, type TrackToolParams as E, type FinishInteractionOptions as F, resolveDisableBatching as G, type Interaction as I, type LocalDebuggerLiveEventInput as L, MAX_INGEST_SIZE_BYTES as M, type PartialAiTrackEvent as P, Raindrop as R, type SubagentResumeOptions as S, type TraceCarrier as T, type WorkflowParams as W, type RaindropSpanProcessor as a, type SubagentRun as b, type Tracer as c, type Attachment as d, type AttachmentType as e, type IdentifyEvent as f, type RaindropFeatureFlagValue as g, type RaindropFeatureFlags as h, type RaindropProperties as i, type RaindropPropertyLeaf as j, type RaindropPropertyValue as k, type SelfDiagnoseOptions as l, type SelfDiagnosticsExecuteContext as m, type SelfDiagnosticsExecuteResult as n, type SelfDiagnosticsSignalDefinition as o, type SelfDiagnosticsSignalDefinitions as p, type SelfDiagnosticsTool as q, type SelfDiagnosticsToolInputSchema as r, type SelfDiagnosticsToolOptions as s, type SignalEvent as t, type SpanParams as u, type SubagentDispatch as v, type SubagentDispatchOptions as w, type SubagentFinishOptions as x, type ToolParams as y, type ToolSpan as z };