@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.
- package/.claude-plugin/plugin.json +1 -1
- package/dist/cli.js +407 -62
- package/dist/index.cjs +387 -44
- package/dist/index.d.cts +55 -9
- package/dist/index.d.ts +55 -9
- package/dist/index.js +387 -44
- package/package.json +3 -3
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-
|
|
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
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 = [...(
|
|
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
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
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
|
-
|
|
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
|
|
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(
|
|
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)
|
|
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 =
|
|
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
|
|
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
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
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
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
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 {
|