@raindrop-ai/claude-code 0.0.19 → 0.0.20
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/README.md +4 -0
- package/dist/cli.js +1005 -115
- package/dist/index.cjs +966 -93
- package/dist/index.d.cts +91 -1
- package/dist/index.d.ts +91 -1
- package/dist/index.js +965 -93
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -7,7 +7,521 @@ 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-BYBMRLZM.js
|
|
11
|
+
var EVAL_CORRELATION_ID_ATTRIBUTE = "raindrop.eval_correlation_id";
|
|
12
|
+
var PROBE_SCOPE = { correlationId: "" };
|
|
13
|
+
var EvalScopeStorage = class {
|
|
14
|
+
constructor() {
|
|
15
|
+
this._als = null;
|
|
16
|
+
this._probed = false;
|
|
17
|
+
}
|
|
18
|
+
maybeAdoptAsyncLocalStorage() {
|
|
19
|
+
if (this._probed) return;
|
|
20
|
+
this._probed = true;
|
|
21
|
+
try {
|
|
22
|
+
const Ctor = globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
|
|
23
|
+
if (!Ctor) return;
|
|
24
|
+
const als = new Ctor();
|
|
25
|
+
als.run(PROBE_SCOPE, () => {
|
|
26
|
+
});
|
|
27
|
+
this._als = als;
|
|
28
|
+
} catch (e) {
|
|
29
|
+
this._als = null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
run(scope, callback) {
|
|
33
|
+
this.maybeAdoptAsyncLocalStorage();
|
|
34
|
+
if (this._als) return this._als.run(scope, callback);
|
|
35
|
+
const previous = this._syncScope;
|
|
36
|
+
this._syncScope = scope;
|
|
37
|
+
try {
|
|
38
|
+
return callback();
|
|
39
|
+
} finally {
|
|
40
|
+
this._syncScope = previous;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
current() {
|
|
44
|
+
this.maybeAdoptAsyncLocalStorage();
|
|
45
|
+
if (this._als) return this._als.getStore();
|
|
46
|
+
return this._syncScope;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
var EVAL_SCOPE_STORAGE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.evalScopeStorage");
|
|
50
|
+
function evalScopeStorage() {
|
|
51
|
+
const holder = globalThis;
|
|
52
|
+
let storage = holder[EVAL_SCOPE_STORAGE_KEY];
|
|
53
|
+
if (!storage) {
|
|
54
|
+
storage = new EvalScopeStorage();
|
|
55
|
+
holder[EVAL_SCOPE_STORAGE_KEY] = storage;
|
|
56
|
+
}
|
|
57
|
+
return storage;
|
|
58
|
+
}
|
|
59
|
+
function currentEvalScope() {
|
|
60
|
+
try {
|
|
61
|
+
return evalScopeStorage().current();
|
|
62
|
+
} catch (e) {
|
|
63
|
+
return void 0;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function evalScopeAttributes() {
|
|
67
|
+
const scope = currentEvalScope();
|
|
68
|
+
if (!scope) return {};
|
|
69
|
+
return { [EVAL_CORRELATION_ID_ATTRIBUTE]: scope.correlationId };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// ../core/dist/chunk-WJOR6M7H.js
|
|
73
|
+
var STATE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.replayTraceRoutingState");
|
|
74
|
+
function state() {
|
|
75
|
+
const holder = globalThis;
|
|
76
|
+
let current = holder[STATE_KEY];
|
|
77
|
+
if (!current) {
|
|
78
|
+
let storage = null;
|
|
79
|
+
try {
|
|
80
|
+
const Ctor = globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
|
|
81
|
+
if (Ctor) storage = new Ctor();
|
|
82
|
+
} catch (e) {
|
|
83
|
+
storage = null;
|
|
84
|
+
}
|
|
85
|
+
current = {
|
|
86
|
+
storage,
|
|
87
|
+
syncDestination: void 0,
|
|
88
|
+
spanDestinations: /* @__PURE__ */ new WeakMap()
|
|
89
|
+
};
|
|
90
|
+
holder[STATE_KEY] = current;
|
|
91
|
+
}
|
|
92
|
+
return current;
|
|
93
|
+
}
|
|
94
|
+
function currentReplayTraceDestination() {
|
|
95
|
+
var _a, _b;
|
|
96
|
+
const routing = state();
|
|
97
|
+
return (_b = (_a = routing.storage) == null ? void 0 : _a.getStore()) != null ? _b : routing.syncDestination;
|
|
98
|
+
}
|
|
99
|
+
function rememberReplayTraceDestination(span) {
|
|
100
|
+
const destination = currentReplayTraceDestination();
|
|
101
|
+
if (destination) state().spanDestinations.set(span, destination);
|
|
102
|
+
}
|
|
103
|
+
function copyReplayTraceDestination(source, target) {
|
|
104
|
+
const destination = state().spanDestinations.get(source);
|
|
105
|
+
if (destination) state().spanDestinations.set(target, destination);
|
|
106
|
+
}
|
|
107
|
+
function replayTraceDestinationFor(value) {
|
|
108
|
+
if (typeof value !== "object" && typeof value !== "function" || value === null) {
|
|
109
|
+
return void 0;
|
|
110
|
+
}
|
|
111
|
+
return state().spanDestinations.get(value);
|
|
112
|
+
}
|
|
113
|
+
function recordReplayExportedSpan(destination, spanId, traceId) {
|
|
114
|
+
var _a, _b;
|
|
115
|
+
if (!destination || !spanId || !traceId) return;
|
|
116
|
+
(_a = destination.exportedSpanIds) == null ? void 0 : _a.add(spanId);
|
|
117
|
+
(_b = destination.exportedTraceIds) == null ? void 0 : _b.add(traceId);
|
|
118
|
+
}
|
|
119
|
+
function replayTraceUrl(baseUrl) {
|
|
120
|
+
return `${baseUrl.replace(/\/+$/, "")}/v1/traces`;
|
|
121
|
+
}
|
|
122
|
+
function getAsyncLocalStorageCtor() {
|
|
123
|
+
return globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
|
|
124
|
+
}
|
|
125
|
+
var MAX_BINDING_STACK = 128;
|
|
126
|
+
var EMPTY_STACK = [];
|
|
127
|
+
var ContextStackStorage = class {
|
|
128
|
+
/** Emitted once when this runtime cannot support an ambient push. */
|
|
129
|
+
constructor(noAmbientBindWarning) {
|
|
130
|
+
this.noAmbientBindWarning = noAmbientBindWarning;
|
|
131
|
+
this._als = null;
|
|
132
|
+
this._enterWithUsable = false;
|
|
133
|
+
this._syncStack = EMPTY_STACK;
|
|
134
|
+
this._adoptionChecked = false;
|
|
135
|
+
this._warnedNoAmbientBind = false;
|
|
136
|
+
}
|
|
137
|
+
maybeAdoptAsyncLocalStorage() {
|
|
138
|
+
if (this._adoptionChecked) return;
|
|
139
|
+
this._adoptionChecked = true;
|
|
140
|
+
const Ctor = getAsyncLocalStorageCtor();
|
|
141
|
+
if (!Ctor) return;
|
|
142
|
+
const als = new Ctor();
|
|
143
|
+
try {
|
|
144
|
+
als.run(EMPTY_STACK, () => {
|
|
145
|
+
});
|
|
146
|
+
} catch (e) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
this._als = als;
|
|
150
|
+
if (typeof als.enterWith === "function") {
|
|
151
|
+
try {
|
|
152
|
+
als.enterWith(EMPTY_STACK);
|
|
153
|
+
this._enterWithUsable = true;
|
|
154
|
+
} catch (e) {
|
|
155
|
+
this._enterWithUsable = false;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
getStack() {
|
|
160
|
+
var _a;
|
|
161
|
+
this.maybeAdoptAsyncLocalStorage();
|
|
162
|
+
if (this._als) return (_a = this._als.getStore()) != null ? _a : this._syncStack;
|
|
163
|
+
return this._syncStack;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Persist an ambient stack mutation. Returns false when an ALS is adopted but
|
|
167
|
+
* `enterWith` is unusable (workerd): callers must NOT fall back to the
|
|
168
|
+
* process-shared sync stack, since concurrent isolates would cross-stamp.
|
|
169
|
+
*/
|
|
170
|
+
setAmbientStack(stack) {
|
|
171
|
+
if (this._als) {
|
|
172
|
+
if (!this._enterWithUsable) return false;
|
|
173
|
+
this._als.enterWith(stack);
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
this._syncStack = stack;
|
|
177
|
+
return true;
|
|
178
|
+
}
|
|
179
|
+
push(binding) {
|
|
180
|
+
this.maybeAdoptAsyncLocalStorage();
|
|
181
|
+
if (this._als && !this._enterWithUsable) {
|
|
182
|
+
this.warnNoAmbientBindOnce();
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
let stack = this.getStack();
|
|
186
|
+
if (stack.length >= MAX_BINDING_STACK) {
|
|
187
|
+
stack = stack.filter((b) => b.isLive());
|
|
188
|
+
if (stack.length >= MAX_BINDING_STACK) {
|
|
189
|
+
stack = stack.slice(stack.length - (MAX_BINDING_STACK - 1));
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
this.setAmbientStack([...stack, binding]);
|
|
193
|
+
}
|
|
194
|
+
remove(binding) {
|
|
195
|
+
binding.markDead();
|
|
196
|
+
const stack = this.getStack();
|
|
197
|
+
const pruned = stack.filter((b) => b !== binding && b.isLive());
|
|
198
|
+
if (pruned.length !== stack.length) {
|
|
199
|
+
this.setAmbientStack(pruned);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
runWith(binding, callback) {
|
|
203
|
+
this.maybeAdoptAsyncLocalStorage();
|
|
204
|
+
if (this._als) {
|
|
205
|
+
return this._als.run([...this.getStack(), binding], callback);
|
|
206
|
+
}
|
|
207
|
+
const previous = this._syncStack;
|
|
208
|
+
this._syncStack = [...previous, binding];
|
|
209
|
+
try {
|
|
210
|
+
return callback();
|
|
211
|
+
} finally {
|
|
212
|
+
this._syncStack = previous;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
current() {
|
|
216
|
+
const stack = this.getStack();
|
|
217
|
+
if (stack.length === 0) return void 0;
|
|
218
|
+
const top = stack[stack.length - 1];
|
|
219
|
+
if (top.isLive()) return top;
|
|
220
|
+
const pruned = stack.filter((b) => b.isLive());
|
|
221
|
+
this.setAmbientStack(pruned);
|
|
222
|
+
return pruned.length > 0 ? pruned[pruned.length - 1] : void 0;
|
|
223
|
+
}
|
|
224
|
+
warnNoAmbientBindOnce() {
|
|
225
|
+
if (this._warnedNoAmbientBind) return;
|
|
226
|
+
this._warnedNoAmbientBind = true;
|
|
227
|
+
console.warn(this.noAmbientBindWarning);
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
var NO_AMBIENT_ROUTING_BIND_WARNING = "[raindrop] This runtime's AsyncLocalStorage does not implement enterWith (e.g. Cloudflare Workers), so begin()/finish() cannot scope auto-instrumented spans to a project without cross-contaminating concurrent requests. Manual events and explicit span routing are unaffected; use asCurrent()/withSpan (run-based) to route auto-instrumented spans on this runtime.";
|
|
231
|
+
var ROUTING_STORAGE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.routingContextStorage");
|
|
232
|
+
function routingStorage() {
|
|
233
|
+
const holder = globalThis;
|
|
234
|
+
let storage = holder[ROUTING_STORAGE_KEY];
|
|
235
|
+
if (!storage) {
|
|
236
|
+
storage = new ContextStackStorage(NO_AMBIENT_ROUTING_BIND_WARNING);
|
|
237
|
+
holder[ROUTING_STORAGE_KEY] = storage;
|
|
238
|
+
}
|
|
239
|
+
return storage;
|
|
240
|
+
}
|
|
241
|
+
function currentRoutingBinding() {
|
|
242
|
+
const bound = routingStorage().current();
|
|
243
|
+
if (!bound) return void 0;
|
|
244
|
+
return {
|
|
245
|
+
projectId: bound.projectId,
|
|
246
|
+
authHint: bound.authHint,
|
|
247
|
+
...bound.appGit ? { appGit: bound.appGit } : {},
|
|
248
|
+
...bound.appGitSource ? { appGitSource: bound.appGitSource } : {}
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
var APP_COMMIT_SHA = "raindrop.app.commit_sha";
|
|
252
|
+
var APP_COMMIT_DIRTY = "raindrop.app.commit_dirty";
|
|
253
|
+
var APP_BRANCH = "raindrop.app.branch";
|
|
254
|
+
var APP_GIT_KEYS = [APP_COMMIT_SHA, APP_COMMIT_DIRTY, APP_BRANCH];
|
|
255
|
+
var own = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
256
|
+
function appGitExplicitKeys(properties) {
|
|
257
|
+
const keys = /* @__PURE__ */ new Set();
|
|
258
|
+
if (!properties) return keys;
|
|
259
|
+
for (const key of APP_GIT_KEYS) {
|
|
260
|
+
if (own(properties, key)) keys.add(key);
|
|
261
|
+
}
|
|
262
|
+
return keys;
|
|
263
|
+
}
|
|
264
|
+
function mergeAppGitSnapshot(base, properties, explicitKeys = /* @__PURE__ */ new Set()) {
|
|
265
|
+
try {
|
|
266
|
+
const result = { ...base };
|
|
267
|
+
if (properties && own(properties, APP_COMMIT_SHA) && properties[APP_COMMIT_SHA] !== result[APP_COMMIT_SHA]) {
|
|
268
|
+
if (!explicitKeys.has(APP_COMMIT_DIRTY) && !own(properties, APP_COMMIT_DIRTY)) {
|
|
269
|
+
delete result[APP_COMMIT_DIRTY];
|
|
270
|
+
}
|
|
271
|
+
if (!explicitKeys.has(APP_BRANCH) && !own(properties, APP_BRANCH)) {
|
|
272
|
+
delete result[APP_BRANCH];
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
for (const key of APP_GIT_KEYS) {
|
|
276
|
+
if (properties && own(properties, key)) result[key] = properties[key];
|
|
277
|
+
}
|
|
278
|
+
return Object.freeze(result);
|
|
279
|
+
} catch (e) {
|
|
280
|
+
return Object.freeze({});
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
function validAppCommitSha(value) {
|
|
284
|
+
if (typeof value !== "string" || value.length > 128) return void 0;
|
|
285
|
+
const cleaned = value.trim();
|
|
286
|
+
return /^(?:[a-fA-F0-9]{40}|[a-fA-F0-9]{64})$/.test(cleaned) ? cleaned.toLowerCase() : void 0;
|
|
287
|
+
}
|
|
288
|
+
function shortString(value) {
|
|
289
|
+
if (typeof value !== "string" || value.length > 1024) return void 0;
|
|
290
|
+
const cleaned = value.trim();
|
|
291
|
+
return cleaned.length > 0 ? cleaned : void 0;
|
|
292
|
+
}
|
|
293
|
+
function flag(value) {
|
|
294
|
+
if (value === true || value === "true" || value === "1") return true;
|
|
295
|
+
if (value === false || value === "false" || value === "0") return false;
|
|
296
|
+
return void 0;
|
|
297
|
+
}
|
|
298
|
+
function environment() {
|
|
299
|
+
try {
|
|
300
|
+
return typeof process === "undefined" ? {} : process.env;
|
|
301
|
+
} catch (e) {
|
|
302
|
+
return {};
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
var DEPLOYMENTS = [
|
|
306
|
+
["VERCEL", "VERCEL_GIT_COMMIT_SHA", "VERCEL_GIT_COMMIT_REF"],
|
|
307
|
+
["NETLIFY", "COMMIT_REF", "BRANCH"],
|
|
308
|
+
["RAILWAY_ENVIRONMENT_NAME", "RAILWAY_GIT_COMMIT_SHA", "RAILWAY_GIT_BRANCH"],
|
|
309
|
+
["RAILWAY_ENVIRONMENT", "RAILWAY_GIT_COMMIT_SHA", "RAILWAY_GIT_BRANCH"],
|
|
310
|
+
["RENDER", "RENDER_GIT_COMMIT", "RENDER_GIT_BRANCH"],
|
|
311
|
+
["DYNO", "HEROKU_BUILD_COMMIT", ""],
|
|
312
|
+
["DYNO", "HEROKU_SLUG_COMMIT", ""],
|
|
313
|
+
["AWS_APP_ID", "AWS_COMMIT_ID", "AWS_BRANCH"],
|
|
314
|
+
["WORKERS_CI", "WORKERS_CI_COMMIT_SHA", "WORKERS_CI_BRANCH"]
|
|
315
|
+
];
|
|
316
|
+
var CI_SOURCES = [
|
|
317
|
+
["GITHUB_ACTIONS", "GITHUB_SHA", "GITHUB_REF_NAME"],
|
|
318
|
+
["GITLAB_CI", "CI_COMMIT_SHA", "CI_COMMIT_REF_NAME"],
|
|
319
|
+
["CIRCLECI", "CIRCLE_SHA1", "CIRCLE_BRANCH"]
|
|
320
|
+
];
|
|
321
|
+
function detectedSource(env, table, detectBranch) {
|
|
322
|
+
for (const row of table) {
|
|
323
|
+
const [marker, shaKey, branchKey] = row;
|
|
324
|
+
if (!marker || !shaKey || !shortString(env[marker]) || flag(env[marker]) === false) continue;
|
|
325
|
+
const commitSha = validAppCommitSha(env[shaKey]);
|
|
326
|
+
if (commitSha)
|
|
327
|
+
return {
|
|
328
|
+
commitSha,
|
|
329
|
+
...detectBranch && branchKey ? { branch: shortString(env[branchKey]) } : {}
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
return {};
|
|
333
|
+
}
|
|
334
|
+
var AppGitContextImpl = class {
|
|
335
|
+
constructor(options, runtime = {}) {
|
|
336
|
+
this.defaults = {};
|
|
337
|
+
this.explicit = {};
|
|
338
|
+
this.explicitKeys = /* @__PURE__ */ new Set();
|
|
339
|
+
this.disposed = false;
|
|
340
|
+
this.operations = /* @__PURE__ */ new Map();
|
|
341
|
+
this.operationOverflow = false;
|
|
342
|
+
this.detectBranch = false;
|
|
343
|
+
this.disabled = false;
|
|
344
|
+
var _a, _b, _c, _d, _e, _f;
|
|
345
|
+
try {
|
|
346
|
+
if (options === false) {
|
|
347
|
+
this.disabled = true;
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
const opts = options != null ? options : {};
|
|
351
|
+
const env = (_a = runtime.env) != null ? _a : environment();
|
|
352
|
+
const detectBranch = (_c = (_b = flag(opts.detectBranch)) != null ? _b : flag(env.RAINDROP_GIT_DETECT_BRANCH)) != null ? _c : false;
|
|
353
|
+
this.detectBranch = detectBranch;
|
|
354
|
+
const collectBranch = detectBranch || runtime.captureLegacyReplayBranch === true;
|
|
355
|
+
const autoDetect = runtime.allowDiscovery === false ? false : (_e = (_d = flag(opts.autoDetect)) != null ? _d : flag(env.RAINDROP_GIT_AUTO_DETECT)) != null ? _e : true;
|
|
356
|
+
const configuredSha = opts.commitSha;
|
|
357
|
+
const explicitSha = configuredSha === void 0 ? env.RAINDROP_COMMIT_SHA : configuredSha;
|
|
358
|
+
if (explicitSha === null) this.explicit[APP_COMMIT_SHA] = null;
|
|
359
|
+
else if (typeof explicitSha === "string" && validAppCommitSha(explicitSha))
|
|
360
|
+
this.explicit[APP_COMMIT_SHA] = explicitSha;
|
|
361
|
+
const configuredDirty = opts.commitDirty;
|
|
362
|
+
const explicitDirty = configuredDirty === void 0 ? flag(env.RAINDROP_COMMIT_DIRTY) : configuredDirty;
|
|
363
|
+
if (explicitDirty === null || typeof explicitDirty === "boolean")
|
|
364
|
+
this.explicit[APP_COMMIT_DIRTY] = explicitDirty;
|
|
365
|
+
const configuredBranch = opts.branch;
|
|
366
|
+
const explicitBranch = configuredBranch === void 0 ? env.RAINDROP_BRANCH : configuredBranch;
|
|
367
|
+
if (explicitBranch === null) this.explicit[APP_BRANCH] = null;
|
|
368
|
+
else if (typeof explicitBranch === "string" && explicitBranch.length <= 1024)
|
|
369
|
+
this.explicit[APP_BRANCH] = explicitBranch;
|
|
370
|
+
this.explicitKeys = appGitExplicitKeys(this.explicit);
|
|
371
|
+
this.defaults = { ...this.explicit };
|
|
372
|
+
if (!autoDetect || explicitSha !== void 0) return;
|
|
373
|
+
const sourceDirectory = (_f = shortString(opts.sourceDirectory)) != null ? _f : shortString(env.RAINDROP_GIT_SOURCE_DIRECTORY);
|
|
374
|
+
if (runtime.allowLocalGit === false && !sourceDirectory) return;
|
|
375
|
+
const deploy = sourceDirectory ? {} : detectedSource(env, DEPLOYMENTS, collectBranch);
|
|
376
|
+
if (deploy.commitSha) {
|
|
377
|
+
this.accept(deploy);
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
const fallback = sourceDirectory ? {} : detectedSource(env, CI_SOURCES, collectBranch);
|
|
381
|
+
if (runtime.resolveLocal && (runtime.allowLocalGit !== false || sourceDirectory)) {
|
|
382
|
+
this.cancel = runtime.resolveLocal(sourceDirectory, collectBranch, (result) => {
|
|
383
|
+
try {
|
|
384
|
+
if (!this.disposed) this.accept(result.commitSha ? result : fallback);
|
|
385
|
+
} catch (e) {
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
} else this.accept(fallback);
|
|
389
|
+
} catch (e) {
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
accept(result) {
|
|
393
|
+
const sha = validAppCommitSha(result.commitSha);
|
|
394
|
+
if (!sha) return;
|
|
395
|
+
this.replayBranch = shortString(result.branch);
|
|
396
|
+
this.defaults = {
|
|
397
|
+
[APP_COMMIT_SHA]: sha,
|
|
398
|
+
...typeof result.commitDirty === "boolean" ? { [APP_COMMIT_DIRTY]: result.commitDirty } : {},
|
|
399
|
+
...this.detectBranch && this.replayBranch ? { [APP_BRANCH]: this.replayBranch } : {},
|
|
400
|
+
...this.explicit
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
snapshot(properties) {
|
|
404
|
+
var _a;
|
|
405
|
+
try {
|
|
406
|
+
const binding = currentRoutingBinding();
|
|
407
|
+
const base = this.disabled && (binding == null ? void 0 : binding.appGitSource) !== "replay-override" ? {} : (_a = binding == null ? void 0 : binding.appGit) != null ? _a : this.defaults;
|
|
408
|
+
return this.mergeSnapshot(base, properties);
|
|
409
|
+
} catch (e) {
|
|
410
|
+
return Object.freeze({});
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
/** Safe defaults when no operation/span start was observed; never infer identity. */
|
|
414
|
+
snapshotExplicit(properties, eventId) {
|
|
415
|
+
try {
|
|
416
|
+
const base = { ...this.explicit };
|
|
417
|
+
const operation = eventId ? this.operations.get(eventId) : void 0;
|
|
418
|
+
if (operation) {
|
|
419
|
+
for (const key of operation.explicitKeys) base[key] = operation.snapshot[key];
|
|
420
|
+
}
|
|
421
|
+
return this.mergeSnapshot(base, properties, new Set(Object.keys(base)));
|
|
422
|
+
} catch (e) {
|
|
423
|
+
return mergeAppGitSnapshot({}, properties);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
/** Existing replay branch reporting stays separate from opt-in event properties. */
|
|
427
|
+
snapshotForReplay() {
|
|
428
|
+
const snapshot = this.snapshot();
|
|
429
|
+
if (this.replayBranch && !own(snapshot, APP_BRANCH) && snapshot[APP_COMMIT_SHA] === this.defaults[APP_COMMIT_SHA]) {
|
|
430
|
+
return Object.freeze({ ...snapshot, [APP_BRANCH]: this.replayBranch });
|
|
431
|
+
}
|
|
432
|
+
return snapshot;
|
|
433
|
+
}
|
|
434
|
+
/** Merge a frozen span snapshot without losing client-authored provenance. */
|
|
435
|
+
mergeSnapshot(base, properties, explicitKeys = this.explicitKeys) {
|
|
436
|
+
return mergeAppGitSnapshot(base, properties, /* @__PURE__ */ new Set([...this.explicitKeys, ...explicitKeys]));
|
|
437
|
+
}
|
|
438
|
+
/** Shippers belonging to one client share this bounded operation registry. */
|
|
439
|
+
forOperation(eventId, properties, owner) {
|
|
440
|
+
if (!eventId) return this.snapshot(properties);
|
|
441
|
+
let operation = this.operations.get(eventId);
|
|
442
|
+
if (!operation) {
|
|
443
|
+
if (this.operations.size >= 1e4) this.operationOverflow = true;
|
|
444
|
+
if (this.operationOverflow) return this.mergeSnapshot({}, properties);
|
|
445
|
+
operation = {
|
|
446
|
+
snapshot: this.snapshot(properties),
|
|
447
|
+
owners: /* @__PURE__ */ new Set(),
|
|
448
|
+
unowned: owner === void 0,
|
|
449
|
+
explicitKeys: appGitExplicitKeys(properties)
|
|
450
|
+
};
|
|
451
|
+
this.operations.set(eventId, operation);
|
|
452
|
+
} else if (properties && APP_GIT_KEYS.some((key) => own(properties, key))) {
|
|
453
|
+
const explicitKeys = /* @__PURE__ */ new Set([...this.explicitKeys, ...operation.explicitKeys]);
|
|
454
|
+
operation.snapshot = this.mergeSnapshot(operation.snapshot, properties, explicitKeys);
|
|
455
|
+
for (const key of appGitExplicitKeys(properties)) operation.explicitKeys.add(key);
|
|
456
|
+
}
|
|
457
|
+
if (!owner) operation.unowned = true;
|
|
458
|
+
if (owner) operation.owners.add(owner);
|
|
459
|
+
return operation.snapshot;
|
|
460
|
+
}
|
|
461
|
+
releaseOperation(eventId, owner) {
|
|
462
|
+
const operation = this.operations.get(eventId);
|
|
463
|
+
if (!operation) return;
|
|
464
|
+
operation.owners.delete(owner);
|
|
465
|
+
if (operation.owners.size === 0 && !operation.unowned) this.operations.delete(eventId);
|
|
466
|
+
}
|
|
467
|
+
finishOperation(eventId) {
|
|
468
|
+
this.operations.delete(eventId);
|
|
469
|
+
}
|
|
470
|
+
dispose() {
|
|
471
|
+
var _a;
|
|
472
|
+
this.disposed = true;
|
|
473
|
+
try {
|
|
474
|
+
(_a = this.cancel) == null ? void 0 : _a.call(this);
|
|
475
|
+
} catch (e) {
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
};
|
|
479
|
+
var AppGitContext = AppGitContextImpl;
|
|
480
|
+
function createAppGitContext(options, runtime = {}) {
|
|
481
|
+
return new AppGitContext(options, runtime);
|
|
482
|
+
}
|
|
483
|
+
function withAppGitProperties(properties, snapshot) {
|
|
484
|
+
try {
|
|
485
|
+
const merged = { ...properties };
|
|
486
|
+
for (const key of APP_GIT_KEYS)
|
|
487
|
+
if (!own(merged, key) && own(snapshot, key)) merged[key] = snapshot[key];
|
|
488
|
+
return merged;
|
|
489
|
+
} catch (e) {
|
|
490
|
+
return properties != null ? properties : {};
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
function withAppGitAttributes(attributes, snapshot) {
|
|
494
|
+
try {
|
|
495
|
+
const present = new Set(attributes.flatMap((attr) => attr ? [attr.key] : []));
|
|
496
|
+
const added = [];
|
|
497
|
+
for (const key of APP_GIT_KEYS) {
|
|
498
|
+
if (present.has(key) || present.has(`ai.telemetry.metadata.${key}`) || present.has(`traceloop.association.properties.${key}`))
|
|
499
|
+
continue;
|
|
500
|
+
const value = snapshot[key];
|
|
501
|
+
if (typeof value === "string") added.push({ key, value: { stringValue: value } });
|
|
502
|
+
else if (typeof value === "boolean") added.push({ key, value: { boolValue: value } });
|
|
503
|
+
}
|
|
504
|
+
return added.length ? [...attributes, ...added] : attributes;
|
|
505
|
+
} catch (e) {
|
|
506
|
+
return attributes;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
function appGitPropertiesFromAttributes(attributes) {
|
|
510
|
+
var _a, _b, _c;
|
|
511
|
+
const properties = {};
|
|
512
|
+
try {
|
|
513
|
+
for (const attr of attributes) {
|
|
514
|
+
if (!attr) continue;
|
|
515
|
+
for (const key of APP_GIT_KEYS) {
|
|
516
|
+
if (attr.key === key || attr.key === `ai.telemetry.metadata.${key}` || attr.key === `traceloop.association.properties.${key}`) {
|
|
517
|
+
properties[key] = (_c = (_b = (_a = attr.value.stringValue) != null ? _a : attr.value.boolValue) != null ? _b : attr.value.intValue) != null ? _c : null;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
} catch (e) {
|
|
522
|
+
}
|
|
523
|
+
return properties;
|
|
524
|
+
}
|
|
11
525
|
function getCrypto() {
|
|
12
526
|
const c = globalThis.crypto;
|
|
13
527
|
return c;
|
|
@@ -22,6 +536,17 @@ function randomBytes(length) {
|
|
|
22
536
|
for (let i = 0; i < out.length; i++) out[i] = Math.floor(Math.random() * 256);
|
|
23
537
|
return out;
|
|
24
538
|
}
|
|
539
|
+
function randomUUID() {
|
|
540
|
+
const cryptoObj = getCrypto();
|
|
541
|
+
if (cryptoObj && typeof cryptoObj.randomUUID === "function") {
|
|
542
|
+
return cryptoObj.randomUUID();
|
|
543
|
+
}
|
|
544
|
+
const b = randomBytes(16);
|
|
545
|
+
b[6] = b[6] & 15 | 64;
|
|
546
|
+
b[8] = b[8] & 63 | 128;
|
|
547
|
+
const hex = [...b].map((x) => x.toString(16).padStart(2, "0")).join("");
|
|
548
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
549
|
+
}
|
|
25
550
|
function base64Encode(bytes) {
|
|
26
551
|
const maybeBuffer = globalThis.Buffer;
|
|
27
552
|
if (maybeBuffer) {
|
|
@@ -51,6 +576,25 @@ function base64Encode(bytes) {
|
|
|
51
576
|
}
|
|
52
577
|
return out;
|
|
53
578
|
}
|
|
579
|
+
function base64ToHex(value) {
|
|
580
|
+
if (!value) return "";
|
|
581
|
+
const maybeBuffer = globalThis.Buffer;
|
|
582
|
+
if (maybeBuffer) {
|
|
583
|
+
return maybeBuffer.from(value, "base64").toString("hex");
|
|
584
|
+
}
|
|
585
|
+
const atobFn = globalThis.atob;
|
|
586
|
+
if (typeof atobFn !== "function") return "";
|
|
587
|
+
try {
|
|
588
|
+
const binary = atobFn(value);
|
|
589
|
+
let hex = "";
|
|
590
|
+
for (let i = 0; i < binary.length; i++) {
|
|
591
|
+
hex += (binary.charCodeAt(i) & 255).toString(16).padStart(2, "0");
|
|
592
|
+
}
|
|
593
|
+
return hex;
|
|
594
|
+
} catch (e) {
|
|
595
|
+
return "";
|
|
596
|
+
}
|
|
597
|
+
}
|
|
54
598
|
var HANDOFF_ATTRIBUTE_SUFFIXES = {
|
|
55
599
|
mode: "raindrop.handoff.mode",
|
|
56
600
|
childEventId: "raindrop.handoff.childEventId",
|
|
@@ -82,7 +626,7 @@ function runWithTracingSuppressed(fn) {
|
|
|
82
626
|
var DEFAULT_REQUEST_TIMEOUT_MS = 3e4;
|
|
83
627
|
var MAX_RETRY_DELAY_MS = 3e4;
|
|
84
628
|
function wait(ms) {
|
|
85
|
-
return new Promise((
|
|
629
|
+
return new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
86
630
|
}
|
|
87
631
|
function formatEndpoint(endpoint) {
|
|
88
632
|
if (!endpoint) return void 0;
|
|
@@ -119,9 +663,9 @@ async function raceWithTimeout(promise, timeoutMs) {
|
|
|
119
663
|
() => true,
|
|
120
664
|
() => true
|
|
121
665
|
),
|
|
122
|
-
new Promise((
|
|
666
|
+
new Promise((resolve3) => {
|
|
123
667
|
var _a;
|
|
124
|
-
timer = setTimeout(() =>
|
|
668
|
+
timer = setTimeout(() => resolve3(false), Math.max(0, timeoutMs));
|
|
125
669
|
(_a = timer.unref) == null ? void 0 : _a.call(timer);
|
|
126
670
|
})
|
|
127
671
|
]);
|
|
@@ -192,6 +736,7 @@ async function postJson(url, body, headers, opts) {
|
|
|
192
736
|
const resp = await runWithTracingSuppressed(
|
|
193
737
|
() => fetch(url, {
|
|
194
738
|
method: "POST",
|
|
739
|
+
redirect: headers["X-Raindrop-Replay-Id"] !== void 0 ? "error" : "follow",
|
|
195
740
|
headers: {
|
|
196
741
|
"Content-Type": "application/json",
|
|
197
742
|
...headers
|
|
@@ -402,6 +947,13 @@ function projectIdHeaders(projectId) {
|
|
|
402
947
|
}
|
|
403
948
|
var SHUTDOWN_DEADLINE_MS = 1e4;
|
|
404
949
|
var POST_SHUTDOWN_TIMEOUT_MS = 5e3;
|
|
950
|
+
function appGitOwnerId(prefix) {
|
|
951
|
+
try {
|
|
952
|
+
return `${prefix}:${randomUUID()}`;
|
|
953
|
+
} catch (e) {
|
|
954
|
+
return `${prefix}:${Date.now().toString(36)}:${Math.random().toString(36).slice(2)}`;
|
|
955
|
+
}
|
|
956
|
+
}
|
|
405
957
|
function mergePatches(target, source) {
|
|
406
958
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
407
959
|
const out = { ...target, ...source };
|
|
@@ -451,22 +1003,25 @@ function eventTelemetryProperties(patch) {
|
|
|
451
1003
|
}
|
|
452
1004
|
var EventShipper = class {
|
|
453
1005
|
constructor(opts) {
|
|
1006
|
+
this.appGitOwner = appGitOwnerId("event");
|
|
454
1007
|
this.buffers = /* @__PURE__ */ new Map();
|
|
455
1008
|
this.sticky = /* @__PURE__ */ new Map();
|
|
456
1009
|
this.timers = /* @__PURE__ */ new Map();
|
|
457
1010
|
this.inFlight = /* @__PURE__ */ new Set();
|
|
458
1011
|
this.hasShutdown = false;
|
|
459
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
460
|
-
this.
|
|
461
|
-
this.
|
|
1012
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
1013
|
+
this.appGitContext = (_a = opts.appGitContext) != null ? _a : createAppGitContext(opts.appGit);
|
|
1014
|
+
this.ownsAppGitContext = opts.appGitContext === void 0;
|
|
1015
|
+
this.writeKey = (_b = opts.writeKey) == null ? void 0 : _b.trim();
|
|
1016
|
+
this.baseUrl = (_c = formatEndpoint(opts.endpoint)) != null ? _c : "https://api.raindrop.ai/v1/";
|
|
462
1017
|
this.enabled = opts.enabled !== false;
|
|
463
1018
|
this.debug = opts.debug;
|
|
464
|
-
this.partialFlushMs = (
|
|
465
|
-
this.sdkName = (
|
|
1019
|
+
this.partialFlushMs = (_d = opts.partialFlushMs) != null ? _d : 1e3;
|
|
1020
|
+
this.sdkName = (_e = opts.sdkName) != null ? _e : "core";
|
|
466
1021
|
this.prefix = `[raindrop-ai/${this.sdkName}]`;
|
|
467
|
-
this.defaultEventName = (
|
|
1022
|
+
this.defaultEventName = (_f = opts.defaultEventName) != null ? _f : "ai_generation";
|
|
468
1023
|
this.maxTextFieldCharsOpt = opts.maxTextFieldChars;
|
|
469
|
-
this.localDebuggerUrl = (
|
|
1024
|
+
this.localDebuggerUrl = (_g = resolveLocalDebuggerBaseUrl(opts.localDebuggerUrl)) != null ? _g : void 0;
|
|
470
1025
|
if (this.debug && this.localDebuggerUrl) {
|
|
471
1026
|
console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
|
|
472
1027
|
}
|
|
@@ -477,8 +1032,8 @@ var EventShipper = class {
|
|
|
477
1032
|
const isNode = typeof process !== "undefined" && typeof process.version === "string";
|
|
478
1033
|
this.context = {
|
|
479
1034
|
library: {
|
|
480
|
-
name: (
|
|
481
|
-
version: (
|
|
1035
|
+
name: (_h = opts.libraryName) != null ? _h : "@raindrop-ai/core",
|
|
1036
|
+
version: (_i = opts.libraryVersion) != null ? _i : "0.0.0"
|
|
482
1037
|
},
|
|
483
1038
|
metadata: {
|
|
484
1039
|
jsRuntime: isNode ? "node" : "web",
|
|
@@ -486,6 +1041,9 @@ var EventShipper = class {
|
|
|
486
1041
|
}
|
|
487
1042
|
};
|
|
488
1043
|
}
|
|
1044
|
+
ownAppGitContextForShutdown() {
|
|
1045
|
+
this.ownsAppGitContext = true;
|
|
1046
|
+
}
|
|
489
1047
|
isDebugEnabled() {
|
|
490
1048
|
return this.debug;
|
|
491
1049
|
}
|
|
@@ -534,6 +1092,15 @@ var EventShipper = class {
|
|
|
534
1092
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
535
1093
|
if (!this.enabled) return;
|
|
536
1094
|
if (!eventId || !eventId.trim()) return;
|
|
1095
|
+
const capturedSticky = this.sticky.get(eventId);
|
|
1096
|
+
const eventAlreadyKnown = capturedSticky !== void 0 || this.buffers.has(eventId);
|
|
1097
|
+
const destination = currentReplayTraceDestination();
|
|
1098
|
+
const cloudReplay = destination !== void 0 && destination.kind !== "workshop";
|
|
1099
|
+
if ((capturedSticky == null ? void 0 : capturedSticky.replayOnly) === true || !eventAlreadyKnown && cloudReplay) {
|
|
1100
|
+
if (patch.isPending === false) this.sticky.delete(eventId);
|
|
1101
|
+
else this.sticky.set(eventId, { ...capturedSticky, replayOnly: true });
|
|
1102
|
+
return;
|
|
1103
|
+
}
|
|
537
1104
|
const maxChars = resolveMaxTextFieldChars(this.maxTextFieldCharsOpt);
|
|
538
1105
|
if (typeof patch.input === "string" && patch.input.length > maxChars) {
|
|
539
1106
|
patch = { ...patch, input: capText(patch.input, maxChars) };
|
|
@@ -555,6 +1122,13 @@ var EventShipper = class {
|
|
|
555
1122
|
}
|
|
556
1123
|
const sticky = (_c = this.sticky.get(eventId)) != null ? _c : {};
|
|
557
1124
|
const existing = (_d = this.buffers.get(eventId)) != null ? _d : {};
|
|
1125
|
+
patch = {
|
|
1126
|
+
...patch,
|
|
1127
|
+
properties: withAppGitProperties(
|
|
1128
|
+
patch.properties,
|
|
1129
|
+
this.appGitContext.forOperation(eventId, patch.properties, this.appGitOwner)
|
|
1130
|
+
)
|
|
1131
|
+
};
|
|
558
1132
|
const merged = mergePatches(existing, patch);
|
|
559
1133
|
merged.isPending = (_g = (_f = (_e = patch.isPending) != null ? _e : existing.isPending) != null ? _f : sticky.isPending) != null ? _g : true;
|
|
560
1134
|
this.buffers.set(eventId, merged);
|
|
@@ -568,6 +1142,8 @@ var EventShipper = class {
|
|
|
568
1142
|
if (t) clearTimeout(t);
|
|
569
1143
|
if (merged.isPending === false) {
|
|
570
1144
|
await this.flushOne(eventId);
|
|
1145
|
+
if (this.appGitContext.releaseOperation) this.appGitContext.releaseOperation(eventId, this.appGitOwner);
|
|
1146
|
+
else this.appGitContext.finishOperation(eventId);
|
|
571
1147
|
return;
|
|
572
1148
|
}
|
|
573
1149
|
const timeout = setTimeout(() => {
|
|
@@ -592,15 +1168,21 @@ var EventShipper = class {
|
|
|
592
1168
|
try {
|
|
593
1169
|
for (const t of this.timers.values()) clearTimeout(t);
|
|
594
1170
|
this.timers.clear();
|
|
1171
|
+
for (const [eventId, sticky] of this.sticky) {
|
|
1172
|
+
if (sticky.replayOnly) this.sticky.delete(eventId);
|
|
1173
|
+
}
|
|
595
1174
|
const settled = await raceWithTimeout(this.flush(), SHUTDOWN_DEADLINE_MS);
|
|
596
1175
|
if (!settled) this.warnShutdownDrop("in-flight request(s) at shutdown");
|
|
597
1176
|
} finally {
|
|
598
1177
|
this.shutdownDeadlineAt = void 0;
|
|
1178
|
+
if (this.ownsAppGitContext) this.appGitContext.dispose();
|
|
599
1179
|
}
|
|
600
1180
|
}
|
|
601
1181
|
async trackSignal(signal) {
|
|
602
1182
|
var _a, _b;
|
|
603
1183
|
if (!this.enabled) return;
|
|
1184
|
+
const destination = currentReplayTraceDestination();
|
|
1185
|
+
if (destination && destination.kind !== "workshop") return;
|
|
604
1186
|
const body = [
|
|
605
1187
|
{
|
|
606
1188
|
event_id: signal.eventId,
|
|
@@ -635,6 +1217,8 @@ var EventShipper = class {
|
|
|
635
1217
|
}
|
|
636
1218
|
async identify(users) {
|
|
637
1219
|
if (!this.enabled) return;
|
|
1220
|
+
const destination = currentReplayTraceDestination();
|
|
1221
|
+
if (destination && destination.kind !== "workshop") return;
|
|
638
1222
|
const list = Array.isArray(users) ? users : [users];
|
|
639
1223
|
const body = list.filter((user) => {
|
|
640
1224
|
if (!(user == null ? void 0 : user.userId) || !user.userId.trim()) {
|
|
@@ -687,8 +1271,9 @@ var EventShipper = class {
|
|
|
687
1271
|
this.buffers.delete(eventId);
|
|
688
1272
|
if (!accumulated) return;
|
|
689
1273
|
const sticky = (_a = this.sticky.get(eventId)) != null ? _a : {};
|
|
690
|
-
const
|
|
691
|
-
const
|
|
1274
|
+
const isPending = (_c = (_b = accumulated.isPending) != null ? _b : sticky.isPending) != null ? _c : true;
|
|
1275
|
+
const eventName = (_e = (_d = accumulated.eventName) != null ? _d : sticky.eventName) != null ? _e : this.defaultEventName;
|
|
1276
|
+
const userId = (_f = accumulated.userId) != null ? _f : sticky.userId;
|
|
692
1277
|
if (!userId) {
|
|
693
1278
|
if (this.debug) {
|
|
694
1279
|
console.warn(`${this.prefix} skipping track_partial for ${eventId}: missing userId`);
|
|
@@ -696,14 +1281,13 @@ var EventShipper = class {
|
|
|
696
1281
|
this.sticky.delete(eventId);
|
|
697
1282
|
return;
|
|
698
1283
|
}
|
|
699
|
-
const { wizardSession, ...restProperties } = (
|
|
1284
|
+
const { wizardSession, ...restProperties } = (_g = accumulated.properties) != null ? _g : {};
|
|
700
1285
|
let telemetryProperties = {};
|
|
701
1286
|
try {
|
|
702
1287
|
telemetryProperties = eventTelemetryProperties(accumulated);
|
|
703
1288
|
} catch (e) {
|
|
704
1289
|
}
|
|
705
|
-
const convoId = (
|
|
706
|
-
const isPending = (_h = (_g = accumulated.isPending) != null ? _g : sticky.isPending) != null ? _h : true;
|
|
1290
|
+
const convoId = (_h = accumulated.convoId) != null ? _h : sticky.convoId;
|
|
707
1291
|
const payload = {
|
|
708
1292
|
event_id: eventId,
|
|
709
1293
|
user_id: userId,
|
|
@@ -1019,6 +1603,13 @@ function redactJsonAttributeValue(key, value) {
|
|
|
1019
1603
|
if (scrubbedJson === json) return void 0;
|
|
1020
1604
|
return { stringValue: scrubbedJson };
|
|
1021
1605
|
}
|
|
1606
|
+
function appGitOwnerId2(prefix) {
|
|
1607
|
+
try {
|
|
1608
|
+
return `${prefix}:${randomUUID()}`;
|
|
1609
|
+
} catch (e) {
|
|
1610
|
+
return `${prefix}:${Date.now().toString(36)}:${Math.random().toString(36).slice(2)}`;
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1022
1613
|
function identityAttrs(args2) {
|
|
1023
1614
|
return [
|
|
1024
1615
|
attrString("ai.telemetry.metadata.raindrop.ai.userId", args2.userId),
|
|
@@ -1041,23 +1632,30 @@ function applyOtelSpanAttributeLimit(limit) {
|
|
|
1041
1632
|
}
|
|
1042
1633
|
var TraceShipper = class {
|
|
1043
1634
|
constructor(opts) {
|
|
1635
|
+
this.appGitOwner = appGitOwnerId2("trace");
|
|
1636
|
+
this.appGitEventIds = /* @__PURE__ */ new WeakMap();
|
|
1637
|
+
this.appGitActiveSpans = /* @__PURE__ */ new Map();
|
|
1638
|
+
this.appGitCaptured = /* @__PURE__ */ new WeakSet();
|
|
1639
|
+
this.appGitAdded = /* @__PURE__ */ new WeakMap();
|
|
1044
1640
|
this.queue = [];
|
|
1045
1641
|
this.inFlight = /* @__PURE__ */ new Set();
|
|
1046
1642
|
this.hasShutdown = false;
|
|
1047
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
1048
|
-
this.
|
|
1049
|
-
this.
|
|
1643
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
1644
|
+
this.appGitContext = (_a = opts.appGitContext) != null ? _a : createAppGitContext(opts.appGit);
|
|
1645
|
+
this.ownsAppGitContext = opts.appGitContext === void 0;
|
|
1646
|
+
this.writeKey = (_b = opts.writeKey) == null ? void 0 : _b.trim();
|
|
1647
|
+
this.baseUrl = (_c = formatEndpoint(opts.endpoint)) != null ? _c : "https://api.raindrop.ai/v1/";
|
|
1050
1648
|
this.enabled = opts.enabled !== false;
|
|
1051
1649
|
this.debug = opts.debug;
|
|
1052
1650
|
this.debugSpans = opts.debugSpans === true;
|
|
1053
|
-
this.flushIntervalMs = (
|
|
1054
|
-
this.maxBatchSize = (
|
|
1055
|
-
this.maxQueueSize = (
|
|
1056
|
-
this.sdkName = (
|
|
1651
|
+
this.flushIntervalMs = (_d = opts.flushIntervalMs) != null ? _d : 1e3;
|
|
1652
|
+
this.maxBatchSize = (_e = opts.maxBatchSize) != null ? _e : 50;
|
|
1653
|
+
this.maxQueueSize = (_f = opts.maxQueueSize) != null ? _f : 5e3;
|
|
1654
|
+
this.sdkName = (_g = opts.sdkName) != null ? _g : "core";
|
|
1057
1655
|
this.prefix = `[raindrop-ai/${this.sdkName}]`;
|
|
1058
|
-
this.serviceName = (
|
|
1059
|
-
this.serviceVersion = (
|
|
1060
|
-
this.localDebuggerUrl = (
|
|
1656
|
+
this.serviceName = (_h = opts.serviceName) != null ? _h : "raindrop.core";
|
|
1657
|
+
this.serviceVersion = (_i = opts.serviceVersion) != null ? _i : "0.0.0";
|
|
1658
|
+
this.localDebuggerUrl = (_j = resolveLocalDebuggerBaseUrl(opts.localDebuggerUrl)) != null ? _j : void 0;
|
|
1061
1659
|
if (this.debug && this.localDebuggerUrl) {
|
|
1062
1660
|
console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
|
|
1063
1661
|
}
|
|
@@ -1121,7 +1719,10 @@ var TraceShipper = class {
|
|
|
1121
1719
|
try {
|
|
1122
1720
|
const result = this.transformSpanHook(current);
|
|
1123
1721
|
if (result === null) return null;
|
|
1124
|
-
if (result !== void 0)
|
|
1722
|
+
if (result !== void 0) {
|
|
1723
|
+
copyReplayTraceDestination(current, result);
|
|
1724
|
+
current = result;
|
|
1725
|
+
}
|
|
1125
1726
|
} catch (err) {
|
|
1126
1727
|
if (this.debug) {
|
|
1127
1728
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -1131,13 +1732,19 @@ var TraceShipper = class {
|
|
|
1131
1732
|
}
|
|
1132
1733
|
}
|
|
1133
1734
|
try {
|
|
1134
|
-
|
|
1735
|
+
const normalized = normalizeModelUsageSpan(current);
|
|
1736
|
+
copyReplayTraceDestination(current, normalized);
|
|
1737
|
+
current = normalized;
|
|
1135
1738
|
} catch (e) {
|
|
1136
1739
|
}
|
|
1137
1740
|
if (!this.disableDefaultRedaction) {
|
|
1138
|
-
|
|
1741
|
+
const redacted = defaultTransformSpan(current);
|
|
1742
|
+
copyReplayTraceDestination(current, redacted);
|
|
1743
|
+
current = redacted;
|
|
1139
1744
|
}
|
|
1140
|
-
|
|
1745
|
+
const capped = this.capSpanAttributes(current);
|
|
1746
|
+
copyReplayTraceDestination(current, capped);
|
|
1747
|
+
return capped;
|
|
1141
1748
|
}
|
|
1142
1749
|
isDebugEnabled() {
|
|
1143
1750
|
return this.debug;
|
|
@@ -1149,36 +1756,64 @@ var TraceShipper = class {
|
|
|
1149
1756
|
return { ...this.authHeaders(), ...projectIdHeaders(this.projectId) };
|
|
1150
1757
|
}
|
|
1151
1758
|
startSpan(args2) {
|
|
1152
|
-
var _a, _b;
|
|
1759
|
+
var _a, _b, _c;
|
|
1153
1760
|
const ids = createSpanIds(args2.parent);
|
|
1154
1761
|
const started = (_a = args2.startTimeUnixNano) != null ? _a : nowUnixNanoString();
|
|
1155
1762
|
const attrs = [
|
|
1156
1763
|
attrString("ai.telemetry.metadata.raindrop.eventId", args2.eventId),
|
|
1157
1764
|
...identityAttrs(args2),
|
|
1158
|
-
attrString("ai.operationId", args2.operationId)
|
|
1765
|
+
attrString("ai.operationId", args2.operationId),
|
|
1766
|
+
...Object.entries(evalScopeAttributes()).map(([key, value]) => attrString(key, value))
|
|
1159
1767
|
];
|
|
1160
1768
|
if ((_b = args2.attributes) == null ? void 0 : _b.length) attrs.push(...args2.attributes);
|
|
1161
|
-
const
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
);
|
|
1769
|
+
const tracksAppGit = this.appGitActiveSpans.has(args2.eventId) || this.appGitActiveSpans.size < 1e4;
|
|
1770
|
+
const appGitOverrides = appGitPropertiesFromAttributes(attrs);
|
|
1771
|
+
const span = {
|
|
1772
|
+
ids,
|
|
1773
|
+
name: args2.name,
|
|
1774
|
+
startTimeUnixNano: started,
|
|
1775
|
+
attributes: withAppGitAttributes(
|
|
1776
|
+
attrs,
|
|
1777
|
+
this.appGitContext.forOperation(args2.eventId, appGitOverrides, this.appGitOwner)
|
|
1778
|
+
)
|
|
1779
|
+
};
|
|
1780
|
+
rememberReplayTraceDestination(span);
|
|
1781
|
+
this.appGitCaptured.add(span);
|
|
1782
|
+
this.appGitEventIds.set(span, args2.eventId);
|
|
1783
|
+
if (tracksAppGit) {
|
|
1784
|
+
this.appGitActiveSpans.set(args2.eventId, ((_c = this.appGitActiveSpans.get(args2.eventId)) != null ? _c : 0) + 1);
|
|
1785
|
+
}
|
|
1786
|
+
this.appGitAdded.set(span, new Set(span.attributes.filter((attr) => !attrs.includes(attr))));
|
|
1787
|
+
const openSpan = buildOtlpSpan({
|
|
1788
|
+
ids: span.ids,
|
|
1789
|
+
name: span.name,
|
|
1790
|
+
startTimeUnixNano: span.startTimeUnixNano,
|
|
1791
|
+
endTimeUnixNano: span.startTimeUnixNano,
|
|
1792
|
+
// placeholder — will be updated on endSpan
|
|
1793
|
+
attributes: span.attributes,
|
|
1794
|
+
status: { code: SpanStatusCode.UNSET }
|
|
1795
|
+
});
|
|
1796
|
+
copyReplayTraceDestination(span, openSpan);
|
|
1797
|
+
this.mirrorToLocalDebugger(openSpan);
|
|
1173
1798
|
return span;
|
|
1174
1799
|
}
|
|
1175
|
-
mirrorToLocalDebugger(span) {
|
|
1176
|
-
|
|
1800
|
+
mirrorToLocalDebugger(span, completed = false) {
|
|
1801
|
+
const destination = replayTraceDestinationFor(span);
|
|
1802
|
+
if (destination && destination.kind !== "workshop") return;
|
|
1803
|
+
const localDebuggerUrl = (destination == null ? void 0 : destination.kind) === "workshop" ? destination.url : this.localDebuggerUrl;
|
|
1804
|
+
if (!localDebuggerUrl) return;
|
|
1177
1805
|
const redacted = this.redactSpan(span);
|
|
1178
1806
|
if (redacted === null) return;
|
|
1807
|
+
if (completed && (destination == null ? void 0 : destination.kind) === "workshop") {
|
|
1808
|
+
recordReplayExportedSpan(
|
|
1809
|
+
destination,
|
|
1810
|
+
base64ToHex(redacted.spanId),
|
|
1811
|
+
base64ToHex(redacted.traceId)
|
|
1812
|
+
);
|
|
1813
|
+
}
|
|
1179
1814
|
const body = buildExportTraceServiceRequest([redacted], this.serviceName, this.serviceVersion);
|
|
1180
1815
|
const p = mirrorTraceExportToLocalDebugger(body, {
|
|
1181
|
-
baseUrl:
|
|
1816
|
+
baseUrl: localDebuggerUrl,
|
|
1182
1817
|
debug: false,
|
|
1183
1818
|
sdkName: this.sdkName
|
|
1184
1819
|
});
|
|
@@ -1188,11 +1823,17 @@ var TraceShipper = class {
|
|
|
1188
1823
|
});
|
|
1189
1824
|
}
|
|
1190
1825
|
endSpan(span, extra) {
|
|
1191
|
-
var _a, _b;
|
|
1826
|
+
var _a, _b, _c;
|
|
1192
1827
|
if (span.endTimeUnixNano) return;
|
|
1193
1828
|
span.endTimeUnixNano = (_a = extra == null ? void 0 : extra.endTimeUnixNano) != null ? _a : nowUnixNanoString();
|
|
1194
1829
|
if ((_b = extra == null ? void 0 : extra.attributes) == null ? void 0 : _b.length) {
|
|
1830
|
+
const overrides = appGitPropertiesFromAttributes(extra.attributes);
|
|
1831
|
+
const eventId2 = this.appGitEventIds.get(span);
|
|
1832
|
+
const snapshot = eventId2 ? this.appGitContext.forOperation(eventId2, overrides, this.appGitOwner) : overrides;
|
|
1833
|
+
const added = this.appGitAdded.get(span);
|
|
1834
|
+
span.attributes = span.attributes.filter((attr) => !(added == null ? void 0 : added.has(attr)) || !attr || !Object.prototype.hasOwnProperty.call(overrides, APP_COMMIT_SHA) && !Object.prototype.hasOwnProperty.call(overrides, attr.key));
|
|
1195
1835
|
span.attributes.push(...extra.attributes);
|
|
1836
|
+
span.attributes = withAppGitAttributes(span.attributes, snapshot);
|
|
1196
1837
|
}
|
|
1197
1838
|
let status = extra == null ? void 0 : extra.status;
|
|
1198
1839
|
if (!status && (extra == null ? void 0 : extra.error) !== void 0) {
|
|
@@ -1207,30 +1848,65 @@ var TraceShipper = class {
|
|
|
1207
1848
|
attributes: span.attributes,
|
|
1208
1849
|
status
|
|
1209
1850
|
});
|
|
1851
|
+
copyReplayTraceDestination(span, otlp);
|
|
1852
|
+
this.appGitCaptured.add(otlp);
|
|
1210
1853
|
this.enqueue(otlp);
|
|
1211
|
-
this.mirrorToLocalDebugger(otlp);
|
|
1854
|
+
this.mirrorToLocalDebugger(otlp, true);
|
|
1855
|
+
const eventId = this.appGitEventIds.get(span);
|
|
1856
|
+
if (eventId && this.appGitActiveSpans.has(eventId)) {
|
|
1857
|
+
const remaining = ((_c = this.appGitActiveSpans.get(eventId)) != null ? _c : 1) - 1;
|
|
1858
|
+
if (remaining > 0) this.appGitActiveSpans.set(eventId, remaining);
|
|
1859
|
+
else {
|
|
1860
|
+
this.appGitActiveSpans.delete(eventId);
|
|
1861
|
+
if (this.appGitContext.releaseOperation) this.appGitContext.releaseOperation(eventId, this.appGitOwner);
|
|
1862
|
+
else if (this.ownsAppGitContext) this.appGitContext.finishOperation(eventId);
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1212
1865
|
}
|
|
1213
1866
|
createSpan(args2) {
|
|
1214
1867
|
var _a;
|
|
1215
1868
|
const ids = createSpanIds(args2.parent);
|
|
1216
1869
|
const attrs = [
|
|
1217
1870
|
attrString("ai.telemetry.metadata.raindrop.eventId", args2.eventId),
|
|
1218
|
-
...identityAttrs(args2)
|
|
1871
|
+
...identityAttrs(args2),
|
|
1872
|
+
...Object.entries(evalScopeAttributes()).map(([key, value]) => attrString(key, value))
|
|
1219
1873
|
];
|
|
1220
1874
|
if ((_a = args2.attributes) == null ? void 0 : _a.length) attrs.push(...args2.attributes);
|
|
1875
|
+
const tracksAppGit = !this.appGitActiveSpans.has(args2.eventId);
|
|
1221
1876
|
const otlp = buildOtlpSpan({
|
|
1222
1877
|
ids,
|
|
1223
1878
|
name: args2.name,
|
|
1224
1879
|
startTimeUnixNano: args2.startTimeUnixNano,
|
|
1225
1880
|
endTimeUnixNano: args2.endTimeUnixNano,
|
|
1226
|
-
attributes:
|
|
1881
|
+
attributes: withAppGitAttributes(
|
|
1882
|
+
attrs,
|
|
1883
|
+
this.appGitContext.forOperation(
|
|
1884
|
+
args2.eventId,
|
|
1885
|
+
appGitPropertiesFromAttributes(attrs),
|
|
1886
|
+
this.appGitOwner
|
|
1887
|
+
)
|
|
1888
|
+
),
|
|
1227
1889
|
status: args2.status
|
|
1228
1890
|
});
|
|
1891
|
+
rememberReplayTraceDestination(otlp);
|
|
1892
|
+
this.appGitCaptured.add(otlp);
|
|
1893
|
+
if (tracksAppGit) {
|
|
1894
|
+
if (this.appGitContext.releaseOperation) this.appGitContext.releaseOperation(args2.eventId, this.appGitOwner);
|
|
1895
|
+
else if (this.ownsAppGitContext) this.appGitContext.finishOperation(args2.eventId);
|
|
1896
|
+
}
|
|
1229
1897
|
this.enqueue(otlp);
|
|
1230
|
-
this.mirrorToLocalDebugger(otlp);
|
|
1898
|
+
this.mirrorToLocalDebugger(otlp, true);
|
|
1231
1899
|
}
|
|
1232
1900
|
enqueue(span) {
|
|
1901
|
+
var _a;
|
|
1233
1902
|
if (!this.enabled) return;
|
|
1903
|
+
const attributes = (_a = span.attributes) != null ? _a : [];
|
|
1904
|
+
const enriched = this.appGitCaptured.has(span) ? attributes : withAppGitAttributes(attributes, this.appGitContext.snapshot(appGitPropertiesFromAttributes(attributes)));
|
|
1905
|
+
if (enriched !== attributes) {
|
|
1906
|
+
const original = span;
|
|
1907
|
+
span = { ...span, attributes: enriched.filter((attr) => attr !== void 0) };
|
|
1908
|
+
copyReplayTraceDestination(original, span);
|
|
1909
|
+
}
|
|
1234
1910
|
if (this.debugSpans) {
|
|
1235
1911
|
const short = (s) => s ? s.slice(-8) : "none";
|
|
1236
1912
|
console.log(
|
|
@@ -1241,6 +1917,13 @@ var TraceShipper = class {
|
|
|
1241
1917
|
}
|
|
1242
1918
|
const redacted = this.redactSpan(span);
|
|
1243
1919
|
if (redacted === null) return;
|
|
1920
|
+
const destination = replayTraceDestinationFor(redacted);
|
|
1921
|
+
recordReplayExportedSpan(
|
|
1922
|
+
destination,
|
|
1923
|
+
base64ToHex(redacted.spanId),
|
|
1924
|
+
base64ToHex(redacted.traceId)
|
|
1925
|
+
);
|
|
1926
|
+
if ((destination == null ? void 0 : destination.kind) === "workshop") return;
|
|
1244
1927
|
if (this.queue.length >= this.maxQueueSize) {
|
|
1245
1928
|
this.queue.shift();
|
|
1246
1929
|
}
|
|
@@ -1259,6 +1942,7 @@ var TraceShipper = class {
|
|
|
1259
1942
|
}
|
|
1260
1943
|
}
|
|
1261
1944
|
async flush() {
|
|
1945
|
+
var _a;
|
|
1262
1946
|
if (!this.enabled) {
|
|
1263
1947
|
await Promise.all([...this.inFlight].map((p) => p.catch(() => {
|
|
1264
1948
|
})));
|
|
@@ -1270,40 +1954,55 @@ var TraceShipper = class {
|
|
|
1270
1954
|
}
|
|
1271
1955
|
while (this.queue.length > 0) {
|
|
1272
1956
|
const batch = this.queue.splice(0, this.maxBatchSize);
|
|
1273
|
-
|
|
1274
|
-
const
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
`${this.prefix} shutdown flush deadline exceeded; dropping ${batch.length} spans`
|
|
1280
|
-
)
|
|
1281
|
-
);
|
|
1282
|
-
continue;
|
|
1283
|
-
}
|
|
1284
|
-
const body = buildExportTraceServiceRequest(batch, this.serviceName, this.serviceVersion);
|
|
1285
|
-
const url = `${this.baseUrl}traces`;
|
|
1286
|
-
if (this.debug) {
|
|
1287
|
-
console.log(`${this.prefix} sending traces batch`, {
|
|
1288
|
-
spans: batch.length,
|
|
1289
|
-
endpoint: url
|
|
1290
|
-
});
|
|
1957
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1958
|
+
for (const span of batch) {
|
|
1959
|
+
const destination = replayTraceDestinationFor(span);
|
|
1960
|
+
const spans = groups.get(destination);
|
|
1961
|
+
if (spans) spans.push(span);
|
|
1962
|
+
else groups.set(destination, [span]);
|
|
1291
1963
|
}
|
|
1292
|
-
const
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
if (this.debug) console.log(`${this.prefix} sent ${batch.length} spans`);
|
|
1298
|
-
} catch (err) {
|
|
1299
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
1964
|
+
for (const [destination, spans] of groups) {
|
|
1965
|
+
if (!destination && !this.writeKey) continue;
|
|
1966
|
+
if ((destination == null ? void 0 : destination.kind) === "workshop") continue;
|
|
1967
|
+
const opts = this.requestOpts();
|
|
1968
|
+
if (!opts) {
|
|
1300
1969
|
rateLimitedLog(
|
|
1301
|
-
`${this.prefix}.
|
|
1302
|
-
() => console.warn(
|
|
1970
|
+
`${this.prefix}.shutdown_deadline`,
|
|
1971
|
+
() => console.warn(
|
|
1972
|
+
`${this.prefix} shutdown flush deadline exceeded; dropping ${spans.length} spans`
|
|
1973
|
+
)
|
|
1303
1974
|
);
|
|
1975
|
+
continue;
|
|
1976
|
+
}
|
|
1977
|
+
const body = buildExportTraceServiceRequest(spans, this.serviceName, this.serviceVersion);
|
|
1978
|
+
const url = destination ? replayTraceUrl(destination.url) : `${this.baseUrl}traces`;
|
|
1979
|
+
const headers = destination ? {
|
|
1980
|
+
Authorization: `Bearer ${destination.apiKey}`,
|
|
1981
|
+
"X-Raindrop-Replay-Id": destination.replayId,
|
|
1982
|
+
"X-Raindrop-Project-Id": (_a = destination.projectId) != null ? _a : "default"
|
|
1983
|
+
} : this.requestHeaders();
|
|
1984
|
+
if (this.debug) {
|
|
1985
|
+
console.log(`${this.prefix} sending traces batch`, {
|
|
1986
|
+
spans: spans.length,
|
|
1987
|
+
endpoint: url
|
|
1988
|
+
});
|
|
1989
|
+
}
|
|
1990
|
+
const p = postJson(url, body, headers, opts);
|
|
1991
|
+
this.inFlight.add(p);
|
|
1992
|
+
try {
|
|
1993
|
+
try {
|
|
1994
|
+
await p;
|
|
1995
|
+
if (this.debug) console.log(`${this.prefix} sent ${spans.length} spans`);
|
|
1996
|
+
} catch (err) {
|
|
1997
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1998
|
+
rateLimitedLog(
|
|
1999
|
+
`${this.prefix}.send_spans_failed`,
|
|
2000
|
+
() => console.warn(`${this.prefix} failed to send ${spans.length} spans: ${msg}`)
|
|
2001
|
+
);
|
|
2002
|
+
}
|
|
2003
|
+
} finally {
|
|
2004
|
+
this.inFlight.delete(p);
|
|
1304
2005
|
}
|
|
1305
|
-
} finally {
|
|
1306
|
-
this.inFlight.delete(p);
|
|
1307
2006
|
}
|
|
1308
2007
|
}
|
|
1309
2008
|
}
|
|
@@ -1346,17 +2045,165 @@ var TraceShipper = class {
|
|
|
1346
2045
|
if (!settled) {
|
|
1347
2046
|
rateLimitedLog(
|
|
1348
2047
|
`${this.prefix}.shutdown_deadline`,
|
|
1349
|
-
() => console.warn(
|
|
2048
|
+
() => console.warn(
|
|
2049
|
+
`${this.prefix} shutdown flush deadline exceeded; abandoning in-flight spans`
|
|
2050
|
+
)
|
|
1350
2051
|
);
|
|
1351
2052
|
}
|
|
1352
2053
|
} finally {
|
|
1353
2054
|
this.shutdownDeadlineAt = void 0;
|
|
2055
|
+
if (this.ownsAppGitContext) this.appGitContext.dispose();
|
|
1354
2056
|
}
|
|
1355
2057
|
}
|
|
1356
2058
|
};
|
|
1357
2059
|
|
|
1358
2060
|
// ../core/dist/index.node.js
|
|
1359
2061
|
import { AsyncLocalStorage } from "async_hooks";
|
|
2062
|
+
import { execFile } from "child_process";
|
|
2063
|
+
import { resolve } from "path";
|
|
2064
|
+
var resolveLocal = (sourceDirectory, detectBranch, completed) => {
|
|
2065
|
+
const cwd = sourceDirectory ? resolve(sourceDirectory) : process.cwd();
|
|
2066
|
+
let cancelled = false;
|
|
2067
|
+
let active;
|
|
2068
|
+
let deadlineTimer;
|
|
2069
|
+
const deadline = Date.now() + 1e3;
|
|
2070
|
+
const run = (args2, done) => {
|
|
2071
|
+
if (cancelled) return;
|
|
2072
|
+
const remaining = deadline - Date.now();
|
|
2073
|
+
if (remaining <= 0) {
|
|
2074
|
+
done(void 0);
|
|
2075
|
+
return;
|
|
2076
|
+
}
|
|
2077
|
+
try {
|
|
2078
|
+
active = execFile(
|
|
2079
|
+
"git",
|
|
2080
|
+
args2,
|
|
2081
|
+
{
|
|
2082
|
+
cwd,
|
|
2083
|
+
encoding: "utf8",
|
|
2084
|
+
maxBuffer: 4096,
|
|
2085
|
+
windowsHide: true,
|
|
2086
|
+
env: {
|
|
2087
|
+
...process.env,
|
|
2088
|
+
// The selected application cwd, not the invoking shell's Git plumbing, owns identity.
|
|
2089
|
+
GIT_DIR: void 0,
|
|
2090
|
+
GIT_WORK_TREE: void 0,
|
|
2091
|
+
GIT_COMMON_DIR: void 0,
|
|
2092
|
+
GIT_NAMESPACE: void 0,
|
|
2093
|
+
GIT_INDEX_FILE: void 0,
|
|
2094
|
+
GIT_OBJECT_DIRECTORY: void 0,
|
|
2095
|
+
GIT_ALTERNATE_OBJECT_DIRECTORIES: void 0,
|
|
2096
|
+
GIT_CONFIG_PARAMETERS: void 0,
|
|
2097
|
+
GIT_CONFIG_COUNT: "0",
|
|
2098
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
2099
|
+
GIT_OPTIONAL_LOCKS: "0"
|
|
2100
|
+
}
|
|
2101
|
+
},
|
|
2102
|
+
(error, stdout) => {
|
|
2103
|
+
clearTimeout(deadlineTimer);
|
|
2104
|
+
deadlineTimer = void 0;
|
|
2105
|
+
active = void 0;
|
|
2106
|
+
if (!cancelled) {
|
|
2107
|
+
try {
|
|
2108
|
+
done(error ? void 0 : stdout.trim());
|
|
2109
|
+
} catch (e) {
|
|
2110
|
+
}
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
2113
|
+
);
|
|
2114
|
+
active.unref();
|
|
2115
|
+
if (active.stdout && "unref" in active.stdout && typeof active.stdout.unref === "function")
|
|
2116
|
+
active.stdout.unref();
|
|
2117
|
+
if (active.stderr && "unref" in active.stderr && typeof active.stderr.unref === "function")
|
|
2118
|
+
active.stderr.unref();
|
|
2119
|
+
deadlineTimer = setTimeout(() => {
|
|
2120
|
+
try {
|
|
2121
|
+
active == null ? void 0 : active.kill("SIGKILL");
|
|
2122
|
+
} catch (e) {
|
|
2123
|
+
}
|
|
2124
|
+
}, remaining);
|
|
2125
|
+
deadlineTimer.unref();
|
|
2126
|
+
} catch (e) {
|
|
2127
|
+
try {
|
|
2128
|
+
done(void 0);
|
|
2129
|
+
} catch (e2) {
|
|
2130
|
+
}
|
|
2131
|
+
}
|
|
2132
|
+
};
|
|
2133
|
+
const scheduled = setTimeout(() => {
|
|
2134
|
+
try {
|
|
2135
|
+
run(["rev-parse", "HEAD"], (rawSha) => {
|
|
2136
|
+
const commitSha = validAppCommitSha(rawSha);
|
|
2137
|
+
if (!commitSha) {
|
|
2138
|
+
completed({});
|
|
2139
|
+
return;
|
|
2140
|
+
}
|
|
2141
|
+
run(["-c", "core.fsmonitor=false", "status", "--porcelain"], (status) => {
|
|
2142
|
+
const finish = (branch) => {
|
|
2143
|
+
run(["rev-parse", "HEAD"], (finalSha) => {
|
|
2144
|
+
const coherent = validAppCommitSha(finalSha) === commitSha;
|
|
2145
|
+
completed({
|
|
2146
|
+
commitSha,
|
|
2147
|
+
...coherent && status !== void 0 ? { commitDirty: status !== "" } : {},
|
|
2148
|
+
...coherent && branch && branch !== "HEAD" ? { branch } : {}
|
|
2149
|
+
});
|
|
2150
|
+
});
|
|
2151
|
+
};
|
|
2152
|
+
if (detectBranch) run(["symbolic-ref", "--quiet", "--short", "HEAD"], finish);
|
|
2153
|
+
else finish();
|
|
2154
|
+
});
|
|
2155
|
+
});
|
|
2156
|
+
} catch (e) {
|
|
2157
|
+
completed({});
|
|
2158
|
+
}
|
|
2159
|
+
}, 0);
|
|
2160
|
+
scheduled.unref();
|
|
2161
|
+
return () => {
|
|
2162
|
+
cancelled = true;
|
|
2163
|
+
clearTimeout(scheduled);
|
|
2164
|
+
clearTimeout(deadlineTimer);
|
|
2165
|
+
try {
|
|
2166
|
+
active == null ? void 0 : active.kill("SIGKILL");
|
|
2167
|
+
} catch (e) {
|
|
2168
|
+
}
|
|
2169
|
+
};
|
|
2170
|
+
};
|
|
2171
|
+
function createAppGitContext2(options, runtime = {}) {
|
|
2172
|
+
return new AppGitContext(options, { ...runtime, resolveLocal });
|
|
2173
|
+
}
|
|
2174
|
+
function hasDestination(options) {
|
|
2175
|
+
var _a;
|
|
2176
|
+
if (options.enabled === false) return false;
|
|
2177
|
+
return Boolean(((_a = options.writeKey) == null ? void 0 : _a.trim()) || resolveLocalDebuggerBaseUrl(options.localDebuggerUrl));
|
|
2178
|
+
}
|
|
2179
|
+
var EventShipper2 = class extends EventShipper {
|
|
2180
|
+
constructor(options) {
|
|
2181
|
+
var _a;
|
|
2182
|
+
const ownsAppGitContext = options.appGitContext === void 0;
|
|
2183
|
+
const appGitContext = (_a = options.appGitContext) != null ? _a : createAppGitContext2(options.appGit, { allowDiscovery: hasDestination(options) });
|
|
2184
|
+
try {
|
|
2185
|
+
super({ ...options, appGitContext });
|
|
2186
|
+
} catch (error) {
|
|
2187
|
+
if (ownsAppGitContext) appGitContext.dispose();
|
|
2188
|
+
throw error;
|
|
2189
|
+
}
|
|
2190
|
+
if (ownsAppGitContext) this.ownAppGitContextForShutdown();
|
|
2191
|
+
}
|
|
2192
|
+
};
|
|
2193
|
+
var TraceShipper2 = class extends TraceShipper {
|
|
2194
|
+
constructor(options) {
|
|
2195
|
+
var _a;
|
|
2196
|
+
const ownsAppGitContext = options.appGitContext === void 0;
|
|
2197
|
+
const appGitContext = (_a = options.appGitContext) != null ? _a : createAppGitContext2(options.appGit, { allowDiscovery: hasDestination(options) });
|
|
2198
|
+
try {
|
|
2199
|
+
super({ ...options, appGitContext });
|
|
2200
|
+
} catch (error) {
|
|
2201
|
+
if (ownsAppGitContext) appGitContext.dispose();
|
|
2202
|
+
throw error;
|
|
2203
|
+
}
|
|
2204
|
+
this.ownsAppGitContext = ownsAppGitContext;
|
|
2205
|
+
}
|
|
2206
|
+
};
|
|
1360
2207
|
globalThis.RAINDROP_ASYNC_LOCAL_STORAGE = AsyncLocalStorage;
|
|
1361
2208
|
var SUPPRESS_TRACING_KEY = /* @__PURE__ */ Symbol.for(
|
|
1362
2209
|
"OpenTelemetry SDK Context Key SUPPRESS_TRACING"
|
|
@@ -1387,7 +2234,7 @@ installTracingSuppressionHook();
|
|
|
1387
2234
|
// package.json
|
|
1388
2235
|
var package_default = {
|
|
1389
2236
|
name: "@raindrop-ai/claude-code",
|
|
1390
|
-
version: "0.0.
|
|
2237
|
+
version: "0.0.20",
|
|
1391
2238
|
description: "Raindrop observability for Claude Code CLI \u2014 automatic session, tool call, and prompt tracing via hooks",
|
|
1392
2239
|
license: "MIT",
|
|
1393
2240
|
homepage: "https://www.raindrop.ai/docs/integrations/claude-code/",
|
|
@@ -1461,7 +2308,7 @@ var PACKAGE_NAME = "@raindrop-ai/claude-code";
|
|
|
1461
2308
|
var PACKAGE_VERSION = package_default.version;
|
|
1462
2309
|
|
|
1463
2310
|
// src/shipper.ts
|
|
1464
|
-
var
|
|
2311
|
+
var EventShipper3 = class extends EventShipper2 {
|
|
1465
2312
|
constructor(opts) {
|
|
1466
2313
|
var _a, _b, _c, _d;
|
|
1467
2314
|
super({
|
|
@@ -1473,7 +2320,7 @@ var EventShipper2 = class extends EventShipper {
|
|
|
1473
2320
|
});
|
|
1474
2321
|
}
|
|
1475
2322
|
};
|
|
1476
|
-
var
|
|
2323
|
+
var TraceShipper3 = class extends TraceShipper2 {
|
|
1477
2324
|
constructor(opts) {
|
|
1478
2325
|
var _a, _b, _c;
|
|
1479
2326
|
super({
|
|
@@ -2475,7 +3322,20 @@ function loadConfig() {
|
|
|
2475
3322
|
})(),
|
|
2476
3323
|
eventName: (_l = (_k = process.env["RAINDROP_EVENT_NAME"]) != null ? _k : file.event_name) != null ? _l : "claude_code_session",
|
|
2477
3324
|
customProperties,
|
|
2478
|
-
selfDiagnostics
|
|
3325
|
+
selfDiagnostics,
|
|
3326
|
+
appGit: mapAppGit(file.app_git)
|
|
3327
|
+
};
|
|
3328
|
+
}
|
|
3329
|
+
function mapAppGit(value) {
|
|
3330
|
+
if (value === false) return false;
|
|
3331
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
3332
|
+
return {
|
|
3333
|
+
commitSha: "commit_sha" in value && (typeof value.commit_sha === "string" || value.commit_sha === null) ? value.commit_sha : void 0,
|
|
3334
|
+
commitDirty: "commit_dirty" in value && (typeof value.commit_dirty === "boolean" || value.commit_dirty === null) ? value.commit_dirty : void 0,
|
|
3335
|
+
branch: "branch" in value && (typeof value.branch === "string" || value.branch === null) ? value.branch : void 0,
|
|
3336
|
+
detectBranch: "detect_branch" in value && typeof value.detect_branch === "boolean" ? value.detect_branch : void 0,
|
|
3337
|
+
sourceDirectory: "source_directory" in value && typeof value.source_directory === "string" ? value.source_directory : void 0,
|
|
3338
|
+
autoDetect: "auto_detect" in value && typeof value.auto_detect === "boolean" ? value.auto_detect : void 0
|
|
2479
3339
|
};
|
|
2480
3340
|
}
|
|
2481
3341
|
function getConfigPath() {
|
|
@@ -2597,16 +3457,16 @@ function hookFlushDeadlineMs() {
|
|
|
2597
3457
|
return DEFAULT_HOOK_FLUSH_DEADLINE_MS;
|
|
2598
3458
|
}
|
|
2599
3459
|
function withDeadline(promise, ms) {
|
|
2600
|
-
return new Promise((
|
|
3460
|
+
return new Promise((resolve3, reject) => {
|
|
2601
3461
|
const timer = setTimeout(() => {
|
|
2602
3462
|
promise.catch(() => {
|
|
2603
3463
|
});
|
|
2604
|
-
|
|
3464
|
+
resolve3("deadline");
|
|
2605
3465
|
}, ms);
|
|
2606
3466
|
promise.then(
|
|
2607
3467
|
(value) => {
|
|
2608
3468
|
clearTimeout(timer);
|
|
2609
|
-
|
|
3469
|
+
resolve3(value);
|
|
2610
3470
|
},
|
|
2611
3471
|
(err) => {
|
|
2612
3472
|
clearTimeout(timer);
|
|
@@ -2628,9 +3488,9 @@ function getOtlpTraceId(sessionId) {
|
|
|
2628
3488
|
}
|
|
2629
3489
|
}
|
|
2630
3490
|
function readStdin() {
|
|
2631
|
-
return new Promise((
|
|
3491
|
+
return new Promise((resolve3) => {
|
|
2632
3492
|
if (process.stdin.isTTY) {
|
|
2633
|
-
|
|
3493
|
+
resolve3("");
|
|
2634
3494
|
return;
|
|
2635
3495
|
}
|
|
2636
3496
|
const chunks = [];
|
|
@@ -2641,7 +3501,7 @@ function readStdin() {
|
|
|
2641
3501
|
clearTimeout(timeout);
|
|
2642
3502
|
process.stdin.removeAllListeners();
|
|
2643
3503
|
process.stdin.destroy();
|
|
2644
|
-
|
|
3504
|
+
resolve3(value);
|
|
2645
3505
|
}
|
|
2646
3506
|
const timeout = setTimeout(() => {
|
|
2647
3507
|
done(chunks.length > 0 ? Buffer.concat(chunks).toString("utf-8") : "");
|
|
@@ -2652,6 +3512,7 @@ function readStdin() {
|
|
|
2652
3512
|
});
|
|
2653
3513
|
}
|
|
2654
3514
|
async function handleHook() {
|
|
3515
|
+
var _a;
|
|
2655
3516
|
const startedAtMs = Date.now();
|
|
2656
3517
|
const raw = await readStdin();
|
|
2657
3518
|
if (!raw.trim()) {
|
|
@@ -2686,7 +3547,11 @@ async function handleHook() {
|
|
|
2686
3547
|
eventName: config.eventName,
|
|
2687
3548
|
customProperties: config.customProperties
|
|
2688
3549
|
};
|
|
2689
|
-
const
|
|
3550
|
+
const appGitContext = createAppGitContext2(
|
|
3551
|
+
((_a = config.writeKey) == null ? void 0 : _a.trim()) || hasDebugger ? config.appGit : false,
|
|
3552
|
+
{ allowLocalGit: false }
|
|
3553
|
+
);
|
|
3554
|
+
const eventShipper = new EventShipper3({
|
|
2690
3555
|
writeKey: config.writeKey,
|
|
2691
3556
|
endpoint: config.endpoint,
|
|
2692
3557
|
debug: config.debug,
|
|
@@ -2694,21 +3559,23 @@ async function handleHook() {
|
|
|
2694
3559
|
// Only ship to the cloud when we have an API key. When only the local
|
|
2695
3560
|
// debugger is present the shipper still needs to be instantiated so the
|
|
2696
3561
|
// event mapper can call patch/finish, but cloud POSTs are skipped.
|
|
2697
|
-
enabled: hasCloudKey
|
|
3562
|
+
enabled: hasCloudKey,
|
|
3563
|
+
appGitContext
|
|
2698
3564
|
});
|
|
2699
|
-
const traceShipper = new
|
|
3565
|
+
const traceShipper = new TraceShipper3({
|
|
2700
3566
|
writeKey: config.writeKey,
|
|
2701
3567
|
endpoint: config.endpoint,
|
|
2702
3568
|
debug: config.debug,
|
|
2703
3569
|
projectId: config.projectId,
|
|
2704
|
-
enabled: hasCloudKey
|
|
3570
|
+
enabled: hasCloudKey,
|
|
3571
|
+
appGitContext
|
|
2705
3572
|
});
|
|
2706
3573
|
if (debugger_.url) {
|
|
2707
3574
|
const debuggerUrl = debugger_.url;
|
|
2708
3575
|
const origPatch = eventShipper.patch.bind(eventShipper);
|
|
2709
3576
|
eventShipper.patch = async (eventId, patch) => {
|
|
2710
|
-
var
|
|
2711
|
-
const traceId = (
|
|
3577
|
+
var _a2, _b, _c, _d;
|
|
3578
|
+
const traceId = (_a2 = getOtlpTraceId(payload.session_id)) != null ? _a2 : payload.session_id;
|
|
2712
3579
|
await Promise.all([
|
|
2713
3580
|
mirrorEventToLocalDebugger(debuggerUrl, {
|
|
2714
3581
|
event_id: eventId,
|
|
@@ -2722,7 +3589,10 @@ async function handleHook() {
|
|
|
2722
3589
|
convo_id: patch.convoId
|
|
2723
3590
|
},
|
|
2724
3591
|
properties: {
|
|
2725
|
-
...
|
|
3592
|
+
...withAppGitProperties(
|
|
3593
|
+
patch.properties,
|
|
3594
|
+
appGitContext.forOperation(eventId, patch.properties)
|
|
3595
|
+
),
|
|
2726
3596
|
...payload.session_id ? { trace_id: traceId } : {}
|
|
2727
3597
|
},
|
|
2728
3598
|
is_pending: (_d = patch.isPending) != null ? _d : true
|
|
@@ -2736,14 +3606,23 @@ async function handleHook() {
|
|
|
2736
3606
|
MIN_FLUSH_WINDOW_MS,
|
|
2737
3607
|
hookFlushDeadlineMs() - (Date.now() - startedAtMs)
|
|
2738
3608
|
);
|
|
2739
|
-
const
|
|
2740
|
-
|
|
3609
|
+
const hookWork = (async () => {
|
|
3610
|
+
try {
|
|
2741
3611
|
await mapHookToRaindrop(payload, mapperConfig, eventShipper, traceShipper);
|
|
2742
3612
|
await Promise.all([eventShipper.flush(), traceShipper.flush()]);
|
|
2743
3613
|
await Promise.all([eventShipper.shutdown(), traceShipper.shutdown()]);
|
|
2744
|
-
}
|
|
2745
|
-
|
|
2746
|
-
|
|
3614
|
+
} finally {
|
|
3615
|
+
try {
|
|
3616
|
+
appGitContext.dispose();
|
|
3617
|
+
} catch (e) {
|
|
3618
|
+
}
|
|
3619
|
+
}
|
|
3620
|
+
})();
|
|
3621
|
+
const outcome = await withDeadline(hookWork, remainingMs);
|
|
3622
|
+
try {
|
|
3623
|
+
appGitContext.dispose();
|
|
3624
|
+
} catch (e) {
|
|
3625
|
+
}
|
|
2747
3626
|
if (outcome === "deadline" && config.debug) {
|
|
2748
3627
|
console.error(
|
|
2749
3628
|
`[raindrop-ai/claude-code] hook work exceeded the ${hookFlushDeadlineMs()}ms deadline; exiting without waiting on the network (pending telemetry dropped)`
|
|
@@ -2761,12 +3640,12 @@ async function handleHook() {
|
|
|
2761
3640
|
// src/setup.ts
|
|
2762
3641
|
import { existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
|
|
2763
3642
|
import { homedir as homedir2, userInfo as userInfo2 } from "os";
|
|
2764
|
-
import { dirname as dirname2, join as join5, resolve } from "path";
|
|
3643
|
+
import { dirname as dirname2, join as join5, resolve as resolve2 } from "path";
|
|
2765
3644
|
import { createInterface } from "readline";
|
|
2766
3645
|
import { execSync as execSync2 } from "child_process";
|
|
2767
3646
|
function getClaudeSettingsPath(scope, cwd) {
|
|
2768
3647
|
if (scope === "project") {
|
|
2769
|
-
return
|
|
3648
|
+
return resolve2(cwd, ".claude", "settings.json");
|
|
2770
3649
|
}
|
|
2771
3650
|
return join5(homedir2(), ".claude", "settings.json");
|
|
2772
3651
|
}
|
|
@@ -2849,10 +3728,10 @@ function makeHookConfig(hookEvents, useAsync) {
|
|
|
2849
3728
|
}
|
|
2850
3729
|
function prompt(question) {
|
|
2851
3730
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
2852
|
-
return new Promise((
|
|
3731
|
+
return new Promise((resolve3) => {
|
|
2853
3732
|
rl.question(question, (answer) => {
|
|
2854
3733
|
rl.close();
|
|
2855
|
-
|
|
3734
|
+
resolve3(answer.trim());
|
|
2856
3735
|
});
|
|
2857
3736
|
});
|
|
2858
3737
|
}
|
|
@@ -3192,6 +4071,7 @@ function resolveCurrentEventId() {
|
|
|
3192
4071
|
}
|
|
3193
4072
|
}
|
|
3194
4073
|
async function executeTool(args2) {
|
|
4074
|
+
var _a;
|
|
3195
4075
|
const category = typeof args2["category"] === "string" ? args2["category"] : "";
|
|
3196
4076
|
const detail = typeof args2["detail"] === "string" ? args2["detail"] : "";
|
|
3197
4077
|
if (!category || !activeSignals[category]) {
|
|
@@ -3217,12 +4097,17 @@ async function executeTool(args2) {
|
|
|
3217
4097
|
if (!eventId) {
|
|
3218
4098
|
return { content: [{ type: "text", text: "Signal noted (no active event found)." }] };
|
|
3219
4099
|
}
|
|
3220
|
-
const
|
|
4100
|
+
const appGitContext = createAppGitContext2(
|
|
4101
|
+
((_a = config.writeKey) == null ? void 0 : _a.trim()) ? config.appGit : false,
|
|
4102
|
+
{ allowLocalGit: false }
|
|
4103
|
+
);
|
|
4104
|
+
const shipper = new EventShipper3({
|
|
3221
4105
|
writeKey: config.writeKey,
|
|
3222
4106
|
endpoint: config.endpoint,
|
|
3223
4107
|
debug: false,
|
|
3224
4108
|
projectId: config.projectId,
|
|
3225
|
-
enabled: true
|
|
4109
|
+
enabled: true,
|
|
4110
|
+
appGitContext
|
|
3226
4111
|
});
|
|
3227
4112
|
try {
|
|
3228
4113
|
const signalDef = activeSignals[category];
|
|
@@ -3249,6 +4134,11 @@ async function executeTool(args2) {
|
|
|
3249
4134
|
});
|
|
3250
4135
|
await shipper.shutdown();
|
|
3251
4136
|
} catch (e) {
|
|
4137
|
+
} finally {
|
|
4138
|
+
try {
|
|
4139
|
+
appGitContext.dispose();
|
|
4140
|
+
} catch (e) {
|
|
4141
|
+
}
|
|
3252
4142
|
}
|
|
3253
4143
|
return { content: [{ type: "text", text: "Signal recorded." }] };
|
|
3254
4144
|
}
|
|
@@ -3374,8 +4264,8 @@ var args = process.argv.slice(2);
|
|
|
3374
4264
|
var command = args[0];
|
|
3375
4265
|
function parseFlag(name) {
|
|
3376
4266
|
const prefix = `--${name}=`;
|
|
3377
|
-
const
|
|
3378
|
-
return
|
|
4267
|
+
const flag2 = args.find((a) => a.startsWith(prefix));
|
|
4268
|
+
return flag2 ? flag2.slice(prefix.length) : void 0;
|
|
3379
4269
|
}
|
|
3380
4270
|
async function main() {
|
|
3381
4271
|
switch (command) {
|