@raindrop-ai/claude-code 0.0.17 → 0.0.19

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "raindrop",
3
- "version": "0.0.13",
3
+ "version": "0.0.19",
4
4
  "description": "Observability for Claude Code \u2014 automatic session, tool call, and prompt tracing",
5
5
  "author": {
6
6
  "name": "Raindrop AI",
package/dist/cli.js CHANGED
@@ -7,7 +7,7 @@ import { randomUUID as randomUUID2 } from "crypto";
7
7
  import { tmpdir } from "os";
8
8
  import { join } from "path";
9
9
 
10
- // ../core/dist/chunk-SK6EJEO7.js
10
+ // ../core/dist/chunk-5PSWD267.js
11
11
  function getCrypto() {
12
12
  const c = globalThis.crypto;
13
13
  return c;
@@ -51,6 +51,34 @@ function base64Encode(bytes) {
51
51
  }
52
52
  return out;
53
53
  }
54
+ var HANDOFF_ATTRIBUTE_SUFFIXES = {
55
+ mode: "raindrop.handoff.mode",
56
+ childEventId: "raindrop.handoff.childEventId",
57
+ parentEventId: "raindrop.handoff.parentEventId",
58
+ parentSpanId: "raindrop.handoff.parentSpanId",
59
+ name: "raindrop.handoff.name",
60
+ terminal: "raindrop.handoff.terminal",
61
+ agentRole: "raindrop.agent.role"
62
+ };
63
+ var HANDOFF_TERMINAL_PROPERTY_KEY = HANDOFF_ATTRIBUTE_SUFFIXES.terminal;
64
+ var TRACEPARENT_HEADER = "traceparent";
65
+ var BAGGAGE_HEADER = "baggage";
66
+ var HANDOFF_HEADER = "x-raindrop-handoff";
67
+ 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.`;
68
+ function runWithTracingSuppressed(fn) {
69
+ const hook = globalThis.RAINDROP_SUPPRESS_TRACING;
70
+ if (typeof hook !== "function") return fn();
71
+ let started = false;
72
+ try {
73
+ return hook(() => {
74
+ started = true;
75
+ return fn();
76
+ });
77
+ } catch (err) {
78
+ if (started) throw err;
79
+ return fn();
80
+ }
81
+ }
54
82
  var DEFAULT_REQUEST_TIMEOUT_MS = 3e4;
55
83
  var MAX_RETRY_DELAY_MS = 3e4;
56
84
  function wait(ms) {
@@ -161,15 +189,17 @@ async function postJson(url, body, headers, opts) {
161
189
  const timeoutMs = (_a = opts.timeoutMs) != null ? _a : DEFAULT_REQUEST_TIMEOUT_MS;
162
190
  await withRetry(
163
191
  async () => {
164
- const resp = await fetch(url, {
165
- method: "POST",
166
- headers: {
167
- "Content-Type": "application/json",
168
- ...headers
169
- },
170
- body: JSON.stringify(body),
171
- signal: AbortSignal.timeout(timeoutMs)
172
- });
192
+ const resp = await runWithTracingSuppressed(
193
+ () => fetch(url, {
194
+ method: "POST",
195
+ headers: {
196
+ "Content-Type": "application/json",
197
+ ...headers
198
+ },
199
+ body: JSON.stringify(body),
200
+ signal: AbortSignal.timeout(timeoutMs)
201
+ })
202
+ );
173
203
  if (!resp.ok) {
174
204
  const text = await resp.text().catch(() => "");
175
205
  const err = new Error(
@@ -325,26 +355,29 @@ function resolveLocalDebuggerBaseUrl(baseUrl) {
325
355
  if (shouldAutoEnableLocalWorkshop()) return DEFAULT_LOCAL_WORKSHOP_URL;
326
356
  return null;
327
357
  }
358
+ var LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS = 2e3;
328
359
  function mirrorTraceExportToLocalDebugger(body, options = {}) {
329
360
  var _a;
330
361
  const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
331
- if (!baseUrl) return;
332
- void postJson(`${baseUrl}traces`, body, {}, {
362
+ if (!baseUrl) return Promise.resolve();
363
+ return postJson(`${baseUrl}traces`, body, {}, {
333
364
  maxAttempts: 1,
334
365
  debug: (_a = options.debug) != null ? _a : false,
335
- sdkName: options.sdkName
366
+ sdkName: options.sdkName,
367
+ timeoutMs: LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS
336
368
  }).catch(() => {
337
369
  });
338
370
  }
339
371
  function mirrorPartialEventToLocalDebugger(event, options = {}) {
340
372
  var _a;
341
373
  const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
342
- if (!baseUrl) return;
374
+ if (!baseUrl) return Promise.resolve();
343
375
  const headers = options.writeKey ? { Authorization: `Bearer ${options.writeKey}` } : {};
344
- void postJson(`${baseUrl}events/track_partial`, event, headers, {
376
+ return postJson(`${baseUrl}events/track_partial`, event, headers, {
345
377
  maxAttempts: 1,
346
378
  debug: (_a = options.debug) != null ? _a : false,
347
- sdkName: options.sdkName
379
+ sdkName: options.sdkName,
380
+ timeoutMs: LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS
348
381
  }).catch(() => {
349
382
  });
350
383
  }
@@ -370,16 +403,52 @@ function projectIdHeaders(projectId) {
370
403
  var SHUTDOWN_DEADLINE_MS = 1e4;
371
404
  var POST_SHUTDOWN_TIMEOUT_MS = 5e3;
372
405
  function mergePatches(target, source) {
373
- var _a, _b, _c, _d;
406
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
374
407
  const out = { ...target, ...source };
375
408
  if (target.properties || source.properties) {
376
409
  out.properties = { ...(_a = target.properties) != null ? _a : {}, ...(_b = source.properties) != null ? _b : {} };
377
410
  }
411
+ if (target.usage || source.usage) {
412
+ out.usage = { ...(_c = target.usage) != null ? _c : {} };
413
+ if (((_d = source.usage) == null ? void 0 : _d.promptTokens) !== void 0) {
414
+ out.usage.promptTokens = source.usage.promptTokens;
415
+ }
416
+ if (((_e = source.usage) == null ? void 0 : _e.completionTokens) !== void 0) {
417
+ out.usage.completionTokens = source.usage.completionTokens;
418
+ }
419
+ }
420
+ if (source.error === void 0) {
421
+ out.error = target.error;
422
+ }
423
+ if (target.featureFlags || source.featureFlags) {
424
+ out.featureFlags = { ...(_f = target.featureFlags) != null ? _f : {}, ...(_g = source.featureFlags) != null ? _g : {} };
425
+ }
378
426
  if (target.attachments || source.attachments) {
379
- out.attachments = [...(_c = target.attachments) != null ? _c : [], ...(_d = source.attachments) != null ? _d : []];
427
+ out.attachments = [...(_h = target.attachments) != null ? _h : [], ...(_i = source.attachments) != null ? _i : []];
380
428
  }
381
429
  return out;
382
430
  }
431
+ function isErrorLike(value) {
432
+ return value !== null && typeof value === "object";
433
+ }
434
+ function eventTelemetryProperties(patch) {
435
+ var _a, _b;
436
+ const properties = {};
437
+ if (((_a = patch.usage) == null ? void 0 : _a.promptTokens) !== void 0 && Number.isFinite(patch.usage.promptTokens)) {
438
+ properties["ai.usage.prompt_tokens"] = patch.usage.promptTokens;
439
+ }
440
+ if (((_b = patch.usage) == null ? void 0 : _b.completionTokens) !== void 0 && Number.isFinite(patch.usage.completionTokens)) {
441
+ properties["ai.usage.completion_tokens"] = patch.usage.completionTokens;
442
+ }
443
+ if (patch.error !== void 0 && patch.error !== null) {
444
+ const constructorName = patch.error instanceof Error && patch.error.constructor !== Error ? patch.error.constructor.name : void 0;
445
+ 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";
446
+ const errorMessage = patch.error instanceof Error ? patch.error.message : isErrorLike(patch.error) && typeof patch.error.message === "string" ? patch.error.message : String(patch.error);
447
+ properties["error.type"] = errorType;
448
+ properties["error.message"] = errorMessage;
449
+ }
450
+ return properties;
451
+ }
383
452
  var EventShipper = class {
384
453
  constructor(opts) {
385
454
  this.buffers = /* @__PURE__ */ new Map();
@@ -628,6 +697,11 @@ var EventShipper = class {
628
697
  return;
629
698
  }
630
699
  const { wizardSession, ...restProperties } = (_e = accumulated.properties) != null ? _e : {};
700
+ let telemetryProperties = {};
701
+ try {
702
+ telemetryProperties = eventTelemetryProperties(accumulated);
703
+ } catch (e) {
704
+ }
631
705
  const convoId = (_f = accumulated.convoId) != null ? _f : sticky.convoId;
632
706
  const isPending = (_h = (_g = accumulated.isPending) != null ? _g : sticky.isPending) != null ? _h : true;
633
707
  const payload = {
@@ -637,15 +711,17 @@ var EventShipper = class {
637
711
  timestamp: (_i = accumulated.timestamp) != null ? _i : (/* @__PURE__ */ new Date()).toISOString(),
638
712
  ai_data: {
639
713
  input: accumulated.input,
640
- output: accumulated.output,
714
+ output: accumulated.error !== void 0 && accumulated.error !== null ? void 0 : accumulated.output,
641
715
  model: accumulated.model,
642
716
  convo_id: convoId
643
717
  },
644
718
  properties: {
645
719
  ...restProperties,
720
+ ...telemetryProperties,
646
721
  ...wizardSession ? { "raindrop.wizardSession": wizardSession } : {},
647
722
  $context: this.context
648
723
  },
724
+ ...accumulated.featureFlags && Object.keys(accumulated.featureFlags).length > 0 ? { feature_flags: accumulated.featureFlags } : {},
649
725
  attachments: accumulated.attachments,
650
726
  is_pending: isPending
651
727
  };
@@ -669,29 +745,30 @@ var EventShipper = class {
669
745
  endpoint: url
670
746
  });
671
747
  }
672
- if (this.localDebuggerUrl) {
673
- mirrorPartialEventToLocalDebugger(payload, {
674
- baseUrl: this.localDebuggerUrl,
675
- writeKey: this.writeKey,
676
- debug: this.debug,
677
- sdkName: this.sdkName
678
- });
679
- }
748
+ const mirror = this.localDebuggerUrl ? mirrorPartialEventToLocalDebugger(payload, {
749
+ baseUrl: this.localDebuggerUrl,
750
+ writeKey: this.writeKey,
751
+ debug: this.debug,
752
+ sdkName: this.sdkName
753
+ }) : void 0;
680
754
  if (!this.writeKey) {
681
755
  if (!isPending) this.sticky.delete(eventId);
756
+ if (mirror) await mirror;
682
757
  return;
683
758
  }
684
759
  const opts = this.requestOpts();
685
760
  if (!opts) {
686
761
  this.warnShutdownDrop(`track_partial ${eventId}`);
687
762
  if (!isPending) this.sticky.delete(eventId);
763
+ if (mirror) await mirror;
688
764
  return;
689
765
  }
690
766
  const p = postJson(url, payload, this.requestHeaders(), opts);
691
- this.inFlight.add(p);
767
+ const combined = mirror ? Promise.all([mirror, p]).then(() => void 0) : p;
768
+ this.inFlight.add(combined);
692
769
  try {
693
770
  try {
694
- await p;
771
+ await combined;
695
772
  if (this.debug) {
696
773
  console.log(`${this.prefix} sent track_partial ${eventId} (${eventName})`);
697
774
  }
@@ -703,13 +780,156 @@ var EventShipper = class {
703
780
  );
704
781
  }
705
782
  } finally {
706
- this.inFlight.delete(p);
783
+ this.inFlight.delete(combined);
707
784
  }
708
785
  if (!isPending) {
709
786
  this.sticky.delete(eventId);
710
787
  }
711
788
  }
712
789
  };
790
+ var MODEL_USAGE_ATTRIBUTES = {
791
+ usageSource: "raindrop.usage.source",
792
+ providerName: "gen_ai.provider.name",
793
+ requestModel: "gen_ai.request.model",
794
+ responseModel: "gen_ai.response.model",
795
+ inputTokens: "gen_ai.usage.input_tokens",
796
+ outputTokens: "gen_ai.usage.output_tokens",
797
+ reasoningTokens: "gen_ai.usage.reasoning_tokens",
798
+ cacheReadInputTokens: "gen_ai.usage.cache_read_input_tokens",
799
+ cacheWriteInputTokens: "gen_ai.usage.cache_write_input_tokens",
800
+ providerReportedCost: "gen_ai.usage.provider_reported_cost",
801
+ nonCachedInputTokens: "raindrop.usage.input_tokens.non_cached",
802
+ nonReasoningOutputTokens: "raindrop.usage.output_tokens.non_reasoning",
803
+ totalOutputTokens: "raindrop.usage.output_tokens.total",
804
+ reasoningOutputTokens: "raindrop.usage.output_tokens.reasoning",
805
+ cacheReadTokens: "raindrop.usage.input_tokens.cache_read",
806
+ cacheWriteTokens: "raindrop.usage.input_tokens.cache_write"
807
+ };
808
+ var MODEL_PROVIDER_NAMES = [
809
+ ["google.vertex.anthropic", "google-vertex"],
810
+ ["google.vertex_ai", "google-vertex"],
811
+ ["google.vertex", "google-vertex"],
812
+ ["gcp.vertex_ai", "google-vertex"],
813
+ ["gcp.gemini", "google"],
814
+ ["google_vertexai", "google-vertex"],
815
+ ["vertex.anthropic", "google-vertex"],
816
+ ["amazon-bedrock", "amazon-bedrock"],
817
+ ["aws.bedrock", "amazon-bedrock"],
818
+ ["bedrock", "amazon-bedrock"],
819
+ ["anthropic", "anthropic"],
820
+ ["openai", "openai"],
821
+ ["google", "google"],
822
+ ["az.ai.openai", "azure"],
823
+ ["azure", "azure"],
824
+ ["openrouter", "openrouter"]
825
+ ];
826
+ function canonicalModelProvider(provider) {
827
+ var _a;
828
+ const normalizedProvider = provider.trim().toLowerCase();
829
+ if (normalizedProvider === "gateway") return "vercel";
830
+ const match = MODEL_PROVIDER_NAMES.find(
831
+ ([family]) => normalizedProvider === family || normalizedProvider.startsWith(`${family}.`)
832
+ );
833
+ return (_a = match == null ? void 0 : match[1]) != null ? _a : normalizedProvider;
834
+ }
835
+ var STRING_ALIASES = {
836
+ [MODEL_USAGE_ATTRIBUTES.requestModel]: ["ai.model.id", "ai.model"]
837
+ };
838
+ var NUMBER_ALIASES = {
839
+ [MODEL_USAGE_ATTRIBUTES.inputTokens]: [
840
+ "gen_ai.usage.prompt_tokens",
841
+ "ai.usage.prompt_tokens",
842
+ "ai.usage.promptTokens",
843
+ "ai.usage.input_tokens",
844
+ "ai.usage.inputTokens"
845
+ ],
846
+ [MODEL_USAGE_ATTRIBUTES.outputTokens]: [
847
+ "gen_ai.usage.completion_tokens",
848
+ "ai.usage.completion_tokens",
849
+ "ai.usage.completionTokens",
850
+ "ai.usage.output_tokens",
851
+ "ai.usage.outputTokens"
852
+ ],
853
+ [MODEL_USAGE_ATTRIBUTES.reasoningTokens]: [
854
+ "gen_ai.usage.reasoning.output_tokens",
855
+ "ai.usage.reasoningTokens",
856
+ "ai.usage.thoughts_tokens"
857
+ ],
858
+ [MODEL_USAGE_ATTRIBUTES.cacheReadInputTokens]: [
859
+ "gen_ai.usage.cache_read_tokens",
860
+ "gen_ai.usage.cache_read.input_tokens",
861
+ "ai.usage.cachedInputTokens",
862
+ "ai.usage.cached_tokens",
863
+ "ai.usage.cache_read_tokens",
864
+ "ai.usage.cache_read_input_tokens",
865
+ "ai.usage.cacheReadInputTokens"
866
+ ],
867
+ [MODEL_USAGE_ATTRIBUTES.cacheWriteInputTokens]: [
868
+ "gen_ai.usage.cache_creation_input_tokens",
869
+ "gen_ai.usage.cache_creation.input_tokens",
870
+ "ai.usage.cacheWriteInputTokens",
871
+ "ai.usage.cache_creation_input_tokens",
872
+ "ai.usage.cacheCreationInputTokens"
873
+ ]
874
+ };
875
+ function hasAttribute(attributes, key) {
876
+ return attributes.some((attribute) => attribute.key === key);
877
+ }
878
+ function findStringAttribute(attributes, keys) {
879
+ return attributes.find(
880
+ (attribute) => keys.includes(attribute.key) && typeof attribute.value.stringValue === "string" && attribute.value.stringValue.length > 0
881
+ );
882
+ }
883
+ function findNumberAttribute(attributes, keys) {
884
+ return attributes.find((attribute) => {
885
+ if (!keys.includes(attribute.key)) return false;
886
+ if (typeof attribute.value.doubleValue === "number" && Number.isSafeInteger(attribute.value.doubleValue) && attribute.value.doubleValue >= 0) {
887
+ return true;
888
+ }
889
+ const intValue = attribute.value.intValue;
890
+ return integerValue(intValue) !== void 0;
891
+ });
892
+ }
893
+ function integerValue(value) {
894
+ if (typeof value === "number") {
895
+ return Number.isSafeInteger(value) && value >= 0 ? value : void 0;
896
+ }
897
+ if (typeof value !== "string") return void 0;
898
+ const parsed = Number(value);
899
+ return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : void 0;
900
+ }
901
+ function appendAlias(attributes, target, source) {
902
+ if (!source || hasAttribute(attributes, target)) return attributes;
903
+ return [...attributes, { key: target, value: { ...source.value } }];
904
+ }
905
+ function appendProviderAlias(attributes) {
906
+ if (hasAttribute(attributes, MODEL_USAGE_ATTRIBUTES.providerName)) return attributes;
907
+ const source = findStringAttribute(attributes, ["gen_ai.system", "ai.model.provider"]);
908
+ if (!(source == null ? void 0 : source.value.stringValue)) return attributes;
909
+ const attribute = attrString(
910
+ MODEL_USAGE_ATTRIBUTES.providerName,
911
+ canonicalModelProvider(source.value.stringValue)
912
+ );
913
+ return attribute ? [...attributes, attribute] : attributes;
914
+ }
915
+ function normalizeModelUsageSpan(span) {
916
+ const original = span.attributes;
917
+ if (!original || original.length === 0) return span;
918
+ const responseModel = findStringAttribute(original, [
919
+ MODEL_USAGE_ATTRIBUTES.responseModel,
920
+ "ai.response.model"
921
+ ]);
922
+ if (!responseModel) return span;
923
+ let attributes = appendAlias(original, MODEL_USAGE_ATTRIBUTES.responseModel, responseModel);
924
+ attributes = appendProviderAlias(attributes);
925
+ for (const [target, aliases] of Object.entries(STRING_ALIASES)) {
926
+ attributes = appendAlias(attributes, target, findStringAttribute(attributes, aliases));
927
+ }
928
+ for (const [target, aliases] of Object.entries(NUMBER_ALIASES)) {
929
+ attributes = appendAlias(attributes, target, findNumberAttribute(attributes, aliases));
930
+ }
931
+ return attributes === original ? span : { ...span, attributes };
932
+ }
713
933
  var DEFAULT_SECRET_KEY_NAMES = [
714
934
  "apikey",
715
935
  "apisecret",
@@ -799,6 +1019,13 @@ function redactJsonAttributeValue(key, value) {
799
1019
  if (scrubbedJson === json) return void 0;
800
1020
  return { stringValue: scrubbedJson };
801
1021
  }
1022
+ function identityAttrs(args2) {
1023
+ return [
1024
+ attrString("ai.telemetry.metadata.raindrop.ai.userId", args2.userId),
1025
+ attrString("ai.telemetry.metadata.raindrop.convoId", args2.convoId),
1026
+ attrString("ai.telemetry.metadata.raindrop.eventName", args2.eventName)
1027
+ ];
1028
+ }
802
1029
  function applyOtelSpanAttributeLimit(limit) {
803
1030
  var _a, _b;
804
1031
  try {
@@ -903,6 +1130,10 @@ var TraceShipper = class {
903
1130
  return null;
904
1131
  }
905
1132
  }
1133
+ try {
1134
+ current = normalizeModelUsageSpan(current);
1135
+ } catch (e) {
1136
+ }
906
1137
  if (!this.disableDefaultRedaction) {
907
1138
  current = defaultTransformSpan(current);
908
1139
  }
@@ -923,6 +1154,7 @@ var TraceShipper = class {
923
1154
  const started = (_a = args2.startTimeUnixNano) != null ? _a : nowUnixNanoString();
924
1155
  const attrs = [
925
1156
  attrString("ai.telemetry.metadata.raindrop.eventId", args2.eventId),
1157
+ ...identityAttrs(args2),
926
1158
  attrString("ai.operationId", args2.operationId)
927
1159
  ];
928
1160
  if ((_b = args2.attributes) == null ? void 0 : _b.length) attrs.push(...args2.attributes);
@@ -945,11 +1177,15 @@ var TraceShipper = class {
945
1177
  const redacted = this.redactSpan(span);
946
1178
  if (redacted === null) return;
947
1179
  const body = buildExportTraceServiceRequest([redacted], this.serviceName, this.serviceVersion);
948
- mirrorTraceExportToLocalDebugger(body, {
1180
+ const p = mirrorTraceExportToLocalDebugger(body, {
949
1181
  baseUrl: this.localDebuggerUrl,
950
1182
  debug: false,
951
1183
  sdkName: this.sdkName
952
1184
  });
1185
+ this.inFlight.add(p);
1186
+ void p.finally(() => {
1187
+ this.inFlight.delete(p);
1188
+ });
953
1189
  }
954
1190
  endSpan(span, extra) {
955
1191
  var _a, _b;
@@ -978,7 +1214,8 @@ var TraceShipper = class {
978
1214
  var _a;
979
1215
  const ids = createSpanIds(args2.parent);
980
1216
  const attrs = [
981
- attrString("ai.telemetry.metadata.raindrop.eventId", args2.eventId)
1217
+ attrString("ai.telemetry.metadata.raindrop.eventId", args2.eventId),
1218
+ ...identityAttrs(args2)
982
1219
  ];
983
1220
  if ((_a = args2.attributes) == null ? void 0 : _a.length) attrs.push(...args2.attributes);
984
1221
  const otlp = buildOtlpSpan({
@@ -1022,7 +1259,11 @@ var TraceShipper = class {
1022
1259
  }
1023
1260
  }
1024
1261
  async flush() {
1025
- if (!this.enabled) return;
1262
+ if (!this.enabled) {
1263
+ await Promise.all([...this.inFlight].map((p) => p.catch(() => {
1264
+ })));
1265
+ return;
1266
+ }
1026
1267
  if (this.timer) {
1027
1268
  clearTimeout(this.timer);
1028
1269
  this.timer = void 0;
@@ -1117,10 +1358,107 @@ var TraceShipper = class {
1117
1358
  // ../core/dist/index.node.js
1118
1359
  import { AsyncLocalStorage } from "async_hooks";
1119
1360
  globalThis.RAINDROP_ASYNC_LOCAL_STORAGE = AsyncLocalStorage;
1361
+ var SUPPRESS_TRACING_KEY = /* @__PURE__ */ Symbol.for(
1362
+ "OpenTelemetry SDK Context Key SUPPRESS_TRACING"
1363
+ );
1364
+ function findOtelContextManager() {
1365
+ var _a;
1366
+ for (const sym of Object.getOwnPropertySymbols(globalThis)) {
1367
+ if (!((_a = sym.description) == null ? void 0 : _a.startsWith("opentelemetry.js.api."))) continue;
1368
+ const api = globalThis[sym];
1369
+ const cm = api == null ? void 0 : api.context;
1370
+ if (cm && typeof cm.with === "function" && typeof cm.active === "function") {
1371
+ return cm;
1372
+ }
1373
+ }
1374
+ return void 0;
1375
+ }
1376
+ function installTracingSuppressionHook() {
1377
+ if (typeof globalThis.RAINDROP_SUPPRESS_TRACING === "function") return;
1378
+ const hook = (fn) => {
1379
+ const cm = findOtelContextManager();
1380
+ if (!cm) return fn();
1381
+ return cm.with(cm.active().setValue(SUPPRESS_TRACING_KEY, true), fn);
1382
+ };
1383
+ globalThis.RAINDROP_SUPPRESS_TRACING = hook;
1384
+ }
1385
+ installTracingSuppressionHook();
1386
+
1387
+ // package.json
1388
+ var package_default = {
1389
+ name: "@raindrop-ai/claude-code",
1390
+ version: "0.0.19",
1391
+ description: "Raindrop observability for Claude Code CLI \u2014 automatic session, tool call, and prompt tracing via hooks",
1392
+ license: "MIT",
1393
+ homepage: "https://www.raindrop.ai/docs/integrations/claude-code/",
1394
+ bugs: {
1395
+ url: "https://www.raindrop.ai/docs/support/"
1396
+ },
1397
+ type: "module",
1398
+ main: "dist/index.cjs",
1399
+ module: "dist/index.js",
1400
+ types: "dist/index.d.ts",
1401
+ bin: {
1402
+ "raindrop-claude-code": "dist/cli.js"
1403
+ },
1404
+ exports: {
1405
+ ".": {
1406
+ import: {
1407
+ types: "./dist/index.d.ts",
1408
+ default: "./dist/index.js"
1409
+ },
1410
+ require: {
1411
+ types: "./dist/index.d.cts",
1412
+ default: "./dist/index.cjs"
1413
+ }
1414
+ }
1415
+ },
1416
+ sideEffects: false,
1417
+ files: [
1418
+ "dist/**",
1419
+ "README.md",
1420
+ ".claude-plugin/**",
1421
+ "hooks/**",
1422
+ ".mcp.json"
1423
+ ],
1424
+ keywords: [
1425
+ "raindrop",
1426
+ "claude-code",
1427
+ "claude",
1428
+ "anthropic",
1429
+ "observability",
1430
+ "tracing",
1431
+ "hooks",
1432
+ "cli"
1433
+ ],
1434
+ engines: {
1435
+ node: ">=18"
1436
+ },
1437
+ scripts: {
1438
+ build: "tsup",
1439
+ postbuild: "chmod +x ./dist/cli.js && node ./scripts/sync-plugin-version.mjs",
1440
+ prepack: "node ./scripts/sync-plugin-version.mjs",
1441
+ dev: "tsup --watch",
1442
+ clean: "rm -rf dist",
1443
+ test: "pnpm build && cd tests && pnpm test",
1444
+ "test:watch": "cd tests && pnpm test:watch"
1445
+ },
1446
+ devDependencies: {
1447
+ "@raindrop-ai/core": "workspace:*",
1448
+ "@types/node": "^20.11.17",
1449
+ msw: "^2.12.7",
1450
+ tsup: "^8.4.0",
1451
+ typescript: "^5.3.3",
1452
+ vitest: "^2.1.0"
1453
+ },
1454
+ publishConfig: {
1455
+ access: "public"
1456
+ }
1457
+ };
1120
1458
 
1121
1459
  // src/package-info.ts
1122
1460
  var PACKAGE_NAME = "@raindrop-ai/claude-code";
1123
- var PACKAGE_VERSION = "0.0.13";
1461
+ var PACKAGE_VERSION = package_default.version;
1124
1462
 
1125
1463
  // src/shipper.ts
1126
1464
  var EventShipper2 = class extends EventShipper {
@@ -2163,7 +2501,6 @@ import { join as join3 } from "path";
2163
2501
  var DEFAULT_PORT = 5899;
2164
2502
  var DEFAULT_URL = `http://localhost:${DEFAULT_PORT}/v1/`;
2165
2503
  var HEALTH_TIMEOUT_MS = 300;
2166
- var MIRROR_TIMEOUT_MS = 2e3;
2167
2504
  var CACHE_DIR = join3(tmpdir2(), "raindrop-claude-code");
2168
2505
  var CACHE_FILE = join3(CACHE_DIR, "debugger_cache");
2169
2506
  var CACHE_TTL_MS = 5e3;
@@ -2188,7 +2525,9 @@ async function healthPing(baseUrl) {
2188
2525
  const healthUrl = baseUrl.replace(/\/v1\/$/, "/health");
2189
2526
  try {
2190
2527
  const signal = AbortSignal.timeout(HEALTH_TIMEOUT_MS);
2191
- const resp = await fetch(healthUrl, { signal });
2528
+ const resp = await runWithTracingSuppressed(
2529
+ () => fetch(healthUrl, { signal })
2530
+ );
2192
2531
  if (resp.ok) {
2193
2532
  const body = await resp.json();
2194
2533
  if (body.ok) return baseUrl;
@@ -2223,18 +2562,22 @@ async function detectLocalDebugger(debug) {
2223
2562
  }
2224
2563
  return { url: detected, autoDetected: detected !== null };
2225
2564
  }
2226
- function mirrorEventToLocalDebugger(baseUrl, payload, debug) {
2565
+ async function mirrorEventToLocalDebugger(baseUrl, payload, debug) {
2227
2566
  const url = `${baseUrl}events/track_partial`;
2228
2567
  if (debug) {
2229
2568
  console.log(`[raindrop-ai/claude-code] Mirroring event to local debugger: ${url}`);
2230
2569
  }
2231
- void fetch(url, {
2232
- method: "POST",
2233
- headers: { "Content-Type": "application/json" },
2234
- body: JSON.stringify(payload),
2235
- signal: AbortSignal.timeout(MIRROR_TIMEOUT_MS)
2236
- }).catch(() => {
2237
- });
2570
+ try {
2571
+ await runWithTracingSuppressed(
2572
+ () => fetch(url, {
2573
+ method: "POST",
2574
+ headers: { "Content-Type": "application/json" },
2575
+ body: JSON.stringify(payload),
2576
+ signal: AbortSignal.timeout(LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS)
2577
+ })
2578
+ );
2579
+ } catch (e) {
2580
+ }
2238
2581
  }
2239
2582
 
2240
2583
  // src/hook-handler.ts
@@ -2366,24 +2709,26 @@ async function handleHook() {
2366
2709
  eventShipper.patch = async (eventId, patch) => {
2367
2710
  var _a, _b, _c, _d;
2368
2711
  const traceId = (_a = getOtlpTraceId(payload.session_id)) != null ? _a : payload.session_id;
2369
- mirrorEventToLocalDebugger(debuggerUrl, {
2370
- event_id: eventId,
2371
- user_id: (_b = patch.userId) != null ? _b : config.userId,
2372
- event: (_c = patch.eventName) != null ? _c : "claude_code_session",
2373
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2374
- ai_data: {
2375
- input: patch.input,
2376
- output: patch.output,
2377
- model: patch.model,
2378
- convo_id: patch.convoId
2379
- },
2380
- properties: {
2381
- ...patch.properties,
2382
- ...payload.session_id ? { trace_id: traceId } : {}
2383
- },
2384
- is_pending: (_d = patch.isPending) != null ? _d : true
2385
- }, config.debug);
2386
- await origPatch(eventId, patch);
2712
+ await Promise.all([
2713
+ mirrorEventToLocalDebugger(debuggerUrl, {
2714
+ event_id: eventId,
2715
+ user_id: (_b = patch.userId) != null ? _b : config.userId,
2716
+ event: (_c = patch.eventName) != null ? _c : "claude_code_session",
2717
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2718
+ ai_data: {
2719
+ input: patch.input,
2720
+ output: patch.output,
2721
+ model: patch.model,
2722
+ convo_id: patch.convoId
2723
+ },
2724
+ properties: {
2725
+ ...patch.properties,
2726
+ ...payload.session_id ? { trace_id: traceId } : {}
2727
+ },
2728
+ is_pending: (_d = patch.isPending) != null ? _d : true
2729
+ }, config.debug),
2730
+ origPatch(eventId, patch)
2731
+ ]);
2387
2732
  };
2388
2733
  }
2389
2734
  try {