@raindrop-ai/claude-code 0.0.18 → 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.
package/dist/index.d.ts CHANGED
@@ -45,6 +45,10 @@ type IdentifyInput = {
45
45
  userId: string;
46
46
  traits?: Record<string, unknown>;
47
47
  };
48
+ type EventUsage = {
49
+ promptTokens?: number;
50
+ completionTokens?: number;
51
+ };
48
52
  type Patch = {
49
53
  eventName?: string;
50
54
  userId?: string;
@@ -52,7 +56,10 @@ type Patch = {
52
56
  input?: string;
53
57
  output?: string;
54
58
  model?: string;
59
+ usage?: EventUsage;
60
+ error?: unknown;
55
61
  properties?: Record<string, unknown>;
62
+ featureFlags?: Record<string, string>;
56
63
  attachments?: Attachment[];
57
64
  isPending?: boolean;
58
65
  timestamp?: string;
@@ -149,12 +156,7 @@ declare class EventShipper$1 {
149
156
  */
150
157
  private requestOpts;
151
158
  patch(eventId: string, patch: Patch): Promise<void>;
152
- finish(eventId: string, patch: {
153
- output?: string;
154
- model?: string;
155
- properties?: Record<string, unknown>;
156
- userId?: string;
157
- }): Promise<void>;
159
+ finish(eventId: string, patch: Pick<Patch, "output" | "model" | "usage" | "error" | "properties" | "featureFlags" | "userId">): Promise<void>;
158
160
  flush(): Promise<void>;
159
161
  shutdown(): Promise<void>;
160
162
  trackSignal(signal: SignalInput): Promise<void>;
@@ -327,6 +329,9 @@ declare class TraceShipper$1 {
327
329
  spanIdB64: string;
328
330
  };
329
331
  eventId: string;
332
+ userId?: string;
333
+ convoId?: string;
334
+ eventName?: string;
330
335
  operationId?: string;
331
336
  attributes?: Array<OtlpKeyValue | undefined>;
332
337
  startTimeUnixNano?: string;
@@ -345,6 +350,9 @@ declare class TraceShipper$1 {
345
350
  spanIdB64: string;
346
351
  };
347
352
  eventId: string;
353
+ userId?: string;
354
+ convoId?: string;
355
+ eventName?: string;
348
356
  startTimeUnixNano: string;
349
357
  endTimeUnixNano: string;
350
358
  attributes?: Array<OtlpKeyValue | undefined>;
@@ -525,7 +533,7 @@ declare function mapHookToRaindrop(payload: HookPayload, config: MapperConfig, e
525
533
  declare function extractAppendSystemPrompt(args: string[]): string | undefined;
526
534
 
527
535
  declare const PACKAGE_NAME = "@raindrop-ai/claude-code";
528
- declare const PACKAGE_VERSION = "0.0.13";
536
+ declare const PACKAGE_VERSION: string;
529
537
 
530
538
  /** A tool call extracted from an assistant message content block. */
531
539
  interface LLMToolCall {
@@ -619,9 +627,11 @@ interface LocalDebuggerResult {
619
627
  declare function detectLocalDebugger(debug: boolean): Promise<LocalDebuggerResult>;
620
628
  /**
621
629
  * Mirror an event payload to the local debugger's track_partial endpoint.
622
- * Fire-and-forget — errors are silently swallowed.
630
+ * Must be awaited: Claude Code hooks call process.exit as soon as handleHook
631
+ * returns, so a fire-and-forget fetch is killed before it leaves the socket.
632
+ * Errors are swallowed — observability must never fail the hook.
623
633
  */
624
- declare function mirrorEventToLocalDebugger(baseUrl: string, payload: Record<string, unknown>, debug: boolean): void;
634
+ declare function mirrorEventToLocalDebugger(baseUrl: string, payload: Record<string, unknown>, debug: boolean): Promise<void>;
625
635
 
626
636
  interface ResolvedSignal {
627
637
  description: string;
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- // ../core/dist/chunk-WKRW55KX.js
1
+ // ../core/dist/chunk-5PSWD267.js
2
2
  function getCrypto() {
3
3
  const c = globalThis.crypto;
4
4
  return c;
@@ -42,6 +42,20 @@ function base64Encode(bytes) {
42
42
  }
43
43
  return out;
44
44
  }
45
+ var HANDOFF_ATTRIBUTE_SUFFIXES = {
46
+ mode: "raindrop.handoff.mode",
47
+ childEventId: "raindrop.handoff.childEventId",
48
+ parentEventId: "raindrop.handoff.parentEventId",
49
+ parentSpanId: "raindrop.handoff.parentSpanId",
50
+ name: "raindrop.handoff.name",
51
+ terminal: "raindrop.handoff.terminal",
52
+ agentRole: "raindrop.agent.role"
53
+ };
54
+ var HANDOFF_TERMINAL_PROPERTY_KEY = HANDOFF_ATTRIBUTE_SUFFIXES.terminal;
55
+ var TRACEPARENT_HEADER = "traceparent";
56
+ var BAGGAGE_HEADER = "baggage";
57
+ var HANDOFF_HEADER = "x-raindrop-handoff";
58
+ 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.`;
45
59
  function runWithTracingSuppressed(fn) {
46
60
  const hook = globalThis.RAINDROP_SUPPRESS_TRACING;
47
61
  if (typeof hook !== "function") return fn();
@@ -332,26 +346,29 @@ function resolveLocalDebuggerBaseUrl(baseUrl) {
332
346
  if (shouldAutoEnableLocalWorkshop()) return DEFAULT_LOCAL_WORKSHOP_URL;
333
347
  return null;
334
348
  }
349
+ var LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS = 2e3;
335
350
  function mirrorTraceExportToLocalDebugger(body, options = {}) {
336
351
  var _a;
337
352
  const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
338
- if (!baseUrl) return;
339
- void postJson(`${baseUrl}traces`, body, {}, {
353
+ if (!baseUrl) return Promise.resolve();
354
+ return postJson(`${baseUrl}traces`, body, {}, {
340
355
  maxAttempts: 1,
341
356
  debug: (_a = options.debug) != null ? _a : false,
342
- sdkName: options.sdkName
357
+ sdkName: options.sdkName,
358
+ timeoutMs: LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS
343
359
  }).catch(() => {
344
360
  });
345
361
  }
346
362
  function mirrorPartialEventToLocalDebugger(event, options = {}) {
347
363
  var _a;
348
364
  const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
349
- if (!baseUrl) return;
365
+ if (!baseUrl) return Promise.resolve();
350
366
  const headers = options.writeKey ? { Authorization: `Bearer ${options.writeKey}` } : {};
351
- void postJson(`${baseUrl}events/track_partial`, event, headers, {
367
+ return postJson(`${baseUrl}events/track_partial`, event, headers, {
352
368
  maxAttempts: 1,
353
369
  debug: (_a = options.debug) != null ? _a : false,
354
- sdkName: options.sdkName
370
+ sdkName: options.sdkName,
371
+ timeoutMs: LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS
355
372
  }).catch(() => {
356
373
  });
357
374
  }
@@ -377,16 +394,52 @@ function projectIdHeaders(projectId) {
377
394
  var SHUTDOWN_DEADLINE_MS = 1e4;
378
395
  var POST_SHUTDOWN_TIMEOUT_MS = 5e3;
379
396
  function mergePatches(target, source) {
380
- var _a, _b, _c, _d;
397
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
381
398
  const out = { ...target, ...source };
382
399
  if (target.properties || source.properties) {
383
400
  out.properties = { ...(_a = target.properties) != null ? _a : {}, ...(_b = source.properties) != null ? _b : {} };
384
401
  }
402
+ if (target.usage || source.usage) {
403
+ out.usage = { ...(_c = target.usage) != null ? _c : {} };
404
+ if (((_d = source.usage) == null ? void 0 : _d.promptTokens) !== void 0) {
405
+ out.usage.promptTokens = source.usage.promptTokens;
406
+ }
407
+ if (((_e = source.usage) == null ? void 0 : _e.completionTokens) !== void 0) {
408
+ out.usage.completionTokens = source.usage.completionTokens;
409
+ }
410
+ }
411
+ if (source.error === void 0) {
412
+ out.error = target.error;
413
+ }
414
+ if (target.featureFlags || source.featureFlags) {
415
+ out.featureFlags = { ...(_f = target.featureFlags) != null ? _f : {}, ...(_g = source.featureFlags) != null ? _g : {} };
416
+ }
385
417
  if (target.attachments || source.attachments) {
386
- out.attachments = [...(_c = target.attachments) != null ? _c : [], ...(_d = source.attachments) != null ? _d : []];
418
+ out.attachments = [...(_h = target.attachments) != null ? _h : [], ...(_i = source.attachments) != null ? _i : []];
387
419
  }
388
420
  return out;
389
421
  }
422
+ function isErrorLike(value) {
423
+ return value !== null && typeof value === "object";
424
+ }
425
+ function eventTelemetryProperties(patch) {
426
+ var _a, _b;
427
+ const properties = {};
428
+ if (((_a = patch.usage) == null ? void 0 : _a.promptTokens) !== void 0 && Number.isFinite(patch.usage.promptTokens)) {
429
+ properties["ai.usage.prompt_tokens"] = patch.usage.promptTokens;
430
+ }
431
+ if (((_b = patch.usage) == null ? void 0 : _b.completionTokens) !== void 0 && Number.isFinite(patch.usage.completionTokens)) {
432
+ properties["ai.usage.completion_tokens"] = patch.usage.completionTokens;
433
+ }
434
+ if (patch.error !== void 0 && patch.error !== null) {
435
+ const constructorName = patch.error instanceof Error && patch.error.constructor !== Error ? patch.error.constructor.name : void 0;
436
+ 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";
437
+ const errorMessage = patch.error instanceof Error ? patch.error.message : isErrorLike(patch.error) && typeof patch.error.message === "string" ? patch.error.message : String(patch.error);
438
+ properties["error.type"] = errorType;
439
+ properties["error.message"] = errorMessage;
440
+ }
441
+ return properties;
442
+ }
390
443
  var EventShipper = class {
391
444
  constructor(opts) {
392
445
  this.buffers = /* @__PURE__ */ new Map();
@@ -635,6 +688,11 @@ var EventShipper = class {
635
688
  return;
636
689
  }
637
690
  const { wizardSession, ...restProperties } = (_e = accumulated.properties) != null ? _e : {};
691
+ let telemetryProperties = {};
692
+ try {
693
+ telemetryProperties = eventTelemetryProperties(accumulated);
694
+ } catch (e) {
695
+ }
638
696
  const convoId = (_f = accumulated.convoId) != null ? _f : sticky.convoId;
639
697
  const isPending = (_h = (_g = accumulated.isPending) != null ? _g : sticky.isPending) != null ? _h : true;
640
698
  const payload = {
@@ -644,15 +702,17 @@ var EventShipper = class {
644
702
  timestamp: (_i = accumulated.timestamp) != null ? _i : (/* @__PURE__ */ new Date()).toISOString(),
645
703
  ai_data: {
646
704
  input: accumulated.input,
647
- output: accumulated.output,
705
+ output: accumulated.error !== void 0 && accumulated.error !== null ? void 0 : accumulated.output,
648
706
  model: accumulated.model,
649
707
  convo_id: convoId
650
708
  },
651
709
  properties: {
652
710
  ...restProperties,
711
+ ...telemetryProperties,
653
712
  ...wizardSession ? { "raindrop.wizardSession": wizardSession } : {},
654
713
  $context: this.context
655
714
  },
715
+ ...accumulated.featureFlags && Object.keys(accumulated.featureFlags).length > 0 ? { feature_flags: accumulated.featureFlags } : {},
656
716
  attachments: accumulated.attachments,
657
717
  is_pending: isPending
658
718
  };
@@ -676,29 +736,30 @@ var EventShipper = class {
676
736
  endpoint: url
677
737
  });
678
738
  }
679
- if (this.localDebuggerUrl) {
680
- mirrorPartialEventToLocalDebugger(payload, {
681
- baseUrl: this.localDebuggerUrl,
682
- writeKey: this.writeKey,
683
- debug: this.debug,
684
- sdkName: this.sdkName
685
- });
686
- }
739
+ const mirror = this.localDebuggerUrl ? mirrorPartialEventToLocalDebugger(payload, {
740
+ baseUrl: this.localDebuggerUrl,
741
+ writeKey: this.writeKey,
742
+ debug: this.debug,
743
+ sdkName: this.sdkName
744
+ }) : void 0;
687
745
  if (!this.writeKey) {
688
746
  if (!isPending) this.sticky.delete(eventId);
747
+ if (mirror) await mirror;
689
748
  return;
690
749
  }
691
750
  const opts = this.requestOpts();
692
751
  if (!opts) {
693
752
  this.warnShutdownDrop(`track_partial ${eventId}`);
694
753
  if (!isPending) this.sticky.delete(eventId);
754
+ if (mirror) await mirror;
695
755
  return;
696
756
  }
697
757
  const p = postJson(url, payload, this.requestHeaders(), opts);
698
- this.inFlight.add(p);
758
+ const combined = mirror ? Promise.all([mirror, p]).then(() => void 0) : p;
759
+ this.inFlight.add(combined);
699
760
  try {
700
761
  try {
701
- await p;
762
+ await combined;
702
763
  if (this.debug) {
703
764
  console.log(`${this.prefix} sent track_partial ${eventId} (${eventName})`);
704
765
  }
@@ -710,13 +771,156 @@ var EventShipper = class {
710
771
  );
711
772
  }
712
773
  } finally {
713
- this.inFlight.delete(p);
774
+ this.inFlight.delete(combined);
714
775
  }
715
776
  if (!isPending) {
716
777
  this.sticky.delete(eventId);
717
778
  }
718
779
  }
719
780
  };
781
+ var MODEL_USAGE_ATTRIBUTES = {
782
+ usageSource: "raindrop.usage.source",
783
+ providerName: "gen_ai.provider.name",
784
+ requestModel: "gen_ai.request.model",
785
+ responseModel: "gen_ai.response.model",
786
+ inputTokens: "gen_ai.usage.input_tokens",
787
+ outputTokens: "gen_ai.usage.output_tokens",
788
+ reasoningTokens: "gen_ai.usage.reasoning_tokens",
789
+ cacheReadInputTokens: "gen_ai.usage.cache_read_input_tokens",
790
+ cacheWriteInputTokens: "gen_ai.usage.cache_write_input_tokens",
791
+ providerReportedCost: "gen_ai.usage.provider_reported_cost",
792
+ nonCachedInputTokens: "raindrop.usage.input_tokens.non_cached",
793
+ nonReasoningOutputTokens: "raindrop.usage.output_tokens.non_reasoning",
794
+ totalOutputTokens: "raindrop.usage.output_tokens.total",
795
+ reasoningOutputTokens: "raindrop.usage.output_tokens.reasoning",
796
+ cacheReadTokens: "raindrop.usage.input_tokens.cache_read",
797
+ cacheWriteTokens: "raindrop.usage.input_tokens.cache_write"
798
+ };
799
+ var MODEL_PROVIDER_NAMES = [
800
+ ["google.vertex.anthropic", "google-vertex"],
801
+ ["google.vertex_ai", "google-vertex"],
802
+ ["google.vertex", "google-vertex"],
803
+ ["gcp.vertex_ai", "google-vertex"],
804
+ ["gcp.gemini", "google"],
805
+ ["google_vertexai", "google-vertex"],
806
+ ["vertex.anthropic", "google-vertex"],
807
+ ["amazon-bedrock", "amazon-bedrock"],
808
+ ["aws.bedrock", "amazon-bedrock"],
809
+ ["bedrock", "amazon-bedrock"],
810
+ ["anthropic", "anthropic"],
811
+ ["openai", "openai"],
812
+ ["google", "google"],
813
+ ["az.ai.openai", "azure"],
814
+ ["azure", "azure"],
815
+ ["openrouter", "openrouter"]
816
+ ];
817
+ function canonicalModelProvider(provider) {
818
+ var _a;
819
+ const normalizedProvider = provider.trim().toLowerCase();
820
+ if (normalizedProvider === "gateway") return "vercel";
821
+ const match = MODEL_PROVIDER_NAMES.find(
822
+ ([family]) => normalizedProvider === family || normalizedProvider.startsWith(`${family}.`)
823
+ );
824
+ return (_a = match == null ? void 0 : match[1]) != null ? _a : normalizedProvider;
825
+ }
826
+ var STRING_ALIASES = {
827
+ [MODEL_USAGE_ATTRIBUTES.requestModel]: ["ai.model.id", "ai.model"]
828
+ };
829
+ var NUMBER_ALIASES = {
830
+ [MODEL_USAGE_ATTRIBUTES.inputTokens]: [
831
+ "gen_ai.usage.prompt_tokens",
832
+ "ai.usage.prompt_tokens",
833
+ "ai.usage.promptTokens",
834
+ "ai.usage.input_tokens",
835
+ "ai.usage.inputTokens"
836
+ ],
837
+ [MODEL_USAGE_ATTRIBUTES.outputTokens]: [
838
+ "gen_ai.usage.completion_tokens",
839
+ "ai.usage.completion_tokens",
840
+ "ai.usage.completionTokens",
841
+ "ai.usage.output_tokens",
842
+ "ai.usage.outputTokens"
843
+ ],
844
+ [MODEL_USAGE_ATTRIBUTES.reasoningTokens]: [
845
+ "gen_ai.usage.reasoning.output_tokens",
846
+ "ai.usage.reasoningTokens",
847
+ "ai.usage.thoughts_tokens"
848
+ ],
849
+ [MODEL_USAGE_ATTRIBUTES.cacheReadInputTokens]: [
850
+ "gen_ai.usage.cache_read_tokens",
851
+ "gen_ai.usage.cache_read.input_tokens",
852
+ "ai.usage.cachedInputTokens",
853
+ "ai.usage.cached_tokens",
854
+ "ai.usage.cache_read_tokens",
855
+ "ai.usage.cache_read_input_tokens",
856
+ "ai.usage.cacheReadInputTokens"
857
+ ],
858
+ [MODEL_USAGE_ATTRIBUTES.cacheWriteInputTokens]: [
859
+ "gen_ai.usage.cache_creation_input_tokens",
860
+ "gen_ai.usage.cache_creation.input_tokens",
861
+ "ai.usage.cacheWriteInputTokens",
862
+ "ai.usage.cache_creation_input_tokens",
863
+ "ai.usage.cacheCreationInputTokens"
864
+ ]
865
+ };
866
+ function hasAttribute(attributes, key) {
867
+ return attributes.some((attribute) => attribute.key === key);
868
+ }
869
+ function findStringAttribute(attributes, keys) {
870
+ return attributes.find(
871
+ (attribute) => keys.includes(attribute.key) && typeof attribute.value.stringValue === "string" && attribute.value.stringValue.length > 0
872
+ );
873
+ }
874
+ function findNumberAttribute(attributes, keys) {
875
+ return attributes.find((attribute) => {
876
+ if (!keys.includes(attribute.key)) return false;
877
+ if (typeof attribute.value.doubleValue === "number" && Number.isSafeInteger(attribute.value.doubleValue) && attribute.value.doubleValue >= 0) {
878
+ return true;
879
+ }
880
+ const intValue = attribute.value.intValue;
881
+ return integerValue(intValue) !== void 0;
882
+ });
883
+ }
884
+ function integerValue(value) {
885
+ if (typeof value === "number") {
886
+ return Number.isSafeInteger(value) && value >= 0 ? value : void 0;
887
+ }
888
+ if (typeof value !== "string") return void 0;
889
+ const parsed = Number(value);
890
+ return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : void 0;
891
+ }
892
+ function appendAlias(attributes, target, source) {
893
+ if (!source || hasAttribute(attributes, target)) return attributes;
894
+ return [...attributes, { key: target, value: { ...source.value } }];
895
+ }
896
+ function appendProviderAlias(attributes) {
897
+ if (hasAttribute(attributes, MODEL_USAGE_ATTRIBUTES.providerName)) return attributes;
898
+ const source = findStringAttribute(attributes, ["gen_ai.system", "ai.model.provider"]);
899
+ if (!(source == null ? void 0 : source.value.stringValue)) return attributes;
900
+ const attribute = attrString(
901
+ MODEL_USAGE_ATTRIBUTES.providerName,
902
+ canonicalModelProvider(source.value.stringValue)
903
+ );
904
+ return attribute ? [...attributes, attribute] : attributes;
905
+ }
906
+ function normalizeModelUsageSpan(span) {
907
+ const original = span.attributes;
908
+ if (!original || original.length === 0) return span;
909
+ const responseModel = findStringAttribute(original, [
910
+ MODEL_USAGE_ATTRIBUTES.responseModel,
911
+ "ai.response.model"
912
+ ]);
913
+ if (!responseModel) return span;
914
+ let attributes = appendAlias(original, MODEL_USAGE_ATTRIBUTES.responseModel, responseModel);
915
+ attributes = appendProviderAlias(attributes);
916
+ for (const [target, aliases] of Object.entries(STRING_ALIASES)) {
917
+ attributes = appendAlias(attributes, target, findStringAttribute(attributes, aliases));
918
+ }
919
+ for (const [target, aliases] of Object.entries(NUMBER_ALIASES)) {
920
+ attributes = appendAlias(attributes, target, findNumberAttribute(attributes, aliases));
921
+ }
922
+ return attributes === original ? span : { ...span, attributes };
923
+ }
720
924
  var DEFAULT_SECRET_KEY_NAMES = [
721
925
  "apikey",
722
926
  "apisecret",
@@ -806,6 +1010,13 @@ function redactJsonAttributeValue(key, value) {
806
1010
  if (scrubbedJson === json) return void 0;
807
1011
  return { stringValue: scrubbedJson };
808
1012
  }
1013
+ function identityAttrs(args) {
1014
+ return [
1015
+ attrString("ai.telemetry.metadata.raindrop.ai.userId", args.userId),
1016
+ attrString("ai.telemetry.metadata.raindrop.convoId", args.convoId),
1017
+ attrString("ai.telemetry.metadata.raindrop.eventName", args.eventName)
1018
+ ];
1019
+ }
809
1020
  function applyOtelSpanAttributeLimit(limit) {
810
1021
  var _a, _b;
811
1022
  try {
@@ -910,6 +1121,10 @@ var TraceShipper = class {
910
1121
  return null;
911
1122
  }
912
1123
  }
1124
+ try {
1125
+ current = normalizeModelUsageSpan(current);
1126
+ } catch (e) {
1127
+ }
913
1128
  if (!this.disableDefaultRedaction) {
914
1129
  current = defaultTransformSpan(current);
915
1130
  }
@@ -930,6 +1145,7 @@ var TraceShipper = class {
930
1145
  const started = (_a = args.startTimeUnixNano) != null ? _a : nowUnixNanoString();
931
1146
  const attrs = [
932
1147
  attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId),
1148
+ ...identityAttrs(args),
933
1149
  attrString("ai.operationId", args.operationId)
934
1150
  ];
935
1151
  if ((_b = args.attributes) == null ? void 0 : _b.length) attrs.push(...args.attributes);
@@ -952,11 +1168,15 @@ var TraceShipper = class {
952
1168
  const redacted = this.redactSpan(span);
953
1169
  if (redacted === null) return;
954
1170
  const body = buildExportTraceServiceRequest([redacted], this.serviceName, this.serviceVersion);
955
- mirrorTraceExportToLocalDebugger(body, {
1171
+ const p = mirrorTraceExportToLocalDebugger(body, {
956
1172
  baseUrl: this.localDebuggerUrl,
957
1173
  debug: false,
958
1174
  sdkName: this.sdkName
959
1175
  });
1176
+ this.inFlight.add(p);
1177
+ void p.finally(() => {
1178
+ this.inFlight.delete(p);
1179
+ });
960
1180
  }
961
1181
  endSpan(span, extra) {
962
1182
  var _a, _b;
@@ -985,7 +1205,8 @@ var TraceShipper = class {
985
1205
  var _a;
986
1206
  const ids = createSpanIds(args.parent);
987
1207
  const attrs = [
988
- attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId)
1208
+ attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId),
1209
+ ...identityAttrs(args)
989
1210
  ];
990
1211
  if ((_a = args.attributes) == null ? void 0 : _a.length) attrs.push(...args.attributes);
991
1212
  const otlp = buildOtlpSpan({
@@ -1029,7 +1250,11 @@ var TraceShipper = class {
1029
1250
  }
1030
1251
  }
1031
1252
  async flush() {
1032
- if (!this.enabled) return;
1253
+ if (!this.enabled) {
1254
+ await Promise.all([...this.inFlight].map((p) => p.catch(() => {
1255
+ })));
1256
+ return;
1257
+ }
1033
1258
  if (this.timer) {
1034
1259
  clearTimeout(this.timer);
1035
1260
  this.timer = void 0;
@@ -1150,9 +1375,81 @@ function installTracingSuppressionHook() {
1150
1375
  }
1151
1376
  installTracingSuppressionHook();
1152
1377
 
1378
+ // package.json
1379
+ var package_default = {
1380
+ name: "@raindrop-ai/claude-code",
1381
+ version: "0.0.19",
1382
+ description: "Raindrop observability for Claude Code CLI \u2014 automatic session, tool call, and prompt tracing via hooks",
1383
+ license: "MIT",
1384
+ homepage: "https://www.raindrop.ai/docs/integrations/claude-code/",
1385
+ bugs: {
1386
+ url: "https://www.raindrop.ai/docs/support/"
1387
+ },
1388
+ type: "module",
1389
+ main: "dist/index.cjs",
1390
+ module: "dist/index.js",
1391
+ types: "dist/index.d.ts",
1392
+ bin: {
1393
+ "raindrop-claude-code": "dist/cli.js"
1394
+ },
1395
+ exports: {
1396
+ ".": {
1397
+ import: {
1398
+ types: "./dist/index.d.ts",
1399
+ default: "./dist/index.js"
1400
+ },
1401
+ require: {
1402
+ types: "./dist/index.d.cts",
1403
+ default: "./dist/index.cjs"
1404
+ }
1405
+ }
1406
+ },
1407
+ sideEffects: false,
1408
+ files: [
1409
+ "dist/**",
1410
+ "README.md",
1411
+ ".claude-plugin/**",
1412
+ "hooks/**",
1413
+ ".mcp.json"
1414
+ ],
1415
+ keywords: [
1416
+ "raindrop",
1417
+ "claude-code",
1418
+ "claude",
1419
+ "anthropic",
1420
+ "observability",
1421
+ "tracing",
1422
+ "hooks",
1423
+ "cli"
1424
+ ],
1425
+ engines: {
1426
+ node: ">=18"
1427
+ },
1428
+ scripts: {
1429
+ build: "tsup",
1430
+ postbuild: "chmod +x ./dist/cli.js && node ./scripts/sync-plugin-version.mjs",
1431
+ prepack: "node ./scripts/sync-plugin-version.mjs",
1432
+ dev: "tsup --watch",
1433
+ clean: "rm -rf dist",
1434
+ test: "pnpm build && cd tests && pnpm test",
1435
+ "test:watch": "cd tests && pnpm test:watch"
1436
+ },
1437
+ devDependencies: {
1438
+ "@raindrop-ai/core": "workspace:*",
1439
+ "@types/node": "^20.11.17",
1440
+ msw: "^2.12.7",
1441
+ tsup: "^8.4.0",
1442
+ typescript: "^5.3.3",
1443
+ vitest: "^2.1.0"
1444
+ },
1445
+ publishConfig: {
1446
+ access: "public"
1447
+ }
1448
+ };
1449
+
1153
1450
  // src/package-info.ts
1154
1451
  var PACKAGE_NAME = "@raindrop-ai/claude-code";
1155
- var PACKAGE_VERSION = "0.0.13";
1452
+ var PACKAGE_VERSION = package_default.version;
1156
1453
 
1157
1454
  // src/shipper.ts
1158
1455
  var EventShipper2 = class extends EventShipper {
@@ -2202,7 +2499,6 @@ import { join as join3 } from "path";
2202
2499
  var DEFAULT_PORT = 5899;
2203
2500
  var DEFAULT_URL = `http://localhost:${DEFAULT_PORT}/v1/`;
2204
2501
  var HEALTH_TIMEOUT_MS = 300;
2205
- var MIRROR_TIMEOUT_MS = 2e3;
2206
2502
  var CACHE_DIR = join3(tmpdir2(), "raindrop-claude-code");
2207
2503
  var CACHE_FILE = join3(CACHE_DIR, "debugger_cache");
2208
2504
  var CACHE_TTL_MS = 5e3;
@@ -2264,20 +2560,22 @@ async function detectLocalDebugger(debug) {
2264
2560
  }
2265
2561
  return { url: detected, autoDetected: detected !== null };
2266
2562
  }
2267
- function mirrorEventToLocalDebugger(baseUrl, payload, debug) {
2563
+ async function mirrorEventToLocalDebugger(baseUrl, payload, debug) {
2268
2564
  const url = `${baseUrl}events/track_partial`;
2269
2565
  if (debug) {
2270
2566
  console.log(`[raindrop-ai/claude-code] Mirroring event to local debugger: ${url}`);
2271
2567
  }
2272
- void runWithTracingSuppressed(
2273
- () => fetch(url, {
2274
- method: "POST",
2275
- headers: { "Content-Type": "application/json" },
2276
- body: JSON.stringify(payload),
2277
- signal: AbortSignal.timeout(MIRROR_TIMEOUT_MS)
2278
- })
2279
- ).catch(() => {
2280
- });
2568
+ try {
2569
+ await runWithTracingSuppressed(
2570
+ () => fetch(url, {
2571
+ method: "POST",
2572
+ headers: { "Content-Type": "application/json" },
2573
+ body: JSON.stringify(payload),
2574
+ signal: AbortSignal.timeout(LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS)
2575
+ })
2576
+ );
2577
+ } catch (e) {
2578
+ }
2281
2579
  }
2282
2580
 
2283
2581
  // src/mcp-serve.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raindrop-ai/claude-code",
3
- "version": "0.0.18",
3
+ "version": "0.0.19",
4
4
  "description": "Raindrop observability for Claude Code CLI — automatic session, tool call, and prompt tracing via hooks",
5
5
  "license": "MIT",
6
6
  "homepage": "https://www.raindrop.ai/docs/integrations/claude-code/",
@@ -53,14 +53,14 @@
53
53
  "tsup": "^8.4.0",
54
54
  "typescript": "^5.3.3",
55
55
  "vitest": "^2.1.0",
56
- "@raindrop-ai/core": "0.0.5"
56
+ "@raindrop-ai/core": "0.2.1"
57
57
  },
58
58
  "publishConfig": {
59
59
  "access": "public"
60
60
  },
61
61
  "scripts": {
62
62
  "build": "tsup",
63
- "postbuild": "chmod +x ./dist/cli.js",
63
+ "postbuild": "chmod +x ./dist/cli.js && node ./scripts/sync-plugin-version.mjs",
64
64
  "dev": "tsup --watch",
65
65
  "clean": "rm -rf dist",
66
66
  "test": "pnpm build && cd tests && pnpm test",