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.
@@ -42,7 +42,7 @@ if (!globalThis.RAINDROP_ASYNC_LOCAL_STORAGE) {
42
42
  }
43
43
 
44
44
  // src/tracing/tracer-core.ts
45
- var import_api4 = require("@opentelemetry/api");
45
+ var import_api5 = require("@opentelemetry/api");
46
46
  var import_exporter_trace_otlp_http = require("@opentelemetry/exporter-trace-otlp-http");
47
47
  var import_instrumentation_anthropic = require("@traceloop/instrumentation-anthropic");
48
48
  var import_instrumentation_bedrock = require("@traceloop/instrumentation-bedrock");
@@ -56,7 +56,7 @@ var import_instrumentation_vertexai = require("@traceloop/instrumentation-vertex
56
56
  var traceloop4 = __toESM(require("@traceloop/node-server-sdk"));
57
57
  var import_weakref = require("weakref");
58
58
 
59
- // ../core/dist/chunk-QTUH3BHZ.js
59
+ // ../core/dist/chunk-YUIXRQWN.js
60
60
  function normalizeFeatureFlags(input) {
61
61
  if (Array.isArray(input)) {
62
62
  return Object.fromEntries(input.map((name) => [name, "true"]));
@@ -65,6 +65,293 @@ function normalizeFeatureFlags(input) {
65
65
  Object.entries(input).map(([k, v]) => [k, String(v)])
66
66
  );
67
67
  }
68
+ function getCrypto() {
69
+ const c = globalThis.crypto;
70
+ return c;
71
+ }
72
+ function randomBytes(length) {
73
+ const cryptoObj = getCrypto();
74
+ const out = new Uint8Array(length);
75
+ if (cryptoObj && typeof cryptoObj.getRandomValues === "function") {
76
+ cryptoObj.getRandomValues(out);
77
+ return out;
78
+ }
79
+ for (let i = 0; i < out.length; i++) out[i] = Math.floor(Math.random() * 256);
80
+ return out;
81
+ }
82
+ function randomUUID() {
83
+ const cryptoObj = getCrypto();
84
+ if (cryptoObj && typeof cryptoObj.randomUUID === "function") {
85
+ return cryptoObj.randomUUID();
86
+ }
87
+ const b = randomBytes(16);
88
+ b[6] = b[6] & 15 | 64;
89
+ b[8] = b[8] & 63 | 128;
90
+ const hex = [...b].map((x) => x.toString(16).padStart(2, "0")).join("");
91
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
92
+ }
93
+ var HANDOFF_ATTRIBUTE_SUFFIXES = {
94
+ mode: "raindrop.handoff.mode",
95
+ childEventId: "raindrop.handoff.childEventId",
96
+ parentEventId: "raindrop.handoff.parentEventId",
97
+ parentSpanId: "raindrop.handoff.parentSpanId",
98
+ name: "raindrop.handoff.name",
99
+ terminal: "raindrop.handoff.terminal",
100
+ agentRole: "raindrop.agent.role"
101
+ };
102
+ var AI_SDK_METADATA_PREFIX = "ai.telemetry.metadata.";
103
+ var DETACHED_MODE = "detached";
104
+ var SUBAGENT_AGENT_ROLE = "subagent";
105
+ var HANDOFF_TERMINAL_CANCELLED = "cancelled";
106
+ var TOOL_EVENTS_SUFFIX = "raindrop.toolEvents";
107
+ var TOOL_EVENTS_ALLOW = "allow";
108
+ var OPERATION_ID_ATTRIBUTE = "ai.operationId";
109
+ var SUBAGENT_ABORT_OPERATION_ID = "ai.subagent.failed";
110
+ var SUBAGENT_ABORT_SPAN_NAME = SUBAGENT_ABORT_OPERATION_ID;
111
+ var DEFAULT_DISPATCH_SPAN_NAME = "launch_subagent";
112
+ var HANDOFF_TERMINAL_PROPERTY_KEY = HANDOFF_ATTRIBUTE_SUFFIXES.terminal;
113
+ function defined(entries) {
114
+ const out = {};
115
+ for (const [key, value] of Object.entries(entries)) {
116
+ if (typeof value === "string" && value.trim().length > 0) out[key] = value;
117
+ }
118
+ return out;
119
+ }
120
+ function detachedDispatchMetadata(dispatch) {
121
+ return defined({
122
+ [HANDOFF_ATTRIBUTE_SUFFIXES.mode]: DETACHED_MODE,
123
+ [HANDOFF_ATTRIBUTE_SUFFIXES.childEventId]: dispatch.childEventId,
124
+ [HANDOFF_ATTRIBUTE_SUFFIXES.name]: dispatch.name
125
+ });
126
+ }
127
+ function detachedChildMetadata(link) {
128
+ return defined({
129
+ [HANDOFF_ATTRIBUTE_SUFFIXES.parentEventId]: link.parentEventId,
130
+ [HANDOFF_ATTRIBUTE_SUFFIXES.parentSpanId]: link.parentSpanId,
131
+ [HANDOFF_ATTRIBUTE_SUFFIXES.name]: link.name,
132
+ [HANDOFF_ATTRIBUTE_SUFFIXES.agentRole]: SUBAGENT_AGENT_ROLE
133
+ });
134
+ }
135
+ function cancelledTerminalMetadata() {
136
+ return { [HANDOFF_ATTRIBUTE_SUFFIXES.terminal]: HANDOFF_TERMINAL_CANCELLED };
137
+ }
138
+ function cancelledTerminalAttributes() {
139
+ const bare = cancelledTerminalMetadata();
140
+ return { ...bare, ...withMetadataPrefix(bare) };
141
+ }
142
+ function toolEventsAllowMetadata() {
143
+ return { [TOOL_EVENTS_SUFFIX]: TOOL_EVENTS_ALLOW };
144
+ }
145
+ function withMetadataPrefix(metadata) {
146
+ const out = {};
147
+ for (const [key, value] of Object.entries(metadata)) {
148
+ out[key.startsWith(AI_SDK_METADATA_PREFIX) ? key : `${AI_SDK_METADATA_PREFIX}${key}`] = value;
149
+ }
150
+ return out;
151
+ }
152
+ var BAGGAGE_KEYS = {
153
+ eventId: "raindrop-event-id",
154
+ childEventId: "raindrop-child-event-id",
155
+ name: "raindrop-handoff-name",
156
+ convoId: "raindrop-convo-id",
157
+ userId: "raindrop-user-id",
158
+ // The dispatch span and its trace, carried as fields as well as in
159
+ // `traceparent`. Not redundant: OTel's HTTP instrumentations rewrite
160
+ // `traceparent` from whatever span is current as the request goes out, so by
161
+ // the time the child reads it the ids name the HTTP client span and its trace
162
+ // instead of the dispatch. The child would then point its reverse reference at
163
+ // a span the launcher's UI does not know as a dispatch. A field states which
164
+ // span it means rather than meaning "whoever wrote this header last".
165
+ dispatchSpanId: "raindrop-dispatch-span-id",
166
+ traceId: "raindrop-trace-id"
167
+ };
168
+ var TRACEPARENT_HEADER = "traceparent";
169
+ var BAGGAGE_HEADER = "baggage";
170
+ var W3C_TRACE_ID = /^[0-9a-f]{32}$/;
171
+ var W3C_SPAN_ID = /^[0-9a-f]{16}$/;
172
+ function isW3CTraceId(value) {
173
+ return value !== void 0 && W3C_TRACE_ID.test(value);
174
+ }
175
+ function isW3CSpanId(value) {
176
+ return value !== void 0 && W3C_SPAN_ID.test(value);
177
+ }
178
+ var warnedNonConformantIds = false;
179
+ function warnNonConformantIdsOnce(traceId, spanId) {
180
+ if (warnedNonConformantIds) return;
181
+ warnedNonConformantIds = true;
182
+ console.warn(
183
+ `[raindrop] hand-off carrier ids are not W3C-shaped (traceId="${traceId}", spanId="${spanId}"). The child still reports as its own event, but its reverse reference names a span id the backend does not store, so the link back to the launcher will not resolve. A LangSmith carrier reads this way \u2014 its run ids are UUIDs; propagate Raindrop's own carrier (toHeaders) to link.`
184
+ );
185
+ }
186
+ var HANDOFF_HEADER = "x-raindrop-handoff";
187
+ var LANGSMITH_TRACE_HEADER = "langsmith-trace";
188
+ var LANGSMITH_METADATA_BAGGAGE_KEY = "langsmith-metadata";
189
+ function encodeBaggage(entries) {
190
+ return Object.entries(entries).filter((entry) => Boolean(entry[1])).map(([key, value]) => `${key}=${encodeURIComponent(value)}`).join(",");
191
+ }
192
+ function decodeBaggage(header) {
193
+ if (!header) return {};
194
+ const parsed = {};
195
+ for (const part of header.split(",")) {
196
+ const [rawKey, ...rest] = part.split("=");
197
+ if (!rawKey || rest.length === 0) continue;
198
+ const key = rawKey.trim();
199
+ let value;
200
+ try {
201
+ value = decodeURIComponent(rest.join("=").trim());
202
+ } catch (e) {
203
+ value = rest.join("=").trim();
204
+ }
205
+ if (key in parsed && parsed[key] !== value) throw new ConflictingCarrierError(key);
206
+ parsed[key] = value;
207
+ }
208
+ return parsed;
209
+ }
210
+ function carrierBaggage(carrier) {
211
+ return {
212
+ [BAGGAGE_KEYS.eventId]: carrier.eventId,
213
+ [BAGGAGE_KEYS.childEventId]: carrier.childEventId,
214
+ [BAGGAGE_KEYS.name]: carrier.name,
215
+ [BAGGAGE_KEYS.convoId]: carrier.convoId,
216
+ [BAGGAGE_KEYS.userId]: carrier.userId,
217
+ [BAGGAGE_KEYS.dispatchSpanId]: carrier.spanId,
218
+ [BAGGAGE_KEYS.traceId]: carrier.traceId
219
+ };
220
+ }
221
+ function toHeaders(carrier) {
222
+ const fields = encodeBaggage(carrierBaggage(carrier));
223
+ const headers = {
224
+ [BAGGAGE_HEADER]: fields,
225
+ [HANDOFF_HEADER]: fields
226
+ };
227
+ if (isW3CTraceId(carrier.traceId) && isW3CSpanId(carrier.spanId)) {
228
+ headers[TRACEPARENT_HEADER] = `00-${carrier.traceId}-${carrier.spanId}-01`;
229
+ }
230
+ return headers;
231
+ }
232
+ function langsmithStamp() {
233
+ return (/* @__PURE__ */ new Date()).toISOString().replace(/[-:]/g, "").replace(/\.\d+Z$/, "000000");
234
+ }
235
+ function toLangSmithHeaders(carrier) {
236
+ const stamp = langsmithStamp();
237
+ const dottedOrder = `${stamp}Z${carrier.traceId}.${stamp}Z${carrier.spanId}`;
238
+ return {
239
+ [LANGSMITH_TRACE_HEADER]: dottedOrder,
240
+ [BAGGAGE_HEADER]: encodeBaggage({
241
+ [LANGSMITH_METADATA_BAGGAGE_KEY]: JSON.stringify(carrierBaggage(carrier))
242
+ }),
243
+ // Carried here too: a LangSmith-shaped carrier is rewritten in transit
244
+ // exactly like the native one, and an injected `traceparent` is preferred
245
+ // over the dotted order on read.
246
+ [HANDOFF_HEADER]: encodeBaggage(carrierBaggage(carrier))
247
+ };
248
+ }
249
+ function isHeaderLookup(headers) {
250
+ return "get" in headers && typeof headers.get === "function";
251
+ }
252
+ var ConflictingCarrierError = class extends Error {
253
+ };
254
+ function readHeader(headers, name) {
255
+ var _a, _b, _c;
256
+ if (isHeaderLookup(headers)) return (_a = headers.get(name)) != null ? _a : void 0;
257
+ const value = (_c = headers[name]) != null ? _c : (_b = Object.entries(headers).find(([key]) => key.toLowerCase() === name)) == null ? void 0 : _b[1];
258
+ if (!Array.isArray(value)) return value;
259
+ const distinct = new Set(value);
260
+ if (distinct.size > 1) throw new ConflictingCarrierError(name);
261
+ return value[0];
262
+ }
263
+ function readTraceHeader(headers, name) {
264
+ const value = readHeader(headers, name);
265
+ if (!(value == null ? void 0 : value.includes(","))) return value;
266
+ const copies = value.split(",").map((copy) => copy.trim());
267
+ if (new Set(copies).size > 1) throw new ConflictingCarrierError(name);
268
+ return copies[0];
269
+ }
270
+ function fromHeaders(headers) {
271
+ var _a, _b;
272
+ let baggage;
273
+ let handoff;
274
+ let traceparent;
275
+ let langsmithTrace;
276
+ try {
277
+ baggage = decodeBaggage(readHeader(headers, BAGGAGE_HEADER));
278
+ handoff = decodeBaggage(readHeader(headers, HANDOFF_HEADER));
279
+ traceparent = readTraceHeader(headers, TRACEPARENT_HEADER);
280
+ langsmithTrace = readTraceHeader(headers, LANGSMITH_TRACE_HEADER);
281
+ } catch (error) {
282
+ if (error instanceof ConflictingCarrierError) return null;
283
+ throw error;
284
+ }
285
+ const langsmithMetadata = baggage[LANGSMITH_METADATA_BAGGAGE_KEY];
286
+ const nested = langsmithMetadata ? safeParseStringRecord(langsmithMetadata) : {};
287
+ for (const [key, value] of Object.entries(nested)) {
288
+ if (key in baggage && baggage[key] !== value) return null;
289
+ }
290
+ const fields = {
291
+ ...baggage,
292
+ ...nested,
293
+ // Last, so it wins: the standard headers may have been rewritten in transit
294
+ // by a propagator, this one is only ever written by us.
295
+ ...handoff
296
+ };
297
+ let traceId;
298
+ let spanId;
299
+ if (traceparent) {
300
+ const [, parsedTraceId, parsedSpanId] = traceparent.split("-");
301
+ if (isW3CTraceId(parsedTraceId) && isW3CSpanId(parsedSpanId)) {
302
+ traceId = parsedTraceId;
303
+ spanId = parsedSpanId;
304
+ }
305
+ }
306
+ if (!traceId && !spanId && langsmithTrace) {
307
+ const segments = langsmithTrace.split(".");
308
+ traceId = (_a = segments[0]) == null ? void 0 : _a.split("Z").pop();
309
+ spanId = (_b = segments[segments.length - 1]) == null ? void 0 : _b.split("Z").pop();
310
+ }
311
+ traceId = fields[BAGGAGE_KEYS.traceId] || traceId;
312
+ spanId = fields[BAGGAGE_KEYS.dispatchSpanId] || spanId;
313
+ const eventId = fields[BAGGAGE_KEYS.eventId];
314
+ if (!traceId || !spanId || !eventId) return null;
315
+ if (!isW3CTraceId(traceId) || !isW3CSpanId(spanId)) {
316
+ warnNonConformantIdsOnce(traceId, spanId);
317
+ }
318
+ const carrier = { traceId, spanId, eventId };
319
+ const childEventId = fields[BAGGAGE_KEYS.childEventId];
320
+ if (childEventId) carrier.childEventId = childEventId;
321
+ const name = fields[BAGGAGE_KEYS.name];
322
+ if (name) carrier.name = name;
323
+ const convoId = fields[BAGGAGE_KEYS.convoId];
324
+ if (convoId) carrier.convoId = convoId;
325
+ const userId = fields[BAGGAGE_KEYS.userId];
326
+ if (userId) carrier.userId = userId;
327
+ return carrier;
328
+ }
329
+ var UNRESOLVED_CARRIER_WARNING = `[raindrop] resume: headers were supplied but no hand-off carrier was found on them (searched ${HANDOFF_HEADER}, ${TRACEPARENT_HEADER}, ${BAGGAGE_HEADER}). This run reports as an UNLINKED event, and the launcher that dispatched it will stay on "queued" forever because nothing ever references its child. Passing headers means a parent handed off, so no carrier on them is almost certainly a defect: a gateway or proxy stripping ${HANDOFF_HEADER}, a middleware overwriting ${BAGGAGE_HEADER}, a request forwarded without its headers, or a hand-built carrier whose field names do not match. Send every header the launcher's dispatch returned. Logged once per process; pass no headers for a directly-invoked sub-agent to silence it.`;
330
+ var UNRESOLVED_CARRIER_WARNED_KEY = /* @__PURE__ */ Symbol.for("raindrop.handoff.warnedUnresolvedCarrier");
331
+ function warnedHolder() {
332
+ return globalThis;
333
+ }
334
+ function warnUnresolvedCarrier(headers, carrier) {
335
+ if (carrier) return;
336
+ if (!headers) return;
337
+ const holder = warnedHolder();
338
+ if (holder[UNRESOLVED_CARRIER_WARNED_KEY]) return;
339
+ holder[UNRESOLVED_CARRIER_WARNED_KEY] = true;
340
+ console.warn(UNRESOLVED_CARRIER_WARNING);
341
+ }
342
+ function safeParseStringRecord(raw) {
343
+ try {
344
+ const parsed = JSON.parse(raw);
345
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return {};
346
+ const result = {};
347
+ for (const [key, value] of Object.entries(parsed)) {
348
+ if (typeof value === "string") result[key] = value;
349
+ }
350
+ return result;
351
+ } catch (e) {
352
+ return {};
353
+ }
354
+ }
68
355
  function runWithTracingSuppressed(fn) {
69
356
  const hook = globalThis.RAINDROP_SUPPRESS_TRACING;
70
357
  if (typeof hook !== "function") return fn();
@@ -408,6 +695,62 @@ function projectIdHeaders(projectId) {
408
695
  }
409
696
  var SHUTDOWN_DEADLINE_MS = 1e4;
410
697
  var POST_SHUTDOWN_TIMEOUT_MS = 5e3;
698
+ var MODEL_USAGE_ATTRIBUTES = {
699
+ providerName: "gen_ai.provider.name",
700
+ requestModel: "gen_ai.request.model",
701
+ responseModel: "gen_ai.response.model",
702
+ inputTokens: "gen_ai.usage.input_tokens",
703
+ outputTokens: "gen_ai.usage.output_tokens",
704
+ reasoningTokens: "gen_ai.usage.reasoning_tokens",
705
+ cacheReadInputTokens: "gen_ai.usage.cache_read_input_tokens",
706
+ cacheWriteInputTokens: "gen_ai.usage.cache_write_input_tokens",
707
+ nonCachedInputTokens: "raindrop.usage.input_tokens.non_cached",
708
+ nonReasoningOutputTokens: "raindrop.usage.output_tokens.non_reasoning",
709
+ totalOutputTokens: "raindrop.usage.output_tokens.total",
710
+ reasoningOutputTokens: "raindrop.usage.output_tokens.reasoning",
711
+ cacheReadTokens: "raindrop.usage.input_tokens.cache_read",
712
+ cacheWriteTokens: "raindrop.usage.input_tokens.cache_write"
713
+ };
714
+ var STRING_ALIASES = {
715
+ [MODEL_USAGE_ATTRIBUTES.requestModel]: ["ai.model.id", "ai.model"]
716
+ };
717
+ var NUMBER_ALIASES = {
718
+ [MODEL_USAGE_ATTRIBUTES.inputTokens]: [
719
+ "gen_ai.usage.prompt_tokens",
720
+ "ai.usage.prompt_tokens",
721
+ "ai.usage.promptTokens",
722
+ "ai.usage.input_tokens",
723
+ "ai.usage.inputTokens"
724
+ ],
725
+ [MODEL_USAGE_ATTRIBUTES.outputTokens]: [
726
+ "gen_ai.usage.completion_tokens",
727
+ "ai.usage.completion_tokens",
728
+ "ai.usage.completionTokens",
729
+ "ai.usage.output_tokens",
730
+ "ai.usage.outputTokens"
731
+ ],
732
+ [MODEL_USAGE_ATTRIBUTES.reasoningTokens]: [
733
+ "gen_ai.usage.reasoning.output_tokens",
734
+ "ai.usage.reasoningTokens",
735
+ "ai.usage.thoughts_tokens"
736
+ ],
737
+ [MODEL_USAGE_ATTRIBUTES.cacheReadInputTokens]: [
738
+ "gen_ai.usage.cache_read_tokens",
739
+ "gen_ai.usage.cache_read.input_tokens",
740
+ "ai.usage.cachedInputTokens",
741
+ "ai.usage.cached_tokens",
742
+ "ai.usage.cache_read_tokens",
743
+ "ai.usage.cache_read_input_tokens",
744
+ "ai.usage.cacheReadInputTokens"
745
+ ],
746
+ [MODEL_USAGE_ATTRIBUTES.cacheWriteInputTokens]: [
747
+ "gen_ai.usage.cache_creation_input_tokens",
748
+ "gen_ai.usage.cache_creation.input_tokens",
749
+ "ai.usage.cacheWriteInputTokens",
750
+ "ai.usage.cache_creation_input_tokens",
751
+ "ai.usage.cacheCreationInputTokens"
752
+ ]
753
+ };
411
754
  var DEFAULT_REDACT_ATTRIBUTE_KEYS = [
412
755
  "ai.request.providerOptions",
413
756
  "ai.response.providerMetadata"
@@ -422,8 +765,10 @@ function getWeakRefCtor() {
422
765
  }
423
766
  var MAX_BINDING_STACK = 128;
424
767
  var EMPTY_STACK = [];
425
- var RoutingContextStorage = class {
426
- constructor() {
768
+ var ContextStackStorage = class {
769
+ /** Emitted once when this runtime cannot support an ambient push. */
770
+ constructor(noAmbientBindWarning) {
771
+ this.noAmbientBindWarning = noAmbientBindWarning;
427
772
  this._als = null;
428
773
  this._enterWithUsable = false;
429
774
  this._syncStack = EMPTY_STACK;
@@ -520,17 +865,17 @@ var RoutingContextStorage = class {
520
865
  warnNoAmbientBindOnce() {
521
866
  if (this._warnedNoAmbientBind) return;
522
867
  this._warnedNoAmbientBind = true;
523
- console.warn(
524
- "[raindrop] This runtime's AsyncLocalStorage does not implement enterWith (e.g. Cloudflare Workers), so begin()/finish() cannot scope auto-instrumented spans to a project without cross-contaminating concurrent requests. Manual events and explicit span routing are unaffected; use asCurrent()/withSpan (run-based) to route auto-instrumented spans on this runtime."
525
- );
868
+ console.warn(this.noAmbientBindWarning);
526
869
  }
527
870
  };
871
+ var NO_AMBIENT_ROUTING_BIND_WARNING = "[raindrop] This runtime's AsyncLocalStorage does not implement enterWith (e.g. Cloudflare Workers), so begin()/finish() cannot scope auto-instrumented spans to a project without cross-contaminating concurrent requests. Manual events and explicit span routing are unaffected; use asCurrent()/withSpan (run-based) to route auto-instrumented spans on this runtime.";
872
+ var NO_AMBIENT_ATTRIBUTE_BIND_WARNING = "[raindrop] This runtime's AsyncLocalStorage does not implement enterWith (e.g. Cloudflare Workers), so contextual span attributes (the detached sub-agent hand-off reference) cannot be bound ambiently without cross-contaminating concurrent requests. The child's own event still reports; only the per-span reverse reference is skipped.";
528
873
  var ROUTING_STORAGE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.routingContextStorage");
529
874
  function routingStorage() {
530
875
  const holder = globalThis;
531
876
  let storage = holder[ROUTING_STORAGE_KEY];
532
877
  if (!storage) {
533
- storage = new RoutingContextStorage();
878
+ storage = new ContextStackStorage(NO_AMBIENT_ROUTING_BIND_WARNING);
534
879
  holder[ROUTING_STORAGE_KEY] = storage;
535
880
  }
536
881
  return storage;
@@ -578,6 +923,104 @@ function currentRoutingBinding() {
578
923
  function isBoundContext(value) {
579
924
  return typeof value.isLive === "function";
580
925
  }
926
+ var ATTRIBUTE_STORAGE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.spanAttributeStorage");
927
+ function attributeStorage() {
928
+ const holder = globalThis;
929
+ let storage = holder[ATTRIBUTE_STORAGE_KEY];
930
+ if (!storage) {
931
+ storage = new ContextStackStorage(NO_AMBIENT_ATTRIBUTE_BIND_WARNING);
932
+ holder[ATTRIBUTE_STORAGE_KEY] = storage;
933
+ }
934
+ return storage;
935
+ }
936
+ function makeAttributeFrame(attributes, owner) {
937
+ const snapshot = { ...attributes };
938
+ const WeakRefCtor = owner !== void 0 ? getWeakRefCtor() : void 0;
939
+ const ref = WeakRefCtor && owner !== void 0 ? new WeakRefCtor(owner) : void 0;
940
+ const owned = /* @__PURE__ */ new WeakSet();
941
+ let dead = false;
942
+ let sawError = false;
943
+ return {
944
+ attributes: snapshot,
945
+ sawErrorSpan: () => sawError,
946
+ ownsSpan: (span) => owned.has(span),
947
+ claimSpan(span) {
948
+ owned.add(span);
949
+ },
950
+ markErrorSpanSeen() {
951
+ sawError = true;
952
+ },
953
+ // A frame whose owner has been collected is dead even though nothing
954
+ // unbound it: a run that never settles must not keep handing its reverse
955
+ // reference to whatever runs next on a reused context.
956
+ isLive() {
957
+ if (dead) return false;
958
+ return ref === void 0 || ref.deref() !== void 0;
959
+ },
960
+ markDead() {
961
+ dead = true;
962
+ }
963
+ };
964
+ }
965
+ function bindSpanAttributes(attributes, owner) {
966
+ if (Object.keys(attributes).length === 0) return void 0;
967
+ const frame = makeAttributeFrame(attributes, owner);
968
+ try {
969
+ attributeStorage().push(frame);
970
+ } catch (e) {
971
+ return void 0;
972
+ }
973
+ return frame;
974
+ }
975
+ function unbindSpanAttributes(frame) {
976
+ if (!frame || !isAttributeFrame(frame)) return;
977
+ try {
978
+ attributeStorage().remove(frame);
979
+ } catch (e) {
980
+ }
981
+ }
982
+ function applySpanAttributeFrames(span, setAttribute) {
983
+ try {
984
+ for (const frame of attributeStorage().getStack()) {
985
+ if (!frame.isLive()) continue;
986
+ frame.claimSpan(span);
987
+ for (const [key, value] of Object.entries(frame.attributes)) {
988
+ setAttribute(key, value);
989
+ }
990
+ }
991
+ } catch (e) {
992
+ }
993
+ }
994
+ function claimSpanForFrames(span) {
995
+ try {
996
+ for (const frame of attributeStorage().getStack()) {
997
+ if (frame.isLive()) frame.claimSpan(span);
998
+ }
999
+ } catch (e) {
1000
+ }
1001
+ }
1002
+ function currentSpanAttributes() {
1003
+ const merged = {};
1004
+ try {
1005
+ for (const frame of attributeStorage().getStack()) {
1006
+ if (!frame.isLive()) continue;
1007
+ Object.assign(merged, frame.attributes);
1008
+ }
1009
+ } catch (e) {
1010
+ }
1011
+ return merged;
1012
+ }
1013
+ function markErrorSpanSeen(span) {
1014
+ try {
1015
+ for (const frame of attributeStorage().getStack()) {
1016
+ if (frame.ownsSpan(span)) frame.markErrorSpanSeen();
1017
+ }
1018
+ } catch (e) {
1019
+ }
1020
+ }
1021
+ function isAttributeFrame(value) {
1022
+ return typeof value.isLive === "function";
1023
+ }
581
1024
 
582
1025
  // ../core/dist/index.node.js
583
1026
  var import_async_hooks = require("async_hooks");
@@ -701,12 +1144,12 @@ async function postJson2(url, body, headers, opts) {
701
1144
  }
702
1145
 
703
1146
  // src/tracing/direct/ids.ts
704
- function getCrypto() {
1147
+ function getCrypto2() {
705
1148
  const c = globalThis.crypto;
706
1149
  return c;
707
1150
  }
708
1151
  function randomBytes2(length) {
709
- const cryptoObj = getCrypto();
1152
+ const cryptoObj = getCrypto2();
710
1153
  const out = new Uint8Array(length);
711
1154
  if (cryptoObj && typeof cryptoObj.getRandomValues === "function") {
712
1155
  cryptoObj.getRandomValues(out);
@@ -744,7 +1187,7 @@ function base64Encode2(bytes) {
744
1187
  }
745
1188
  return out;
746
1189
  }
747
- function base64ToHex(base64) {
1190
+ function base64ToHex2(base64) {
748
1191
  const maybeBuffer = globalThis.Buffer;
749
1192
  if (maybeBuffer) {
750
1193
  return maybeBuffer.from(base64, "base64").toString("hex");
@@ -764,7 +1207,7 @@ function base64ToHex(base64) {
764
1207
  // package.json
765
1208
  var package_default = {
766
1209
  name: "raindrop-ai",
767
- version: "0.2.4",
1210
+ version: "0.3.0",
768
1211
  main: "dist/index.js",
769
1212
  module: "dist/index.mjs",
770
1213
  types: "dist/index.d.ts",
@@ -961,6 +1404,7 @@ var PROJECT_ID_SPAN_ATTRIBUTE = "raindrop.project_id";
961
1404
  var AUTH_HINT_SPAN_ATTRIBUTE = "raindrop.auth_hint";
962
1405
  var EXPORT_SUCCESS = 0;
963
1406
  var EXPORT_FAILED = 1;
1407
+ var SPAN_STATUS_ERROR = 2;
964
1408
  function authHintForKey(writeKey) {
965
1409
  if (!writeKey) return void 0;
966
1410
  return (0, import_node_crypto.createHash)("sha256").update(writeKey, "utf8").digest("hex").slice(0, 8);
@@ -1023,16 +1467,29 @@ function stampSpan(span, projectId, authHint) {
1023
1467
  } catch (e) {
1024
1468
  }
1025
1469
  }
1470
+ function stampContextAttributes(span) {
1471
+ try {
1472
+ applySpanAttributeFrames(span, (key, value) => span.setAttribute(key, value));
1473
+ } catch (e) {
1474
+ }
1475
+ }
1026
1476
  var RaindropContextSpanProcessor = class {
1027
1477
  onStart(span) {
1028
1478
  try {
1479
+ stampContextAttributes(span);
1029
1480
  const bound = currentRoutingBinding();
1030
1481
  if (!bound) return;
1031
1482
  stampSpan(span, bound.projectId, bound.authHint);
1032
1483
  } catch (e) {
1033
1484
  }
1034
1485
  }
1035
- onEnd() {
1486
+ onEnd(span) {
1487
+ var _a;
1488
+ try {
1489
+ if (((_a = span == null ? void 0 : span.status) == null ? void 0 : _a.code) !== SPAN_STATUS_ERROR) return;
1490
+ markErrorSpanSeen(span);
1491
+ } catch (e) {
1492
+ }
1036
1493
  }
1037
1494
  async forceFlush() {
1038
1495
  }
@@ -1211,9 +1668,18 @@ var DirectTraceShipper = class {
1211
1668
  attrString2(`traceloop.association.properties.${key}`, serializeAssociationValue(value))
1212
1669
  );
1213
1670
  }
1671
+ const spanIdentity = { spanIdB64 };
1672
+ claimSpanForFrames(spanIdentity);
1673
+ for (const [key, value] of Object.entries({
1674
+ ...currentSpanAttributes(),
1675
+ ...params.attributes
1676
+ })) {
1677
+ attributes.push(attrString2(key, value));
1678
+ }
1214
1679
  let status;
1215
1680
  if (params.error) {
1216
1681
  status = { code: 2, message: params.error };
1682
+ markErrorSpanSeen(spanIdentity);
1217
1683
  } else {
1218
1684
  status = {
1219
1685
  code: 1
@@ -1362,18 +1828,305 @@ var DirectTraceShipper = class {
1362
1828
  };
1363
1829
 
1364
1830
  // src/tracing/liveInteraction.ts
1365
- var import_api2 = require("@opentelemetry/api");
1831
+ var import_api3 = require("@opentelemetry/api");
1366
1832
  var traceloop = __toESM(require("@traceloop/node-server-sdk"));
1367
- function getPropertiesFromContext(context5) {
1833
+
1834
+ // src/tracing/subagents.ts
1835
+ var import_api2 = require("@opentelemetry/api");
1836
+ var DEFAULT_SUBAGENT_NAME = "subagent";
1837
+ var DISPATCH_ACCEPTED = "accepted";
1838
+ function reasonText(reason) {
1839
+ var _a;
1840
+ if (reason instanceof Error) return `${reason.name}: ${reason.message}`;
1841
+ if (typeof reason === "string") return reason;
1842
+ if (reason === void 0 || reason === null) return "";
1843
+ try {
1844
+ return (_a = JSON.stringify(reason)) != null ? _a : String(reason);
1845
+ } catch (e) {
1846
+ return String(reason);
1847
+ }
1848
+ }
1849
+ function stampCurrentSpan(attributes) {
1850
+ try {
1851
+ const span = import_api2.trace.getSpan(import_api2.context.active());
1852
+ if (!(span == null ? void 0 : span.isRecording())) return;
1853
+ for (const [key, value] of Object.entries(attributes)) {
1854
+ span.setAttribute(key, value);
1855
+ }
1856
+ } catch (e) {
1857
+ }
1858
+ }
1859
+ function stampOwnSpan(attributes, frame) {
1860
+ if (!frame) return;
1861
+ try {
1862
+ const span = import_api2.trace.getSpan(import_api2.context.active());
1863
+ if (!(span == null ? void 0 : span.isRecording()) || !frame.ownsSpan(span)) return;
1864
+ for (const [key, value] of Object.entries(attributes)) {
1865
+ span.setAttribute(key, value);
1866
+ }
1867
+ } catch (e) {
1868
+ }
1869
+ }
1870
+ function failOwnSpan(reason, frame) {
1871
+ try {
1872
+ const span = import_api2.trace.getSpan(import_api2.context.active());
1873
+ if (!(span == null ? void 0 : span.isRecording())) return false;
1874
+ if (!(frame == null ? void 0 : frame.ownsSpan(span))) return false;
1875
+ const message = reasonText(reason);
1876
+ span.setStatus({ code: import_api2.SpanStatusCode.ERROR, message });
1877
+ span.recordException(reason instanceof Error ? reason : new Error(message));
1878
+ return true;
1879
+ } catch (e) {
1880
+ return false;
1881
+ }
1882
+ }
1883
+ function allowToolEvents(interaction) {
1884
+ const attributes = withMetadataPrefix(toolEventsAllowMetadata());
1885
+ interaction.bindToolEventsOptIn(attributes);
1886
+ stampCurrentSpan(attributes);
1887
+ }
1888
+ function recordSubagentDispatch(interaction, options) {
1889
+ var _a;
1890
+ const childEventId = options.childEventId || randomUUID();
1891
+ const name = options.name || DEFAULT_SUBAGENT_NAME;
1892
+ const parentEventId = (_a = interaction.getEventId()) != null ? _a : "";
1893
+ let traceIdHex;
1894
+ let dispatchSpanId;
1895
+ try {
1896
+ allowToolEvents(interaction);
1897
+ const recorded = interaction.recordDispatchSpan({
1898
+ name: options.toolName || DEFAULT_DISPATCH_SPAN_NAME,
1899
+ input: options.input,
1900
+ // A launch's "result" is the job handle; the answer belongs to the
1901
+ // child's event and never appears here.
1902
+ output: { jobId: childEventId, status: DISPATCH_ACCEPTED },
1903
+ properties: options.properties,
1904
+ attributes: detachedDispatchMetadata({ childEventId, name })
1905
+ });
1906
+ traceIdHex = recorded.traceIdHex;
1907
+ dispatchSpanId = recorded.spanIdHex;
1908
+ if (!dispatchSpanId) {
1909
+ console.warn(
1910
+ `[raindrop] subagent(${name}): no dispatch span was recorded, so event ${parentEventId} will not show the launch and NO carrier is returned \u2014 there is no span for the child to reference. Pass childEventId (${childEventId}) to the worker yourself if it must still report under that id. Tracing must be enabled for dispatches to be recorded.`
1911
+ );
1912
+ }
1913
+ } catch (error) {
1914
+ console.warn(
1915
+ `[raindrop] subagent(${name}) failed to record the dispatch; returning a carrier so the child still links back.`,
1916
+ error instanceof Error ? error.message : error
1917
+ );
1918
+ }
1919
+ if (!traceIdHex || !dispatchSpanId) {
1920
+ return {
1921
+ childEventId,
1922
+ name,
1923
+ parentEventId,
1924
+ dispatchSpanId: void 0,
1925
+ carrier: null,
1926
+ headers: {},
1927
+ langsmithHeaders: {}
1928
+ };
1929
+ }
1930
+ const carrier = {
1931
+ traceId: traceIdHex,
1932
+ spanId: dispatchSpanId,
1933
+ eventId: parentEventId,
1934
+ childEventId,
1935
+ name,
1936
+ ...interaction.getConvoId() ? { convoId: interaction.getConvoId() } : {},
1937
+ ...interaction.getUserId() ? { userId: interaction.getUserId() } : {}
1938
+ };
1939
+ return {
1940
+ childEventId,
1941
+ name,
1942
+ parentEventId,
1943
+ dispatchSpanId,
1944
+ carrier,
1945
+ headers: toHeaders(carrier),
1946
+ langsmithHeaders: toLangSmithHeaders(carrier)
1947
+ };
1948
+ }
1949
+ function carrierFirst(local, carried, field) {
1950
+ if (carried && local && local !== carried) {
1951
+ console.warn(
1952
+ `[raindrop] resumeSubagent: ignoring ${field}="${local}" in favor of the launcher's "${carried}" from the carrier; the launcher allocated it, and a child that substitutes its own breaks the link back to it.`
1953
+ );
1954
+ }
1955
+ return carried || local;
1956
+ }
1957
+ function isTraceCarrier(value) {
1958
+ const candidate = value;
1959
+ return typeof candidate.traceId === "string" && typeof candidate.spanId === "string" && typeof candidate.eventId === "string";
1960
+ }
1961
+ function readCarrier(carrierOrHeaders) {
1962
+ if (!carrierOrHeaders) return null;
1963
+ try {
1964
+ if (isTraceCarrier(carrierOrHeaders)) return carrierOrHeaders;
1965
+ return fromHeaders(carrierOrHeaders);
1966
+ } catch (error) {
1967
+ console.warn(
1968
+ `[raindrop] resumeSubagent: ignoring an unreadable hand-off carrier; the run reports as an unlinked event.`,
1969
+ error instanceof Error ? error.message : error
1970
+ );
1971
+ return null;
1972
+ }
1973
+ }
1974
+ function resolveSubagentResume(carrierOrHeaders, options = {}) {
1975
+ const parentStated = options.parent !== void 0;
1976
+ const parent = parentStated ? options.parent : readCarrier(carrierOrHeaders);
1977
+ if (!parentStated) warnUnresolvedCarrier(carrierOrHeaders, parent);
1978
+ const name = carrierFirst(options.name, parent == null ? void 0 : parent.name, "name") || DEFAULT_SUBAGENT_NAME;
1979
+ const eventId = carrierFirst(options.eventId, parent == null ? void 0 : parent.childEventId, "eventId") || randomUUID();
1980
+ const userId = carrierFirst(options.userId, parent == null ? void 0 : parent.userId, "userId") || "";
1981
+ const convoId = carrierFirst(options.convoId, parent == null ? void 0 : parent.convoId, "convoId");
1982
+ const link = parent ? {
1983
+ parentEventId: parent.eventId,
1984
+ ...parent.spanId ? { parentSpanId: parent.spanId } : {},
1985
+ name
1986
+ } : null;
1987
+ return {
1988
+ parent,
1989
+ link,
1990
+ name,
1991
+ eventId,
1992
+ event: options.event || `subagent.${name}`,
1993
+ userId,
1994
+ ...convoId ? { convoId } : {}
1995
+ };
1996
+ }
1997
+ function bindSubagentLink(link, owner) {
1998
+ if (!link) return void 0;
1999
+ return bindSpanAttributes(detachedChildMetadata(link), owner);
2000
+ }
2001
+ var LiveSubagentRun = class {
2002
+ constructor(params) {
2003
+ this.settled = false;
2004
+ this.interaction = params.interaction;
2005
+ this.eventId = params.eventId;
2006
+ this.name = params.name;
2007
+ this.convoId = params.convoId;
2008
+ this.parent = params.parent;
2009
+ this.frame = params.frame;
2010
+ this.frameOwner = params.frameOwner;
2011
+ }
2012
+ get linked() {
2013
+ return this.parent !== null;
2014
+ }
2015
+ async finish(result) {
2016
+ await this.close(result);
2017
+ }
2018
+ async fail(reason) {
2019
+ await this.abort(reason);
2020
+ }
2021
+ async cancel(reason) {
2022
+ const text = reason === void 0 ? "cancelled by caller" : reasonText(reason);
2023
+ const cancelled = cancelledTerminalAttributes();
2024
+ stampOwnSpan(cancelled, this.frame);
2025
+ await this.close({
2026
+ output: `Cancelled: ${text}`,
2027
+ // The caller's view of the child is its EVENT, not its spans, so the
2028
+ // marker has to be a property of the event as well.
2029
+ properties: { [HANDOFF_TERMINAL_PROPERTY_KEY]: HANDOFF_TERMINAL_CANCELLED }
2030
+ });
2031
+ }
2032
+ /**
2033
+ * Close the run with an abort reason, having first made sure the failure is
2034
+ * visible on a span.
2035
+ *
2036
+ * A failure has to leave an errored span behind or it is derived as finished.
2037
+ * Mark whatever is open; if nothing is and the child has not errored a span
2038
+ * already, record one — the killed-before-it-reached-the-model case, which is
2039
+ * much of what aborting is.
2040
+ */
2041
+ async abort(reason) {
2042
+ var _a, _b, _c;
2043
+ const text = reasonText(reason);
2044
+ if (!this.settled && !failOwnSpan(reason, this.frame)) {
2045
+ if (!((_a = this.frame) == null ? void 0 : _a.sawErrorSpan())) {
2046
+ this.interaction.recordSubagentAbortSpan({
2047
+ reason,
2048
+ message: text,
2049
+ attributes: {
2050
+ [HANDOFF_ATTRIBUTE_SUFFIXES.name]: this.name,
2051
+ // The name explicitly, not only via the frame: an UNLINKED run has
2052
+ // no frame, and since the span is named for the operation
2053
+ // (`ai.subagent.failed`) rather than the sub-agent, this attribute
2054
+ // is the only thing left that says which sub-agent failed.
2055
+ ...(_c = (_b = this.frame) == null ? void 0 : _b.attributes) != null ? _c : {}
2056
+ }
2057
+ });
2058
+ }
2059
+ }
2060
+ await this.close({ output: text ? `Aborted: ${text}` : "Aborted before producing a result." });
2061
+ }
2062
+ async close(result) {
2063
+ if (this.settled) return;
2064
+ this.settled = true;
2065
+ try {
2066
+ await this.interaction.finish({ ...result, eventId: this.eventId });
2067
+ } finally {
2068
+ unbindSpanAttributes(this.frame);
2069
+ this.frame = void 0;
2070
+ this.frameOwner = void 0;
2071
+ }
2072
+ }
2073
+ /**
2074
+ * Run `fn` and guarantee the run reports an outcome, mirroring the Python
2075
+ * SDK's `with rd.resume_subagent(...) as run:`.
2076
+ *
2077
+ * A run that leaves without reporting output is closed with its abort reason.
2078
+ * That is not cosmetic: an event is created only from a run with non-empty
2079
+ * output, so a child that dies silently produces no event at all and the
2080
+ * caller's launch stays `queued` forever — indistinguishable from a job that
2081
+ * never started.
2082
+ */
2083
+ async use(fn) {
2084
+ try {
2085
+ const result = await fn(this);
2086
+ if (!this.settled) {
2087
+ console.warn(
2088
+ `[raindrop] sub-agent run ${this.eventId} (${this.name}) ended without reporting output; closing it with an abort reason. An event needs non-empty output to exist, so a silent child leaves its launcher showing "queued" forever \u2014 call finish({ output }), fail(reason) or cancel() before returning.`
2089
+ );
2090
+ await this.abortQuietly("sub-agent ended without reporting output");
2091
+ }
2092
+ return result;
2093
+ } catch (error) {
2094
+ await this.abortQuietly(error);
2095
+ throw error;
2096
+ }
2097
+ }
2098
+ /**
2099
+ * {@link abort} for the outcomes this class reports on the caller's behalf.
2100
+ *
2101
+ * `abort()` ends in `interaction.finish()`, which awaits the terminal event
2102
+ * POST and rejects when it fails. An explicit `fail()` may surface that — the
2103
+ * caller awaited it — but an implicit one must not: rejecting on the error
2104
+ * path replaces the caller's exception with a telemetry one, and rejecting on
2105
+ * the success path loses a result `fn` already produced.
2106
+ */
2107
+ async abortQuietly(reason) {
2108
+ try {
2109
+ await this.abort(reason);
2110
+ } catch (error) {
2111
+ console.warn(
2112
+ `[raindrop] sub-agent run ${this.eventId} (${this.name}) could not report its outcome; the run itself is unaffected.`,
2113
+ error instanceof Error ? error.message : error
2114
+ );
2115
+ }
2116
+ }
2117
+ };
2118
+
2119
+ // src/tracing/liveInteraction.ts
2120
+ function getPropertiesFromContext(context6) {
1368
2121
  const properties = {
1369
- ...context5.userId && { user_id: context5.userId },
1370
- ...context5.convoId && { convo_id: context5.convoId },
1371
- ...context5.eventId && { event_id: context5.eventId },
1372
- ...context5.event && { event_name: context5.event },
1373
- ...context5.properties || {}
2122
+ ...context6.userId && { user_id: context6.userId },
2123
+ ...context6.convoId && { convo_id: context6.convoId },
2124
+ ...context6.eventId && { event_id: context6.eventId },
2125
+ ...context6.event && { event_name: context6.event },
2126
+ ...context6.properties || {}
1374
2127
  };
1375
- if (context5.attachments && context5.attachments.length > 0) {
1376
- properties.attachments = stringifyBounded(context5.attachments);
2128
+ if (context6.attachments && context6.attachments.length > 0) {
2129
+ properties.attachments = stringifyBounded(context6.attachments);
1377
2130
  }
1378
2131
  return properties;
1379
2132
  }
@@ -1393,12 +2146,12 @@ function serializeAssociationProperties(properties) {
1393
2146
  function serializeSpanValue(value) {
1394
2147
  return stringifyBounded(value);
1395
2148
  }
1396
- function getLocalDebuggerMetadata(context5) {
2149
+ function getLocalDebuggerMetadata(context6) {
1397
2150
  return {
1398
- ...context5.eventId ? { eventId: context5.eventId } : {},
1399
- ...context5.event ? { eventName: context5.event } : {},
1400
- ...context5.userId ? { userId: context5.userId } : {},
1401
- ...context5.convoId ? { convoId: context5.convoId } : {}
2151
+ ...context6.eventId ? { eventId: context6.eventId } : {},
2152
+ ...context6.event ? { eventName: context6.event } : {},
2153
+ ...context6.userId ? { userId: context6.userId } : {},
2154
+ ...context6.convoId ? { convoId: context6.convoId } : {}
1402
2155
  };
1403
2156
  }
1404
2157
  var LiveToolSpan = class {
@@ -1410,7 +2163,7 @@ var LiveToolSpan = class {
1410
2163
  }
1411
2164
  spanIdHex() {
1412
2165
  const ctx = this.span.spanContext();
1413
- return (0, import_api2.isValidSpanId)(ctx.spanId) ? ctx.spanId : void 0;
2166
+ return (0, import_api3.isValidSpanId)(ctx.spanId) ? ctx.spanId : void 0;
1414
2167
  }
1415
2168
  setInput(input) {
1416
2169
  this.span.setAttribute("traceloop.entity.input", serializeSpanValue(input));
@@ -1422,13 +2175,13 @@ var LiveToolSpan = class {
1422
2175
  setError(error) {
1423
2176
  this.hasError = true;
1424
2177
  this.errorMessage = error instanceof Error ? error.message : String(error);
1425
- this.span.setStatus({ code: import_api2.SpanStatusCode.ERROR, message: this.errorMessage });
2178
+ this.span.setStatus({ code: import_api3.SpanStatusCode.ERROR, message: this.errorMessage });
1426
2179
  this.span.recordException(error instanceof Error ? error : new Error(this.errorMessage));
1427
2180
  }
1428
2181
  end() {
1429
2182
  var _a;
1430
2183
  if (!this.hasError) {
1431
- this.span.setStatus({ code: import_api2.SpanStatusCode.OK });
2184
+ this.span.setStatus({ code: import_api3.SpanStatusCode.OK });
1432
2185
  }
1433
2186
  this.span.end();
1434
2187
  (_a = this.emitLiveEvent) == null ? void 0 : _a.call(this, {
@@ -1499,10 +2252,10 @@ var DirectToolSpan = class {
1499
2252
  }
1500
2253
  };
1501
2254
  var LiveInteraction = class {
1502
- constructor(context5, traceId, analytics, directShipper, routing) {
1503
- this.context = context5;
2255
+ constructor(context6, traceId, analytics, directShipper, routing) {
2256
+ this.context = context6;
1504
2257
  this.analytics = analytics;
1505
- this.tracer = import_api2.trace.getTracer("traceloop.tracer");
2258
+ this.tracer = import_api3.trace.getTracer("traceloop.tracer");
1506
2259
  this.traceId = traceId;
1507
2260
  this.directShipper = directShipper;
1508
2261
  this.routing = routing;
@@ -1537,7 +2290,7 @@ var LiveInteraction = class {
1537
2290
  this.traceId = explicitTraceId;
1538
2291
  return explicitTraceId;
1539
2292
  }
1540
- const activeSpan = import_api2.trace.getSpan(import_api2.context.active());
2293
+ const activeSpan = import_api3.trace.getSpan(import_api3.context.active());
1541
2294
  const activeTraceId = activeSpan == null ? void 0 : activeSpan.spanContext().traceId;
1542
2295
  if (activeTraceId) {
1543
2296
  this.traceId = activeTraceId;
@@ -1580,17 +2333,17 @@ var LiveInteraction = class {
1580
2333
  const spanIdB64 = base64Encode2(randomBytes2(8));
1581
2334
  const startTimeMs = Date.now();
1582
2335
  const spanContext = {
1583
- traceId: base64ToHex(traceIdB64),
1584
- spanId: base64ToHex(spanIdB64),
1585
- traceFlags: import_api2.TraceFlags.SAMPLED
2336
+ traceId: base64ToHex2(traceIdB64),
2337
+ spanId: base64ToHex2(spanIdB64),
2338
+ traceFlags: import_api3.TraceFlags.SAMPLED
1586
2339
  };
1587
- const wrappedContext = import_api2.trace.setSpan(
1588
- import_api2.context.active(),
1589
- import_api2.trace.wrapSpanContext(spanContext)
2340
+ const wrappedContext = import_api3.trace.setSpan(
2341
+ import_api3.context.active(),
2342
+ import_api3.trace.wrapSpanContext(spanContext)
1590
2343
  );
1591
2344
  const invoke = () => this.routing ? withRoutingContext(this.routing, () => fn.apply(thisArg, args)) : fn.apply(thisArg, args);
1592
2345
  try {
1593
- const result = await import_api2.context.with(wrappedContext, invoke);
2346
+ const result = await import_api3.context.with(wrappedContext, invoke);
1594
2347
  const endTimeMs = Date.now();
1595
2348
  this.directShipper.sendSpan({
1596
2349
  name: taskName,
@@ -1625,7 +2378,7 @@ var LiveInteraction = class {
1625
2378
  }
1626
2379
  }
1627
2380
  const wrappedFn = (...fnArgs) => {
1628
- const activeSpan = import_api2.trace.getSpan(import_api2.context.active());
2381
+ const activeSpan = import_api3.trace.getSpan(import_api3.context.active());
1629
2382
  const activeTraceId = activeSpan == null ? void 0 : activeSpan.spanContext().traceId;
1630
2383
  if (activeTraceId) {
1631
2384
  this.traceId = activeTraceId;
@@ -1675,19 +2428,19 @@ var LiveInteraction = class {
1675
2428
  metadata: params.inputParameters ? { args: params.inputParameters } : void 0
1676
2429
  });
1677
2430
  const spanContext = {
1678
- traceId: base64ToHex(traceIdB64),
1679
- spanId: base64ToHex(spanIdB64),
1680
- traceFlags: import_api2.TraceFlags.SAMPLED
2431
+ traceId: base64ToHex2(traceIdB64),
2432
+ spanId: base64ToHex2(spanIdB64),
2433
+ traceFlags: import_api3.TraceFlags.SAMPLED
1681
2434
  };
1682
- const wrappedContext = import_api2.trace.setSpan(
1683
- import_api2.context.active(),
1684
- import_api2.trace.wrapSpanContext(spanContext)
2435
+ const wrappedContext = import_api3.trace.setSpan(
2436
+ import_api3.context.active(),
2437
+ import_api3.trace.wrapSpanContext(spanContext)
1685
2438
  );
1686
2439
  const invoke = () => this.routing ? withRoutingContext(this.routing, () => fn.apply(thisArg, args)) : fn.apply(thisArg, args);
1687
2440
  let result;
1688
2441
  let error;
1689
2442
  try {
1690
- result = await import_api2.context.with(wrappedContext, invoke);
2443
+ result = await import_api3.context.with(wrappedContext, invoke);
1691
2444
  } catch (err) {
1692
2445
  error = err instanceof Error ? err.message : String(err);
1693
2446
  const endTimeMs2 = Date.now();
@@ -1752,9 +2505,9 @@ var LiveInteraction = class {
1752
2505
  const inputParams = params.inputParameters ? [params.inputParameters] : void 0;
1753
2506
  const emitLive = (event) => this.emitLiveEvent(event);
1754
2507
  const wrapped = async (...wrappedArgs) => {
1755
- const activeSpan = import_api2.trace.getSpan(import_api2.context.active());
2508
+ const activeSpan = import_api3.trace.getSpan(import_api3.context.active());
1756
2509
  const ctx = activeSpan == null ? void 0 : activeSpan.spanContext();
1757
- const liveSpanId = ctx && (0, import_api2.isValidSpanId)(ctx.spanId) ? ctx.spanId : void 0;
2510
+ const liveSpanId = ctx && (0, import_api3.isValidSpanId)(ctx.spanId) ? ctx.spanId : void 0;
1758
2511
  if (activeSpan) {
1759
2512
  this.stampRouting(activeSpan);
1760
2513
  }
@@ -1862,7 +2615,7 @@ var LiveInteraction = class {
1862
2615
  console.log(`[raindrop] startToolSpan: started tool span "${name}"`);
1863
2616
  }
1864
2617
  const startSpanCtx = span.spanContext();
1865
- const startSpanIdHex = (0, import_api2.isValidSpanId)(startSpanCtx.spanId) ? startSpanCtx.spanId : void 0;
2618
+ const startSpanIdHex = (0, import_api3.isValidSpanId)(startSpanCtx.spanId) ? startSpanCtx.spanId : void 0;
1866
2619
  this.emitLiveEvent({
1867
2620
  type: "tool_start",
1868
2621
  spanId: startSpanIdHex,
@@ -1955,10 +2708,151 @@ var LiveInteraction = class {
1955
2708
  getEventId() {
1956
2709
  return this.context.eventId;
1957
2710
  }
2711
+ getUserId() {
2712
+ return this.context.userId;
2713
+ }
2714
+ getConvoId() {
2715
+ return this.context.convoId;
2716
+ }
2717
+ /**
2718
+ * Bind this turn's tool-call event opt-in, once.
2719
+ *
2720
+ * Owned by the interaction rather than by the execution context: the frame
2721
+ * lives exactly as long as the turn does (removed by `finish()`, and dead once
2722
+ * this interaction is collected), instead of outliving it on a context the
2723
+ * host may reuse for unrelated work.
2724
+ */
2725
+ bindToolEventsOptIn(attributes) {
2726
+ if (this.toolEventsFrame) return;
2727
+ this.toolEventsFrame = bindSpanAttributes(attributes, this);
2728
+ }
2729
+ subagent(options) {
2730
+ return recordSubagentDispatch(this, options);
2731
+ }
2732
+ /**
2733
+ * Record the tool span a detached dispatch is written on.
2734
+ *
2735
+ * Distinct from {@link startToolSpan} in the two ways the hand-off needs:
2736
+ * the contract's keys are set as RAW span attributes (under the
2737
+ * `traceloop.association.properties.` prefix the backend's reader cannot see
2738
+ * them), and the caller needs the span's ids to build the carrier.
2739
+ *
2740
+ * @internal
2741
+ */
2742
+ recordDispatchSpan(params) {
2743
+ var _a;
2744
+ const properties = {
2745
+ ...getPropertiesFromContext(this.context),
2746
+ ...(_a = params.properties) != null ? _a : {}
2747
+ };
2748
+ const input = params.input !== void 0 ? serializeSpanValue(params.input) : void 0;
2749
+ const output = serializeSpanValue(params.output);
2750
+ if (this.directShipper) {
2751
+ const activeContext = getActiveTraceContext();
2752
+ const traceIdB64 = this.ensureTraceId(activeContext.traceIdB64);
2753
+ const spanIdB64 = base64Encode2(randomBytes2(8));
2754
+ const timeMs = Date.now();
2755
+ this.directShipper.sendToolSpan({
2756
+ name: params.name,
2757
+ spanId: spanIdB64,
2758
+ input,
2759
+ output,
2760
+ durationMs: 0,
2761
+ startTimeMs: timeMs,
2762
+ endTimeMs: timeMs,
2763
+ properties,
2764
+ traceId: traceIdB64,
2765
+ parentSpanId: activeContext.parentSpanIdB64,
2766
+ attributes: params.attributes
2767
+ });
2768
+ this.emitLiveEvent({
2769
+ traceId: traceIdB64,
2770
+ spanId: spanIdB64,
2771
+ type: "tool_result",
2772
+ content: params.name,
2773
+ timestamp: timeMs,
2774
+ metadata: { result: params.output }
2775
+ });
2776
+ return { traceIdHex: base64ToHex2(traceIdB64), spanIdHex: base64ToHex2(spanIdB64) };
2777
+ }
2778
+ const span = this.tracer.startSpan(params.name);
2779
+ setAssociationProperties(span, properties);
2780
+ span.setAttribute("traceloop.span.kind", "tool");
2781
+ this.stampRouting(span);
2782
+ for (const [key, value] of Object.entries(params.attributes)) {
2783
+ span.setAttribute(key, value);
2784
+ }
2785
+ if (input !== void 0) {
2786
+ span.setAttribute("traceloop.entity.input", input);
2787
+ }
2788
+ span.setAttribute("traceloop.entity.output", output);
2789
+ span.setStatus({ code: import_api3.SpanStatusCode.OK });
2790
+ const spanContext = span.spanContext();
2791
+ span.end();
2792
+ this.emitLiveEvent({
2793
+ spanId: (0, import_api3.isValidSpanId)(spanContext.spanId) ? spanContext.spanId : void 0,
2794
+ type: "tool_result",
2795
+ content: params.name,
2796
+ timestamp: Date.now(),
2797
+ metadata: { result: params.output }
2798
+ });
2799
+ return {
2800
+ traceIdHex: (0, import_api3.isValidTraceId)(spanContext.traceId) ? spanContext.traceId : void 0,
2801
+ spanIdHex: (0, import_api3.isValidSpanId)(spanContext.spanId) ? spanContext.spanId : void 0
2802
+ };
2803
+ }
2804
+ /**
2805
+ * Record the errored span a detached sub-agent's failure needs when nothing
2806
+ * else is open.
2807
+ *
2808
+ * Frequently the child's ONLY span, so it carries the full reverse reference:
2809
+ * anything reading it alone still knows which launch it belongs to. Those
2810
+ * attributes come from the run's own frame rather than the ambient stack,
2811
+ * because `fail()` is often called from a different task than the one that
2812
+ * opened the run and this is the span that can least afford to lose the link.
2813
+ *
2814
+ * @internal
2815
+ */
2816
+ recordSubagentAbortSpan(params) {
2817
+ const { reason, message, attributes } = params;
2818
+ const properties = getPropertiesFromContext(this.context);
2819
+ if (this.directShipper) {
2820
+ const activeContext = getActiveTraceContext();
2821
+ const timeMs = Date.now();
2822
+ this.directShipper.sendSpan({
2823
+ name: SUBAGENT_ABORT_SPAN_NAME,
2824
+ // Not "tool": the run died, it did not call anything. `ai.operationId`
2825
+ // below is what keeps the span (see the attribute's docs in core).
2826
+ spanKind: "task",
2827
+ spanId: base64Encode2(randomBytes2(8)),
2828
+ durationMs: 0,
2829
+ startTimeMs: timeMs,
2830
+ endTimeMs: timeMs,
2831
+ error: message,
2832
+ properties,
2833
+ traceId: this.ensureTraceId(activeContext.traceIdB64),
2834
+ parentSpanId: activeContext.parentSpanIdB64,
2835
+ attributes: { ...attributes, [OPERATION_ID_ATTRIBUTE]: SUBAGENT_ABORT_OPERATION_ID }
2836
+ });
2837
+ return;
2838
+ }
2839
+ const span = this.tracer.startSpan(SUBAGENT_ABORT_SPAN_NAME);
2840
+ span.setAttribute(OPERATION_ID_ATTRIBUTE, SUBAGENT_ABORT_OPERATION_ID);
2841
+ setAssociationProperties(span, properties);
2842
+ this.stampRouting(span);
2843
+ for (const [key, value] of Object.entries(attributes)) {
2844
+ span.setAttribute(key, value);
2845
+ }
2846
+ span.setStatus({ code: import_api3.SpanStatusCode.ERROR, message });
2847
+ span.recordException(reason instanceof Error ? reason : new Error(message));
2848
+ span.end();
2849
+ }
1958
2850
  async finish(resultEvent) {
1959
2851
  var _a, _b, _c, _d;
1960
2852
  unbindRoutingContext(this.boundContext);
1961
2853
  this.boundContext = void 0;
2854
+ unbindSpanAttributes(this.toolEventsFrame);
2855
+ this.toolEventsFrame = void 0;
1962
2856
  if (!this.traceId) {
1963
2857
  this.resolveLiveTraceId();
1964
2858
  }
@@ -2068,10 +2962,10 @@ var LiveInteraction = class {
2068
2962
  }
2069
2963
  if (error) {
2070
2964
  const errorMessage = error instanceof Error ? error.message : String(error);
2071
- span.setStatus({ code: import_api2.SpanStatusCode.ERROR, message: errorMessage });
2965
+ span.setStatus({ code: import_api3.SpanStatusCode.ERROR, message: errorMessage });
2072
2966
  span.recordException(error instanceof Error ? error : new Error(errorMessage));
2073
2967
  } else {
2074
- span.setStatus({ code: import_api2.SpanStatusCode.OK });
2968
+ span.setStatus({ code: import_api3.SpanStatusCode.OK });
2075
2969
  }
2076
2970
  span.end(endTimeMs);
2077
2971
  if ((_c = this.analytics) == null ? void 0 : _c.debugLogs) {
@@ -2083,7 +2977,7 @@ var LiveInteraction = class {
2083
2977
  });
2084
2978
  }
2085
2979
  const trackToolCtx = span.spanContext();
2086
- const trackToolSpanIdHex = (0, import_api2.isValidSpanId)(trackToolCtx.spanId) ? trackToolCtx.spanId : void 0;
2980
+ const trackToolSpanIdHex = (0, import_api3.isValidSpanId)(trackToolCtx.spanId) ? trackToolCtx.spanId : void 0;
2087
2981
  this.emitLiveEvent({
2088
2982
  type: "tool_result",
2089
2983
  spanId: trackToolSpanIdHex,
@@ -2099,11 +2993,11 @@ var LiveInteraction = class {
2099
2993
  };
2100
2994
 
2101
2995
  // src/tracing/liveTracer.ts
2102
- var import_api3 = require("@opentelemetry/api");
2996
+ var import_api4 = require("@opentelemetry/api");
2103
2997
  var traceloop2 = __toESM(require("@traceloop/node-server-sdk"));
2104
2998
  var LiveTracer = class {
2105
2999
  constructor(globalProperties, directShipper, routing) {
2106
- this.tracer = import_api3.trace.getTracer("traceloop.tracer");
3000
+ this.tracer = import_api4.trace.getTracer("traceloop.tracer");
2107
3001
  this.globalProperties = globalProperties || {};
2108
3002
  this.directShipper = directShipper;
2109
3003
  this.routing = routing;
@@ -2115,7 +3009,7 @@ var LiveTracer = class {
2115
3009
  }
2116
3010
  emitLiveEvent(event) {
2117
3011
  var _a, _b;
2118
- const activeSpan = import_api3.trace.getSpan(import_api3.context.active());
3012
+ const activeSpan = import_api4.trace.getSpan(import_api4.context.active());
2119
3013
  const activeTraceId = activeSpan == null ? void 0 : activeSpan.spanContext().traceId;
2120
3014
  const active = getActiveTraceContext();
2121
3015
  const traceId = (_b = (_a = event.traceId) != null ? _a : activeTraceId) != null ? _b : active.traceIdB64;
@@ -2135,7 +3029,7 @@ var LiveTracer = class {
2135
3029
  };
2136
3030
  const inputParameters = typeof params === "string" ? void 0 : params.inputParameters;
2137
3031
  const wrappedFn = (...fnArgs) => {
2138
- const activeSpan = import_api3.trace.getSpan(import_api3.context.active());
3032
+ const activeSpan = import_api4.trace.getSpan(import_api4.context.active());
2139
3033
  if (activeSpan) {
2140
3034
  this.stampRouting(activeSpan);
2141
3035
  }
@@ -2230,15 +3124,15 @@ var LiveTracer = class {
2230
3124
  }
2231
3125
  if (error) {
2232
3126
  const errorMessage = error instanceof Error ? error.message : String(error);
2233
- span.setStatus({ code: import_api3.SpanStatusCode.ERROR, message: errorMessage });
3127
+ span.setStatus({ code: import_api4.SpanStatusCode.ERROR, message: errorMessage });
2234
3128
  span.recordException(error instanceof Error ? error : new Error(errorMessage));
2235
3129
  } else {
2236
- span.setStatus({ code: import_api3.SpanStatusCode.OK });
3130
+ span.setStatus({ code: import_api4.SpanStatusCode.OK });
2237
3131
  }
2238
3132
  span.end(endTimeMs);
2239
3133
  const ctx = span.spanContext();
2240
- const traceId = ctx.traceId || ((_b = import_api3.trace.getSpan(import_api3.context.active())) == null ? void 0 : _b.spanContext().traceId);
2241
- const spanIdHex = (0, import_api3.isValidSpanId)(ctx.spanId) ? ctx.spanId : void 0;
3134
+ const traceId = ctx.traceId || ((_b = import_api4.trace.getSpan(import_api4.context.active())) == null ? void 0 : _b.spanContext().traceId);
3135
+ const spanIdHex = (0, import_api4.isValidSpanId)(ctx.spanId) ? ctx.spanId : void 0;
2242
3136
  if (traceId) {
2243
3137
  this.emitLiveEvent({
2244
3138
  traceId,
@@ -2530,7 +3424,7 @@ try {
2530
3424
  e instanceof Error ? e.message : e
2531
3425
  );
2532
3426
  span.setStatus({
2533
- code: import_api4.SpanStatusCode.ERROR,
3427
+ code: import_api5.SpanStatusCode.ERROR,
2534
3428
  message: e instanceof Error ? e.message : String(e)
2535
3429
  });
2536
3430
  span.end();
@@ -2562,7 +3456,7 @@ try {
2562
3456
  );
2563
3457
  if (!spanEnded) {
2564
3458
  span.setStatus({
2565
- code: import_api4.SpanStatusCode.ERROR,
3459
+ code: import_api5.SpanStatusCode.ERROR,
2566
3460
  message: e instanceof Error ? e.message : String(e)
2567
3461
  });
2568
3462
  span.end();
@@ -2576,7 +3470,7 @@ try {
2576
3470
  } catch (error) {
2577
3471
  if (!spanEnded) {
2578
3472
  const msg = error instanceof Error ? error.message : String(error);
2579
- span.setStatus({ code: import_api4.SpanStatusCode.ERROR, message: msg });
3473
+ span.setStatus({ code: import_api5.SpanStatusCode.ERROR, message: msg });
2580
3474
  span.recordException(error);
2581
3475
  span.end();
2582
3476
  spanEnded = true;
@@ -2599,7 +3493,7 @@ try {
2599
3493
  return result;
2600
3494
  }).catch((error) => {
2601
3495
  span.setStatus({
2602
- code: import_api4.SpanStatusCode.ERROR,
3496
+ code: import_api5.SpanStatusCode.ERROR,
2603
3497
  message: error.message
2604
3498
  });
2605
3499
  span.recordException(error);
@@ -2662,7 +3556,7 @@ function patchBedrockStreamingBug(inst) {
2662
3556
  } catch (error) {
2663
3557
  if (!spanEnded) {
2664
3558
  const msg = error instanceof Error ? error.message : String(error);
2665
- span.setStatus({ code: import_api4.SpanStatusCode.ERROR, message: msg });
3559
+ span.setStatus({ code: import_api5.SpanStatusCode.ERROR, message: msg });
2666
3560
  span.recordException(error);
2667
3561
  span.end();
2668
3562
  spanEnded = true;
@@ -2685,7 +3579,7 @@ function patchBedrockStreamingBug(inst) {
2685
3579
  return result;
2686
3580
  }).catch((error) => {
2687
3581
  span.setStatus({
2688
- code: import_api4.SpanStatusCode.ERROR,
3582
+ code: import_api5.SpanStatusCode.ERROR,
2689
3583
  message: error.message
2690
3584
  });
2691
3585
  span.recordException(error);
@@ -2767,7 +3661,7 @@ function createManualInstrumentations(instrumentModules) {
2767
3661
  }
2768
3662
  function getCurrentTraceId() {
2769
3663
  var _a;
2770
- return (_a = import_api4.trace.getSpan(import_api4.context.active())) == null ? void 0 : _a.spanContext().traceId;
3664
+ return (_a = import_api5.trace.getSpan(import_api5.context.active())) == null ? void 0 : _a.spanContext().traceId;
2771
3665
  }
2772
3666
  var tracing = (analytics, apiUrl, writeKey, options, isDebug = false) => {
2773
3667
  var _a;
@@ -2960,6 +3854,72 @@ var tracing = (analytics, apiUrl, writeKey, options, isDebug = false) => {
2960
3854
  } catch (e) {
2961
3855
  }
2962
3856
  }) : void 0;
3857
+ const beginInteraction = (traceContext) => {
3858
+ var _a2;
3859
+ if (!traceContext.eventId) {
3860
+ traceContext.eventId = crypto.randomUUID();
3861
+ }
3862
+ const traceId = getCurrentTraceId();
3863
+ const interaction = new LiveInteraction(
3864
+ traceContext,
3865
+ traceId,
3866
+ analytics,
3867
+ directShipper,
3868
+ { projectId, authHint }
3869
+ );
3870
+ const bound = bindRoutingContext({ projectId, authHint }, interaction);
3871
+ interaction.setBoundContext(bound);
3872
+ try {
3873
+ analytics._trackAiPartial({
3874
+ ...traceContext,
3875
+ properties: {
3876
+ ...(_a2 = traceContext.properties) != null ? _a2 : {},
3877
+ ...interaction.getTraceId() ? { trace_id: interaction.getTraceId() } : {}
3878
+ }
3879
+ });
3880
+ if (interaction.getTraceId()) {
3881
+ activeInteractions.set(interaction.getTraceId(), interaction);
3882
+ }
3883
+ activeInteractionsByEventId.set(traceContext.eventId, interaction);
3884
+ } catch (error) {
3885
+ unbindRoutingContext(bound);
3886
+ throw error;
3887
+ }
3888
+ return interaction;
3889
+ };
3890
+ const openSubagentRun = (carrierOrHeaders, options2) => {
3891
+ const resolved = resolveSubagentResume(carrierOrHeaders, options2);
3892
+ if (!resolved.parent && isDebug) {
3893
+ console.log(
3894
+ `[raindrop] resumeSubagent(${resolved.name}): no hand-off carrier on the request; reporting as an unlinked event ${resolved.eventId}.`
3895
+ );
3896
+ }
3897
+ const frameOwner = { subagentEventId: resolved.eventId };
3898
+ const frame = bindSubagentLink(resolved.link, frameOwner);
3899
+ let interaction;
3900
+ try {
3901
+ interaction = beginInteraction({
3902
+ eventId: resolved.eventId,
3903
+ event: resolved.event,
3904
+ userId: resolved.userId,
3905
+ ...resolved.convoId ? { convoId: resolved.convoId } : {},
3906
+ ...options2.input !== void 0 ? { input: options2.input } : {},
3907
+ ...options2.model !== void 0 ? { model: options2.model } : {},
3908
+ ...options2.properties ? { properties: options2.properties } : {}
3909
+ });
3910
+ } catch (error) {
3911
+ unbindSpanAttributes(frame);
3912
+ throw error;
3913
+ }
3914
+ return new LiveSubagentRun({
3915
+ interaction,
3916
+ eventId: resolved.eventId,
3917
+ name: resolved.name,
3918
+ ...resolved.convoId ? { convoId: resolved.convoId } : {},
3919
+ parent: resolved.link,
3920
+ ...frame ? { frame, frameOwner } : {}
3921
+ });
3922
+ };
2963
3923
  return {
2964
3924
  /**
2965
3925
  * Returns instrumentation instances for your NodeSDK.
@@ -3069,37 +4029,13 @@ var tracing = (analytics, apiUrl, writeKey, options, isDebug = false) => {
3069
4029
  );
3070
4030
  },
3071
4031
  begin(traceContext) {
3072
- var _a2;
3073
- if (!traceContext.eventId) {
3074
- traceContext.eventId = crypto.randomUUID();
3075
- }
3076
- const traceId = getCurrentTraceId();
3077
- const interaction = new LiveInteraction(
3078
- traceContext,
3079
- traceId,
3080
- analytics,
3081
- directShipper,
3082
- { projectId, authHint }
3083
- );
3084
- const bound = bindRoutingContext({ projectId, authHint }, interaction);
3085
- interaction.setBoundContext(bound);
3086
- try {
3087
- analytics._trackAiPartial({
3088
- ...traceContext,
3089
- properties: {
3090
- ...(_a2 = traceContext.properties) != null ? _a2 : {},
3091
- ...interaction.getTraceId() ? { trace_id: interaction.getTraceId() } : {}
3092
- }
3093
- });
3094
- if (interaction.getTraceId()) {
3095
- activeInteractions.set(interaction.getTraceId(), interaction);
3096
- }
3097
- activeInteractionsByEventId.set(traceContext.eventId, interaction);
3098
- } catch (error) {
3099
- unbindRoutingContext(bound);
3100
- throw error;
3101
- }
3102
- return interaction;
4032
+ return beginInteraction(traceContext);
4033
+ },
4034
+ resumeSubagent(carrierOrHeaders, options2 = {}) {
4035
+ return openSubagentRun(carrierOrHeaders, options2);
4036
+ },
4037
+ withSubagentRun(carrierOrHeaders, fn, options2 = {}) {
4038
+ return openSubagentRun(carrierOrHeaders, options2).use(fn);
3103
4039
  },
3104
4040
  getActiveInteraction(eventId) {
3105
4041
  const interactionByEventId = activeInteractionsByEventId.get(eventId);