@raindrop-ai/eve 0.0.22 → 0.0.24
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/README.md +22 -0
- package/dist/index.d.mts +154 -2
- package/dist/index.d.ts +154 -2
- package/dist/index.js +1042 -348
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1042 -349
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -4,11 +4,794 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var api = require('@opentelemetry/api');
|
|
6
6
|
var aiSdk = require('@raindrop-ai/ai-sdk');
|
|
7
|
-
var module$1 = require('module');
|
|
8
7
|
var async_hooks = require('async_hooks');
|
|
8
|
+
var child_process = require('child_process');
|
|
9
|
+
var path = require('path');
|
|
10
|
+
var module$1 = require('module');
|
|
9
11
|
|
|
10
12
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
11
13
|
// src/index.ts
|
|
14
|
+
|
|
15
|
+
// ../core/dist/chunk-WJOR6M7H.js
|
|
16
|
+
function getAsyncLocalStorageCtor() {
|
|
17
|
+
return globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
|
|
18
|
+
}
|
|
19
|
+
var MAX_BINDING_STACK = 128;
|
|
20
|
+
var EMPTY_STACK = [];
|
|
21
|
+
var ContextStackStorage = class {
|
|
22
|
+
/** Emitted once when this runtime cannot support an ambient push. */
|
|
23
|
+
constructor(noAmbientBindWarning) {
|
|
24
|
+
this.noAmbientBindWarning = noAmbientBindWarning;
|
|
25
|
+
this._als = null;
|
|
26
|
+
this._enterWithUsable = false;
|
|
27
|
+
this._syncStack = EMPTY_STACK;
|
|
28
|
+
this._adoptionChecked = false;
|
|
29
|
+
this._warnedNoAmbientBind = false;
|
|
30
|
+
}
|
|
31
|
+
maybeAdoptAsyncLocalStorage() {
|
|
32
|
+
if (this._adoptionChecked) return;
|
|
33
|
+
this._adoptionChecked = true;
|
|
34
|
+
const Ctor = getAsyncLocalStorageCtor();
|
|
35
|
+
if (!Ctor) return;
|
|
36
|
+
const als = new Ctor();
|
|
37
|
+
try {
|
|
38
|
+
als.run(EMPTY_STACK, () => {
|
|
39
|
+
});
|
|
40
|
+
} catch (e) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
this._als = als;
|
|
44
|
+
if (typeof als.enterWith === "function") {
|
|
45
|
+
try {
|
|
46
|
+
als.enterWith(EMPTY_STACK);
|
|
47
|
+
this._enterWithUsable = true;
|
|
48
|
+
} catch (e) {
|
|
49
|
+
this._enterWithUsable = false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
getStack() {
|
|
54
|
+
var _a;
|
|
55
|
+
this.maybeAdoptAsyncLocalStorage();
|
|
56
|
+
if (this._als) return (_a = this._als.getStore()) != null ? _a : this._syncStack;
|
|
57
|
+
return this._syncStack;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Persist an ambient stack mutation. Returns false when an ALS is adopted but
|
|
61
|
+
* `enterWith` is unusable (workerd): callers must NOT fall back to the
|
|
62
|
+
* process-shared sync stack, since concurrent isolates would cross-stamp.
|
|
63
|
+
*/
|
|
64
|
+
setAmbientStack(stack) {
|
|
65
|
+
if (this._als) {
|
|
66
|
+
if (!this._enterWithUsable) return false;
|
|
67
|
+
this._als.enterWith(stack);
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
this._syncStack = stack;
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
push(binding) {
|
|
74
|
+
this.maybeAdoptAsyncLocalStorage();
|
|
75
|
+
if (this._als && !this._enterWithUsable) {
|
|
76
|
+
this.warnNoAmbientBindOnce();
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
let stack = this.getStack();
|
|
80
|
+
if (stack.length >= MAX_BINDING_STACK) {
|
|
81
|
+
stack = stack.filter((b) => b.isLive());
|
|
82
|
+
if (stack.length >= MAX_BINDING_STACK) {
|
|
83
|
+
stack = stack.slice(stack.length - (MAX_BINDING_STACK - 1));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
this.setAmbientStack([...stack, binding]);
|
|
87
|
+
}
|
|
88
|
+
remove(binding) {
|
|
89
|
+
binding.markDead();
|
|
90
|
+
const stack = this.getStack();
|
|
91
|
+
const pruned = stack.filter((b) => b !== binding && b.isLive());
|
|
92
|
+
if (pruned.length !== stack.length) {
|
|
93
|
+
this.setAmbientStack(pruned);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
runWith(binding, callback) {
|
|
97
|
+
this.maybeAdoptAsyncLocalStorage();
|
|
98
|
+
if (this._als) {
|
|
99
|
+
return this._als.run([...this.getStack(), binding], callback);
|
|
100
|
+
}
|
|
101
|
+
const previous = this._syncStack;
|
|
102
|
+
this._syncStack = [...previous, binding];
|
|
103
|
+
try {
|
|
104
|
+
return callback();
|
|
105
|
+
} finally {
|
|
106
|
+
this._syncStack = previous;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
current() {
|
|
110
|
+
const stack = this.getStack();
|
|
111
|
+
if (stack.length === 0) return void 0;
|
|
112
|
+
const top = stack[stack.length - 1];
|
|
113
|
+
if (top.isLive()) return top;
|
|
114
|
+
const pruned = stack.filter((b) => b.isLive());
|
|
115
|
+
this.setAmbientStack(pruned);
|
|
116
|
+
return pruned.length > 0 ? pruned[pruned.length - 1] : void 0;
|
|
117
|
+
}
|
|
118
|
+
warnNoAmbientBindOnce() {
|
|
119
|
+
if (this._warnedNoAmbientBind) return;
|
|
120
|
+
this._warnedNoAmbientBind = true;
|
|
121
|
+
console.warn(this.noAmbientBindWarning);
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
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.";
|
|
125
|
+
var ROUTING_STORAGE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.routingContextStorage");
|
|
126
|
+
function routingStorage() {
|
|
127
|
+
const holder = globalThis;
|
|
128
|
+
let storage = holder[ROUTING_STORAGE_KEY];
|
|
129
|
+
if (!storage) {
|
|
130
|
+
storage = new ContextStackStorage(NO_AMBIENT_ROUTING_BIND_WARNING);
|
|
131
|
+
holder[ROUTING_STORAGE_KEY] = storage;
|
|
132
|
+
}
|
|
133
|
+
return storage;
|
|
134
|
+
}
|
|
135
|
+
function currentRoutingBinding() {
|
|
136
|
+
const bound = routingStorage().current();
|
|
137
|
+
if (!bound) return void 0;
|
|
138
|
+
return {
|
|
139
|
+
projectId: bound.projectId,
|
|
140
|
+
authHint: bound.authHint,
|
|
141
|
+
...bound.appGit ? { appGit: bound.appGit } : {},
|
|
142
|
+
...bound.appGitSource ? { appGitSource: bound.appGitSource } : {}
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
var APP_COMMIT_SHA = "raindrop.app.commit_sha";
|
|
146
|
+
var APP_COMMIT_DIRTY = "raindrop.app.commit_dirty";
|
|
147
|
+
var APP_BRANCH = "raindrop.app.branch";
|
|
148
|
+
var APP_GIT_KEYS = [APP_COMMIT_SHA, APP_COMMIT_DIRTY, APP_BRANCH];
|
|
149
|
+
var own = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
150
|
+
function appGitExplicitKeys(properties) {
|
|
151
|
+
const keys = /* @__PURE__ */ new Set();
|
|
152
|
+
if (!properties) return keys;
|
|
153
|
+
for (const key of APP_GIT_KEYS) {
|
|
154
|
+
if (own(properties, key)) keys.add(key);
|
|
155
|
+
}
|
|
156
|
+
return keys;
|
|
157
|
+
}
|
|
158
|
+
function mergeAppGitSnapshot(base, properties, explicitKeys = /* @__PURE__ */ new Set()) {
|
|
159
|
+
try {
|
|
160
|
+
const result = { ...base };
|
|
161
|
+
if (properties && own(properties, APP_COMMIT_SHA) && properties[APP_COMMIT_SHA] !== result[APP_COMMIT_SHA]) {
|
|
162
|
+
if (!explicitKeys.has(APP_COMMIT_DIRTY) && !own(properties, APP_COMMIT_DIRTY)) {
|
|
163
|
+
delete result[APP_COMMIT_DIRTY];
|
|
164
|
+
}
|
|
165
|
+
if (!explicitKeys.has(APP_BRANCH) && !own(properties, APP_BRANCH)) {
|
|
166
|
+
delete result[APP_BRANCH];
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
for (const key of APP_GIT_KEYS) {
|
|
170
|
+
if (properties && own(properties, key)) result[key] = properties[key];
|
|
171
|
+
}
|
|
172
|
+
return Object.freeze(result);
|
|
173
|
+
} catch (e) {
|
|
174
|
+
return Object.freeze({});
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
function validAppCommitSha(value) {
|
|
178
|
+
if (typeof value !== "string" || value.length > 128) return void 0;
|
|
179
|
+
const cleaned = value.trim();
|
|
180
|
+
return /^(?:[a-fA-F0-9]{40}|[a-fA-F0-9]{64})$/.test(cleaned) ? cleaned.toLowerCase() : void 0;
|
|
181
|
+
}
|
|
182
|
+
function shortString(value) {
|
|
183
|
+
if (typeof value !== "string" || value.length > 1024) return void 0;
|
|
184
|
+
const cleaned = value.trim();
|
|
185
|
+
return cleaned.length > 0 ? cleaned : void 0;
|
|
186
|
+
}
|
|
187
|
+
function flag(value) {
|
|
188
|
+
if (value === true || value === "true" || value === "1") return true;
|
|
189
|
+
if (value === false || value === "false" || value === "0") return false;
|
|
190
|
+
return void 0;
|
|
191
|
+
}
|
|
192
|
+
function environment() {
|
|
193
|
+
try {
|
|
194
|
+
return typeof process === "undefined" ? {} : process.env;
|
|
195
|
+
} catch (e) {
|
|
196
|
+
return {};
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
var DEPLOYMENTS = [
|
|
200
|
+
["VERCEL", "VERCEL_GIT_COMMIT_SHA", "VERCEL_GIT_COMMIT_REF"],
|
|
201
|
+
["NETLIFY", "COMMIT_REF", "BRANCH"],
|
|
202
|
+
["RAILWAY_ENVIRONMENT_NAME", "RAILWAY_GIT_COMMIT_SHA", "RAILWAY_GIT_BRANCH"],
|
|
203
|
+
["RAILWAY_ENVIRONMENT", "RAILWAY_GIT_COMMIT_SHA", "RAILWAY_GIT_BRANCH"],
|
|
204
|
+
["RENDER", "RENDER_GIT_COMMIT", "RENDER_GIT_BRANCH"],
|
|
205
|
+
["DYNO", "HEROKU_BUILD_COMMIT", ""],
|
|
206
|
+
["DYNO", "HEROKU_SLUG_COMMIT", ""],
|
|
207
|
+
["AWS_APP_ID", "AWS_COMMIT_ID", "AWS_BRANCH"],
|
|
208
|
+
["WORKERS_CI", "WORKERS_CI_COMMIT_SHA", "WORKERS_CI_BRANCH"]
|
|
209
|
+
];
|
|
210
|
+
var CI_SOURCES = [
|
|
211
|
+
["GITHUB_ACTIONS", "GITHUB_SHA", "GITHUB_REF_NAME"],
|
|
212
|
+
["GITLAB_CI", "CI_COMMIT_SHA", "CI_COMMIT_REF_NAME"],
|
|
213
|
+
["CIRCLECI", "CIRCLE_SHA1", "CIRCLE_BRANCH"]
|
|
214
|
+
];
|
|
215
|
+
function detectedSource(env, table, detectBranch) {
|
|
216
|
+
for (const row of table) {
|
|
217
|
+
const [marker, shaKey, branchKey] = row;
|
|
218
|
+
if (!marker || !shaKey || !shortString(env[marker]) || flag(env[marker]) === false) continue;
|
|
219
|
+
const commitSha = validAppCommitSha(env[shaKey]);
|
|
220
|
+
if (commitSha)
|
|
221
|
+
return {
|
|
222
|
+
commitSha,
|
|
223
|
+
...detectBranch && branchKey ? { branch: shortString(env[branchKey]) } : {}
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
return {};
|
|
227
|
+
}
|
|
228
|
+
var AppGitContextImpl = class {
|
|
229
|
+
constructor(options, runtime = {}) {
|
|
230
|
+
this.defaults = {};
|
|
231
|
+
this.explicit = {};
|
|
232
|
+
this.explicitKeys = /* @__PURE__ */ new Set();
|
|
233
|
+
this.disposed = false;
|
|
234
|
+
this.operations = /* @__PURE__ */ new Map();
|
|
235
|
+
this.operationOverflow = false;
|
|
236
|
+
this.detectBranch = false;
|
|
237
|
+
this.disabled = false;
|
|
238
|
+
var _a, _b, _c, _d, _e, _f;
|
|
239
|
+
try {
|
|
240
|
+
if (options === false) {
|
|
241
|
+
this.disabled = true;
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
const opts = options != null ? options : {};
|
|
245
|
+
const env = (_a = runtime.env) != null ? _a : environment();
|
|
246
|
+
const detectBranch = (_c = (_b = flag(opts.detectBranch)) != null ? _b : flag(env.RAINDROP_GIT_DETECT_BRANCH)) != null ? _c : false;
|
|
247
|
+
this.detectBranch = detectBranch;
|
|
248
|
+
const collectBranch = detectBranch || runtime.captureLegacyReplayBranch === true;
|
|
249
|
+
const autoDetect = runtime.allowDiscovery === false ? false : (_e = (_d = flag(opts.autoDetect)) != null ? _d : flag(env.RAINDROP_GIT_AUTO_DETECT)) != null ? _e : true;
|
|
250
|
+
const configuredSha = opts.commitSha;
|
|
251
|
+
const explicitSha = configuredSha === void 0 ? env.RAINDROP_COMMIT_SHA : configuredSha;
|
|
252
|
+
if (explicitSha === null) this.explicit[APP_COMMIT_SHA] = null;
|
|
253
|
+
else if (typeof explicitSha === "string" && validAppCommitSha(explicitSha))
|
|
254
|
+
this.explicit[APP_COMMIT_SHA] = explicitSha;
|
|
255
|
+
const configuredDirty = opts.commitDirty;
|
|
256
|
+
const explicitDirty = configuredDirty === void 0 ? flag(env.RAINDROP_COMMIT_DIRTY) : configuredDirty;
|
|
257
|
+
if (explicitDirty === null || typeof explicitDirty === "boolean")
|
|
258
|
+
this.explicit[APP_COMMIT_DIRTY] = explicitDirty;
|
|
259
|
+
const configuredBranch = opts.branch;
|
|
260
|
+
const explicitBranch = configuredBranch === void 0 ? env.RAINDROP_BRANCH : configuredBranch;
|
|
261
|
+
if (explicitBranch === null) this.explicit[APP_BRANCH] = null;
|
|
262
|
+
else if (typeof explicitBranch === "string" && explicitBranch.length <= 1024)
|
|
263
|
+
this.explicit[APP_BRANCH] = explicitBranch;
|
|
264
|
+
this.explicitKeys = appGitExplicitKeys(this.explicit);
|
|
265
|
+
this.defaults = { ...this.explicit };
|
|
266
|
+
if (!autoDetect || explicitSha !== void 0) return;
|
|
267
|
+
const sourceDirectory = (_f = shortString(opts.sourceDirectory)) != null ? _f : shortString(env.RAINDROP_GIT_SOURCE_DIRECTORY);
|
|
268
|
+
if (runtime.allowLocalGit === false && !sourceDirectory) return;
|
|
269
|
+
const deploy = sourceDirectory ? {} : detectedSource(env, DEPLOYMENTS, collectBranch);
|
|
270
|
+
if (deploy.commitSha) {
|
|
271
|
+
this.accept(deploy);
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
const fallback = sourceDirectory ? {} : detectedSource(env, CI_SOURCES, collectBranch);
|
|
275
|
+
if (runtime.resolveLocal && (runtime.allowLocalGit !== false || sourceDirectory)) {
|
|
276
|
+
this.cancel = runtime.resolveLocal(sourceDirectory, collectBranch, (result) => {
|
|
277
|
+
try {
|
|
278
|
+
if (!this.disposed) this.accept(result.commitSha ? result : fallback);
|
|
279
|
+
} catch (e) {
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
} else this.accept(fallback);
|
|
283
|
+
} catch (e) {
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
accept(result) {
|
|
287
|
+
const sha = validAppCommitSha(result.commitSha);
|
|
288
|
+
if (!sha) return;
|
|
289
|
+
this.replayBranch = shortString(result.branch);
|
|
290
|
+
this.defaults = {
|
|
291
|
+
[APP_COMMIT_SHA]: sha,
|
|
292
|
+
...typeof result.commitDirty === "boolean" ? { [APP_COMMIT_DIRTY]: result.commitDirty } : {},
|
|
293
|
+
...this.detectBranch && this.replayBranch ? { [APP_BRANCH]: this.replayBranch } : {},
|
|
294
|
+
...this.explicit
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
snapshot(properties) {
|
|
298
|
+
var _a;
|
|
299
|
+
try {
|
|
300
|
+
const binding = currentRoutingBinding();
|
|
301
|
+
const base = this.disabled && (binding == null ? void 0 : binding.appGitSource) !== "replay-override" ? {} : (_a = binding == null ? void 0 : binding.appGit) != null ? _a : this.defaults;
|
|
302
|
+
return this.mergeSnapshot(base, properties);
|
|
303
|
+
} catch (e) {
|
|
304
|
+
return Object.freeze({});
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
/** Safe defaults when no operation/span start was observed; never infer identity. */
|
|
308
|
+
snapshotExplicit(properties, eventId) {
|
|
309
|
+
try {
|
|
310
|
+
const base = { ...this.explicit };
|
|
311
|
+
const operation = eventId ? this.operations.get(eventId) : void 0;
|
|
312
|
+
if (operation) {
|
|
313
|
+
for (const key of operation.explicitKeys) base[key] = operation.snapshot[key];
|
|
314
|
+
}
|
|
315
|
+
return this.mergeSnapshot(base, properties, new Set(Object.keys(base)));
|
|
316
|
+
} catch (e) {
|
|
317
|
+
return mergeAppGitSnapshot({}, properties);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
/** Existing replay branch reporting stays separate from opt-in event properties. */
|
|
321
|
+
snapshotForReplay() {
|
|
322
|
+
const snapshot = this.snapshot();
|
|
323
|
+
if (this.replayBranch && !own(snapshot, APP_BRANCH) && snapshot[APP_COMMIT_SHA] === this.defaults[APP_COMMIT_SHA]) {
|
|
324
|
+
return Object.freeze({ ...snapshot, [APP_BRANCH]: this.replayBranch });
|
|
325
|
+
}
|
|
326
|
+
return snapshot;
|
|
327
|
+
}
|
|
328
|
+
/** Merge a frozen span snapshot without losing client-authored provenance. */
|
|
329
|
+
mergeSnapshot(base, properties, explicitKeys = this.explicitKeys) {
|
|
330
|
+
return mergeAppGitSnapshot(base, properties, /* @__PURE__ */ new Set([...this.explicitKeys, ...explicitKeys]));
|
|
331
|
+
}
|
|
332
|
+
/** Shippers belonging to one client share this bounded operation registry. */
|
|
333
|
+
forOperation(eventId, properties, owner) {
|
|
334
|
+
if (!eventId) return this.snapshot(properties);
|
|
335
|
+
let operation = this.operations.get(eventId);
|
|
336
|
+
if (!operation) {
|
|
337
|
+
if (this.operations.size >= 1e4) this.operationOverflow = true;
|
|
338
|
+
if (this.operationOverflow) return this.mergeSnapshot({}, properties);
|
|
339
|
+
operation = {
|
|
340
|
+
snapshot: this.snapshot(properties),
|
|
341
|
+
owners: /* @__PURE__ */ new Set(),
|
|
342
|
+
unowned: owner === void 0,
|
|
343
|
+
explicitKeys: appGitExplicitKeys(properties)
|
|
344
|
+
};
|
|
345
|
+
this.operations.set(eventId, operation);
|
|
346
|
+
} else if (properties && APP_GIT_KEYS.some((key) => own(properties, key))) {
|
|
347
|
+
const explicitKeys = /* @__PURE__ */ new Set([...this.explicitKeys, ...operation.explicitKeys]);
|
|
348
|
+
operation.snapshot = this.mergeSnapshot(operation.snapshot, properties, explicitKeys);
|
|
349
|
+
for (const key of appGitExplicitKeys(properties)) operation.explicitKeys.add(key);
|
|
350
|
+
}
|
|
351
|
+
if (!owner) operation.unowned = true;
|
|
352
|
+
if (owner) operation.owners.add(owner);
|
|
353
|
+
return operation.snapshot;
|
|
354
|
+
}
|
|
355
|
+
releaseOperation(eventId, owner) {
|
|
356
|
+
const operation = this.operations.get(eventId);
|
|
357
|
+
if (!operation) return;
|
|
358
|
+
operation.owners.delete(owner);
|
|
359
|
+
if (operation.owners.size === 0 && !operation.unowned) this.operations.delete(eventId);
|
|
360
|
+
}
|
|
361
|
+
finishOperation(eventId) {
|
|
362
|
+
this.operations.delete(eventId);
|
|
363
|
+
}
|
|
364
|
+
dispose() {
|
|
365
|
+
var _a;
|
|
366
|
+
this.disposed = true;
|
|
367
|
+
try {
|
|
368
|
+
(_a = this.cancel) == null ? void 0 : _a.call(this);
|
|
369
|
+
} catch (e) {
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
var AppGitContext = AppGitContextImpl;
|
|
374
|
+
function withAppGitAttributes(attributes, snapshot) {
|
|
375
|
+
try {
|
|
376
|
+
const present = new Set(attributes.flatMap((attr) => attr ? [attr.key] : []));
|
|
377
|
+
const added = [];
|
|
378
|
+
for (const key of APP_GIT_KEYS) {
|
|
379
|
+
if (present.has(key) || present.has(`ai.telemetry.metadata.${key}`) || present.has(`traceloop.association.properties.${key}`))
|
|
380
|
+
continue;
|
|
381
|
+
const value = snapshot[key];
|
|
382
|
+
if (typeof value === "string") added.push({ key, value: { stringValue: value } });
|
|
383
|
+
else if (typeof value === "boolean") added.push({ key, value: { boolValue: value } });
|
|
384
|
+
}
|
|
385
|
+
return added.length ? [...attributes, ...added] : attributes;
|
|
386
|
+
} catch (e) {
|
|
387
|
+
return attributes;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
function getCrypto() {
|
|
391
|
+
const c = globalThis.crypto;
|
|
392
|
+
return c;
|
|
393
|
+
}
|
|
394
|
+
function randomBytes(length) {
|
|
395
|
+
const cryptoObj = getCrypto();
|
|
396
|
+
const out = new Uint8Array(length);
|
|
397
|
+
if (cryptoObj && typeof cryptoObj.getRandomValues === "function") {
|
|
398
|
+
cryptoObj.getRandomValues(out);
|
|
399
|
+
return out;
|
|
400
|
+
}
|
|
401
|
+
for (let i = 0; i < out.length; i++) out[i] = Math.floor(Math.random() * 256);
|
|
402
|
+
return out;
|
|
403
|
+
}
|
|
404
|
+
function randomUUID() {
|
|
405
|
+
const cryptoObj = getCrypto();
|
|
406
|
+
if (cryptoObj && typeof cryptoObj.randomUUID === "function") {
|
|
407
|
+
return cryptoObj.randomUUID();
|
|
408
|
+
}
|
|
409
|
+
const b = randomBytes(16);
|
|
410
|
+
b[6] = b[6] & 15 | 64;
|
|
411
|
+
b[8] = b[8] & 63 | 128;
|
|
412
|
+
const hex = [...b].map((x) => x.toString(16).padStart(2, "0")).join("");
|
|
413
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
414
|
+
}
|
|
415
|
+
function runWithTracingSuppressed(fn) {
|
|
416
|
+
const hook = globalThis.RAINDROP_SUPPRESS_TRACING;
|
|
417
|
+
if (typeof hook !== "function") return fn();
|
|
418
|
+
let started = false;
|
|
419
|
+
try {
|
|
420
|
+
return hook(() => {
|
|
421
|
+
started = true;
|
|
422
|
+
return fn();
|
|
423
|
+
});
|
|
424
|
+
} catch (err) {
|
|
425
|
+
if (started) throw err;
|
|
426
|
+
return fn();
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
var DEFAULT_REQUEST_TIMEOUT_MS = 3e4;
|
|
430
|
+
var MAX_RETRY_DELAY_MS = 3e4;
|
|
431
|
+
function wait(ms) {
|
|
432
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
433
|
+
}
|
|
434
|
+
function formatEndpoint(endpoint) {
|
|
435
|
+
if (!endpoint) return void 0;
|
|
436
|
+
return endpoint.endsWith("/") ? endpoint : `${endpoint}/`;
|
|
437
|
+
}
|
|
438
|
+
function redactUrlForLog(url) {
|
|
439
|
+
try {
|
|
440
|
+
const parsed = new URL(url);
|
|
441
|
+
parsed.username = "";
|
|
442
|
+
parsed.password = "";
|
|
443
|
+
parsed.search = "";
|
|
444
|
+
parsed.hash = "";
|
|
445
|
+
return parsed.toString();
|
|
446
|
+
} catch (e) {
|
|
447
|
+
return "<unparseable-url>";
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
function parseRetryAfter(headers) {
|
|
451
|
+
var _a;
|
|
452
|
+
const value = (_a = headers.get("Retry-After")) != null ? _a : headers.get("retry-after");
|
|
453
|
+
if (!value) return void 0;
|
|
454
|
+
const asNumber = Number(value);
|
|
455
|
+
if (value.trim() !== "" && !Number.isNaN(asNumber)) return asNumber * 1e3;
|
|
456
|
+
const asDate = new Date(value).getTime();
|
|
457
|
+
if (!Number.isNaN(asDate)) {
|
|
458
|
+
const delta = asDate - Date.now();
|
|
459
|
+
return delta > 0 ? delta : 0;
|
|
460
|
+
}
|
|
461
|
+
return void 0;
|
|
462
|
+
}
|
|
463
|
+
function getRetryDelayMs(attemptNumber, previousError) {
|
|
464
|
+
if (previousError && typeof previousError === "object" && previousError !== null && "retryAfterMs" in previousError) {
|
|
465
|
+
const v = previousError.retryAfterMs;
|
|
466
|
+
if (typeof v === "number") return Math.min(Math.max(0, v), MAX_RETRY_DELAY_MS);
|
|
467
|
+
}
|
|
468
|
+
if (attemptNumber <= 1) return 0;
|
|
469
|
+
const base = 500;
|
|
470
|
+
const factor = Math.pow(2, attemptNumber - 2);
|
|
471
|
+
return Math.min(base * factor, MAX_RETRY_DELAY_MS);
|
|
472
|
+
}
|
|
473
|
+
async function withRetry(operation, opName, opts) {
|
|
474
|
+
const prefix = opts.sdkName ? `[raindrop-ai/${opts.sdkName}]` : "[raindrop-ai/core]";
|
|
475
|
+
let lastError = void 0;
|
|
476
|
+
for (let attemptNumber = 1; attemptNumber <= opts.maxAttempts; attemptNumber++) {
|
|
477
|
+
if (attemptNumber > 1) {
|
|
478
|
+
const delay = getRetryDelayMs(attemptNumber, lastError);
|
|
479
|
+
if (opts.debug) {
|
|
480
|
+
console.warn(
|
|
481
|
+
`${prefix} ${opName} retry ${attemptNumber}/${opts.maxAttempts} in ${delay}ms`
|
|
482
|
+
);
|
|
483
|
+
}
|
|
484
|
+
if (delay > 0) await wait(delay);
|
|
485
|
+
} else if (opts.debug) {
|
|
486
|
+
console.log(`${prefix} ${opName} attempt ${attemptNumber}/${opts.maxAttempts}`);
|
|
487
|
+
}
|
|
488
|
+
try {
|
|
489
|
+
return await operation();
|
|
490
|
+
} catch (err) {
|
|
491
|
+
lastError = err;
|
|
492
|
+
if (opts.debug) {
|
|
493
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
494
|
+
console.warn(
|
|
495
|
+
`${prefix} ${opName} attempt ${attemptNumber} failed: ${msg}${attemptNumber === opts.maxAttempts ? " (no more retries)" : ""}`
|
|
496
|
+
);
|
|
497
|
+
}
|
|
498
|
+
if (lastError && typeof lastError === "object" && "retryable" in lastError && !lastError.retryable)
|
|
499
|
+
break;
|
|
500
|
+
if (attemptNumber === opts.maxAttempts) break;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
throw lastError instanceof Error ? lastError : new Error(String(lastError));
|
|
504
|
+
}
|
|
505
|
+
async function postJson(url, body, headers, opts) {
|
|
506
|
+
var _a;
|
|
507
|
+
const opName = `POST ${redactUrlForLog(url)}`;
|
|
508
|
+
const timeoutMs = (_a = opts.timeoutMs) != null ? _a : DEFAULT_REQUEST_TIMEOUT_MS;
|
|
509
|
+
await withRetry(
|
|
510
|
+
async () => {
|
|
511
|
+
const resp = await runWithTracingSuppressed(
|
|
512
|
+
() => fetch(url, {
|
|
513
|
+
method: "POST",
|
|
514
|
+
redirect: headers["X-Raindrop-Replay-Id"] !== void 0 ? "error" : "follow",
|
|
515
|
+
headers: {
|
|
516
|
+
"Content-Type": "application/json",
|
|
517
|
+
...headers
|
|
518
|
+
},
|
|
519
|
+
body: JSON.stringify(body),
|
|
520
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
521
|
+
})
|
|
522
|
+
);
|
|
523
|
+
if (!resp.ok) {
|
|
524
|
+
const text = await resp.text().catch(() => "");
|
|
525
|
+
const err = new Error(
|
|
526
|
+
`HTTP ${resp.status} ${resp.statusText}${text ? `: ${text}` : ""}`
|
|
527
|
+
);
|
|
528
|
+
const retryAfterMs = parseRetryAfter(resp.headers);
|
|
529
|
+
if (typeof retryAfterMs === "number") err.retryAfterMs = retryAfterMs;
|
|
530
|
+
err.retryable = resp.status === 429 || resp.status >= 500;
|
|
531
|
+
throw err;
|
|
532
|
+
}
|
|
533
|
+
},
|
|
534
|
+
opName,
|
|
535
|
+
opts
|
|
536
|
+
);
|
|
537
|
+
}
|
|
538
|
+
var SpanStatusCode = {
|
|
539
|
+
UNSET: 0,
|
|
540
|
+
OK: 1,
|
|
541
|
+
ERROR: 2
|
|
542
|
+
};
|
|
543
|
+
function buildExportTraceServiceRequest(spans, serviceName = "raindrop.core", serviceVersion = "0.0.0") {
|
|
544
|
+
return {
|
|
545
|
+
resourceSpans: [
|
|
546
|
+
{
|
|
547
|
+
resource: {
|
|
548
|
+
attributes: [{ key: "service.name", value: { stringValue: serviceName } }]
|
|
549
|
+
},
|
|
550
|
+
scopeSpans: [
|
|
551
|
+
{
|
|
552
|
+
scope: { name: serviceName, version: serviceVersion },
|
|
553
|
+
spans
|
|
554
|
+
}
|
|
555
|
+
]
|
|
556
|
+
}
|
|
557
|
+
]
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
var LOCAL_DEBUGGER_ENV_VAR = "RAINDROP_LOCAL_DEBUGGER";
|
|
561
|
+
var WORKSHOP_ENV_VAR = "RAINDROP_WORKSHOP";
|
|
562
|
+
var DEFAULT_LOCAL_WORKSHOP_URL = "http://localhost:5899/v1/";
|
|
563
|
+
function readEnvVar(name) {
|
|
564
|
+
var _a;
|
|
565
|
+
try {
|
|
566
|
+
const env = (_a = globalThis == null ? void 0 : globalThis.process) == null ? void 0 : _a.env;
|
|
567
|
+
if (env && typeof env[name] === "string" && env[name].length > 0) {
|
|
568
|
+
return env[name];
|
|
569
|
+
}
|
|
570
|
+
} catch (e) {
|
|
571
|
+
}
|
|
572
|
+
return void 0;
|
|
573
|
+
}
|
|
574
|
+
function readWorkshopEnv() {
|
|
575
|
+
const raw = readEnvVar(WORKSHOP_ENV_VAR);
|
|
576
|
+
if (raw === void 0) return void 0;
|
|
577
|
+
const trimmed = raw.trim();
|
|
578
|
+
if (trimmed.length === 0) return void 0;
|
|
579
|
+
if (/^https?:\/\//i.test(trimmed)) return { url: trimmed };
|
|
580
|
+
if (/^(1|true|yes|on)$/i.test(trimmed)) return "enable";
|
|
581
|
+
if (/^(0|false|no|off)$/i.test(trimmed)) return "disable";
|
|
582
|
+
return void 0;
|
|
583
|
+
}
|
|
584
|
+
function isLocalDevHost(hostname) {
|
|
585
|
+
if (!hostname) return false;
|
|
586
|
+
if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "0.0.0.0" || hostname === "::1") {
|
|
587
|
+
return true;
|
|
588
|
+
}
|
|
589
|
+
if (hostname.endsWith(".localhost")) return true;
|
|
590
|
+
return false;
|
|
591
|
+
}
|
|
592
|
+
function readRuntimeHostname() {
|
|
593
|
+
try {
|
|
594
|
+
const loc = globalThis == null ? void 0 : globalThis.location;
|
|
595
|
+
if (loc && typeof loc.hostname === "string" && loc.hostname.length > 0) {
|
|
596
|
+
return loc.hostname;
|
|
597
|
+
}
|
|
598
|
+
} catch (e) {
|
|
599
|
+
}
|
|
600
|
+
return void 0;
|
|
601
|
+
}
|
|
602
|
+
function shouldAutoEnableLocalWorkshop() {
|
|
603
|
+
if (isLocalDevHost(readRuntimeHostname())) return true;
|
|
604
|
+
if (readEnvVar("NODE_ENV") === "development") return true;
|
|
605
|
+
return false;
|
|
606
|
+
}
|
|
607
|
+
function resolveLocalDebuggerBaseUrl(baseUrl) {
|
|
608
|
+
var _a, _b, _c;
|
|
609
|
+
if (baseUrl === null) return null;
|
|
610
|
+
if (typeof baseUrl === "string" && baseUrl.length > 0) {
|
|
611
|
+
return (_a = formatEndpoint(baseUrl)) != null ? _a : null;
|
|
612
|
+
}
|
|
613
|
+
const explicitUrlEnv = readEnvVar(LOCAL_DEBUGGER_ENV_VAR);
|
|
614
|
+
if (explicitUrlEnv) return (_b = formatEndpoint(explicitUrlEnv)) != null ? _b : null;
|
|
615
|
+
const workshopEnv = readWorkshopEnv();
|
|
616
|
+
if (workshopEnv === "disable") return null;
|
|
617
|
+
if (workshopEnv === "enable") return DEFAULT_LOCAL_WORKSHOP_URL;
|
|
618
|
+
if (workshopEnv && "url" in workshopEnv) return (_c = formatEndpoint(workshopEnv.url)) != null ? _c : null;
|
|
619
|
+
if (shouldAutoEnableLocalWorkshop()) return DEFAULT_LOCAL_WORKSHOP_URL;
|
|
620
|
+
return null;
|
|
621
|
+
}
|
|
622
|
+
var LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS = 2e3;
|
|
623
|
+
function mirrorTraceExportToLocalDebugger(body, options = {}) {
|
|
624
|
+
var _a;
|
|
625
|
+
const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
|
|
626
|
+
if (!baseUrl) return Promise.resolve();
|
|
627
|
+
return postJson(`${baseUrl}traces`, body, {}, {
|
|
628
|
+
maxAttempts: 1,
|
|
629
|
+
debug: (_a = options.debug) != null ? _a : false,
|
|
630
|
+
sdkName: options.sdkName,
|
|
631
|
+
timeoutMs: LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS
|
|
632
|
+
}).catch(() => {
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
var PROJECT_ID_HEADER = "X-Raindrop-Project-Id";
|
|
636
|
+
var PROJECT_ID_SLUG_PATTERN = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
|
|
637
|
+
function isValidProjectIdSlug(value) {
|
|
638
|
+
return PROJECT_ID_SLUG_PATTERN.test(value);
|
|
639
|
+
}
|
|
640
|
+
function normalizeProjectId(raw, opts) {
|
|
641
|
+
if (typeof raw !== "string") return void 0;
|
|
642
|
+
const trimmed = raw.trim();
|
|
643
|
+
if (!trimmed) return void 0;
|
|
644
|
+
if (!isValidProjectIdSlug(trimmed) && opts.debug) {
|
|
645
|
+
console.warn(
|
|
646
|
+
`${opts.prefix} projectId "${trimmed}" does not match slug ${PROJECT_ID_SLUG_PATTERN.source}; sending anyway \u2014 backend may reject with HTTP 400`
|
|
647
|
+
);
|
|
648
|
+
}
|
|
649
|
+
return trimmed;
|
|
650
|
+
}
|
|
651
|
+
function projectIdHeaders(projectId) {
|
|
652
|
+
return projectId ? { [PROJECT_ID_HEADER]: projectId } : {};
|
|
653
|
+
}
|
|
654
|
+
var DEFAULT_REDACT_ATTRIBUTE_KEYS = [
|
|
655
|
+
"ai.request.providerOptions",
|
|
656
|
+
"ai.response.providerMetadata"
|
|
657
|
+
];
|
|
658
|
+
new Set(DEFAULT_REDACT_ATTRIBUTE_KEYS);
|
|
659
|
+
var resolveLocal = (sourceDirectory, detectBranch, completed) => {
|
|
660
|
+
const cwd = sourceDirectory ? path.resolve(sourceDirectory) : process.cwd();
|
|
661
|
+
let cancelled = false;
|
|
662
|
+
let active;
|
|
663
|
+
let deadlineTimer;
|
|
664
|
+
const deadline = Date.now() + 1e3;
|
|
665
|
+
const run = (args, done) => {
|
|
666
|
+
if (cancelled) return;
|
|
667
|
+
const remaining = deadline - Date.now();
|
|
668
|
+
if (remaining <= 0) {
|
|
669
|
+
done(void 0);
|
|
670
|
+
return;
|
|
671
|
+
}
|
|
672
|
+
try {
|
|
673
|
+
active = child_process.execFile(
|
|
674
|
+
"git",
|
|
675
|
+
args,
|
|
676
|
+
{
|
|
677
|
+
cwd,
|
|
678
|
+
encoding: "utf8",
|
|
679
|
+
maxBuffer: 4096,
|
|
680
|
+
windowsHide: true,
|
|
681
|
+
env: {
|
|
682
|
+
...process.env,
|
|
683
|
+
// The selected application cwd, not the invoking shell's Git plumbing, owns identity.
|
|
684
|
+
GIT_DIR: void 0,
|
|
685
|
+
GIT_WORK_TREE: void 0,
|
|
686
|
+
GIT_COMMON_DIR: void 0,
|
|
687
|
+
GIT_NAMESPACE: void 0,
|
|
688
|
+
GIT_INDEX_FILE: void 0,
|
|
689
|
+
GIT_OBJECT_DIRECTORY: void 0,
|
|
690
|
+
GIT_ALTERNATE_OBJECT_DIRECTORIES: void 0,
|
|
691
|
+
GIT_CONFIG_PARAMETERS: void 0,
|
|
692
|
+
GIT_CONFIG_COUNT: "0",
|
|
693
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
694
|
+
GIT_OPTIONAL_LOCKS: "0"
|
|
695
|
+
}
|
|
696
|
+
},
|
|
697
|
+
(error, stdout) => {
|
|
698
|
+
clearTimeout(deadlineTimer);
|
|
699
|
+
deadlineTimer = void 0;
|
|
700
|
+
active = void 0;
|
|
701
|
+
if (!cancelled) {
|
|
702
|
+
try {
|
|
703
|
+
done(error ? void 0 : stdout.trim());
|
|
704
|
+
} catch (e) {
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
);
|
|
709
|
+
active.unref();
|
|
710
|
+
if (active.stdout && "unref" in active.stdout && typeof active.stdout.unref === "function")
|
|
711
|
+
active.stdout.unref();
|
|
712
|
+
if (active.stderr && "unref" in active.stderr && typeof active.stderr.unref === "function")
|
|
713
|
+
active.stderr.unref();
|
|
714
|
+
deadlineTimer = setTimeout(() => {
|
|
715
|
+
try {
|
|
716
|
+
active == null ? void 0 : active.kill("SIGKILL");
|
|
717
|
+
} catch (e) {
|
|
718
|
+
}
|
|
719
|
+
}, remaining);
|
|
720
|
+
deadlineTimer.unref();
|
|
721
|
+
} catch (e) {
|
|
722
|
+
try {
|
|
723
|
+
done(void 0);
|
|
724
|
+
} catch (e2) {
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
};
|
|
728
|
+
const scheduled = setTimeout(() => {
|
|
729
|
+
try {
|
|
730
|
+
run(["rev-parse", "HEAD"], (rawSha) => {
|
|
731
|
+
const commitSha = validAppCommitSha(rawSha);
|
|
732
|
+
if (!commitSha) {
|
|
733
|
+
completed({});
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
run(["-c", "core.fsmonitor=false", "status", "--porcelain"], (status) => {
|
|
737
|
+
const finish = (branch) => {
|
|
738
|
+
run(["rev-parse", "HEAD"], (finalSha) => {
|
|
739
|
+
const coherent = validAppCommitSha(finalSha) === commitSha;
|
|
740
|
+
completed({
|
|
741
|
+
commitSha,
|
|
742
|
+
...coherent && status !== void 0 ? { commitDirty: status !== "" } : {},
|
|
743
|
+
...coherent && branch && branch !== "HEAD" ? { branch } : {}
|
|
744
|
+
});
|
|
745
|
+
});
|
|
746
|
+
};
|
|
747
|
+
if (detectBranch) run(["symbolic-ref", "--quiet", "--short", "HEAD"], finish);
|
|
748
|
+
else finish();
|
|
749
|
+
});
|
|
750
|
+
});
|
|
751
|
+
} catch (e) {
|
|
752
|
+
completed({});
|
|
753
|
+
}
|
|
754
|
+
}, 0);
|
|
755
|
+
scheduled.unref();
|
|
756
|
+
return () => {
|
|
757
|
+
cancelled = true;
|
|
758
|
+
clearTimeout(scheduled);
|
|
759
|
+
clearTimeout(deadlineTimer);
|
|
760
|
+
try {
|
|
761
|
+
active == null ? void 0 : active.kill("SIGKILL");
|
|
762
|
+
} catch (e) {
|
|
763
|
+
}
|
|
764
|
+
};
|
|
765
|
+
};
|
|
766
|
+
function createAppGitContext(options, runtime = {}) {
|
|
767
|
+
return new AppGitContext(options, { ...runtime, resolveLocal });
|
|
768
|
+
}
|
|
769
|
+
globalThis.RAINDROP_ASYNC_LOCAL_STORAGE = async_hooks.AsyncLocalStorage;
|
|
770
|
+
var SUPPRESS_TRACING_KEY = /* @__PURE__ */ Symbol.for(
|
|
771
|
+
"OpenTelemetry SDK Context Key SUPPRESS_TRACING"
|
|
772
|
+
);
|
|
773
|
+
function findOtelContextManager() {
|
|
774
|
+
var _a;
|
|
775
|
+
for (const sym of Object.getOwnPropertySymbols(globalThis)) {
|
|
776
|
+
if (!((_a = sym.description) == null ? void 0 : _a.startsWith("opentelemetry.js.api."))) continue;
|
|
777
|
+
const api = globalThis[sym];
|
|
778
|
+
const cm = api == null ? void 0 : api.context;
|
|
779
|
+
if (cm && typeof cm.with === "function" && typeof cm.active === "function") {
|
|
780
|
+
return cm;
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
return void 0;
|
|
784
|
+
}
|
|
785
|
+
function installTracingSuppressionHook() {
|
|
786
|
+
if (typeof globalThis.RAINDROP_SUPPRESS_TRACING === "function") return;
|
|
787
|
+
const hook = (fn) => {
|
|
788
|
+
const cm = findOtelContextManager();
|
|
789
|
+
if (!cm) return fn();
|
|
790
|
+
return cm.with(cm.active().setValue(SUPPRESS_TRACING_KEY, true), fn);
|
|
791
|
+
};
|
|
792
|
+
globalThis.RAINDROP_SUPPRESS_TRACING = hook;
|
|
793
|
+
}
|
|
794
|
+
installTracingSuppressionHook();
|
|
12
795
|
function parseEveSessionParent(value) {
|
|
13
796
|
if (typeof value !== "object" || value === null) return void 0;
|
|
14
797
|
const p = value;
|
|
@@ -142,346 +925,79 @@ var EveTurnRegistry = class {
|
|
|
142
925
|
}
|
|
143
926
|
if (stack.length === 0) {
|
|
144
927
|
this.stacks.delete(traceId);
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Drop all entries. Called from the SpanProcessor's `shutdown` hook
|
|
150
|
-
* during exporter teardown.
|
|
151
|
-
*/
|
|
152
|
-
clear() {
|
|
153
|
-
this.stacks.clear();
|
|
154
|
-
}
|
|
155
|
-
/**
|
|
156
|
-
* Total number of in-flight entries across all traces. For tests +
|
|
157
|
-
* diagnostic logging.
|
|
158
|
-
*/
|
|
159
|
-
get size() {
|
|
160
|
-
let total = 0;
|
|
161
|
-
for (const stack of this.stacks.values()) total += stack.length;
|
|
162
|
-
return total;
|
|
163
|
-
}
|
|
164
|
-
};
|
|
165
|
-
var registry = new EveTurnRegistry();
|
|
166
|
-
function createEveTurnSpanProcessor() {
|
|
167
|
-
return {
|
|
168
|
-
onStart(span) {
|
|
169
|
-
if (span.name !== EVE_TURN_SPAN_NAME) return;
|
|
170
|
-
const attrs = span.attributes;
|
|
171
|
-
if (!attrs) return;
|
|
172
|
-
const ctx = span.spanContext();
|
|
173
|
-
const continuationToken = typeof attrs[EVE_CONTINUATION_TOKEN_ATTR] === "string" ? attrs[EVE_CONTINUATION_TOKEN_ATTR] : void 0;
|
|
174
|
-
const sessionId = typeof attrs[EVE_SESSION_ID_ATTR] === "string" ? attrs[EVE_SESSION_ID_ATTR] : void 0;
|
|
175
|
-
registry.record(ctx.traceId, ctx.spanId, {
|
|
176
|
-
continuationToken,
|
|
177
|
-
sessionId
|
|
178
|
-
});
|
|
179
|
-
},
|
|
180
|
-
onEnd(span) {
|
|
181
|
-
if (span.name !== EVE_TURN_SPAN_NAME) return;
|
|
182
|
-
const ctx = span.spanContext();
|
|
183
|
-
registry.releaseAfterTick(ctx.traceId, ctx.spanId);
|
|
184
|
-
},
|
|
185
|
-
forceFlush() {
|
|
186
|
-
return Promise.resolve();
|
|
187
|
-
},
|
|
188
|
-
shutdown() {
|
|
189
|
-
registry.clear();
|
|
190
|
-
return Promise.resolve();
|
|
191
|
-
}
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
function lookupEveTurn(traceId) {
|
|
195
|
-
return registry.lookup(traceId);
|
|
196
|
-
}
|
|
197
|
-
function installEveTurnSpanProcessor(traceApi) {
|
|
198
|
-
if (installState.installed) return true;
|
|
199
|
-
try {
|
|
200
|
-
let provider = traceApi.getTracerProvider();
|
|
201
|
-
const proxyProvider = provider;
|
|
202
|
-
if (typeof proxyProvider.getDelegate === "function") {
|
|
203
|
-
const delegate = proxyProvider.getDelegate();
|
|
204
|
-
if (delegate) provider = delegate;
|
|
205
|
-
}
|
|
206
|
-
const tp = provider;
|
|
207
|
-
if (typeof tp.addSpanProcessor !== "function") {
|
|
208
|
-
return false;
|
|
209
|
-
}
|
|
210
|
-
tp.addSpanProcessor(createEveTurnSpanProcessor());
|
|
211
|
-
installState.installed = true;
|
|
212
|
-
return true;
|
|
213
|
-
} catch {
|
|
214
|
-
return false;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
var installState = { installed: false };
|
|
218
|
-
function runWithTracingSuppressed(fn) {
|
|
219
|
-
const hook = globalThis.RAINDROP_SUPPRESS_TRACING;
|
|
220
|
-
if (typeof hook !== "function") return fn();
|
|
221
|
-
let started = false;
|
|
222
|
-
try {
|
|
223
|
-
return hook(() => {
|
|
224
|
-
started = true;
|
|
225
|
-
return fn();
|
|
226
|
-
});
|
|
227
|
-
} catch (err) {
|
|
228
|
-
if (started) throw err;
|
|
229
|
-
return fn();
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
var DEFAULT_REQUEST_TIMEOUT_MS = 3e4;
|
|
233
|
-
var MAX_RETRY_DELAY_MS = 3e4;
|
|
234
|
-
function wait(ms) {
|
|
235
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
236
|
-
}
|
|
237
|
-
function formatEndpoint(endpoint) {
|
|
238
|
-
if (!endpoint) return void 0;
|
|
239
|
-
return endpoint.endsWith("/") ? endpoint : `${endpoint}/`;
|
|
240
|
-
}
|
|
241
|
-
function redactUrlForLog(url) {
|
|
242
|
-
try {
|
|
243
|
-
const parsed = new URL(url);
|
|
244
|
-
parsed.username = "";
|
|
245
|
-
parsed.password = "";
|
|
246
|
-
parsed.search = "";
|
|
247
|
-
parsed.hash = "";
|
|
248
|
-
return parsed.toString();
|
|
249
|
-
} catch (e) {
|
|
250
|
-
return "<unparseable-url>";
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
function parseRetryAfter(headers) {
|
|
254
|
-
var _a;
|
|
255
|
-
const value = (_a = headers.get("Retry-After")) != null ? _a : headers.get("retry-after");
|
|
256
|
-
if (!value) return void 0;
|
|
257
|
-
const asNumber = Number(value);
|
|
258
|
-
if (value.trim() !== "" && !Number.isNaN(asNumber)) return asNumber * 1e3;
|
|
259
|
-
const asDate = new Date(value).getTime();
|
|
260
|
-
if (!Number.isNaN(asDate)) {
|
|
261
|
-
const delta = asDate - Date.now();
|
|
262
|
-
return delta > 0 ? delta : 0;
|
|
263
|
-
}
|
|
264
|
-
return void 0;
|
|
265
|
-
}
|
|
266
|
-
function getRetryDelayMs(attemptNumber, previousError) {
|
|
267
|
-
if (previousError && typeof previousError === "object" && previousError !== null && "retryAfterMs" in previousError) {
|
|
268
|
-
const v = previousError.retryAfterMs;
|
|
269
|
-
if (typeof v === "number") return Math.min(Math.max(0, v), MAX_RETRY_DELAY_MS);
|
|
270
|
-
}
|
|
271
|
-
if (attemptNumber <= 1) return 0;
|
|
272
|
-
const base = 500;
|
|
273
|
-
const factor = Math.pow(2, attemptNumber - 2);
|
|
274
|
-
return Math.min(base * factor, MAX_RETRY_DELAY_MS);
|
|
275
|
-
}
|
|
276
|
-
async function withRetry(operation, opName, opts) {
|
|
277
|
-
const prefix = opts.sdkName ? `[raindrop-ai/${opts.sdkName}]` : "[raindrop-ai/core]";
|
|
278
|
-
let lastError = void 0;
|
|
279
|
-
for (let attemptNumber = 1; attemptNumber <= opts.maxAttempts; attemptNumber++) {
|
|
280
|
-
if (attemptNumber > 1) {
|
|
281
|
-
const delay = getRetryDelayMs(attemptNumber, lastError);
|
|
282
|
-
if (opts.debug) {
|
|
283
|
-
console.warn(
|
|
284
|
-
`${prefix} ${opName} retry ${attemptNumber}/${opts.maxAttempts} in ${delay}ms`
|
|
285
|
-
);
|
|
286
|
-
}
|
|
287
|
-
if (delay > 0) await wait(delay);
|
|
288
|
-
} else if (opts.debug) {
|
|
289
|
-
console.log(`${prefix} ${opName} attempt ${attemptNumber}/${opts.maxAttempts}`);
|
|
290
|
-
}
|
|
291
|
-
try {
|
|
292
|
-
return await operation();
|
|
293
|
-
} catch (err) {
|
|
294
|
-
lastError = err;
|
|
295
|
-
if (opts.debug) {
|
|
296
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
297
|
-
console.warn(
|
|
298
|
-
`${prefix} ${opName} attempt ${attemptNumber} failed: ${msg}${attemptNumber === opts.maxAttempts ? " (no more retries)" : ""}`
|
|
299
|
-
);
|
|
300
|
-
}
|
|
301
|
-
if (lastError && typeof lastError === "object" && "retryable" in lastError && !lastError.retryable)
|
|
302
|
-
break;
|
|
303
|
-
if (attemptNumber === opts.maxAttempts) break;
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
throw lastError instanceof Error ? lastError : new Error(String(lastError));
|
|
307
|
-
}
|
|
308
|
-
async function postJson(url, body, headers, opts) {
|
|
309
|
-
var _a;
|
|
310
|
-
const opName = `POST ${redactUrlForLog(url)}`;
|
|
311
|
-
const timeoutMs = (_a = opts.timeoutMs) != null ? _a : DEFAULT_REQUEST_TIMEOUT_MS;
|
|
312
|
-
await withRetry(
|
|
313
|
-
async () => {
|
|
314
|
-
const resp = await runWithTracingSuppressed(
|
|
315
|
-
() => fetch(url, {
|
|
316
|
-
method: "POST",
|
|
317
|
-
headers: {
|
|
318
|
-
"Content-Type": "application/json",
|
|
319
|
-
...headers
|
|
320
|
-
},
|
|
321
|
-
body: JSON.stringify(body),
|
|
322
|
-
signal: AbortSignal.timeout(timeoutMs)
|
|
323
|
-
})
|
|
324
|
-
);
|
|
325
|
-
if (!resp.ok) {
|
|
326
|
-
const text = await resp.text().catch(() => "");
|
|
327
|
-
const err = new Error(
|
|
328
|
-
`HTTP ${resp.status} ${resp.statusText}${text ? `: ${text}` : ""}`
|
|
329
|
-
);
|
|
330
|
-
const retryAfterMs = parseRetryAfter(resp.headers);
|
|
331
|
-
if (typeof retryAfterMs === "number") err.retryAfterMs = retryAfterMs;
|
|
332
|
-
err.retryable = resp.status === 429 || resp.status >= 500;
|
|
333
|
-
throw err;
|
|
334
|
-
}
|
|
335
|
-
},
|
|
336
|
-
opName,
|
|
337
|
-
opts
|
|
338
|
-
);
|
|
339
|
-
}
|
|
340
|
-
var SpanStatusCode = {
|
|
341
|
-
UNSET: 0,
|
|
342
|
-
OK: 1,
|
|
343
|
-
ERROR: 2
|
|
928
|
+
}
|
|
929
|
+
});
|
|
930
|
+
}
|
|
931
|
+
/**
|
|
932
|
+
* Drop all entries. Called from the SpanProcessor's `shutdown` hook
|
|
933
|
+
* during exporter teardown.
|
|
934
|
+
*/
|
|
935
|
+
clear() {
|
|
936
|
+
this.stacks.clear();
|
|
937
|
+
}
|
|
938
|
+
/**
|
|
939
|
+
* Total number of in-flight entries across all traces. For tests +
|
|
940
|
+
* diagnostic logging.
|
|
941
|
+
*/
|
|
942
|
+
get size() {
|
|
943
|
+
let total = 0;
|
|
944
|
+
for (const stack of this.stacks.values()) total += stack.length;
|
|
945
|
+
return total;
|
|
946
|
+
}
|
|
344
947
|
};
|
|
345
|
-
|
|
948
|
+
var registry = new EveTurnRegistry();
|
|
949
|
+
function createEveTurnSpanProcessor() {
|
|
346
950
|
return {
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
return env[name];
|
|
951
|
+
onStart(span) {
|
|
952
|
+
if (span.name !== EVE_TURN_SPAN_NAME) return;
|
|
953
|
+
const attrs = span.attributes;
|
|
954
|
+
if (!attrs) return;
|
|
955
|
+
const ctx = span.spanContext();
|
|
956
|
+
const continuationToken = typeof attrs[EVE_CONTINUATION_TOKEN_ATTR] === "string" ? attrs[EVE_CONTINUATION_TOKEN_ATTR] : void 0;
|
|
957
|
+
const sessionId = typeof attrs[EVE_SESSION_ID_ATTR] === "string" ? attrs[EVE_SESSION_ID_ATTR] : void 0;
|
|
958
|
+
registry.record(ctx.traceId, ctx.spanId, {
|
|
959
|
+
continuationToken,
|
|
960
|
+
sessionId
|
|
961
|
+
});
|
|
962
|
+
},
|
|
963
|
+
onEnd(span) {
|
|
964
|
+
if (span.name !== EVE_TURN_SPAN_NAME) return;
|
|
965
|
+
const ctx = span.spanContext();
|
|
966
|
+
registry.releaseAfterTick(ctx.traceId, ctx.spanId);
|
|
967
|
+
},
|
|
968
|
+
forceFlush() {
|
|
969
|
+
return Promise.resolve();
|
|
970
|
+
},
|
|
971
|
+
shutdown() {
|
|
972
|
+
registry.clear();
|
|
973
|
+
return Promise.resolve();
|
|
371
974
|
}
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
return void 0;
|
|
375
|
-
}
|
|
376
|
-
function readWorkshopEnv() {
|
|
377
|
-
const raw = readEnvVar(WORKSHOP_ENV_VAR);
|
|
378
|
-
if (raw === void 0) return void 0;
|
|
379
|
-
const trimmed = raw.trim();
|
|
380
|
-
if (trimmed.length === 0) return void 0;
|
|
381
|
-
if (/^https?:\/\//i.test(trimmed)) return { url: trimmed };
|
|
382
|
-
if (/^(1|true|yes|on)$/i.test(trimmed)) return "enable";
|
|
383
|
-
if (/^(0|false|no|off)$/i.test(trimmed)) return "disable";
|
|
384
|
-
return void 0;
|
|
975
|
+
};
|
|
385
976
|
}
|
|
386
|
-
function
|
|
387
|
-
|
|
388
|
-
if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "0.0.0.0" || hostname === "::1") {
|
|
389
|
-
return true;
|
|
390
|
-
}
|
|
391
|
-
if (hostname.endsWith(".localhost")) return true;
|
|
392
|
-
return false;
|
|
977
|
+
function lookupEveTurn(traceId) {
|
|
978
|
+
return registry.lookup(traceId);
|
|
393
979
|
}
|
|
394
|
-
function
|
|
980
|
+
function installEveTurnSpanProcessor(traceApi) {
|
|
981
|
+
if (installState.installed) return true;
|
|
395
982
|
try {
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
983
|
+
let provider = traceApi.getTracerProvider();
|
|
984
|
+
const proxyProvider = provider;
|
|
985
|
+
if (typeof proxyProvider.getDelegate === "function") {
|
|
986
|
+
const delegate = proxyProvider.getDelegate();
|
|
987
|
+
if (delegate) provider = delegate;
|
|
399
988
|
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
}
|
|
404
|
-
function shouldAutoEnableLocalWorkshop() {
|
|
405
|
-
if (isLocalDevHost(readRuntimeHostname())) return true;
|
|
406
|
-
if (readEnvVar("NODE_ENV") === "development") return true;
|
|
407
|
-
return false;
|
|
408
|
-
}
|
|
409
|
-
function resolveLocalDebuggerBaseUrl(baseUrl) {
|
|
410
|
-
var _a, _b, _c;
|
|
411
|
-
if (baseUrl === null) return null;
|
|
412
|
-
if (typeof baseUrl === "string" && baseUrl.length > 0) {
|
|
413
|
-
return (_a = formatEndpoint(baseUrl)) != null ? _a : null;
|
|
414
|
-
}
|
|
415
|
-
const explicitUrlEnv = readEnvVar(LOCAL_DEBUGGER_ENV_VAR);
|
|
416
|
-
if (explicitUrlEnv) return (_b = formatEndpoint(explicitUrlEnv)) != null ? _b : null;
|
|
417
|
-
const workshopEnv = readWorkshopEnv();
|
|
418
|
-
if (workshopEnv === "disable") return null;
|
|
419
|
-
if (workshopEnv === "enable") return DEFAULT_LOCAL_WORKSHOP_URL;
|
|
420
|
-
if (workshopEnv && "url" in workshopEnv) return (_c = formatEndpoint(workshopEnv.url)) != null ? _c : null;
|
|
421
|
-
if (shouldAutoEnableLocalWorkshop()) return DEFAULT_LOCAL_WORKSHOP_URL;
|
|
422
|
-
return null;
|
|
423
|
-
}
|
|
424
|
-
function mirrorTraceExportToLocalDebugger(body, options = {}) {
|
|
425
|
-
var _a;
|
|
426
|
-
const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
|
|
427
|
-
if (!baseUrl) return;
|
|
428
|
-
void postJson(`${baseUrl}traces`, body, {}, {
|
|
429
|
-
maxAttempts: 1,
|
|
430
|
-
debug: (_a = options.debug) != null ? _a : false,
|
|
431
|
-
sdkName: options.sdkName
|
|
432
|
-
}).catch(() => {
|
|
433
|
-
});
|
|
434
|
-
}
|
|
435
|
-
var PROJECT_ID_HEADER = "X-Raindrop-Project-Id";
|
|
436
|
-
var PROJECT_ID_SLUG_PATTERN = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
|
|
437
|
-
function isValidProjectIdSlug(value) {
|
|
438
|
-
return PROJECT_ID_SLUG_PATTERN.test(value);
|
|
439
|
-
}
|
|
440
|
-
function normalizeProjectId(raw, opts) {
|
|
441
|
-
if (typeof raw !== "string") return void 0;
|
|
442
|
-
const trimmed = raw.trim();
|
|
443
|
-
if (!trimmed) return void 0;
|
|
444
|
-
if (!isValidProjectIdSlug(trimmed) && opts.debug) {
|
|
445
|
-
console.warn(
|
|
446
|
-
`${opts.prefix} projectId "${trimmed}" does not match slug ${PROJECT_ID_SLUG_PATTERN.source}; sending anyway \u2014 backend may reject with HTTP 400`
|
|
447
|
-
);
|
|
448
|
-
}
|
|
449
|
-
return trimmed;
|
|
450
|
-
}
|
|
451
|
-
function projectIdHeaders(projectId) {
|
|
452
|
-
return projectId ? { [PROJECT_ID_HEADER]: projectId } : {};
|
|
453
|
-
}
|
|
454
|
-
var DEFAULT_REDACT_ATTRIBUTE_KEYS = [
|
|
455
|
-
"ai.request.providerOptions",
|
|
456
|
-
"ai.response.providerMetadata"
|
|
457
|
-
];
|
|
458
|
-
new Set(DEFAULT_REDACT_ATTRIBUTE_KEYS);
|
|
459
|
-
globalThis.RAINDROP_ASYNC_LOCAL_STORAGE = async_hooks.AsyncLocalStorage;
|
|
460
|
-
var SUPPRESS_TRACING_KEY = /* @__PURE__ */ Symbol.for(
|
|
461
|
-
"OpenTelemetry SDK Context Key SUPPRESS_TRACING"
|
|
462
|
-
);
|
|
463
|
-
function findOtelContextManager() {
|
|
464
|
-
var _a;
|
|
465
|
-
for (const sym of Object.getOwnPropertySymbols(globalThis)) {
|
|
466
|
-
if (!((_a = sym.description) == null ? void 0 : _a.startsWith("opentelemetry.js.api."))) continue;
|
|
467
|
-
const api = globalThis[sym];
|
|
468
|
-
const cm = api == null ? void 0 : api.context;
|
|
469
|
-
if (cm && typeof cm.with === "function" && typeof cm.active === "function") {
|
|
470
|
-
return cm;
|
|
989
|
+
const tp = provider;
|
|
990
|
+
if (typeof tp.addSpanProcessor !== "function") {
|
|
991
|
+
return false;
|
|
471
992
|
}
|
|
993
|
+
tp.addSpanProcessor(createEveTurnSpanProcessor());
|
|
994
|
+
installState.installed = true;
|
|
995
|
+
return true;
|
|
996
|
+
} catch {
|
|
997
|
+
return false;
|
|
472
998
|
}
|
|
473
|
-
return void 0;
|
|
474
|
-
}
|
|
475
|
-
function installTracingSuppressionHook() {
|
|
476
|
-
if (typeof globalThis.RAINDROP_SUPPRESS_TRACING === "function") return;
|
|
477
|
-
const hook = (fn) => {
|
|
478
|
-
const cm = findOtelContextManager();
|
|
479
|
-
if (!cm) return fn();
|
|
480
|
-
return cm.with(cm.active().setValue(SUPPRESS_TRACING_KEY, true), fn);
|
|
481
|
-
};
|
|
482
|
-
globalThis.RAINDROP_SUPPRESS_TRACING = hook;
|
|
483
999
|
}
|
|
484
|
-
|
|
1000
|
+
var installState = { installed: false };
|
|
485
1001
|
|
|
486
1002
|
// src/internal/limits.ts
|
|
487
1003
|
var DEFAULT_MAX_TEXT_FIELD_CHARS2 = 1e6;
|
|
@@ -509,6 +1025,13 @@ function truncateText(value, limit) {
|
|
|
509
1025
|
}
|
|
510
1026
|
|
|
511
1027
|
// src/internal/exporter.ts
|
|
1028
|
+
var EVE_APP_GIT_OWNER_PREFIX = "eve-trace";
|
|
1029
|
+
var MAX_EVE_APP_GIT_ACTIVE_EVENTS = 1e4;
|
|
1030
|
+
var APP_GIT_KEYS2 = [
|
|
1031
|
+
"raindrop.app.commit_sha",
|
|
1032
|
+
"raindrop.app.commit_dirty",
|
|
1033
|
+
"raindrop.app.branch"
|
|
1034
|
+
];
|
|
512
1035
|
function hexToBase64(hex) {
|
|
513
1036
|
if (!hex) return void 0;
|
|
514
1037
|
if (hex.length === 0 || /^0+$/.test(hex)) return void 0;
|
|
@@ -561,6 +1084,45 @@ function attributesToKeyValues(attrs, maxChars) {
|
|
|
561
1084
|
}
|
|
562
1085
|
return out;
|
|
563
1086
|
}
|
|
1087
|
+
function eventIdFromAttributes(attrs) {
|
|
1088
|
+
if (!attrs) return void 0;
|
|
1089
|
+
const value = attrs["raindrop.eventId"] ?? attrs["ai.telemetry.metadata.raindrop.eventId"] ?? attrs["traceloop.association.properties.event_id"];
|
|
1090
|
+
return typeof value === "string" ? value : void 0;
|
|
1091
|
+
}
|
|
1092
|
+
function appGitPropertiesFromReadableAttributes(attrs) {
|
|
1093
|
+
const properties = {};
|
|
1094
|
+
if (!attrs) return properties;
|
|
1095
|
+
for (const key of ["raindrop.app.commit_sha", "raindrop.app.commit_dirty", "raindrop.app.branch"]) {
|
|
1096
|
+
for (const attributeKey of [key, `ai.telemetry.metadata.${key}`, `traceloop.association.properties.${key}`]) {
|
|
1097
|
+
if (Object.prototype.hasOwnProperty.call(attrs, attributeKey)) {
|
|
1098
|
+
properties[key] = attrs[attributeKey];
|
|
1099
|
+
break;
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
return properties;
|
|
1104
|
+
}
|
|
1105
|
+
function appGitExplicitKeys2(properties) {
|
|
1106
|
+
const keys = /* @__PURE__ */ new Set();
|
|
1107
|
+
for (const key of APP_GIT_KEYS2) {
|
|
1108
|
+
if (Object.prototype.hasOwnProperty.call(properties, key)) keys.add(key);
|
|
1109
|
+
}
|
|
1110
|
+
return keys;
|
|
1111
|
+
}
|
|
1112
|
+
function appGitOwnerId(prefix) {
|
|
1113
|
+
try {
|
|
1114
|
+
return `${prefix}:${randomUUID()}`;
|
|
1115
|
+
} catch {
|
|
1116
|
+
return `${prefix}:${Date.now().toString(36)}:${Math.random().toString(36).slice(2)}`;
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
function explicitAppGitSnapshot(context, properties, eventId) {
|
|
1120
|
+
try {
|
|
1121
|
+
return context.snapshotExplicit?.(properties, eventId) ?? properties;
|
|
1122
|
+
} catch {
|
|
1123
|
+
return properties;
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
564
1126
|
function statusFromReadable(span) {
|
|
565
1127
|
const code = span.status?.code;
|
|
566
1128
|
if (code === void 0) return void 0;
|
|
@@ -572,7 +1134,7 @@ function statusFromReadable(span) {
|
|
|
572
1134
|
}
|
|
573
1135
|
return { code: SpanStatusCode.UNSET };
|
|
574
1136
|
}
|
|
575
|
-
function readableSpanToOtlp(span, maxChars) {
|
|
1137
|
+
function readableSpanToOtlp(span, maxChars, appGitContext, operationEventId, appGitOwner, appGitExplicitOnly, startedAppGitSnapshot, startedAppGitExplicitKeys) {
|
|
576
1138
|
const ctx = span.spanContext();
|
|
577
1139
|
const parentSpanIdHex = span.parentSpanContext?.spanId ?? span.parentSpanId;
|
|
578
1140
|
const traceId = hexToBase64(ctx.traceId);
|
|
@@ -583,7 +1145,17 @@ function readableSpanToOtlp(span, maxChars) {
|
|
|
583
1145
|
);
|
|
584
1146
|
}
|
|
585
1147
|
const parentSpanId = hexToBase64(parentSpanIdHex);
|
|
586
|
-
|
|
1148
|
+
eventIdFromAttributes(span.attributes);
|
|
1149
|
+
const appProperties = appGitPropertiesFromReadableAttributes(span.attributes);
|
|
1150
|
+
const appGitSnapshot = startedAppGitSnapshot !== void 0 ? appGitContext.mergeSnapshot ? appGitContext.mergeSnapshot(startedAppGitSnapshot, appProperties, startedAppGitExplicitKeys) : mergeAppGitSnapshot(startedAppGitSnapshot, appProperties, startedAppGitExplicitKeys) : appGitExplicitOnly ? explicitAppGitSnapshot(appGitContext, appProperties, operationEventId) : appGitContext.forOperation(
|
|
1151
|
+
operationEventId,
|
|
1152
|
+
appProperties,
|
|
1153
|
+
operationEventId ? appGitOwner : void 0
|
|
1154
|
+
);
|
|
1155
|
+
const attrs = withAppGitAttributes(
|
|
1156
|
+
attributesToKeyValues(span.attributes, maxChars),
|
|
1157
|
+
appGitSnapshot
|
|
1158
|
+
).filter((attribute) => attribute !== void 0);
|
|
587
1159
|
const otlp = {
|
|
588
1160
|
traceId,
|
|
589
1161
|
spanId,
|
|
@@ -598,7 +1170,10 @@ function readableSpanToOtlp(span, maxChars) {
|
|
|
598
1170
|
return otlp;
|
|
599
1171
|
}
|
|
600
1172
|
var RaindropEveSpanExporter = class {
|
|
601
|
-
constructor(opts = {}) {
|
|
1173
|
+
constructor(opts = {}, appGitContext) {
|
|
1174
|
+
this.startedAppGitSpans = /* @__PURE__ */ new WeakMap();
|
|
1175
|
+
this.activeAppGitEvents = /* @__PURE__ */ new Map();
|
|
1176
|
+
this.appGitOwner = appGitOwnerId(EVE_APP_GIT_OWNER_PREFIX);
|
|
602
1177
|
this.inFlight = /* @__PURE__ */ new Set();
|
|
603
1178
|
this.shuttingDown = false;
|
|
604
1179
|
this.auxShutdowns = [];
|
|
@@ -616,6 +1191,10 @@ var RaindropEveSpanExporter = class {
|
|
|
616
1191
|
});
|
|
617
1192
|
const explicit = opts.localWorkshopUrl === false ? null : opts.localWorkshopUrl;
|
|
618
1193
|
this.localDebuggerUrl = resolveLocalDebuggerBaseUrl(explicit) ?? void 0;
|
|
1194
|
+
this.appGitContext = appGitContext ?? createAppGitContext(
|
|
1195
|
+
this.writeKey || this.localDebuggerUrl ? opts.appGit : false,
|
|
1196
|
+
{ allowLocalGit: false }
|
|
1197
|
+
);
|
|
619
1198
|
if (this.debug) {
|
|
620
1199
|
console.log(
|
|
621
1200
|
`${this.prefix} Initialized`,
|
|
@@ -630,6 +1209,55 @@ var RaindropEveSpanExporter = class {
|
|
|
630
1209
|
hasDestinations() {
|
|
631
1210
|
return Boolean(this.writeKey || this.localDebuggerUrl);
|
|
632
1211
|
}
|
|
1212
|
+
captureSpanStart(span) {
|
|
1213
|
+
if (this.startedAppGitSpans.has(span)) return;
|
|
1214
|
+
const eventId = eventIdFromAttributes(span.attributes);
|
|
1215
|
+
const appProperties = appGitPropertiesFromReadableAttributes(span.attributes);
|
|
1216
|
+
const snapshot = this.appGitContext.forOperation(
|
|
1217
|
+
eventId,
|
|
1218
|
+
appProperties,
|
|
1219
|
+
eventId ? this.appGitOwner : void 0
|
|
1220
|
+
);
|
|
1221
|
+
if (!eventId) {
|
|
1222
|
+
this.startedAppGitSpans.set(span, {
|
|
1223
|
+
eventId: void 0,
|
|
1224
|
+
snapshot,
|
|
1225
|
+
explicitKeys: appGitExplicitKeys2(appProperties)
|
|
1226
|
+
});
|
|
1227
|
+
return;
|
|
1228
|
+
}
|
|
1229
|
+
const tracksAppGit = this.activeAppGitEvents.has(eventId) || this.activeAppGitEvents.size < MAX_EVE_APP_GIT_ACTIVE_EVENTS;
|
|
1230
|
+
if (tracksAppGit) {
|
|
1231
|
+
this.activeAppGitEvents.set(eventId, (this.activeAppGitEvents.get(eventId) ?? 0) + 1);
|
|
1232
|
+
this.startedAppGitSpans.set(span, {
|
|
1233
|
+
eventId,
|
|
1234
|
+
snapshot,
|
|
1235
|
+
explicitKeys: appGitExplicitKeys2(appProperties)
|
|
1236
|
+
});
|
|
1237
|
+
} else {
|
|
1238
|
+
this.appGitContext.releaseOperation?.(eventId, this.appGitOwner);
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
releaseStartedAppGitSpan(span, eventId) {
|
|
1242
|
+
const started = this.startedAppGitSpans.get(span);
|
|
1243
|
+
const startedEventId = started?.eventId;
|
|
1244
|
+
this.startedAppGitSpans.delete(span);
|
|
1245
|
+
const trackedEventId = startedEventId ?? eventId;
|
|
1246
|
+
if (!trackedEventId || !this.appGitContext.releaseOperation) return;
|
|
1247
|
+
if (!startedEventId) {
|
|
1248
|
+
if (!this.activeAppGitEvents.has(trackedEventId)) {
|
|
1249
|
+
this.appGitContext.releaseOperation(trackedEventId, this.appGitOwner);
|
|
1250
|
+
}
|
|
1251
|
+
return;
|
|
1252
|
+
}
|
|
1253
|
+
const remaining = (this.activeAppGitEvents.get(startedEventId) ?? 1) - 1;
|
|
1254
|
+
if (remaining > 0) {
|
|
1255
|
+
this.activeAppGitEvents.set(startedEventId, remaining);
|
|
1256
|
+
return;
|
|
1257
|
+
}
|
|
1258
|
+
this.activeAppGitEvents.delete(startedEventId);
|
|
1259
|
+
this.appGitContext.releaseOperation(startedEventId, this.appGitOwner);
|
|
1260
|
+
}
|
|
633
1261
|
/**
|
|
634
1262
|
* Update the OTLP `service.name` attribute. Called by Eve's
|
|
635
1263
|
* `setup({ agentName })` so the resource attribute reflects the actual
|
|
@@ -654,12 +1282,28 @@ var RaindropEveSpanExporter = class {
|
|
|
654
1282
|
const maxChars = effectiveAttributeLimit(this.maxTextFieldChars);
|
|
655
1283
|
const otlpSpans = [];
|
|
656
1284
|
for (const span of spans) {
|
|
1285
|
+
const eventId = eventIdFromAttributes(span.attributes);
|
|
1286
|
+
const startedAppGit = this.startedAppGitSpans.get(span);
|
|
1287
|
+
const appGitExplicitOnly = startedAppGit === void 0;
|
|
657
1288
|
try {
|
|
658
|
-
otlpSpans.push(
|
|
1289
|
+
otlpSpans.push(
|
|
1290
|
+
readableSpanToOtlp(
|
|
1291
|
+
span,
|
|
1292
|
+
maxChars,
|
|
1293
|
+
this.appGitContext,
|
|
1294
|
+
startedAppGit?.eventId ?? eventId,
|
|
1295
|
+
this.appGitOwner,
|
|
1296
|
+
appGitExplicitOnly,
|
|
1297
|
+
startedAppGit?.eventId ? void 0 : startedAppGit?.snapshot,
|
|
1298
|
+
startedAppGit?.eventId ? void 0 : startedAppGit?.explicitKeys
|
|
1299
|
+
)
|
|
1300
|
+
);
|
|
659
1301
|
} catch (err) {
|
|
660
1302
|
if (this.debug) {
|
|
661
1303
|
console.warn(`${this.prefix} failed to convert span`, err);
|
|
662
1304
|
}
|
|
1305
|
+
} finally {
|
|
1306
|
+
this.releaseStartedAppGitSpan(span, eventId);
|
|
663
1307
|
}
|
|
664
1308
|
}
|
|
665
1309
|
if (otlpSpans.length === 0) {
|
|
@@ -711,11 +1355,18 @@ var RaindropEveSpanExporter = class {
|
|
|
711
1355
|
}
|
|
712
1356
|
async shutdown() {
|
|
713
1357
|
this.shuttingDown = true;
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
1358
|
+
try {
|
|
1359
|
+
await this.forceFlush();
|
|
1360
|
+
await Promise.all(
|
|
1361
|
+
this.auxShutdowns.map((fn) => fn().catch(() => {
|
|
1362
|
+
}))
|
|
1363
|
+
);
|
|
1364
|
+
} finally {
|
|
1365
|
+
try {
|
|
1366
|
+
this.appGitContext.dispose();
|
|
1367
|
+
} catch {
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
719
1370
|
}
|
|
720
1371
|
/**
|
|
721
1372
|
* Register an extra teardown hook to run during {@link shutdown}. Used to
|
|
@@ -728,11 +1379,44 @@ var RaindropEveSpanExporter = class {
|
|
|
728
1379
|
this.auxShutdowns.push(fn);
|
|
729
1380
|
}
|
|
730
1381
|
};
|
|
1382
|
+
function installEveAppGitSpanProcessor(traceApi, exporter) {
|
|
1383
|
+
try {
|
|
1384
|
+
let provider = traceApi.getTracerProvider();
|
|
1385
|
+
if (provider === null || typeof provider !== "object" && typeof provider !== "function") return false;
|
|
1386
|
+
if ("getDelegate" in provider && typeof provider.getDelegate === "function") {
|
|
1387
|
+
const delegate = provider.getDelegate();
|
|
1388
|
+
if (delegate) provider = delegate;
|
|
1389
|
+
}
|
|
1390
|
+
if (provider === null || typeof provider !== "object" && typeof provider !== "function" || !("addSpanProcessor" in provider) || typeof provider.addSpanProcessor !== "function") return false;
|
|
1391
|
+
provider.addSpanProcessor(createEveAppGitSpanProcessor(exporter));
|
|
1392
|
+
return true;
|
|
1393
|
+
} catch {
|
|
1394
|
+
return false;
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1397
|
+
function createEveAppGitSpanProcessor(exporter) {
|
|
1398
|
+
return {
|
|
1399
|
+
onStart(span) {
|
|
1400
|
+
try {
|
|
1401
|
+
exporter.captureSpanStart(span);
|
|
1402
|
+
} catch {
|
|
1403
|
+
}
|
|
1404
|
+
},
|
|
1405
|
+
onEnd() {
|
|
1406
|
+
},
|
|
1407
|
+
forceFlush() {
|
|
1408
|
+
return Promise.resolve();
|
|
1409
|
+
},
|
|
1410
|
+
shutdown() {
|
|
1411
|
+
return Promise.resolve();
|
|
1412
|
+
}
|
|
1413
|
+
};
|
|
1414
|
+
}
|
|
731
1415
|
|
|
732
1416
|
// package.json
|
|
733
1417
|
var package_default = {
|
|
734
1418
|
name: "@raindrop-ai/eve",
|
|
735
|
-
version: "0.0.
|
|
1419
|
+
version: "0.0.24"};
|
|
736
1420
|
|
|
737
1421
|
// src/internal/version.ts
|
|
738
1422
|
var libraryName = package_default.name;
|
|
@@ -1014,18 +1698,21 @@ function buildEveStepStartedResolver(opts, staticMetadata) {
|
|
|
1014
1698
|
};
|
|
1015
1699
|
}
|
|
1016
1700
|
function buildEveMetadataConfig(opts, staticMetadata) {
|
|
1017
|
-
const
|
|
1018
|
-
return { "step.started": (input) =>
|
|
1701
|
+
const resolve2 = buildEveStepStartedResolver(opts, staticMetadata);
|
|
1702
|
+
return { "step.started": (input) => resolve2(input) };
|
|
1019
1703
|
}
|
|
1020
1704
|
function buildEveEventsConfig(opts, staticMetadata) {
|
|
1021
|
-
const
|
|
1022
|
-
return { "step.started": (input) => ({ runtimeContext:
|
|
1705
|
+
const resolve2 = buildEveStepStartedResolver(opts, staticMetadata);
|
|
1706
|
+
return { "step.started": (input) => ({ runtimeContext: resolve2(input) }) };
|
|
1023
1707
|
}
|
|
1024
1708
|
function defineRaindropInstrumentation(opts = {}) {
|
|
1025
1709
|
const debug = opts.debug === true || envDebug();
|
|
1026
1710
|
const writeKey = opts.writeKey ?? envWriteKey();
|
|
1027
1711
|
const endpoint = opts.endpoint ?? envEndpoint();
|
|
1028
1712
|
const projectId = opts.projectId ?? envProjectId();
|
|
1713
|
+
const localWorkshopInput = opts.localWorkshopUrl === false ? null : opts.localWorkshopUrl;
|
|
1714
|
+
const hasDestination = Boolean(writeKey?.trim()) || Boolean(resolveLocalDebuggerBaseUrl(localWorkshopInput));
|
|
1715
|
+
const appGitContext = createAppGitContext(hasDestination ? opts.appGit : false, { allowLocalGit: false });
|
|
1029
1716
|
const exporter = new RaindropEveSpanExporter({
|
|
1030
1717
|
writeKey,
|
|
1031
1718
|
endpoint,
|
|
@@ -1036,7 +1723,7 @@ function defineRaindropInstrumentation(opts = {}) {
|
|
|
1036
1723
|
sdkName: "eve",
|
|
1037
1724
|
debug,
|
|
1038
1725
|
maxTextFieldChars: opts.maxTextFieldChars
|
|
1039
|
-
});
|
|
1726
|
+
}, appGitContext);
|
|
1040
1727
|
const localWorkshopUrl = opts.localWorkshopUrl === false ? false : opts.localWorkshopUrl;
|
|
1041
1728
|
const raindrop = aiSdk.createRaindropAISDK({
|
|
1042
1729
|
writeKey,
|
|
@@ -1044,7 +1731,8 @@ function defineRaindropInstrumentation(opts = {}) {
|
|
|
1044
1731
|
projectId,
|
|
1045
1732
|
localWorkshopUrl,
|
|
1046
1733
|
events: { debug },
|
|
1047
|
-
traces: { debug }
|
|
1734
|
+
traces: { debug },
|
|
1735
|
+
appGitContext
|
|
1048
1736
|
});
|
|
1049
1737
|
exporter.attachAuxShutdown(() => raindrop.shutdown());
|
|
1050
1738
|
const prefix = "[raindrop-ai/eve]";
|
|
@@ -1073,8 +1761,13 @@ function defineRaindropInstrumentation(opts = {}) {
|
|
|
1073
1761
|
if (already === void 0) {
|
|
1074
1762
|
opts.registerOTel({
|
|
1075
1763
|
serviceName,
|
|
1076
|
-
traceExporter: exporter
|
|
1764
|
+
traceExporter: exporter,
|
|
1765
|
+
spanProcessors: [
|
|
1766
|
+
"auto",
|
|
1767
|
+
createEveAppGitSpanProcessor(exporter)
|
|
1768
|
+
]
|
|
1077
1769
|
});
|
|
1770
|
+
installEveAppGitSpanProcessor(api.trace, exporter);
|
|
1078
1771
|
g[RAINDROP_EVE_OTEL_REGISTERED] = { exporter };
|
|
1079
1772
|
if (debug) {
|
|
1080
1773
|
console.log(`${prefix} registered OTel for serviceName=${serviceName}`);
|
|
@@ -1122,6 +1815,7 @@ exports.RAINDROP_EVE_SDK_NAME = RAINDROP_EVE_SDK_NAME;
|
|
|
1122
1815
|
exports.RAINDROP_EVE_SDK_VERSION = RAINDROP_EVE_SDK_VERSION;
|
|
1123
1816
|
exports.RaindropEveSpanExporter = RaindropEveSpanExporter;
|
|
1124
1817
|
exports._resetCanonicalTurnIds = _resetCanonicalTurnIds;
|
|
1818
|
+
exports.createEveAppGitSpanProcessor = createEveAppGitSpanProcessor;
|
|
1125
1819
|
exports.default = index_default;
|
|
1126
1820
|
exports.defineRaindropInstrumentation = defineRaindropInstrumentation;
|
|
1127
1821
|
//# sourceMappingURL=index.js.map
|