@raindrop-ai/claude-code 0.0.14 → 0.0.15
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/cli.js +47 -10
- package/dist/index.cjs +45 -10
- package/dist/index.d.cts +26 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +45 -10
- package/package.json +2 -2
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-SK6EJEO7.js
|
|
11
11
|
function getCrypto() {
|
|
12
12
|
const c = globalThis.crypto;
|
|
13
13
|
return c;
|
|
@@ -348,6 +348,25 @@ function mirrorPartialEventToLocalDebugger(event, options = {}) {
|
|
|
348
348
|
}).catch(() => {
|
|
349
349
|
});
|
|
350
350
|
}
|
|
351
|
+
var PROJECT_ID_HEADER = "X-Raindrop-Project-Id";
|
|
352
|
+
var PROJECT_ID_SLUG_PATTERN = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
|
|
353
|
+
function isValidProjectIdSlug(value) {
|
|
354
|
+
return PROJECT_ID_SLUG_PATTERN.test(value);
|
|
355
|
+
}
|
|
356
|
+
function normalizeProjectId(raw, opts) {
|
|
357
|
+
if (typeof raw !== "string") return void 0;
|
|
358
|
+
const trimmed = raw.trim();
|
|
359
|
+
if (!trimmed) return void 0;
|
|
360
|
+
if (!isValidProjectIdSlug(trimmed) && opts.debug) {
|
|
361
|
+
console.warn(
|
|
362
|
+
`${opts.prefix} projectId "${trimmed}" does not match slug ${PROJECT_ID_SLUG_PATTERN.source}; sending anyway \u2014 backend may reject with HTTP 400`
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
return trimmed;
|
|
366
|
+
}
|
|
367
|
+
function projectIdHeaders(projectId) {
|
|
368
|
+
return projectId ? { [PROJECT_ID_HEADER]: projectId } : {};
|
|
369
|
+
}
|
|
351
370
|
var SHUTDOWN_DEADLINE_MS = 1e4;
|
|
352
371
|
var POST_SHUTDOWN_TIMEOUT_MS = 5e3;
|
|
353
372
|
function mergePatches(target, source) {
|
|
@@ -382,6 +401,10 @@ var EventShipper = class {
|
|
|
382
401
|
if (this.debug && this.localDebuggerUrl) {
|
|
383
402
|
console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
|
|
384
403
|
}
|
|
404
|
+
this.projectId = normalizeProjectId(opts.projectId, {
|
|
405
|
+
debug: this.debug,
|
|
406
|
+
prefix: this.prefix
|
|
407
|
+
});
|
|
385
408
|
const isNode = typeof process !== "undefined" && typeof process.version === "string";
|
|
386
409
|
this.context = {
|
|
387
410
|
library: {
|
|
@@ -400,6 +423,9 @@ var EventShipper = class {
|
|
|
400
423
|
authHeaders() {
|
|
401
424
|
return this.writeKey ? { Authorization: `Bearer ${this.writeKey}` } : {};
|
|
402
425
|
}
|
|
426
|
+
requestHeaders() {
|
|
427
|
+
return { ...this.authHeaders(), ...projectIdHeaders(this.projectId) };
|
|
428
|
+
}
|
|
403
429
|
/**
|
|
404
430
|
* Build the retry/timeout options for one POST, honoring the shutdown
|
|
405
431
|
* deadline. Returns `null` when the shutdown drain window is exhausted —
|
|
@@ -529,7 +555,7 @@ var EventShipper = class {
|
|
|
529
555
|
return;
|
|
530
556
|
}
|
|
531
557
|
try {
|
|
532
|
-
await postJson(url, body, this.
|
|
558
|
+
await postJson(url, body, this.requestHeaders(), opts);
|
|
533
559
|
} catch (err) {
|
|
534
560
|
const msg = err instanceof Error ? err.message : String(err);
|
|
535
561
|
rateLimitedLog(
|
|
@@ -565,7 +591,7 @@ var EventShipper = class {
|
|
|
565
591
|
return;
|
|
566
592
|
}
|
|
567
593
|
try {
|
|
568
|
-
await postJson(url, body, this.
|
|
594
|
+
await postJson(url, body, this.requestHeaders(), opts);
|
|
569
595
|
} catch (err) {
|
|
570
596
|
const msg = err instanceof Error ? err.message : String(err);
|
|
571
597
|
rateLimitedLog(
|
|
@@ -661,7 +687,7 @@ var EventShipper = class {
|
|
|
661
687
|
if (!isPending) this.sticky.delete(eventId);
|
|
662
688
|
return;
|
|
663
689
|
}
|
|
664
|
-
const p = postJson(url, payload, this.
|
|
690
|
+
const p = postJson(url, payload, this.requestHeaders(), opts);
|
|
665
691
|
this.inFlight.add(p);
|
|
666
692
|
try {
|
|
667
693
|
try {
|
|
@@ -808,6 +834,10 @@ var TraceShipper = class {
|
|
|
808
834
|
if (this.debug && this.localDebuggerUrl) {
|
|
809
835
|
console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
|
|
810
836
|
}
|
|
837
|
+
this.projectId = normalizeProjectId(opts.projectId, {
|
|
838
|
+
debug: this.debug,
|
|
839
|
+
prefix: this.prefix
|
|
840
|
+
});
|
|
811
841
|
this.transformSpanHook = opts.transformSpan;
|
|
812
842
|
this.disableDefaultRedaction = opts.disableDefaultRedaction === true;
|
|
813
843
|
this.maxTextFieldCharsOpt = opts.maxTextFieldChars;
|
|
@@ -884,6 +914,9 @@ var TraceShipper = class {
|
|
|
884
914
|
authHeaders() {
|
|
885
915
|
return this.writeKey ? { Authorization: `Bearer ${this.writeKey}` } : {};
|
|
886
916
|
}
|
|
917
|
+
requestHeaders() {
|
|
918
|
+
return { ...this.authHeaders(), ...projectIdHeaders(this.projectId) };
|
|
919
|
+
}
|
|
887
920
|
startSpan(args2) {
|
|
888
921
|
var _a, _b;
|
|
889
922
|
const ids = createSpanIds(args2.parent);
|
|
@@ -1015,7 +1048,7 @@ var TraceShipper = class {
|
|
|
1015
1048
|
endpoint: url
|
|
1016
1049
|
});
|
|
1017
1050
|
}
|
|
1018
|
-
const p = postJson(url, body, this.
|
|
1051
|
+
const p = postJson(url, body, this.requestHeaders(), opts);
|
|
1019
1052
|
this.inFlight.add(p);
|
|
1020
1053
|
try {
|
|
1021
1054
|
try {
|
|
@@ -2051,7 +2084,7 @@ import { homedir, userInfo } from "os";
|
|
|
2051
2084
|
import { dirname, join as join2 } from "path";
|
|
2052
2085
|
var CONFIG_PATH = join2(homedir(), ".config", "raindrop", "config.json");
|
|
2053
2086
|
function loadConfig() {
|
|
2054
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
2087
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
|
|
2055
2088
|
let file = {};
|
|
2056
2089
|
try {
|
|
2057
2090
|
if (existsSync3(CONFIG_PATH)) {
|
|
@@ -2091,9 +2124,10 @@ function loadConfig() {
|
|
|
2091
2124
|
return {
|
|
2092
2125
|
writeKey: (_c = (_b = process.env["RAINDROP_WRITE_KEY"]) != null ? _b : file.write_key) != null ? _c : "",
|
|
2093
2126
|
endpoint: (_e = (_d = process.env["RAINDROP_API_URL"]) != null ? _d : file.api_url) != null ? _e : "https://api.raindrop.ai/v1",
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2127
|
+
projectId: (_f = process.env["RAINDROP_PROJECT_ID"]) != null ? _f : file.project_id,
|
|
2128
|
+
userId: (_h = (_g = process.env["RAINDROP_USER_ID"]) != null ? _g : file.user_id) != null ? _h : systemUser,
|
|
2129
|
+
convoId: ((_i = process.env["RAINDROP_CONVO_ID"]) == null ? void 0 : _i.trim()) || void 0,
|
|
2130
|
+
debug: process.env["RAINDROP_DEBUG"] === "true" ? true : (_j = file.debug) != null ? _j : false,
|
|
2097
2131
|
enabled: (() => {
|
|
2098
2132
|
var _a2;
|
|
2099
2133
|
const env = process.env["RAINDROP_ENABLED"];
|
|
@@ -2101,7 +2135,7 @@ function loadConfig() {
|
|
|
2101
2135
|
const lower = env.toLowerCase();
|
|
2102
2136
|
return lower !== "false" && env !== "0";
|
|
2103
2137
|
})(),
|
|
2104
|
-
eventName: (
|
|
2138
|
+
eventName: (_l = (_k = process.env["RAINDROP_EVENT_NAME"]) != null ? _k : file.event_name) != null ? _l : "claude_code_session",
|
|
2105
2139
|
customProperties,
|
|
2106
2140
|
selfDiagnostics
|
|
2107
2141
|
};
|
|
@@ -2313,6 +2347,7 @@ async function handleHook() {
|
|
|
2313
2347
|
writeKey: config.writeKey,
|
|
2314
2348
|
endpoint: config.endpoint,
|
|
2315
2349
|
debug: config.debug,
|
|
2350
|
+
projectId: config.projectId,
|
|
2316
2351
|
// Only ship to the cloud when we have an API key. When only the local
|
|
2317
2352
|
// debugger is present the shipper still needs to be instantiated so the
|
|
2318
2353
|
// event mapper can call patch/finish, but cloud POSTs are skipped.
|
|
@@ -2322,6 +2357,7 @@ async function handleHook() {
|
|
|
2322
2357
|
writeKey: config.writeKey,
|
|
2323
2358
|
endpoint: config.endpoint,
|
|
2324
2359
|
debug: config.debug,
|
|
2360
|
+
projectId: config.projectId,
|
|
2325
2361
|
enabled: hasCloudKey
|
|
2326
2362
|
});
|
|
2327
2363
|
if (debugger_.url) {
|
|
@@ -2840,6 +2876,7 @@ async function executeTool(args2) {
|
|
|
2840
2876
|
writeKey: config.writeKey,
|
|
2841
2877
|
endpoint: config.endpoint,
|
|
2842
2878
|
debug: false,
|
|
2879
|
+
projectId: config.projectId,
|
|
2843
2880
|
enabled: true
|
|
2844
2881
|
});
|
|
2845
2882
|
try {
|
package/dist/index.cjs
CHANGED
|
@@ -43,7 +43,7 @@ __export(src_exports, {
|
|
|
43
43
|
});
|
|
44
44
|
module.exports = __toCommonJS(src_exports);
|
|
45
45
|
|
|
46
|
-
// ../core/dist/chunk-
|
|
46
|
+
// ../core/dist/chunk-SK6EJEO7.js
|
|
47
47
|
function getCrypto() {
|
|
48
48
|
const c = globalThis.crypto;
|
|
49
49
|
return c;
|
|
@@ -384,6 +384,25 @@ function mirrorPartialEventToLocalDebugger(event, options = {}) {
|
|
|
384
384
|
}).catch(() => {
|
|
385
385
|
});
|
|
386
386
|
}
|
|
387
|
+
var PROJECT_ID_HEADER = "X-Raindrop-Project-Id";
|
|
388
|
+
var PROJECT_ID_SLUG_PATTERN = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
|
|
389
|
+
function isValidProjectIdSlug(value) {
|
|
390
|
+
return PROJECT_ID_SLUG_PATTERN.test(value);
|
|
391
|
+
}
|
|
392
|
+
function normalizeProjectId(raw, opts) {
|
|
393
|
+
if (typeof raw !== "string") return void 0;
|
|
394
|
+
const trimmed = raw.trim();
|
|
395
|
+
if (!trimmed) return void 0;
|
|
396
|
+
if (!isValidProjectIdSlug(trimmed) && opts.debug) {
|
|
397
|
+
console.warn(
|
|
398
|
+
`${opts.prefix} projectId "${trimmed}" does not match slug ${PROJECT_ID_SLUG_PATTERN.source}; sending anyway \u2014 backend may reject with HTTP 400`
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
return trimmed;
|
|
402
|
+
}
|
|
403
|
+
function projectIdHeaders(projectId) {
|
|
404
|
+
return projectId ? { [PROJECT_ID_HEADER]: projectId } : {};
|
|
405
|
+
}
|
|
387
406
|
var SHUTDOWN_DEADLINE_MS = 1e4;
|
|
388
407
|
var POST_SHUTDOWN_TIMEOUT_MS = 5e3;
|
|
389
408
|
function mergePatches(target, source) {
|
|
@@ -418,6 +437,10 @@ var EventShipper = class {
|
|
|
418
437
|
if (this.debug && this.localDebuggerUrl) {
|
|
419
438
|
console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
|
|
420
439
|
}
|
|
440
|
+
this.projectId = normalizeProjectId(opts.projectId, {
|
|
441
|
+
debug: this.debug,
|
|
442
|
+
prefix: this.prefix
|
|
443
|
+
});
|
|
421
444
|
const isNode = typeof process !== "undefined" && typeof process.version === "string";
|
|
422
445
|
this.context = {
|
|
423
446
|
library: {
|
|
@@ -436,6 +459,9 @@ var EventShipper = class {
|
|
|
436
459
|
authHeaders() {
|
|
437
460
|
return this.writeKey ? { Authorization: `Bearer ${this.writeKey}` } : {};
|
|
438
461
|
}
|
|
462
|
+
requestHeaders() {
|
|
463
|
+
return { ...this.authHeaders(), ...projectIdHeaders(this.projectId) };
|
|
464
|
+
}
|
|
439
465
|
/**
|
|
440
466
|
* Build the retry/timeout options for one POST, honoring the shutdown
|
|
441
467
|
* deadline. Returns `null` when the shutdown drain window is exhausted —
|
|
@@ -565,7 +591,7 @@ var EventShipper = class {
|
|
|
565
591
|
return;
|
|
566
592
|
}
|
|
567
593
|
try {
|
|
568
|
-
await postJson(url, body, this.
|
|
594
|
+
await postJson(url, body, this.requestHeaders(), opts);
|
|
569
595
|
} catch (err) {
|
|
570
596
|
const msg = err instanceof Error ? err.message : String(err);
|
|
571
597
|
rateLimitedLog(
|
|
@@ -601,7 +627,7 @@ var EventShipper = class {
|
|
|
601
627
|
return;
|
|
602
628
|
}
|
|
603
629
|
try {
|
|
604
|
-
await postJson(url, body, this.
|
|
630
|
+
await postJson(url, body, this.requestHeaders(), opts);
|
|
605
631
|
} catch (err) {
|
|
606
632
|
const msg = err instanceof Error ? err.message : String(err);
|
|
607
633
|
rateLimitedLog(
|
|
@@ -697,7 +723,7 @@ var EventShipper = class {
|
|
|
697
723
|
if (!isPending) this.sticky.delete(eventId);
|
|
698
724
|
return;
|
|
699
725
|
}
|
|
700
|
-
const p = postJson(url, payload, this.
|
|
726
|
+
const p = postJson(url, payload, this.requestHeaders(), opts);
|
|
701
727
|
this.inFlight.add(p);
|
|
702
728
|
try {
|
|
703
729
|
try {
|
|
@@ -844,6 +870,10 @@ var TraceShipper = class {
|
|
|
844
870
|
if (this.debug && this.localDebuggerUrl) {
|
|
845
871
|
console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
|
|
846
872
|
}
|
|
873
|
+
this.projectId = normalizeProjectId(opts.projectId, {
|
|
874
|
+
debug: this.debug,
|
|
875
|
+
prefix: this.prefix
|
|
876
|
+
});
|
|
847
877
|
this.transformSpanHook = opts.transformSpan;
|
|
848
878
|
this.disableDefaultRedaction = opts.disableDefaultRedaction === true;
|
|
849
879
|
this.maxTextFieldCharsOpt = opts.maxTextFieldChars;
|
|
@@ -920,6 +950,9 @@ var TraceShipper = class {
|
|
|
920
950
|
authHeaders() {
|
|
921
951
|
return this.writeKey ? { Authorization: `Bearer ${this.writeKey}` } : {};
|
|
922
952
|
}
|
|
953
|
+
requestHeaders() {
|
|
954
|
+
return { ...this.authHeaders(), ...projectIdHeaders(this.projectId) };
|
|
955
|
+
}
|
|
923
956
|
startSpan(args) {
|
|
924
957
|
var _a, _b;
|
|
925
958
|
const ids = createSpanIds(args.parent);
|
|
@@ -1051,7 +1084,7 @@ var TraceShipper = class {
|
|
|
1051
1084
|
endpoint: url
|
|
1052
1085
|
});
|
|
1053
1086
|
}
|
|
1054
|
-
const p = postJson(url, body, this.
|
|
1087
|
+
const p = postJson(url, body, this.requestHeaders(), opts);
|
|
1055
1088
|
this.inFlight.add(p);
|
|
1056
1089
|
try {
|
|
1057
1090
|
try {
|
|
@@ -1166,7 +1199,7 @@ var import_node_os = require("os");
|
|
|
1166
1199
|
var import_node_path = require("path");
|
|
1167
1200
|
var CONFIG_PATH = (0, import_node_path.join)((0, import_node_os.homedir)(), ".config", "raindrop", "config.json");
|
|
1168
1201
|
function loadConfig() {
|
|
1169
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
1202
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
|
|
1170
1203
|
let file = {};
|
|
1171
1204
|
try {
|
|
1172
1205
|
if ((0, import_node_fs.existsSync)(CONFIG_PATH)) {
|
|
@@ -1206,9 +1239,10 @@ function loadConfig() {
|
|
|
1206
1239
|
return {
|
|
1207
1240
|
writeKey: (_c = (_b = process.env["RAINDROP_WRITE_KEY"]) != null ? _b : file.write_key) != null ? _c : "",
|
|
1208
1241
|
endpoint: (_e = (_d = process.env["RAINDROP_API_URL"]) != null ? _d : file.api_url) != null ? _e : "https://api.raindrop.ai/v1",
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1242
|
+
projectId: (_f = process.env["RAINDROP_PROJECT_ID"]) != null ? _f : file.project_id,
|
|
1243
|
+
userId: (_h = (_g = process.env["RAINDROP_USER_ID"]) != null ? _g : file.user_id) != null ? _h : systemUser,
|
|
1244
|
+
convoId: ((_i = process.env["RAINDROP_CONVO_ID"]) == null ? void 0 : _i.trim()) || void 0,
|
|
1245
|
+
debug: process.env["RAINDROP_DEBUG"] === "true" ? true : (_j = file.debug) != null ? _j : false,
|
|
1212
1246
|
enabled: (() => {
|
|
1213
1247
|
var _a2;
|
|
1214
1248
|
const env = process.env["RAINDROP_ENABLED"];
|
|
@@ -1216,7 +1250,7 @@ function loadConfig() {
|
|
|
1216
1250
|
const lower = env.toLowerCase();
|
|
1217
1251
|
return lower !== "false" && env !== "0";
|
|
1218
1252
|
})(),
|
|
1219
|
-
eventName: (
|
|
1253
|
+
eventName: (_l = (_k = process.env["RAINDROP_EVENT_NAME"]) != null ? _k : file.event_name) != null ? _l : "claude_code_session",
|
|
1220
1254
|
customProperties,
|
|
1221
1255
|
selfDiagnostics
|
|
1222
1256
|
};
|
|
@@ -2382,6 +2416,7 @@ async function executeTool(args) {
|
|
|
2382
2416
|
writeKey: config.writeKey,
|
|
2383
2417
|
endpoint: config.endpoint,
|
|
2384
2418
|
debug: false,
|
|
2419
|
+
projectId: config.projectId,
|
|
2385
2420
|
enabled: true
|
|
2386
2421
|
});
|
|
2387
2422
|
try {
|
package/dist/index.d.cts
CHANGED
|
@@ -83,6 +83,13 @@ type EventShipperOptions = {
|
|
|
83
83
|
* Pass `null` to opt out of all mirroring (including auto-detect).
|
|
84
84
|
*/
|
|
85
85
|
localDebuggerUrl?: string | null;
|
|
86
|
+
/**
|
|
87
|
+
* Optional project slug. When set, every outbound cloud request includes an
|
|
88
|
+
* `X-Raindrop-Project-Id: <projectId>` header. Empty / whitespace-only
|
|
89
|
+
* values are ignored. Slug format is validated on construction but never
|
|
90
|
+
* throws — the backend returns 400 on invalid values.
|
|
91
|
+
*/
|
|
92
|
+
projectId?: string;
|
|
86
93
|
/**
|
|
87
94
|
* Per-field character cap applied to event input/output BEFORE buffering
|
|
88
95
|
* or serialization, so oversized payloads cost the cap — not the payload —
|
|
@@ -101,6 +108,7 @@ declare class EventShipper$1 {
|
|
|
101
108
|
private sdkName;
|
|
102
109
|
private prefix;
|
|
103
110
|
private defaultEventName;
|
|
111
|
+
private projectId;
|
|
104
112
|
private context;
|
|
105
113
|
private buffers;
|
|
106
114
|
private sticky;
|
|
@@ -124,6 +132,7 @@ declare class EventShipper$1 {
|
|
|
124
132
|
constructor(opts: EventShipperOptions);
|
|
125
133
|
isDebugEnabled(): boolean;
|
|
126
134
|
private authHeaders;
|
|
135
|
+
private requestHeaders;
|
|
127
136
|
/**
|
|
128
137
|
* Build the retry/timeout options for one POST, honoring the shutdown
|
|
129
138
|
* deadline. Returns `null` when the shutdown drain window is exhausted —
|
|
@@ -195,6 +204,13 @@ type TraceShipperOptions = {
|
|
|
195
204
|
* Pass `null` to opt out of all mirroring (including auto-detect).
|
|
196
205
|
*/
|
|
197
206
|
localDebuggerUrl?: string | null;
|
|
207
|
+
/**
|
|
208
|
+
* Optional project slug. When set, every OTLP trace export includes an
|
|
209
|
+
* `X-Raindrop-Project-Id: <projectId>` header. Empty / whitespace-only
|
|
210
|
+
* values are ignored. Slug format is validated on construction but never
|
|
211
|
+
* throws — the backend returns 400 on invalid values.
|
|
212
|
+
*/
|
|
213
|
+
projectId?: string;
|
|
198
214
|
/**
|
|
199
215
|
* Per-span hook that fires for every OTLP span right before the span is
|
|
200
216
|
* shipped (both to the Raindrop API and to a local debugger). Lets callers
|
|
@@ -252,6 +268,7 @@ declare class TraceShipper$1 {
|
|
|
252
268
|
private flushIntervalMs;
|
|
253
269
|
private maxBatchSize;
|
|
254
270
|
private maxQueueSize;
|
|
271
|
+
private projectId;
|
|
255
272
|
private queue;
|
|
256
273
|
private timer;
|
|
257
274
|
private inFlight;
|
|
@@ -302,6 +319,7 @@ declare class TraceShipper$1 {
|
|
|
302
319
|
private redactSpan;
|
|
303
320
|
isDebugEnabled(): boolean;
|
|
304
321
|
private authHeaders;
|
|
322
|
+
private requestHeaders;
|
|
305
323
|
startSpan(args: {
|
|
306
324
|
name: string;
|
|
307
325
|
parent?: {
|
|
@@ -386,6 +404,7 @@ interface SelfDiagnosticsConfig {
|
|
|
386
404
|
interface ConfigFile {
|
|
387
405
|
write_key?: string;
|
|
388
406
|
api_url?: string;
|
|
407
|
+
project_id?: string;
|
|
389
408
|
user_id?: string;
|
|
390
409
|
debug?: boolean;
|
|
391
410
|
enabled?: boolean;
|
|
@@ -396,6 +415,13 @@ interface ConfigFile {
|
|
|
396
415
|
interface RaindropConfig {
|
|
397
416
|
writeKey: string;
|
|
398
417
|
endpoint: string;
|
|
418
|
+
/**
|
|
419
|
+
* Optional Raindrop project slug. When set, every outbound cloud request
|
|
420
|
+
* carries an `X-Raindrop-Project-Id` header. Unset → no header (the project
|
|
421
|
+
* resolves to `default` server-side; byte-identical to prior behavior).
|
|
422
|
+
* Sourced from `RAINDROP_PROJECT_ID` or the `project_id` config-file key.
|
|
423
|
+
*/
|
|
424
|
+
projectId?: string;
|
|
399
425
|
userId: string;
|
|
400
426
|
convoId?: string;
|
|
401
427
|
debug: boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -83,6 +83,13 @@ type EventShipperOptions = {
|
|
|
83
83
|
* Pass `null` to opt out of all mirroring (including auto-detect).
|
|
84
84
|
*/
|
|
85
85
|
localDebuggerUrl?: string | null;
|
|
86
|
+
/**
|
|
87
|
+
* Optional project slug. When set, every outbound cloud request includes an
|
|
88
|
+
* `X-Raindrop-Project-Id: <projectId>` header. Empty / whitespace-only
|
|
89
|
+
* values are ignored. Slug format is validated on construction but never
|
|
90
|
+
* throws — the backend returns 400 on invalid values.
|
|
91
|
+
*/
|
|
92
|
+
projectId?: string;
|
|
86
93
|
/**
|
|
87
94
|
* Per-field character cap applied to event input/output BEFORE buffering
|
|
88
95
|
* or serialization, so oversized payloads cost the cap — not the payload —
|
|
@@ -101,6 +108,7 @@ declare class EventShipper$1 {
|
|
|
101
108
|
private sdkName;
|
|
102
109
|
private prefix;
|
|
103
110
|
private defaultEventName;
|
|
111
|
+
private projectId;
|
|
104
112
|
private context;
|
|
105
113
|
private buffers;
|
|
106
114
|
private sticky;
|
|
@@ -124,6 +132,7 @@ declare class EventShipper$1 {
|
|
|
124
132
|
constructor(opts: EventShipperOptions);
|
|
125
133
|
isDebugEnabled(): boolean;
|
|
126
134
|
private authHeaders;
|
|
135
|
+
private requestHeaders;
|
|
127
136
|
/**
|
|
128
137
|
* Build the retry/timeout options for one POST, honoring the shutdown
|
|
129
138
|
* deadline. Returns `null` when the shutdown drain window is exhausted —
|
|
@@ -195,6 +204,13 @@ type TraceShipperOptions = {
|
|
|
195
204
|
* Pass `null` to opt out of all mirroring (including auto-detect).
|
|
196
205
|
*/
|
|
197
206
|
localDebuggerUrl?: string | null;
|
|
207
|
+
/**
|
|
208
|
+
* Optional project slug. When set, every OTLP trace export includes an
|
|
209
|
+
* `X-Raindrop-Project-Id: <projectId>` header. Empty / whitespace-only
|
|
210
|
+
* values are ignored. Slug format is validated on construction but never
|
|
211
|
+
* throws — the backend returns 400 on invalid values.
|
|
212
|
+
*/
|
|
213
|
+
projectId?: string;
|
|
198
214
|
/**
|
|
199
215
|
* Per-span hook that fires for every OTLP span right before the span is
|
|
200
216
|
* shipped (both to the Raindrop API and to a local debugger). Lets callers
|
|
@@ -252,6 +268,7 @@ declare class TraceShipper$1 {
|
|
|
252
268
|
private flushIntervalMs;
|
|
253
269
|
private maxBatchSize;
|
|
254
270
|
private maxQueueSize;
|
|
271
|
+
private projectId;
|
|
255
272
|
private queue;
|
|
256
273
|
private timer;
|
|
257
274
|
private inFlight;
|
|
@@ -302,6 +319,7 @@ declare class TraceShipper$1 {
|
|
|
302
319
|
private redactSpan;
|
|
303
320
|
isDebugEnabled(): boolean;
|
|
304
321
|
private authHeaders;
|
|
322
|
+
private requestHeaders;
|
|
305
323
|
startSpan(args: {
|
|
306
324
|
name: string;
|
|
307
325
|
parent?: {
|
|
@@ -386,6 +404,7 @@ interface SelfDiagnosticsConfig {
|
|
|
386
404
|
interface ConfigFile {
|
|
387
405
|
write_key?: string;
|
|
388
406
|
api_url?: string;
|
|
407
|
+
project_id?: string;
|
|
389
408
|
user_id?: string;
|
|
390
409
|
debug?: boolean;
|
|
391
410
|
enabled?: boolean;
|
|
@@ -396,6 +415,13 @@ interface ConfigFile {
|
|
|
396
415
|
interface RaindropConfig {
|
|
397
416
|
writeKey: string;
|
|
398
417
|
endpoint: string;
|
|
418
|
+
/**
|
|
419
|
+
* Optional Raindrop project slug. When set, every outbound cloud request
|
|
420
|
+
* carries an `X-Raindrop-Project-Id` header. Unset → no header (the project
|
|
421
|
+
* resolves to `default` server-side; byte-identical to prior behavior).
|
|
422
|
+
* Sourced from `RAINDROP_PROJECT_ID` or the `project_id` config-file key.
|
|
423
|
+
*/
|
|
424
|
+
projectId?: string;
|
|
399
425
|
userId: string;
|
|
400
426
|
convoId?: string;
|
|
401
427
|
debug: boolean;
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// ../core/dist/chunk-
|
|
1
|
+
// ../core/dist/chunk-SK6EJEO7.js
|
|
2
2
|
function getCrypto() {
|
|
3
3
|
const c = globalThis.crypto;
|
|
4
4
|
return c;
|
|
@@ -339,6 +339,25 @@ function mirrorPartialEventToLocalDebugger(event, options = {}) {
|
|
|
339
339
|
}).catch(() => {
|
|
340
340
|
});
|
|
341
341
|
}
|
|
342
|
+
var PROJECT_ID_HEADER = "X-Raindrop-Project-Id";
|
|
343
|
+
var PROJECT_ID_SLUG_PATTERN = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
|
|
344
|
+
function isValidProjectIdSlug(value) {
|
|
345
|
+
return PROJECT_ID_SLUG_PATTERN.test(value);
|
|
346
|
+
}
|
|
347
|
+
function normalizeProjectId(raw, opts) {
|
|
348
|
+
if (typeof raw !== "string") return void 0;
|
|
349
|
+
const trimmed = raw.trim();
|
|
350
|
+
if (!trimmed) return void 0;
|
|
351
|
+
if (!isValidProjectIdSlug(trimmed) && opts.debug) {
|
|
352
|
+
console.warn(
|
|
353
|
+
`${opts.prefix} projectId "${trimmed}" does not match slug ${PROJECT_ID_SLUG_PATTERN.source}; sending anyway \u2014 backend may reject with HTTP 400`
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
return trimmed;
|
|
357
|
+
}
|
|
358
|
+
function projectIdHeaders(projectId) {
|
|
359
|
+
return projectId ? { [PROJECT_ID_HEADER]: projectId } : {};
|
|
360
|
+
}
|
|
342
361
|
var SHUTDOWN_DEADLINE_MS = 1e4;
|
|
343
362
|
var POST_SHUTDOWN_TIMEOUT_MS = 5e3;
|
|
344
363
|
function mergePatches(target, source) {
|
|
@@ -373,6 +392,10 @@ var EventShipper = class {
|
|
|
373
392
|
if (this.debug && this.localDebuggerUrl) {
|
|
374
393
|
console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
|
|
375
394
|
}
|
|
395
|
+
this.projectId = normalizeProjectId(opts.projectId, {
|
|
396
|
+
debug: this.debug,
|
|
397
|
+
prefix: this.prefix
|
|
398
|
+
});
|
|
376
399
|
const isNode = typeof process !== "undefined" && typeof process.version === "string";
|
|
377
400
|
this.context = {
|
|
378
401
|
library: {
|
|
@@ -391,6 +414,9 @@ var EventShipper = class {
|
|
|
391
414
|
authHeaders() {
|
|
392
415
|
return this.writeKey ? { Authorization: `Bearer ${this.writeKey}` } : {};
|
|
393
416
|
}
|
|
417
|
+
requestHeaders() {
|
|
418
|
+
return { ...this.authHeaders(), ...projectIdHeaders(this.projectId) };
|
|
419
|
+
}
|
|
394
420
|
/**
|
|
395
421
|
* Build the retry/timeout options for one POST, honoring the shutdown
|
|
396
422
|
* deadline. Returns `null` when the shutdown drain window is exhausted —
|
|
@@ -520,7 +546,7 @@ var EventShipper = class {
|
|
|
520
546
|
return;
|
|
521
547
|
}
|
|
522
548
|
try {
|
|
523
|
-
await postJson(url, body, this.
|
|
549
|
+
await postJson(url, body, this.requestHeaders(), opts);
|
|
524
550
|
} catch (err) {
|
|
525
551
|
const msg = err instanceof Error ? err.message : String(err);
|
|
526
552
|
rateLimitedLog(
|
|
@@ -556,7 +582,7 @@ var EventShipper = class {
|
|
|
556
582
|
return;
|
|
557
583
|
}
|
|
558
584
|
try {
|
|
559
|
-
await postJson(url, body, this.
|
|
585
|
+
await postJson(url, body, this.requestHeaders(), opts);
|
|
560
586
|
} catch (err) {
|
|
561
587
|
const msg = err instanceof Error ? err.message : String(err);
|
|
562
588
|
rateLimitedLog(
|
|
@@ -652,7 +678,7 @@ var EventShipper = class {
|
|
|
652
678
|
if (!isPending) this.sticky.delete(eventId);
|
|
653
679
|
return;
|
|
654
680
|
}
|
|
655
|
-
const p = postJson(url, payload, this.
|
|
681
|
+
const p = postJson(url, payload, this.requestHeaders(), opts);
|
|
656
682
|
this.inFlight.add(p);
|
|
657
683
|
try {
|
|
658
684
|
try {
|
|
@@ -799,6 +825,10 @@ var TraceShipper = class {
|
|
|
799
825
|
if (this.debug && this.localDebuggerUrl) {
|
|
800
826
|
console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
|
|
801
827
|
}
|
|
828
|
+
this.projectId = normalizeProjectId(opts.projectId, {
|
|
829
|
+
debug: this.debug,
|
|
830
|
+
prefix: this.prefix
|
|
831
|
+
});
|
|
802
832
|
this.transformSpanHook = opts.transformSpan;
|
|
803
833
|
this.disableDefaultRedaction = opts.disableDefaultRedaction === true;
|
|
804
834
|
this.maxTextFieldCharsOpt = opts.maxTextFieldChars;
|
|
@@ -875,6 +905,9 @@ var TraceShipper = class {
|
|
|
875
905
|
authHeaders() {
|
|
876
906
|
return this.writeKey ? { Authorization: `Bearer ${this.writeKey}` } : {};
|
|
877
907
|
}
|
|
908
|
+
requestHeaders() {
|
|
909
|
+
return { ...this.authHeaders(), ...projectIdHeaders(this.projectId) };
|
|
910
|
+
}
|
|
878
911
|
startSpan(args) {
|
|
879
912
|
var _a, _b;
|
|
880
913
|
const ids = createSpanIds(args.parent);
|
|
@@ -1006,7 +1039,7 @@ var TraceShipper = class {
|
|
|
1006
1039
|
endpoint: url
|
|
1007
1040
|
});
|
|
1008
1041
|
}
|
|
1009
|
-
const p = postJson(url, body, this.
|
|
1042
|
+
const p = postJson(url, body, this.requestHeaders(), opts);
|
|
1010
1043
|
this.inFlight.add(p);
|
|
1011
1044
|
try {
|
|
1012
1045
|
try {
|
|
@@ -1121,7 +1154,7 @@ import { homedir, userInfo } from "os";
|
|
|
1121
1154
|
import { dirname, join } from "path";
|
|
1122
1155
|
var CONFIG_PATH = join(homedir(), ".config", "raindrop", "config.json");
|
|
1123
1156
|
function loadConfig() {
|
|
1124
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
1157
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
|
|
1125
1158
|
let file = {};
|
|
1126
1159
|
try {
|
|
1127
1160
|
if (existsSync(CONFIG_PATH)) {
|
|
@@ -1161,9 +1194,10 @@ function loadConfig() {
|
|
|
1161
1194
|
return {
|
|
1162
1195
|
writeKey: (_c = (_b = process.env["RAINDROP_WRITE_KEY"]) != null ? _b : file.write_key) != null ? _c : "",
|
|
1163
1196
|
endpoint: (_e = (_d = process.env["RAINDROP_API_URL"]) != null ? _d : file.api_url) != null ? _e : "https://api.raindrop.ai/v1",
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1197
|
+
projectId: (_f = process.env["RAINDROP_PROJECT_ID"]) != null ? _f : file.project_id,
|
|
1198
|
+
userId: (_h = (_g = process.env["RAINDROP_USER_ID"]) != null ? _g : file.user_id) != null ? _h : systemUser,
|
|
1199
|
+
convoId: ((_i = process.env["RAINDROP_CONVO_ID"]) == null ? void 0 : _i.trim()) || void 0,
|
|
1200
|
+
debug: process.env["RAINDROP_DEBUG"] === "true" ? true : (_j = file.debug) != null ? _j : false,
|
|
1167
1201
|
enabled: (() => {
|
|
1168
1202
|
var _a2;
|
|
1169
1203
|
const env = process.env["RAINDROP_ENABLED"];
|
|
@@ -1171,7 +1205,7 @@ function loadConfig() {
|
|
|
1171
1205
|
const lower = env.toLowerCase();
|
|
1172
1206
|
return lower !== "false" && env !== "0";
|
|
1173
1207
|
})(),
|
|
1174
|
-
eventName: (
|
|
1208
|
+
eventName: (_l = (_k = process.env["RAINDROP_EVENT_NAME"]) != null ? _k : file.event_name) != null ? _l : "claude_code_session",
|
|
1175
1209
|
customProperties,
|
|
1176
1210
|
selfDiagnostics
|
|
1177
1211
|
};
|
|
@@ -2337,6 +2371,7 @@ async function executeTool(args) {
|
|
|
2337
2371
|
writeKey: config.writeKey,
|
|
2338
2372
|
endpoint: config.endpoint,
|
|
2339
2373
|
debug: false,
|
|
2374
|
+
projectId: config.projectId,
|
|
2340
2375
|
enabled: true
|
|
2341
2376
|
});
|
|
2342
2377
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@raindrop-ai/claude-code",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.15",
|
|
4
4
|
"description": "Raindrop observability for Claude Code CLI — automatic session, tool call, and prompt tracing via hooks",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"tsup": "^8.4.0",
|
|
59
59
|
"typescript": "^5.3.3",
|
|
60
60
|
"vitest": "^2.1.0",
|
|
61
|
-
"@raindrop-ai/core": "0.0.
|
|
61
|
+
"@raindrop-ai/core": "0.0.4"
|
|
62
62
|
},
|
|
63
63
|
"publishConfig": {
|
|
64
64
|
"access": "public"
|