@raindrop-ai/deep-agents 0.0.6 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -28,7 +28,69 @@ module.exports = __toCommonJS(index_exports);
28
28
  // src/callback-handler.ts
29
29
  var import_base = require("@langchain/core/callbacks/base");
30
30
 
31
- // ../core/dist/chunk-WKRW55KX.js
31
+ // ../core/dist/chunk-BYBMRLZM.js
32
+ var EVAL_CORRELATION_ID_ATTRIBUTE = "raindrop.eval_correlation_id";
33
+ var PROBE_SCOPE = { correlationId: "" };
34
+ var EvalScopeStorage = class {
35
+ constructor() {
36
+ this._als = null;
37
+ this._probed = false;
38
+ }
39
+ maybeAdoptAsyncLocalStorage() {
40
+ if (this._probed) return;
41
+ this._probed = true;
42
+ try {
43
+ const Ctor = globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
44
+ if (!Ctor) return;
45
+ const als = new Ctor();
46
+ als.run(PROBE_SCOPE, () => {
47
+ });
48
+ this._als = als;
49
+ } catch (e) {
50
+ this._als = null;
51
+ }
52
+ }
53
+ run(scope, callback) {
54
+ this.maybeAdoptAsyncLocalStorage();
55
+ if (this._als) return this._als.run(scope, callback);
56
+ const previous = this._syncScope;
57
+ this._syncScope = scope;
58
+ try {
59
+ return callback();
60
+ } finally {
61
+ this._syncScope = previous;
62
+ }
63
+ }
64
+ current() {
65
+ this.maybeAdoptAsyncLocalStorage();
66
+ if (this._als) return this._als.getStore();
67
+ return this._syncScope;
68
+ }
69
+ };
70
+ var EVAL_SCOPE_STORAGE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.evalScopeStorage");
71
+ function evalScopeStorage() {
72
+ const holder = globalThis;
73
+ let storage = holder[EVAL_SCOPE_STORAGE_KEY];
74
+ if (!storage) {
75
+ storage = new EvalScopeStorage();
76
+ holder[EVAL_SCOPE_STORAGE_KEY] = storage;
77
+ }
78
+ return storage;
79
+ }
80
+ function currentEvalScope() {
81
+ try {
82
+ return evalScopeStorage().current();
83
+ } catch (e) {
84
+ return void 0;
85
+ }
86
+ }
87
+ function evalScopeAttributes() {
88
+ const scope = currentEvalScope();
89
+ if (!scope) return {};
90
+ return { [EVAL_CORRELATION_ID_ATTRIBUTE]: scope.correlationId };
91
+ }
92
+
93
+ // ../core/dist/chunk-T53LQAH7.js
32
94
  function getCrypto() {
33
95
  const c = globalThis.crypto;
34
96
  return c;
@@ -83,6 +145,39 @@ function base64Encode(bytes) {
83
145
  }
84
146
  return out;
85
147
  }
148
+ function base64ToHex(value) {
149
+ if (!value) return "";
150
+ const maybeBuffer = globalThis.Buffer;
151
+ if (maybeBuffer) {
152
+ return maybeBuffer.from(value, "base64").toString("hex");
153
+ }
154
+ const atobFn = globalThis.atob;
155
+ if (typeof atobFn !== "function") return "";
156
+ try {
157
+ const binary = atobFn(value);
158
+ let hex = "";
159
+ for (let i = 0; i < binary.length; i++) {
160
+ hex += (binary.charCodeAt(i) & 255).toString(16).padStart(2, "0");
161
+ }
162
+ return hex;
163
+ } catch (e) {
164
+ return "";
165
+ }
166
+ }
167
+ var HANDOFF_ATTRIBUTE_SUFFIXES = {
168
+ mode: "raindrop.handoff.mode",
169
+ childEventId: "raindrop.handoff.childEventId",
170
+ parentEventId: "raindrop.handoff.parentEventId",
171
+ parentSpanId: "raindrop.handoff.parentSpanId",
172
+ name: "raindrop.handoff.name",
173
+ terminal: "raindrop.handoff.terminal",
174
+ agentRole: "raindrop.agent.role"
175
+ };
176
+ var HANDOFF_TERMINAL_PROPERTY_KEY = HANDOFF_ATTRIBUTE_SUFFIXES.terminal;
177
+ var TRACEPARENT_HEADER = "traceparent";
178
+ var BAGGAGE_HEADER = "baggage";
179
+ var HANDOFF_HEADER = "x-raindrop-handoff";
180
+ 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.`;
86
181
  function runWithTracingSuppressed(fn) {
87
182
  const hook = globalThis.RAINDROP_SUPPRESS_TRACING;
88
183
  if (typeof hook !== "function") return fn();
@@ -210,6 +305,7 @@ async function postJson(url, body, headers, opts) {
210
305
  const resp = await runWithTracingSuppressed(
211
306
  () => fetch(url, {
212
307
  method: "POST",
308
+ redirect: headers["X-Raindrop-Replay-Id"] !== void 0 ? "error" : "follow",
213
309
  headers: {
214
310
  "Content-Type": "application/json",
215
311
  ...headers
@@ -311,6 +407,55 @@ function buildExportTraceServiceRequest(spans, serviceName = "raindrop.core", se
311
407
  ]
312
408
  };
313
409
  }
410
+ var STATE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.replayTraceRoutingState");
411
+ function state() {
412
+ const holder = globalThis;
413
+ let current = holder[STATE_KEY];
414
+ if (!current) {
415
+ let storage = null;
416
+ try {
417
+ const Ctor = globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
418
+ if (Ctor) storage = new Ctor();
419
+ } catch (e) {
420
+ storage = null;
421
+ }
422
+ current = {
423
+ storage,
424
+ syncDestination: void 0,
425
+ spanDestinations: /* @__PURE__ */ new WeakMap()
426
+ };
427
+ holder[STATE_KEY] = current;
428
+ }
429
+ return current;
430
+ }
431
+ function currentReplayTraceDestination() {
432
+ var _a, _b;
433
+ const routing = state();
434
+ return (_b = (_a = routing.storage) == null ? void 0 : _a.getStore()) != null ? _b : routing.syncDestination;
435
+ }
436
+ function rememberReplayTraceDestination(span) {
437
+ const destination = currentReplayTraceDestination();
438
+ if (destination) state().spanDestinations.set(span, destination);
439
+ }
440
+ function copyReplayTraceDestination(source, target) {
441
+ const destination = state().spanDestinations.get(source);
442
+ if (destination) state().spanDestinations.set(target, destination);
443
+ }
444
+ function replayTraceDestinationFor(value) {
445
+ if (typeof value !== "object" && typeof value !== "function" || value === null) {
446
+ return void 0;
447
+ }
448
+ return state().spanDestinations.get(value);
449
+ }
450
+ function recordReplayExportedSpan(destination, spanId, traceId) {
451
+ var _a, _b;
452
+ if (!destination || !spanId || !traceId) return;
453
+ (_a = destination.exportedSpanIds) == null ? void 0 : _a.add(spanId);
454
+ (_b = destination.exportedTraceIds) == null ? void 0 : _b.add(traceId);
455
+ }
456
+ function replayTraceUrl(baseUrl) {
457
+ return `${baseUrl.replace(/\/+$/, "")}/v1/traces`;
458
+ }
314
459
  var LOCAL_DEBUGGER_ENV_VAR = "RAINDROP_LOCAL_DEBUGGER";
315
460
  var WORKSHOP_ENV_VAR = "RAINDROP_WORKSHOP";
316
461
  var DEFAULT_LOCAL_WORKSHOP_URL = "http://localhost:5899/v1/";
@@ -373,26 +518,29 @@ function resolveLocalDebuggerBaseUrl(baseUrl) {
373
518
  if (shouldAutoEnableLocalWorkshop()) return DEFAULT_LOCAL_WORKSHOP_URL;
374
519
  return null;
375
520
  }
521
+ var LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS = 2e3;
376
522
  function mirrorTraceExportToLocalDebugger(body, options = {}) {
377
523
  var _a;
378
524
  const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
379
- if (!baseUrl) return;
380
- void postJson(`${baseUrl}traces`, body, {}, {
525
+ if (!baseUrl) return Promise.resolve();
526
+ return postJson(`${baseUrl}traces`, body, {}, {
381
527
  maxAttempts: 1,
382
528
  debug: (_a = options.debug) != null ? _a : false,
383
- sdkName: options.sdkName
529
+ sdkName: options.sdkName,
530
+ timeoutMs: LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS
384
531
  }).catch(() => {
385
532
  });
386
533
  }
387
534
  function mirrorPartialEventToLocalDebugger(event, options = {}) {
388
535
  var _a;
389
536
  const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
390
- if (!baseUrl) return;
537
+ if (!baseUrl) return Promise.resolve();
391
538
  const headers = options.writeKey ? { Authorization: `Bearer ${options.writeKey}` } : {};
392
- void postJson(`${baseUrl}events/track_partial`, event, headers, {
539
+ return postJson(`${baseUrl}events/track_partial`, event, headers, {
393
540
  maxAttempts: 1,
394
541
  debug: (_a = options.debug) != null ? _a : false,
395
- sdkName: options.sdkName
542
+ sdkName: options.sdkName,
543
+ timeoutMs: LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS
396
544
  }).catch(() => {
397
545
  });
398
546
  }
@@ -418,16 +566,52 @@ function projectIdHeaders(projectId) {
418
566
  var SHUTDOWN_DEADLINE_MS = 1e4;
419
567
  var POST_SHUTDOWN_TIMEOUT_MS = 5e3;
420
568
  function mergePatches(target, source) {
421
- var _a, _b, _c, _d;
569
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
422
570
  const out = { ...target, ...source };
423
571
  if (target.properties || source.properties) {
424
572
  out.properties = { ...(_a = target.properties) != null ? _a : {}, ...(_b = source.properties) != null ? _b : {} };
425
573
  }
574
+ if (target.usage || source.usage) {
575
+ out.usage = { ...(_c = target.usage) != null ? _c : {} };
576
+ if (((_d = source.usage) == null ? void 0 : _d.promptTokens) !== void 0) {
577
+ out.usage.promptTokens = source.usage.promptTokens;
578
+ }
579
+ if (((_e = source.usage) == null ? void 0 : _e.completionTokens) !== void 0) {
580
+ out.usage.completionTokens = source.usage.completionTokens;
581
+ }
582
+ }
583
+ if (source.error === void 0) {
584
+ out.error = target.error;
585
+ }
586
+ if (target.featureFlags || source.featureFlags) {
587
+ out.featureFlags = { ...(_f = target.featureFlags) != null ? _f : {}, ...(_g = source.featureFlags) != null ? _g : {} };
588
+ }
426
589
  if (target.attachments || source.attachments) {
427
- out.attachments = [...(_c = target.attachments) != null ? _c : [], ...(_d = source.attachments) != null ? _d : []];
590
+ out.attachments = [...(_h = target.attachments) != null ? _h : [], ...(_i = source.attachments) != null ? _i : []];
428
591
  }
429
592
  return out;
430
593
  }
594
+ function isErrorLike(value) {
595
+ return value !== null && typeof value === "object";
596
+ }
597
+ function eventTelemetryProperties(patch) {
598
+ var _a, _b;
599
+ const properties = {};
600
+ if (((_a = patch.usage) == null ? void 0 : _a.promptTokens) !== void 0 && Number.isFinite(patch.usage.promptTokens)) {
601
+ properties["ai.usage.prompt_tokens"] = patch.usage.promptTokens;
602
+ }
603
+ if (((_b = patch.usage) == null ? void 0 : _b.completionTokens) !== void 0 && Number.isFinite(patch.usage.completionTokens)) {
604
+ properties["ai.usage.completion_tokens"] = patch.usage.completionTokens;
605
+ }
606
+ if (patch.error !== void 0 && patch.error !== null) {
607
+ const constructorName = patch.error instanceof Error && patch.error.constructor !== Error ? patch.error.constructor.name : void 0;
608
+ const errorType = patch.error instanceof Error ? patch.error.name && patch.error.name !== "Error" ? patch.error.name : constructorName || patch.error.name || "Error" : isErrorLike(patch.error) && typeof patch.error.name === "string" && patch.error.name.length > 0 ? patch.error.name : "Error";
609
+ const errorMessage = patch.error instanceof Error ? patch.error.message : isErrorLike(patch.error) && typeof patch.error.message === "string" ? patch.error.message : String(patch.error);
610
+ properties["error.type"] = errorType;
611
+ properties["error.message"] = errorMessage;
612
+ }
613
+ return properties;
614
+ }
431
615
  var EventShipper = class {
432
616
  constructor(opts) {
433
617
  this.buffers = /* @__PURE__ */ new Map();
@@ -513,6 +697,15 @@ var EventShipper = class {
513
697
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
514
698
  if (!this.enabled) return;
515
699
  if (!eventId || !eventId.trim()) return;
700
+ const capturedSticky = this.sticky.get(eventId);
701
+ const eventAlreadyKnown = capturedSticky !== void 0 || this.buffers.has(eventId);
702
+ const destination = currentReplayTraceDestination();
703
+ const cloudReplay = destination !== void 0 && destination.kind !== "workshop";
704
+ if ((capturedSticky == null ? void 0 : capturedSticky.replayOnly) === true || !eventAlreadyKnown && cloudReplay) {
705
+ if (patch.isPending === false) this.sticky.delete(eventId);
706
+ else this.sticky.set(eventId, { ...capturedSticky, replayOnly: true });
707
+ return;
708
+ }
516
709
  const maxChars = resolveMaxTextFieldChars(this.maxTextFieldCharsOpt);
517
710
  if (typeof patch.input === "string" && patch.input.length > maxChars) {
518
711
  patch = { ...patch, input: capText(patch.input, maxChars) };
@@ -571,6 +764,9 @@ var EventShipper = class {
571
764
  try {
572
765
  for (const t of this.timers.values()) clearTimeout(t);
573
766
  this.timers.clear();
767
+ for (const [eventId, sticky] of this.sticky) {
768
+ if (sticky.replayOnly) this.sticky.delete(eventId);
769
+ }
574
770
  const settled = await raceWithTimeout(this.flush(), SHUTDOWN_DEADLINE_MS);
575
771
  if (!settled) this.warnShutdownDrop("in-flight request(s) at shutdown");
576
772
  } finally {
@@ -580,6 +776,8 @@ var EventShipper = class {
580
776
  async trackSignal(signal) {
581
777
  var _a, _b;
582
778
  if (!this.enabled) return;
779
+ const destination = currentReplayTraceDestination();
780
+ if (destination && destination.kind !== "workshop") return;
583
781
  const body = [
584
782
  {
585
783
  event_id: signal.eventId,
@@ -614,6 +812,8 @@ var EventShipper = class {
614
812
  }
615
813
  async identify(users) {
616
814
  if (!this.enabled) return;
815
+ const destination = currentReplayTraceDestination();
816
+ if (destination && destination.kind !== "workshop") return;
617
817
  const list = Array.isArray(users) ? users : [users];
618
818
  const body = list.filter((user) => {
619
819
  if (!(user == null ? void 0 : user.userId) || !user.userId.trim()) {
@@ -666,8 +866,9 @@ var EventShipper = class {
666
866
  this.buffers.delete(eventId);
667
867
  if (!accumulated) return;
668
868
  const sticky = (_a = this.sticky.get(eventId)) != null ? _a : {};
669
- const eventName = (_c = (_b = accumulated.eventName) != null ? _b : sticky.eventName) != null ? _c : this.defaultEventName;
670
- const userId = (_d = accumulated.userId) != null ? _d : sticky.userId;
869
+ const isPending = (_c = (_b = accumulated.isPending) != null ? _b : sticky.isPending) != null ? _c : true;
870
+ const eventName = (_e = (_d = accumulated.eventName) != null ? _d : sticky.eventName) != null ? _e : this.defaultEventName;
871
+ const userId = (_f = accumulated.userId) != null ? _f : sticky.userId;
671
872
  if (!userId) {
672
873
  if (this.debug) {
673
874
  console.warn(`${this.prefix} skipping track_partial for ${eventId}: missing userId`);
@@ -675,9 +876,13 @@ var EventShipper = class {
675
876
  this.sticky.delete(eventId);
676
877
  return;
677
878
  }
678
- const { wizardSession, ...restProperties } = (_e = accumulated.properties) != null ? _e : {};
679
- const convoId = (_f = accumulated.convoId) != null ? _f : sticky.convoId;
680
- const isPending = (_h = (_g = accumulated.isPending) != null ? _g : sticky.isPending) != null ? _h : true;
879
+ const { wizardSession, ...restProperties } = (_g = accumulated.properties) != null ? _g : {};
880
+ let telemetryProperties = {};
881
+ try {
882
+ telemetryProperties = eventTelemetryProperties(accumulated);
883
+ } catch (e) {
884
+ }
885
+ const convoId = (_h = accumulated.convoId) != null ? _h : sticky.convoId;
681
886
  const payload = {
682
887
  event_id: eventId,
683
888
  user_id: userId,
@@ -685,15 +890,17 @@ var EventShipper = class {
685
890
  timestamp: (_i = accumulated.timestamp) != null ? _i : (/* @__PURE__ */ new Date()).toISOString(),
686
891
  ai_data: {
687
892
  input: accumulated.input,
688
- output: accumulated.output,
893
+ output: accumulated.error !== void 0 && accumulated.error !== null ? void 0 : accumulated.output,
689
894
  model: accumulated.model,
690
895
  convo_id: convoId
691
896
  },
692
897
  properties: {
693
898
  ...restProperties,
899
+ ...telemetryProperties,
694
900
  ...wizardSession ? { "raindrop.wizardSession": wizardSession } : {},
695
901
  $context: this.context
696
902
  },
903
+ ...accumulated.featureFlags && Object.keys(accumulated.featureFlags).length > 0 ? { feature_flags: accumulated.featureFlags } : {},
697
904
  attachments: accumulated.attachments,
698
905
  is_pending: isPending
699
906
  };
@@ -717,29 +924,30 @@ var EventShipper = class {
717
924
  endpoint: url
718
925
  });
719
926
  }
720
- if (this.localDebuggerUrl) {
721
- mirrorPartialEventToLocalDebugger(payload, {
722
- baseUrl: this.localDebuggerUrl,
723
- writeKey: this.writeKey,
724
- debug: this.debug,
725
- sdkName: this.sdkName
726
- });
727
- }
927
+ const mirror = this.localDebuggerUrl ? mirrorPartialEventToLocalDebugger(payload, {
928
+ baseUrl: this.localDebuggerUrl,
929
+ writeKey: this.writeKey,
930
+ debug: this.debug,
931
+ sdkName: this.sdkName
932
+ }) : void 0;
728
933
  if (!this.writeKey) {
729
934
  if (!isPending) this.sticky.delete(eventId);
935
+ if (mirror) await mirror;
730
936
  return;
731
937
  }
732
938
  const opts = this.requestOpts();
733
939
  if (!opts) {
734
940
  this.warnShutdownDrop(`track_partial ${eventId}`);
735
941
  if (!isPending) this.sticky.delete(eventId);
942
+ if (mirror) await mirror;
736
943
  return;
737
944
  }
738
945
  const p = postJson(url, payload, this.requestHeaders(), opts);
739
- this.inFlight.add(p);
946
+ const combined = mirror ? Promise.all([mirror, p]).then(() => void 0) : p;
947
+ this.inFlight.add(combined);
740
948
  try {
741
949
  try {
742
- await p;
950
+ await combined;
743
951
  if (this.debug) {
744
952
  console.log(`${this.prefix} sent track_partial ${eventId} (${eventName})`);
745
953
  }
@@ -751,13 +959,156 @@ var EventShipper = class {
751
959
  );
752
960
  }
753
961
  } finally {
754
- this.inFlight.delete(p);
962
+ this.inFlight.delete(combined);
755
963
  }
756
964
  if (!isPending) {
757
965
  this.sticky.delete(eventId);
758
966
  }
759
967
  }
760
968
  };
969
+ var MODEL_USAGE_ATTRIBUTES = {
970
+ usageSource: "raindrop.usage.source",
971
+ providerName: "gen_ai.provider.name",
972
+ requestModel: "gen_ai.request.model",
973
+ responseModel: "gen_ai.response.model",
974
+ inputTokens: "gen_ai.usage.input_tokens",
975
+ outputTokens: "gen_ai.usage.output_tokens",
976
+ reasoningTokens: "gen_ai.usage.reasoning_tokens",
977
+ cacheReadInputTokens: "gen_ai.usage.cache_read_input_tokens",
978
+ cacheWriteInputTokens: "gen_ai.usage.cache_write_input_tokens",
979
+ providerReportedCost: "gen_ai.usage.provider_reported_cost",
980
+ nonCachedInputTokens: "raindrop.usage.input_tokens.non_cached",
981
+ nonReasoningOutputTokens: "raindrop.usage.output_tokens.non_reasoning",
982
+ totalOutputTokens: "raindrop.usage.output_tokens.total",
983
+ reasoningOutputTokens: "raindrop.usage.output_tokens.reasoning",
984
+ cacheReadTokens: "raindrop.usage.input_tokens.cache_read",
985
+ cacheWriteTokens: "raindrop.usage.input_tokens.cache_write"
986
+ };
987
+ var MODEL_PROVIDER_NAMES = [
988
+ ["google.vertex.anthropic", "google-vertex"],
989
+ ["google.vertex_ai", "google-vertex"],
990
+ ["google.vertex", "google-vertex"],
991
+ ["gcp.vertex_ai", "google-vertex"],
992
+ ["gcp.gemini", "google"],
993
+ ["google_vertexai", "google-vertex"],
994
+ ["vertex.anthropic", "google-vertex"],
995
+ ["amazon-bedrock", "amazon-bedrock"],
996
+ ["aws.bedrock", "amazon-bedrock"],
997
+ ["bedrock", "amazon-bedrock"],
998
+ ["anthropic", "anthropic"],
999
+ ["openai", "openai"],
1000
+ ["google", "google"],
1001
+ ["az.ai.openai", "azure"],
1002
+ ["azure", "azure"],
1003
+ ["openrouter", "openrouter"]
1004
+ ];
1005
+ function canonicalModelProvider(provider) {
1006
+ var _a;
1007
+ const normalizedProvider = provider.trim().toLowerCase();
1008
+ if (normalizedProvider === "gateway") return "vercel";
1009
+ const match = MODEL_PROVIDER_NAMES.find(
1010
+ ([family]) => normalizedProvider === family || normalizedProvider.startsWith(`${family}.`)
1011
+ );
1012
+ return (_a = match == null ? void 0 : match[1]) != null ? _a : normalizedProvider;
1013
+ }
1014
+ var STRING_ALIASES = {
1015
+ [MODEL_USAGE_ATTRIBUTES.requestModel]: ["ai.model.id", "ai.model"]
1016
+ };
1017
+ var NUMBER_ALIASES = {
1018
+ [MODEL_USAGE_ATTRIBUTES.inputTokens]: [
1019
+ "gen_ai.usage.prompt_tokens",
1020
+ "ai.usage.prompt_tokens",
1021
+ "ai.usage.promptTokens",
1022
+ "ai.usage.input_tokens",
1023
+ "ai.usage.inputTokens"
1024
+ ],
1025
+ [MODEL_USAGE_ATTRIBUTES.outputTokens]: [
1026
+ "gen_ai.usage.completion_tokens",
1027
+ "ai.usage.completion_tokens",
1028
+ "ai.usage.completionTokens",
1029
+ "ai.usage.output_tokens",
1030
+ "ai.usage.outputTokens"
1031
+ ],
1032
+ [MODEL_USAGE_ATTRIBUTES.reasoningTokens]: [
1033
+ "gen_ai.usage.reasoning.output_tokens",
1034
+ "ai.usage.reasoningTokens",
1035
+ "ai.usage.thoughts_tokens"
1036
+ ],
1037
+ [MODEL_USAGE_ATTRIBUTES.cacheReadInputTokens]: [
1038
+ "gen_ai.usage.cache_read_tokens",
1039
+ "gen_ai.usage.cache_read.input_tokens",
1040
+ "ai.usage.cachedInputTokens",
1041
+ "ai.usage.cached_tokens",
1042
+ "ai.usage.cache_read_tokens",
1043
+ "ai.usage.cache_read_input_tokens",
1044
+ "ai.usage.cacheReadInputTokens"
1045
+ ],
1046
+ [MODEL_USAGE_ATTRIBUTES.cacheWriteInputTokens]: [
1047
+ "gen_ai.usage.cache_creation_input_tokens",
1048
+ "gen_ai.usage.cache_creation.input_tokens",
1049
+ "ai.usage.cacheWriteInputTokens",
1050
+ "ai.usage.cache_creation_input_tokens",
1051
+ "ai.usage.cacheCreationInputTokens"
1052
+ ]
1053
+ };
1054
+ function hasAttribute(attributes, key) {
1055
+ return attributes.some((attribute) => attribute.key === key);
1056
+ }
1057
+ function findStringAttribute(attributes, keys) {
1058
+ return attributes.find(
1059
+ (attribute) => keys.includes(attribute.key) && typeof attribute.value.stringValue === "string" && attribute.value.stringValue.length > 0
1060
+ );
1061
+ }
1062
+ function findNumberAttribute(attributes, keys) {
1063
+ return attributes.find((attribute) => {
1064
+ if (!keys.includes(attribute.key)) return false;
1065
+ if (typeof attribute.value.doubleValue === "number" && Number.isSafeInteger(attribute.value.doubleValue) && attribute.value.doubleValue >= 0) {
1066
+ return true;
1067
+ }
1068
+ const intValue = attribute.value.intValue;
1069
+ return integerValue(intValue) !== void 0;
1070
+ });
1071
+ }
1072
+ function integerValue(value) {
1073
+ if (typeof value === "number") {
1074
+ return Number.isSafeInteger(value) && value >= 0 ? value : void 0;
1075
+ }
1076
+ if (typeof value !== "string") return void 0;
1077
+ const parsed = Number(value);
1078
+ return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : void 0;
1079
+ }
1080
+ function appendAlias(attributes, target, source) {
1081
+ if (!source || hasAttribute(attributes, target)) return attributes;
1082
+ return [...attributes, { key: target, value: { ...source.value } }];
1083
+ }
1084
+ function appendProviderAlias(attributes) {
1085
+ if (hasAttribute(attributes, MODEL_USAGE_ATTRIBUTES.providerName)) return attributes;
1086
+ const source = findStringAttribute(attributes, ["gen_ai.system", "ai.model.provider"]);
1087
+ if (!(source == null ? void 0 : source.value.stringValue)) return attributes;
1088
+ const attribute = attrString(
1089
+ MODEL_USAGE_ATTRIBUTES.providerName,
1090
+ canonicalModelProvider(source.value.stringValue)
1091
+ );
1092
+ return attribute ? [...attributes, attribute] : attributes;
1093
+ }
1094
+ function normalizeModelUsageSpan(span) {
1095
+ const original = span.attributes;
1096
+ if (!original || original.length === 0) return span;
1097
+ const responseModel = findStringAttribute(original, [
1098
+ MODEL_USAGE_ATTRIBUTES.responseModel,
1099
+ "ai.response.model"
1100
+ ]);
1101
+ if (!responseModel) return span;
1102
+ let attributes = appendAlias(original, MODEL_USAGE_ATTRIBUTES.responseModel, responseModel);
1103
+ attributes = appendProviderAlias(attributes);
1104
+ for (const [target, aliases] of Object.entries(STRING_ALIASES)) {
1105
+ attributes = appendAlias(attributes, target, findStringAttribute(attributes, aliases));
1106
+ }
1107
+ for (const [target, aliases] of Object.entries(NUMBER_ALIASES)) {
1108
+ attributes = appendAlias(attributes, target, findNumberAttribute(attributes, aliases));
1109
+ }
1110
+ return attributes === original ? span : { ...span, attributes };
1111
+ }
761
1112
  var DEFAULT_SECRET_KEY_NAMES = [
762
1113
  "apikey",
763
1114
  "apisecret",
@@ -847,6 +1198,13 @@ function redactJsonAttributeValue(key, value) {
847
1198
  if (scrubbedJson === json) return void 0;
848
1199
  return { stringValue: scrubbedJson };
849
1200
  }
1201
+ function identityAttrs(args) {
1202
+ return [
1203
+ attrString("ai.telemetry.metadata.raindrop.ai.userId", args.userId),
1204
+ attrString("ai.telemetry.metadata.raindrop.convoId", args.convoId),
1205
+ attrString("ai.telemetry.metadata.raindrop.eventName", args.eventName)
1206
+ ];
1207
+ }
850
1208
  function applyOtelSpanAttributeLimit(limit) {
851
1209
  var _a, _b;
852
1210
  try {
@@ -942,7 +1300,10 @@ var TraceShipper = class {
942
1300
  try {
943
1301
  const result = this.transformSpanHook(current);
944
1302
  if (result === null) return null;
945
- if (result !== void 0) current = result;
1303
+ if (result !== void 0) {
1304
+ copyReplayTraceDestination(current, result);
1305
+ current = result;
1306
+ }
946
1307
  } catch (err) {
947
1308
  if (this.debug) {
948
1309
  const msg = err instanceof Error ? err.message : String(err);
@@ -951,10 +1312,20 @@ var TraceShipper = class {
951
1312
  return null;
952
1313
  }
953
1314
  }
1315
+ try {
1316
+ const normalized = normalizeModelUsageSpan(current);
1317
+ copyReplayTraceDestination(current, normalized);
1318
+ current = normalized;
1319
+ } catch (e) {
1320
+ }
954
1321
  if (!this.disableDefaultRedaction) {
955
- current = defaultTransformSpan(current);
1322
+ const redacted = defaultTransformSpan(current);
1323
+ copyReplayTraceDestination(current, redacted);
1324
+ current = redacted;
956
1325
  }
957
- return this.capSpanAttributes(current);
1326
+ const capped = this.capSpanAttributes(current);
1327
+ copyReplayTraceDestination(current, capped);
1328
+ return capped;
958
1329
  }
959
1330
  isDebugEnabled() {
960
1331
  return this.debug;
@@ -971,33 +1342,55 @@ var TraceShipper = class {
971
1342
  const started = (_a = args.startTimeUnixNano) != null ? _a : nowUnixNanoString();
972
1343
  const attrs = [
973
1344
  attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId),
974
- attrString("ai.operationId", args.operationId)
1345
+ ...identityAttrs(args),
1346
+ attrString("ai.operationId", args.operationId),
1347
+ ...Object.entries(evalScopeAttributes()).map(([key, value]) => attrString(key, value))
975
1348
  ];
976
1349
  if ((_b = args.attributes) == null ? void 0 : _b.length) attrs.push(...args.attributes);
977
- const span = { ids, name: args.name, startTimeUnixNano: started, attributes: attrs };
978
- this.mirrorToLocalDebugger(
979
- buildOtlpSpan({
980
- ids: span.ids,
981
- name: span.name,
982
- startTimeUnixNano: span.startTimeUnixNano,
983
- endTimeUnixNano: span.startTimeUnixNano,
984
- // placeholder — will be updated on endSpan
985
- attributes: span.attributes,
986
- status: { code: SpanStatusCode.UNSET }
987
- })
988
- );
1350
+ const span = {
1351
+ ids,
1352
+ name: args.name,
1353
+ startTimeUnixNano: started,
1354
+ attributes: attrs
1355
+ };
1356
+ rememberReplayTraceDestination(span);
1357
+ const openSpan = buildOtlpSpan({
1358
+ ids: span.ids,
1359
+ name: span.name,
1360
+ startTimeUnixNano: span.startTimeUnixNano,
1361
+ endTimeUnixNano: span.startTimeUnixNano,
1362
+ // placeholder — will be updated on endSpan
1363
+ attributes: span.attributes,
1364
+ status: { code: SpanStatusCode.UNSET }
1365
+ });
1366
+ copyReplayTraceDestination(span, openSpan);
1367
+ this.mirrorToLocalDebugger(openSpan);
989
1368
  return span;
990
1369
  }
991
- mirrorToLocalDebugger(span) {
992
- if (!this.localDebuggerUrl) return;
1370
+ mirrorToLocalDebugger(span, completed = false) {
1371
+ const destination = replayTraceDestinationFor(span);
1372
+ if (destination && destination.kind !== "workshop") return;
1373
+ const localDebuggerUrl = (destination == null ? void 0 : destination.kind) === "workshop" ? destination.url : this.localDebuggerUrl;
1374
+ if (!localDebuggerUrl) return;
993
1375
  const redacted = this.redactSpan(span);
994
1376
  if (redacted === null) return;
1377
+ if (completed && (destination == null ? void 0 : destination.kind) === "workshop") {
1378
+ recordReplayExportedSpan(
1379
+ destination,
1380
+ base64ToHex(redacted.spanId),
1381
+ base64ToHex(redacted.traceId)
1382
+ );
1383
+ }
995
1384
  const body = buildExportTraceServiceRequest([redacted], this.serviceName, this.serviceVersion);
996
- mirrorTraceExportToLocalDebugger(body, {
997
- baseUrl: this.localDebuggerUrl,
1385
+ const p = mirrorTraceExportToLocalDebugger(body, {
1386
+ baseUrl: localDebuggerUrl,
998
1387
  debug: false,
999
1388
  sdkName: this.sdkName
1000
1389
  });
1390
+ this.inFlight.add(p);
1391
+ void p.finally(() => {
1392
+ this.inFlight.delete(p);
1393
+ });
1001
1394
  }
1002
1395
  endSpan(span, extra) {
1003
1396
  var _a, _b;
@@ -1019,14 +1412,17 @@ var TraceShipper = class {
1019
1412
  attributes: span.attributes,
1020
1413
  status
1021
1414
  });
1415
+ copyReplayTraceDestination(span, otlp);
1022
1416
  this.enqueue(otlp);
1023
- this.mirrorToLocalDebugger(otlp);
1417
+ this.mirrorToLocalDebugger(otlp, true);
1024
1418
  }
1025
1419
  createSpan(args) {
1026
1420
  var _a;
1027
1421
  const ids = createSpanIds(args.parent);
1028
1422
  const attrs = [
1029
- attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId)
1423
+ attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId),
1424
+ ...identityAttrs(args),
1425
+ ...Object.entries(evalScopeAttributes()).map(([key, value]) => attrString(key, value))
1030
1426
  ];
1031
1427
  if ((_a = args.attributes) == null ? void 0 : _a.length) attrs.push(...args.attributes);
1032
1428
  const otlp = buildOtlpSpan({
@@ -1037,8 +1433,9 @@ var TraceShipper = class {
1037
1433
  attributes: attrs,
1038
1434
  status: args.status
1039
1435
  });
1436
+ rememberReplayTraceDestination(otlp);
1040
1437
  this.enqueue(otlp);
1041
- this.mirrorToLocalDebugger(otlp);
1438
+ this.mirrorToLocalDebugger(otlp, true);
1042
1439
  }
1043
1440
  enqueue(span) {
1044
1441
  if (!this.enabled) return;
@@ -1052,6 +1449,13 @@ var TraceShipper = class {
1052
1449
  }
1053
1450
  const redacted = this.redactSpan(span);
1054
1451
  if (redacted === null) return;
1452
+ const destination = replayTraceDestinationFor(redacted);
1453
+ recordReplayExportedSpan(
1454
+ destination,
1455
+ base64ToHex(redacted.spanId),
1456
+ base64ToHex(redacted.traceId)
1457
+ );
1458
+ if ((destination == null ? void 0 : destination.kind) === "workshop") return;
1055
1459
  if (this.queue.length >= this.maxQueueSize) {
1056
1460
  this.queue.shift();
1057
1461
  }
@@ -1070,47 +1474,67 @@ var TraceShipper = class {
1070
1474
  }
1071
1475
  }
1072
1476
  async flush() {
1073
- if (!this.enabled) return;
1477
+ var _a;
1478
+ if (!this.enabled) {
1479
+ await Promise.all([...this.inFlight].map((p) => p.catch(() => {
1480
+ })));
1481
+ return;
1482
+ }
1074
1483
  if (this.timer) {
1075
1484
  clearTimeout(this.timer);
1076
1485
  this.timer = void 0;
1077
1486
  }
1078
1487
  while (this.queue.length > 0) {
1079
1488
  const batch = this.queue.splice(0, this.maxBatchSize);
1080
- if (!this.writeKey) continue;
1081
- const opts = this.requestOpts();
1082
- if (!opts) {
1083
- rateLimitedLog(
1084
- `${this.prefix}.shutdown_deadline`,
1085
- () => console.warn(
1086
- `${this.prefix} shutdown flush deadline exceeded; dropping ${batch.length} spans`
1087
- )
1088
- );
1089
- continue;
1090
- }
1091
- const body = buildExportTraceServiceRequest(batch, this.serviceName, this.serviceVersion);
1092
- const url = `${this.baseUrl}traces`;
1093
- if (this.debug) {
1094
- console.log(`${this.prefix} sending traces batch`, {
1095
- spans: batch.length,
1096
- endpoint: url
1097
- });
1489
+ const groups = /* @__PURE__ */ new Map();
1490
+ for (const span of batch) {
1491
+ const destination = replayTraceDestinationFor(span);
1492
+ const spans = groups.get(destination);
1493
+ if (spans) spans.push(span);
1494
+ else groups.set(destination, [span]);
1098
1495
  }
1099
- const p = postJson(url, body, this.requestHeaders(), opts);
1100
- this.inFlight.add(p);
1101
- try {
1102
- try {
1103
- await p;
1104
- if (this.debug) console.log(`${this.prefix} sent ${batch.length} spans`);
1105
- } catch (err) {
1106
- const msg = err instanceof Error ? err.message : String(err);
1496
+ for (const [destination, spans] of groups) {
1497
+ if (!destination && !this.writeKey) continue;
1498
+ if ((destination == null ? void 0 : destination.kind) === "workshop") continue;
1499
+ const opts = this.requestOpts();
1500
+ if (!opts) {
1107
1501
  rateLimitedLog(
1108
- `${this.prefix}.send_spans_failed`,
1109
- () => console.warn(`${this.prefix} failed to send ${batch.length} spans: ${msg}`)
1502
+ `${this.prefix}.shutdown_deadline`,
1503
+ () => console.warn(
1504
+ `${this.prefix} shutdown flush deadline exceeded; dropping ${spans.length} spans`
1505
+ )
1110
1506
  );
1507
+ continue;
1508
+ }
1509
+ const body = buildExportTraceServiceRequest(spans, this.serviceName, this.serviceVersion);
1510
+ const url = destination ? replayTraceUrl(destination.url) : `${this.baseUrl}traces`;
1511
+ const headers = destination ? {
1512
+ Authorization: `Bearer ${destination.apiKey}`,
1513
+ "X-Raindrop-Replay-Id": destination.replayId,
1514
+ "X-Raindrop-Project-Id": (_a = destination.projectId) != null ? _a : "default"
1515
+ } : this.requestHeaders();
1516
+ if (this.debug) {
1517
+ console.log(`${this.prefix} sending traces batch`, {
1518
+ spans: spans.length,
1519
+ endpoint: url
1520
+ });
1521
+ }
1522
+ const p = postJson(url, body, headers, opts);
1523
+ this.inFlight.add(p);
1524
+ try {
1525
+ try {
1526
+ await p;
1527
+ if (this.debug) console.log(`${this.prefix} sent ${spans.length} spans`);
1528
+ } catch (err) {
1529
+ const msg = err instanceof Error ? err.message : String(err);
1530
+ rateLimitedLog(
1531
+ `${this.prefix}.send_spans_failed`,
1532
+ () => console.warn(`${this.prefix} failed to send ${spans.length} spans: ${msg}`)
1533
+ );
1534
+ }
1535
+ } finally {
1536
+ this.inFlight.delete(p);
1111
1537
  }
1112
- } finally {
1113
- this.inFlight.delete(p);
1114
1538
  }
1115
1539
  }
1116
1540
  }
@@ -1153,7 +1577,9 @@ var TraceShipper = class {
1153
1577
  if (!settled) {
1154
1578
  rateLimitedLog(
1155
1579
  `${this.prefix}.shutdown_deadline`,
1156
- () => console.warn(`${this.prefix} shutdown flush deadline exceeded; abandoning in-flight spans`)
1580
+ () => console.warn(
1581
+ `${this.prefix} shutdown flush deadline exceeded; abandoning in-flight spans`
1582
+ )
1157
1583
  );
1158
1584
  }
1159
1585
  } finally {
@@ -1192,6 +1618,15 @@ function installTracingSuppressionHook() {
1192
1618
  installTracingSuppressionHook();
1193
1619
 
1194
1620
  // src/callback-handler.ts
1621
+ function resolveEventId(source) {
1622
+ if (typeof source !== "function") return randomUUID();
1623
+ try {
1624
+ const id = source();
1625
+ return typeof id === "string" && id.trim() !== "" ? id : randomUUID();
1626
+ } catch {
1627
+ return randomUUID();
1628
+ }
1629
+ }
1195
1630
  function isInternalName(name) {
1196
1631
  if (name.startsWith("Branch:")) return true;
1197
1632
  if (name.startsWith("ChannelWrite")) return true;
@@ -1240,13 +1675,15 @@ var RaindropDeepAgentsHandler = class extends import_base.BaseCallbackHandler {
1240
1675
  this.traceShipper = opts.traceShipper;
1241
1676
  this.userId = opts.userId;
1242
1677
  this.convoId = opts.convoId;
1678
+ this.eventName = opts.eventName;
1679
+ this.eventIdSource = opts.eventId;
1243
1680
  this.traceChains = opts.traceChains ?? true;
1244
1681
  }
1245
1682
  getEventId(runId, parentRunId) {
1246
1683
  const rootId = parentRunId ? this.rootRunIds.get(parentRunId) ?? parentRunId : runId;
1247
1684
  this.rootRunIds.set(runId, rootId);
1248
1685
  if (!this.eventIds.has(rootId)) {
1249
- this.eventIds.set(rootId, randomUUID());
1686
+ this.eventIds.set(rootId, resolveEventId(this.eventIdSource));
1250
1687
  }
1251
1688
  return this.eventIds.get(rootId);
1252
1689
  }
@@ -1275,10 +1712,11 @@ var RaindropDeepAgentsHandler = class extends import_base.BaseCallbackHandler {
1275
1712
  const eventId = this.eventIds.get(rootId);
1276
1713
  if (!eventId) return;
1277
1714
  if (isRoot) {
1278
- if (this.convoId) {
1715
+ if (this.convoId || this.eventName) {
1279
1716
  await this.eventShipper.patch(eventId, {
1280
1717
  userId: this.userId,
1281
1718
  convoId: this.convoId,
1719
+ eventName: this.eventName,
1282
1720
  isPending: true
1283
1721
  });
1284
1722
  }
@@ -1287,11 +1725,16 @@ var RaindropDeepAgentsHandler = class extends import_base.BaseCallbackHandler {
1287
1725
  await this.eventShipper.patch(eventId, {
1288
1726
  userId: this.userId,
1289
1727
  convoId: this.convoId,
1728
+ eventName: this.eventName,
1290
1729
  ...patch,
1291
1730
  isPending: true
1292
1731
  });
1293
1732
  }
1294
1733
  }
1734
+ rootErrorPatch(runId, error) {
1735
+ const rootId = this.rootRunIds.get(runId) ?? runId;
1736
+ return rootId === runId ? { error } : void 0;
1737
+ }
1295
1738
  // ---------------------------------------------------------------------------
1296
1739
  // LLM events
1297
1740
  // ---------------------------------------------------------------------------
@@ -1313,6 +1756,7 @@ var RaindropDeepAgentsHandler = class extends import_base.BaseCallbackHandler {
1313
1756
  await this.eventShipper.patch(eventId, {
1314
1757
  userId: this.userId,
1315
1758
  convoId: this.convoId,
1759
+ eventName: this.eventName,
1316
1760
  input: truncate(prompts.join("\n"), CHAIN_TEXT_MAX_LEN),
1317
1761
  properties: buildProperties(tags, metadata),
1318
1762
  isPending: true
@@ -1346,6 +1790,7 @@ var RaindropDeepAgentsHandler = class extends import_base.BaseCallbackHandler {
1346
1790
  await this.eventShipper.patch(eventId, {
1347
1791
  userId: this.userId,
1348
1792
  convoId: this.convoId,
1793
+ eventName: this.eventName,
1349
1794
  input: inputText,
1350
1795
  properties: buildProperties(tags, metadata),
1351
1796
  isPending: true
@@ -1385,8 +1830,6 @@ var RaindropDeepAgentsHandler = class extends import_base.BaseCallbackHandler {
1385
1830
  ]
1386
1831
  });
1387
1832
  const properties = {};
1388
- if (promptTokens != null) properties["ai.usage.prompt_tokens"] = promptTokens;
1389
- if (completionTokens != null) properties["ai.usage.completion_tokens"] = completionTokens;
1390
1833
  if (cachedTokens != null) properties["ai.usage.cached_tokens"] = cachedTokens;
1391
1834
  if (reasoningTokens != null) properties["ai.usage.thoughts_tokens"] = reasoningTokens;
1392
1835
  if (finishReason != null) properties["ai.finish_reason"] = finishReason;
@@ -1394,6 +1837,7 @@ var RaindropDeepAgentsHandler = class extends import_base.BaseCallbackHandler {
1394
1837
  await this.finalizeEventIfRoot(runId, {
1395
1838
  output: cappedOutput,
1396
1839
  model,
1840
+ usage: { promptTokens, completionTokens },
1397
1841
  properties: Object.keys(properties).length > 0 ? properties : void 0
1398
1842
  });
1399
1843
  } catch {
@@ -1411,14 +1855,7 @@ var RaindropDeepAgentsHandler = class extends import_base.BaseCallbackHandler {
1411
1855
  if (span) {
1412
1856
  this.traceShipper.endSpan(span, { error: err });
1413
1857
  }
1414
- const errorInfo = extractErrorInfo(err);
1415
- await this.finalizeEventIfRoot(runId, {
1416
- output: `[Error] ${errorInfo.type}: ${errorInfo.message}`,
1417
- properties: {
1418
- "error.type": errorInfo.type,
1419
- "error.message": errorInfo.message
1420
- }
1421
- });
1858
+ await this.finalizeEventIfRoot(runId, this.rootErrorPatch(runId, err));
1422
1859
  } catch {
1423
1860
  } finally {
1424
1861
  this.cleanup(runId);
@@ -1480,14 +1917,7 @@ var RaindropDeepAgentsHandler = class extends import_base.BaseCallbackHandler {
1480
1917
  const span = this.spans.get(runId);
1481
1918
  if (span) this.traceShipper.endSpan(span, { error: err });
1482
1919
  }
1483
- const errorInfo = extractErrorInfo(err);
1484
- await this.finalizeEventIfRoot(runId, {
1485
- output: `[Error] ${errorInfo.type}: ${errorInfo.message}`,
1486
- properties: {
1487
- "error.type": errorInfo.type,
1488
- "error.message": errorInfo.message
1489
- }
1490
- });
1920
+ await this.finalizeEventIfRoot(runId, this.rootErrorPatch(runId, err));
1491
1921
  } catch {
1492
1922
  } finally {
1493
1923
  this.cleanup(runId);
@@ -1542,14 +1972,7 @@ var RaindropDeepAgentsHandler = class extends import_base.BaseCallbackHandler {
1542
1972
  try {
1543
1973
  const span = this.spans.get(runId);
1544
1974
  if (span) this.traceShipper.endSpan(span, { error: err });
1545
- const errorInfo = extractErrorInfo(err);
1546
- await this.finalizeEventIfRoot(runId, {
1547
- output: `[Error] ${errorInfo.type}: ${errorInfo.message}`,
1548
- properties: {
1549
- "error.type": errorInfo.type,
1550
- "error.message": errorInfo.message
1551
- }
1552
- });
1975
+ await this.finalizeEventIfRoot(runId, this.rootErrorPatch(runId, err));
1553
1976
  } catch {
1554
1977
  } finally {
1555
1978
  this.cleanup(runId);
@@ -1714,18 +2137,6 @@ function asNumber(val) {
1714
2137
  const n = typeof val === "number" ? val : Number(val);
1715
2138
  return Number.isFinite(n) ? n : void 0;
1716
2139
  }
1717
- function extractErrorInfo(err) {
1718
- if (err instanceof Error) {
1719
- return { type: err.name || err.constructor.name, message: err.message };
1720
- }
1721
- if (typeof err === "object" && err !== null) {
1722
- const e = err;
1723
- const type = e.name ?? e.constructor?.name ?? "Error";
1724
- const message = e.message ?? safeStringify(err);
1725
- return { type, message };
1726
- }
1727
- return { type: "Error", message: String(err) };
1728
- }
1729
2140
 
1730
2141
  // src/version.ts
1731
2142
  var libraryName = "@raindrop-ai/deep-agents";
@@ -1765,6 +2176,8 @@ function createRaindropDeepAgents(opts) {
1765
2176
  traceShipper,
1766
2177
  userId: opts.userId,
1767
2178
  convoId: opts.convoId,
2179
+ eventName: opts.eventName,
2180
+ eventId: opts.eventId,
1768
2181
  traceChains: opts.traceChains
1769
2182
  });
1770
2183
  return {