@raindrop-ai/openai-managed-agents 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,2958 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ RaindropManagedAgentsHandler: () => RaindropManagedAgentsHandler,
24
+ createRaindropOpenAIManagedAgents: () => createRaindropOpenAIManagedAgents
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+
28
+ // ../core/dist/chunk-BYBMRLZM.js
29
+ var EVAL_CORRELATION_ID_ATTRIBUTE = "raindrop.eval_correlation_id";
30
+ var PROBE_SCOPE = { correlationId: "" };
31
+ var EvalScopeStorage = class {
32
+ constructor() {
33
+ this._als = null;
34
+ this._probed = false;
35
+ }
36
+ maybeAdoptAsyncLocalStorage() {
37
+ if (this._probed) return;
38
+ this._probed = true;
39
+ try {
40
+ const Ctor = globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
41
+ if (!Ctor) return;
42
+ const als = new Ctor();
43
+ als.run(PROBE_SCOPE, () => {
44
+ });
45
+ this._als = als;
46
+ } catch (e) {
47
+ this._als = null;
48
+ }
49
+ }
50
+ run(scope, callback) {
51
+ this.maybeAdoptAsyncLocalStorage();
52
+ if (this._als) return this._als.run(scope, callback);
53
+ const previous = this._syncScope;
54
+ this._syncScope = scope;
55
+ try {
56
+ return callback();
57
+ } finally {
58
+ this._syncScope = previous;
59
+ }
60
+ }
61
+ current() {
62
+ this.maybeAdoptAsyncLocalStorage();
63
+ if (this._als) return this._als.getStore();
64
+ return this._syncScope;
65
+ }
66
+ };
67
+ var EVAL_SCOPE_STORAGE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.evalScopeStorage");
68
+ function evalScopeStorage() {
69
+ const holder = globalThis;
70
+ let storage = holder[EVAL_SCOPE_STORAGE_KEY];
71
+ if (!storage) {
72
+ storage = new EvalScopeStorage();
73
+ holder[EVAL_SCOPE_STORAGE_KEY] = storage;
74
+ }
75
+ return storage;
76
+ }
77
+ function currentEvalScope() {
78
+ try {
79
+ return evalScopeStorage().current();
80
+ } catch (e) {
81
+ return void 0;
82
+ }
83
+ }
84
+ function evalScopeAttributes() {
85
+ const scope = currentEvalScope();
86
+ if (!scope) return {};
87
+ return { [EVAL_CORRELATION_ID_ATTRIBUTE]: scope.correlationId };
88
+ }
89
+
90
+ // ../core/dist/chunk-WJOR6M7H.js
91
+ var STATE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.replayTraceRoutingState");
92
+ function state() {
93
+ const holder = globalThis;
94
+ let current = holder[STATE_KEY];
95
+ if (!current) {
96
+ let storage = null;
97
+ try {
98
+ const Ctor = globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
99
+ if (Ctor) storage = new Ctor();
100
+ } catch (e) {
101
+ storage = null;
102
+ }
103
+ current = {
104
+ storage,
105
+ syncDestination: void 0,
106
+ spanDestinations: /* @__PURE__ */ new WeakMap()
107
+ };
108
+ holder[STATE_KEY] = current;
109
+ }
110
+ return current;
111
+ }
112
+ function currentReplayTraceDestination() {
113
+ var _a, _b;
114
+ const routing = state();
115
+ return (_b = (_a = routing.storage) == null ? void 0 : _a.getStore()) != null ? _b : routing.syncDestination;
116
+ }
117
+ function rememberReplayTraceDestination(span) {
118
+ const destination = currentReplayTraceDestination();
119
+ if (destination) state().spanDestinations.set(span, destination);
120
+ }
121
+ function copyReplayTraceDestination(source, target) {
122
+ const destination = state().spanDestinations.get(source);
123
+ if (destination) state().spanDestinations.set(target, destination);
124
+ }
125
+ function replayTraceDestinationFor(value) {
126
+ if (typeof value !== "object" && typeof value !== "function" || value === null) {
127
+ return void 0;
128
+ }
129
+ return state().spanDestinations.get(value);
130
+ }
131
+ function recordReplayExportedSpan(destination, spanId, traceId) {
132
+ var _a, _b;
133
+ if (!destination || !spanId || !traceId) return;
134
+ (_a = destination.exportedSpanIds) == null ? void 0 : _a.add(spanId);
135
+ (_b = destination.exportedTraceIds) == null ? void 0 : _b.add(traceId);
136
+ }
137
+ function replayTraceUrl(baseUrl) {
138
+ return `${baseUrl.replace(/\/+$/, "")}/v1/traces`;
139
+ }
140
+ function getAsyncLocalStorageCtor() {
141
+ return globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
142
+ }
143
+ var MAX_BINDING_STACK = 128;
144
+ var EMPTY_STACK = [];
145
+ var ContextStackStorage = class {
146
+ /** Emitted once when this runtime cannot support an ambient push. */
147
+ constructor(noAmbientBindWarning) {
148
+ this.noAmbientBindWarning = noAmbientBindWarning;
149
+ this._als = null;
150
+ this._enterWithUsable = false;
151
+ this._syncStack = EMPTY_STACK;
152
+ this._adoptionChecked = false;
153
+ this._warnedNoAmbientBind = false;
154
+ }
155
+ maybeAdoptAsyncLocalStorage() {
156
+ if (this._adoptionChecked) return;
157
+ this._adoptionChecked = true;
158
+ const Ctor = getAsyncLocalStorageCtor();
159
+ if (!Ctor) return;
160
+ const als = new Ctor();
161
+ try {
162
+ als.run(EMPTY_STACK, () => {
163
+ });
164
+ } catch (e) {
165
+ return;
166
+ }
167
+ this._als = als;
168
+ if (typeof als.enterWith === "function") {
169
+ try {
170
+ als.enterWith(EMPTY_STACK);
171
+ this._enterWithUsable = true;
172
+ } catch (e) {
173
+ this._enterWithUsable = false;
174
+ }
175
+ }
176
+ }
177
+ getStack() {
178
+ var _a;
179
+ this.maybeAdoptAsyncLocalStorage();
180
+ if (this._als) return (_a = this._als.getStore()) != null ? _a : this._syncStack;
181
+ return this._syncStack;
182
+ }
183
+ /**
184
+ * Persist an ambient stack mutation. Returns false when an ALS is adopted but
185
+ * `enterWith` is unusable (workerd): callers must NOT fall back to the
186
+ * process-shared sync stack, since concurrent isolates would cross-stamp.
187
+ */
188
+ setAmbientStack(stack) {
189
+ if (this._als) {
190
+ if (!this._enterWithUsable) return false;
191
+ this._als.enterWith(stack);
192
+ return true;
193
+ }
194
+ this._syncStack = stack;
195
+ return true;
196
+ }
197
+ push(binding) {
198
+ this.maybeAdoptAsyncLocalStorage();
199
+ if (this._als && !this._enterWithUsable) {
200
+ this.warnNoAmbientBindOnce();
201
+ return;
202
+ }
203
+ let stack = this.getStack();
204
+ if (stack.length >= MAX_BINDING_STACK) {
205
+ stack = stack.filter((b) => b.isLive());
206
+ if (stack.length >= MAX_BINDING_STACK) {
207
+ stack = stack.slice(stack.length - (MAX_BINDING_STACK - 1));
208
+ }
209
+ }
210
+ this.setAmbientStack([...stack, binding]);
211
+ }
212
+ remove(binding) {
213
+ binding.markDead();
214
+ const stack = this.getStack();
215
+ const pruned = stack.filter((b) => b !== binding && b.isLive());
216
+ if (pruned.length !== stack.length) {
217
+ this.setAmbientStack(pruned);
218
+ }
219
+ }
220
+ runWith(binding, callback) {
221
+ this.maybeAdoptAsyncLocalStorage();
222
+ if (this._als) {
223
+ return this._als.run([...this.getStack(), binding], callback);
224
+ }
225
+ const previous = this._syncStack;
226
+ this._syncStack = [...previous, binding];
227
+ try {
228
+ return callback();
229
+ } finally {
230
+ this._syncStack = previous;
231
+ }
232
+ }
233
+ current() {
234
+ const stack = this.getStack();
235
+ if (stack.length === 0) return void 0;
236
+ const top = stack[stack.length - 1];
237
+ if (top.isLive()) return top;
238
+ const pruned = stack.filter((b) => b.isLive());
239
+ this.setAmbientStack(pruned);
240
+ return pruned.length > 0 ? pruned[pruned.length - 1] : void 0;
241
+ }
242
+ warnNoAmbientBindOnce() {
243
+ if (this._warnedNoAmbientBind) return;
244
+ this._warnedNoAmbientBind = true;
245
+ console.warn(this.noAmbientBindWarning);
246
+ }
247
+ };
248
+ 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.";
249
+ var ROUTING_STORAGE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.routingContextStorage");
250
+ function routingStorage() {
251
+ const holder = globalThis;
252
+ let storage = holder[ROUTING_STORAGE_KEY];
253
+ if (!storage) {
254
+ storage = new ContextStackStorage(NO_AMBIENT_ROUTING_BIND_WARNING);
255
+ holder[ROUTING_STORAGE_KEY] = storage;
256
+ }
257
+ return storage;
258
+ }
259
+ function currentRoutingBinding() {
260
+ const bound = routingStorage().current();
261
+ if (!bound) return void 0;
262
+ return {
263
+ projectId: bound.projectId,
264
+ authHint: bound.authHint,
265
+ ...bound.appGit ? { appGit: bound.appGit } : {},
266
+ ...bound.appGitSource ? { appGitSource: bound.appGitSource } : {}
267
+ };
268
+ }
269
+ var APP_COMMIT_SHA = "raindrop.app.commit_sha";
270
+ var APP_COMMIT_DIRTY = "raindrop.app.commit_dirty";
271
+ var APP_BRANCH = "raindrop.app.branch";
272
+ var APP_GIT_KEYS = [APP_COMMIT_SHA, APP_COMMIT_DIRTY, APP_BRANCH];
273
+ var own = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
274
+ function appGitExplicitKeys(properties) {
275
+ const keys = /* @__PURE__ */ new Set();
276
+ if (!properties) return keys;
277
+ for (const key of APP_GIT_KEYS) {
278
+ if (own(properties, key)) keys.add(key);
279
+ }
280
+ return keys;
281
+ }
282
+ function mergeAppGitSnapshot(base, properties, explicitKeys = /* @__PURE__ */ new Set()) {
283
+ try {
284
+ const result = { ...base };
285
+ if (properties && own(properties, APP_COMMIT_SHA) && properties[APP_COMMIT_SHA] !== result[APP_COMMIT_SHA]) {
286
+ if (!explicitKeys.has(APP_COMMIT_DIRTY) && !own(properties, APP_COMMIT_DIRTY)) {
287
+ delete result[APP_COMMIT_DIRTY];
288
+ }
289
+ if (!explicitKeys.has(APP_BRANCH) && !own(properties, APP_BRANCH)) {
290
+ delete result[APP_BRANCH];
291
+ }
292
+ }
293
+ for (const key of APP_GIT_KEYS) {
294
+ if (properties && own(properties, key)) result[key] = properties[key];
295
+ }
296
+ return Object.freeze(result);
297
+ } catch (e) {
298
+ return Object.freeze({});
299
+ }
300
+ }
301
+ function validAppCommitSha(value) {
302
+ if (typeof value !== "string" || value.length > 128) return void 0;
303
+ const cleaned = value.trim();
304
+ return /^(?:[a-fA-F0-9]{40}|[a-fA-F0-9]{64})$/.test(cleaned) ? cleaned.toLowerCase() : void 0;
305
+ }
306
+ function shortString(value) {
307
+ if (typeof value !== "string" || value.length > 1024) return void 0;
308
+ const cleaned = value.trim();
309
+ return cleaned.length > 0 ? cleaned : void 0;
310
+ }
311
+ function flag(value) {
312
+ if (value === true || value === "true" || value === "1") return true;
313
+ if (value === false || value === "false" || value === "0") return false;
314
+ return void 0;
315
+ }
316
+ function environment() {
317
+ try {
318
+ return typeof process === "undefined" ? {} : process.env;
319
+ } catch (e) {
320
+ return {};
321
+ }
322
+ }
323
+ var DEPLOYMENTS = [
324
+ ["VERCEL", "VERCEL_GIT_COMMIT_SHA", "VERCEL_GIT_COMMIT_REF"],
325
+ ["NETLIFY", "COMMIT_REF", "BRANCH"],
326
+ ["RAILWAY_ENVIRONMENT_NAME", "RAILWAY_GIT_COMMIT_SHA", "RAILWAY_GIT_BRANCH"],
327
+ ["RAILWAY_ENVIRONMENT", "RAILWAY_GIT_COMMIT_SHA", "RAILWAY_GIT_BRANCH"],
328
+ ["RENDER", "RENDER_GIT_COMMIT", "RENDER_GIT_BRANCH"],
329
+ ["DYNO", "HEROKU_BUILD_COMMIT", ""],
330
+ ["DYNO", "HEROKU_SLUG_COMMIT", ""],
331
+ ["AWS_APP_ID", "AWS_COMMIT_ID", "AWS_BRANCH"],
332
+ ["WORKERS_CI", "WORKERS_CI_COMMIT_SHA", "WORKERS_CI_BRANCH"]
333
+ ];
334
+ var CI_SOURCES = [
335
+ ["GITHUB_ACTIONS", "GITHUB_SHA", "GITHUB_REF_NAME"],
336
+ ["GITLAB_CI", "CI_COMMIT_SHA", "CI_COMMIT_REF_NAME"],
337
+ ["CIRCLECI", "CIRCLE_SHA1", "CIRCLE_BRANCH"]
338
+ ];
339
+ function detectedSource(env, table, detectBranch) {
340
+ for (const row of table) {
341
+ const [marker, shaKey, branchKey] = row;
342
+ if (!marker || !shaKey || !shortString(env[marker]) || flag(env[marker]) === false) continue;
343
+ const commitSha = validAppCommitSha(env[shaKey]);
344
+ if (commitSha)
345
+ return {
346
+ commitSha,
347
+ ...detectBranch && branchKey ? { branch: shortString(env[branchKey]) } : {}
348
+ };
349
+ }
350
+ return {};
351
+ }
352
+ var AppGitContextImpl = class {
353
+ constructor(options, runtime = {}) {
354
+ this.defaults = {};
355
+ this.explicit = {};
356
+ this.explicitKeys = /* @__PURE__ */ new Set();
357
+ this.disposed = false;
358
+ this.operations = /* @__PURE__ */ new Map();
359
+ this.operationOverflow = false;
360
+ this.detectBranch = false;
361
+ this.disabled = false;
362
+ var _a, _b, _c, _d, _e, _f;
363
+ try {
364
+ if (options === false) {
365
+ this.disabled = true;
366
+ return;
367
+ }
368
+ const opts = options != null ? options : {};
369
+ const env = (_a = runtime.env) != null ? _a : environment();
370
+ const detectBranch = (_c = (_b = flag(opts.detectBranch)) != null ? _b : flag(env.RAINDROP_GIT_DETECT_BRANCH)) != null ? _c : false;
371
+ this.detectBranch = detectBranch;
372
+ const collectBranch = detectBranch || runtime.captureLegacyReplayBranch === true;
373
+ const autoDetect = runtime.allowDiscovery === false ? false : (_e = (_d = flag(opts.autoDetect)) != null ? _d : flag(env.RAINDROP_GIT_AUTO_DETECT)) != null ? _e : true;
374
+ const configuredSha = opts.commitSha;
375
+ const explicitSha = configuredSha === void 0 ? env.RAINDROP_COMMIT_SHA : configuredSha;
376
+ if (explicitSha === null) this.explicit[APP_COMMIT_SHA] = null;
377
+ else if (typeof explicitSha === "string" && validAppCommitSha(explicitSha))
378
+ this.explicit[APP_COMMIT_SHA] = explicitSha;
379
+ const configuredDirty = opts.commitDirty;
380
+ const explicitDirty = configuredDirty === void 0 ? flag(env.RAINDROP_COMMIT_DIRTY) : configuredDirty;
381
+ if (explicitDirty === null || typeof explicitDirty === "boolean")
382
+ this.explicit[APP_COMMIT_DIRTY] = explicitDirty;
383
+ const configuredBranch = opts.branch;
384
+ const explicitBranch = configuredBranch === void 0 ? env.RAINDROP_BRANCH : configuredBranch;
385
+ if (explicitBranch === null) this.explicit[APP_BRANCH] = null;
386
+ else if (typeof explicitBranch === "string" && explicitBranch.length <= 1024)
387
+ this.explicit[APP_BRANCH] = explicitBranch;
388
+ this.explicitKeys = appGitExplicitKeys(this.explicit);
389
+ this.defaults = { ...this.explicit };
390
+ if (!autoDetect || explicitSha !== void 0) return;
391
+ const sourceDirectory = (_f = shortString(opts.sourceDirectory)) != null ? _f : shortString(env.RAINDROP_GIT_SOURCE_DIRECTORY);
392
+ if (runtime.allowLocalGit === false && !sourceDirectory) return;
393
+ const deploy = sourceDirectory ? {} : detectedSource(env, DEPLOYMENTS, collectBranch);
394
+ if (deploy.commitSha) {
395
+ this.accept(deploy);
396
+ return;
397
+ }
398
+ const fallback = sourceDirectory ? {} : detectedSource(env, CI_SOURCES, collectBranch);
399
+ if (runtime.resolveLocal && (runtime.allowLocalGit !== false || sourceDirectory)) {
400
+ this.cancel = runtime.resolveLocal(sourceDirectory, collectBranch, (result) => {
401
+ try {
402
+ if (!this.disposed) this.accept(result.commitSha ? result : fallback);
403
+ } catch (e) {
404
+ }
405
+ });
406
+ } else this.accept(fallback);
407
+ } catch (e) {
408
+ }
409
+ }
410
+ accept(result) {
411
+ const sha = validAppCommitSha(result.commitSha);
412
+ if (!sha) return;
413
+ this.replayBranch = shortString(result.branch);
414
+ this.defaults = {
415
+ [APP_COMMIT_SHA]: sha,
416
+ ...typeof result.commitDirty === "boolean" ? { [APP_COMMIT_DIRTY]: result.commitDirty } : {},
417
+ ...this.detectBranch && this.replayBranch ? { [APP_BRANCH]: this.replayBranch } : {},
418
+ ...this.explicit
419
+ };
420
+ }
421
+ snapshot(properties) {
422
+ var _a;
423
+ try {
424
+ const binding = currentRoutingBinding();
425
+ const base = this.disabled && (binding == null ? void 0 : binding.appGitSource) !== "replay-override" ? {} : (_a = binding == null ? void 0 : binding.appGit) != null ? _a : this.defaults;
426
+ return this.mergeSnapshot(base, properties);
427
+ } catch (e) {
428
+ return Object.freeze({});
429
+ }
430
+ }
431
+ /** Safe defaults when no operation/span start was observed; never infer identity. */
432
+ snapshotExplicit(properties, eventId) {
433
+ try {
434
+ const base = { ...this.explicit };
435
+ const operation = eventId ? this.operations.get(eventId) : void 0;
436
+ if (operation) {
437
+ for (const key of operation.explicitKeys) base[key] = operation.snapshot[key];
438
+ }
439
+ return this.mergeSnapshot(base, properties, new Set(Object.keys(base)));
440
+ } catch (e) {
441
+ return mergeAppGitSnapshot({}, properties);
442
+ }
443
+ }
444
+ /** Existing replay branch reporting stays separate from opt-in event properties. */
445
+ snapshotForReplay() {
446
+ const snapshot = this.snapshot();
447
+ if (this.replayBranch && !own(snapshot, APP_BRANCH) && snapshot[APP_COMMIT_SHA] === this.defaults[APP_COMMIT_SHA]) {
448
+ return Object.freeze({ ...snapshot, [APP_BRANCH]: this.replayBranch });
449
+ }
450
+ return snapshot;
451
+ }
452
+ /** Merge a frozen span snapshot without losing client-authored provenance. */
453
+ mergeSnapshot(base, properties, explicitKeys = this.explicitKeys) {
454
+ return mergeAppGitSnapshot(base, properties, /* @__PURE__ */ new Set([...this.explicitKeys, ...explicitKeys]));
455
+ }
456
+ /** Shippers belonging to one client share this bounded operation registry. */
457
+ forOperation(eventId, properties, owner) {
458
+ if (!eventId) return this.snapshot(properties);
459
+ let operation = this.operations.get(eventId);
460
+ if (!operation) {
461
+ if (this.operations.size >= 1e4) this.operationOverflow = true;
462
+ if (this.operationOverflow) return this.mergeSnapshot({}, properties);
463
+ operation = {
464
+ snapshot: this.snapshot(properties),
465
+ owners: /* @__PURE__ */ new Set(),
466
+ unowned: owner === void 0,
467
+ explicitKeys: appGitExplicitKeys(properties)
468
+ };
469
+ this.operations.set(eventId, operation);
470
+ } else if (properties && APP_GIT_KEYS.some((key) => own(properties, key))) {
471
+ const explicitKeys = /* @__PURE__ */ new Set([...this.explicitKeys, ...operation.explicitKeys]);
472
+ operation.snapshot = this.mergeSnapshot(operation.snapshot, properties, explicitKeys);
473
+ for (const key of appGitExplicitKeys(properties)) operation.explicitKeys.add(key);
474
+ }
475
+ if (!owner) operation.unowned = true;
476
+ if (owner) operation.owners.add(owner);
477
+ return operation.snapshot;
478
+ }
479
+ releaseOperation(eventId, owner) {
480
+ const operation = this.operations.get(eventId);
481
+ if (!operation) return;
482
+ operation.owners.delete(owner);
483
+ if (operation.owners.size === 0 && !operation.unowned) this.operations.delete(eventId);
484
+ }
485
+ finishOperation(eventId) {
486
+ this.operations.delete(eventId);
487
+ }
488
+ dispose() {
489
+ var _a;
490
+ this.disposed = true;
491
+ try {
492
+ (_a = this.cancel) == null ? void 0 : _a.call(this);
493
+ } catch (e) {
494
+ }
495
+ }
496
+ };
497
+ var AppGitContext = AppGitContextImpl;
498
+ function createAppGitContext(options, runtime = {}) {
499
+ return new AppGitContext(options, runtime);
500
+ }
501
+ function withAppGitProperties(properties, snapshot) {
502
+ try {
503
+ const merged = { ...properties };
504
+ for (const key of APP_GIT_KEYS)
505
+ if (!own(merged, key) && own(snapshot, key)) merged[key] = snapshot[key];
506
+ return merged;
507
+ } catch (e) {
508
+ return properties != null ? properties : {};
509
+ }
510
+ }
511
+ function withAppGitAttributes(attributes, snapshot) {
512
+ try {
513
+ const present = new Set(attributes.flatMap((attr) => attr ? [attr.key] : []));
514
+ const added = [];
515
+ for (const key of APP_GIT_KEYS) {
516
+ if (present.has(key) || present.has(`ai.telemetry.metadata.${key}`) || present.has(`traceloop.association.properties.${key}`))
517
+ continue;
518
+ const value = snapshot[key];
519
+ if (typeof value === "string") added.push({ key, value: { stringValue: value } });
520
+ else if (typeof value === "boolean") added.push({ key, value: { boolValue: value } });
521
+ }
522
+ return added.length ? [...attributes, ...added] : attributes;
523
+ } catch (e) {
524
+ return attributes;
525
+ }
526
+ }
527
+ function appGitPropertiesFromAttributes(attributes) {
528
+ var _a, _b, _c;
529
+ const properties = {};
530
+ try {
531
+ for (const attr of attributes) {
532
+ if (!attr) continue;
533
+ for (const key of APP_GIT_KEYS) {
534
+ if (attr.key === key || attr.key === `ai.telemetry.metadata.${key}` || attr.key === `traceloop.association.properties.${key}`) {
535
+ properties[key] = (_c = (_b = (_a = attr.value.stringValue) != null ? _a : attr.value.boolValue) != null ? _b : attr.value.intValue) != null ? _c : null;
536
+ }
537
+ }
538
+ }
539
+ } catch (e) {
540
+ }
541
+ return properties;
542
+ }
543
+ function getCrypto() {
544
+ const c = globalThis.crypto;
545
+ return c;
546
+ }
547
+ function randomBytes(length) {
548
+ const cryptoObj = getCrypto();
549
+ const out = new Uint8Array(length);
550
+ if (cryptoObj && typeof cryptoObj.getRandomValues === "function") {
551
+ cryptoObj.getRandomValues(out);
552
+ return out;
553
+ }
554
+ for (let i = 0; i < out.length; i++) out[i] = Math.floor(Math.random() * 256);
555
+ return out;
556
+ }
557
+ function randomUUID() {
558
+ const cryptoObj = getCrypto();
559
+ if (cryptoObj && typeof cryptoObj.randomUUID === "function") {
560
+ return cryptoObj.randomUUID();
561
+ }
562
+ const b = randomBytes(16);
563
+ b[6] = b[6] & 15 | 64;
564
+ b[8] = b[8] & 63 | 128;
565
+ const hex = [...b].map((x) => x.toString(16).padStart(2, "0")).join("");
566
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
567
+ }
568
+ function base64Encode(bytes) {
569
+ const maybeBuffer = globalThis.Buffer;
570
+ if (maybeBuffer) {
571
+ return maybeBuffer.from(bytes).toString("base64");
572
+ }
573
+ let binary = "";
574
+ for (let i2 = 0; i2 < bytes.length; i2++) {
575
+ binary += String.fromCharCode(bytes[i2]);
576
+ }
577
+ const btoaFn = globalThis.btoa;
578
+ if (typeof btoaFn === "function") return btoaFn(binary);
579
+ const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
580
+ let out = "";
581
+ let i = 0;
582
+ while (i < binary.length) {
583
+ const c1 = binary.charCodeAt(i++) & 255;
584
+ const c2 = i < binary.length ? binary.charCodeAt(i++) & 255 : NaN;
585
+ const c3 = i < binary.length ? binary.charCodeAt(i++) & 255 : NaN;
586
+ const e1 = c1 >> 2;
587
+ const e2 = (c1 & 3) << 4 | (Number.isNaN(c2) ? 0 : c2 >> 4);
588
+ const e3 = Number.isNaN(c2) ? 64 : (c2 & 15) << 2 | (Number.isNaN(c3) ? 0 : c3 >> 6);
589
+ const e4 = Number.isNaN(c3) ? 64 : c3 & 63;
590
+ out += alphabet.charAt(e1);
591
+ out += alphabet.charAt(e2);
592
+ out += e3 === 64 ? "=" : alphabet.charAt(e3);
593
+ out += e4 === 64 ? "=" : alphabet.charAt(e4);
594
+ }
595
+ return out;
596
+ }
597
+ function base64ToHex(value) {
598
+ if (!value) return "";
599
+ const maybeBuffer = globalThis.Buffer;
600
+ if (maybeBuffer) {
601
+ return maybeBuffer.from(value, "base64").toString("hex");
602
+ }
603
+ const atobFn = globalThis.atob;
604
+ if (typeof atobFn !== "function") return "";
605
+ try {
606
+ const binary = atobFn(value);
607
+ let hex = "";
608
+ for (let i = 0; i < binary.length; i++) {
609
+ hex += (binary.charCodeAt(i) & 255).toString(16).padStart(2, "0");
610
+ }
611
+ return hex;
612
+ } catch (e) {
613
+ return "";
614
+ }
615
+ }
616
+ var HANDOFF_ATTRIBUTE_SUFFIXES = {
617
+ mode: "raindrop.handoff.mode",
618
+ childEventId: "raindrop.handoff.childEventId",
619
+ parentEventId: "raindrop.handoff.parentEventId",
620
+ parentSpanId: "raindrop.handoff.parentSpanId",
621
+ name: "raindrop.handoff.name",
622
+ terminal: "raindrop.handoff.terminal",
623
+ agentRole: "raindrop.agent.role"
624
+ };
625
+ var HANDOFF_TERMINAL_PROPERTY_KEY = HANDOFF_ATTRIBUTE_SUFFIXES.terminal;
626
+ var TRACEPARENT_HEADER = "traceparent";
627
+ var BAGGAGE_HEADER = "baggage";
628
+ var HANDOFF_HEADER = "x-raindrop-handoff";
629
+ var UNRESOLVED_CARRIER_WARNING = `[raindrop] resume: headers were supplied but no hand-off carrier was found on them (searched ${HANDOFF_HEADER}, ${TRACEPARENT_HEADER}, ${BAGGAGE_HEADER}). This run reports as an UNLINKED event, and the launcher that dispatched it will stay on "queued" forever because nothing ever references its child. Passing headers means a parent handed off, so no carrier on them is almost certainly a defect: a gateway or proxy stripping ${HANDOFF_HEADER}, a middleware overwriting ${BAGGAGE_HEADER}, a request forwarded without its headers, or a hand-built carrier whose field names do not match. Send every header the launcher's dispatch returned. Logged once per process; pass no headers for a directly-invoked sub-agent to silence it.`;
630
+ function runWithTracingSuppressed(fn) {
631
+ const hook = globalThis.RAINDROP_SUPPRESS_TRACING;
632
+ if (typeof hook !== "function") return fn();
633
+ let started = false;
634
+ try {
635
+ return hook(() => {
636
+ started = true;
637
+ return fn();
638
+ });
639
+ } catch (err) {
640
+ if (started) throw err;
641
+ return fn();
642
+ }
643
+ }
644
+ var DEFAULT_REQUEST_TIMEOUT_MS = 3e4;
645
+ var MAX_RETRY_DELAY_MS = 3e4;
646
+ function wait(ms) {
647
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
648
+ }
649
+ function formatEndpoint(endpoint) {
650
+ if (!endpoint) return void 0;
651
+ return endpoint.endsWith("/") ? endpoint : `${endpoint}/`;
652
+ }
653
+ function redactUrlForLog(url) {
654
+ try {
655
+ const parsed = new URL(url);
656
+ parsed.username = "";
657
+ parsed.password = "";
658
+ parsed.search = "";
659
+ parsed.hash = "";
660
+ return parsed.toString();
661
+ } catch (e) {
662
+ return "<unparseable-url>";
663
+ }
664
+ }
665
+ var RATE_LIMITED_LOG_INTERVAL_MS = 3e4;
666
+ var rateLimitedLogLast = /* @__PURE__ */ new Map();
667
+ function rateLimitedLog(key, log) {
668
+ const now = Date.now();
669
+ const last = rateLimitedLogLast.get(key);
670
+ if (last !== void 0 && now - last < RATE_LIMITED_LOG_INTERVAL_MS) {
671
+ return false;
672
+ }
673
+ rateLimitedLogLast.set(key, now);
674
+ log();
675
+ return true;
676
+ }
677
+ async function raceWithTimeout(promise, timeoutMs) {
678
+ let timer;
679
+ const settledInTime = await Promise.race([
680
+ promise.then(
681
+ () => true,
682
+ () => true
683
+ ),
684
+ new Promise((resolve2) => {
685
+ var _a;
686
+ timer = setTimeout(() => resolve2(false), Math.max(0, timeoutMs));
687
+ (_a = timer.unref) == null ? void 0 : _a.call(timer);
688
+ })
689
+ ]);
690
+ if (timer) clearTimeout(timer);
691
+ return settledInTime;
692
+ }
693
+ function parseRetryAfter(headers) {
694
+ var _a;
695
+ const value = (_a = headers.get("Retry-After")) != null ? _a : headers.get("retry-after");
696
+ if (!value) return void 0;
697
+ const asNumber = Number(value);
698
+ if (value.trim() !== "" && !Number.isNaN(asNumber)) return asNumber * 1e3;
699
+ const asDate = new Date(value).getTime();
700
+ if (!Number.isNaN(asDate)) {
701
+ const delta = asDate - Date.now();
702
+ return delta > 0 ? delta : 0;
703
+ }
704
+ return void 0;
705
+ }
706
+ function getRetryDelayMs(attemptNumber, previousError) {
707
+ if (previousError && typeof previousError === "object" && previousError !== null && "retryAfterMs" in previousError) {
708
+ const v = previousError.retryAfterMs;
709
+ if (typeof v === "number") return Math.min(Math.max(0, v), MAX_RETRY_DELAY_MS);
710
+ }
711
+ if (attemptNumber <= 1) return 0;
712
+ const base = 500;
713
+ const factor = Math.pow(2, attemptNumber - 2);
714
+ return Math.min(base * factor, MAX_RETRY_DELAY_MS);
715
+ }
716
+ async function withRetry(operation, opName, opts) {
717
+ const prefix = opts.sdkName ? `[raindrop-ai/${opts.sdkName}]` : "[raindrop-ai/core]";
718
+ let lastError = void 0;
719
+ for (let attemptNumber = 1; attemptNumber <= opts.maxAttempts; attemptNumber++) {
720
+ if (attemptNumber > 1) {
721
+ const delay = getRetryDelayMs(attemptNumber, lastError);
722
+ if (opts.debug) {
723
+ console.warn(
724
+ `${prefix} ${opName} retry ${attemptNumber}/${opts.maxAttempts} in ${delay}ms`
725
+ );
726
+ }
727
+ if (delay > 0) await wait(delay);
728
+ } else if (opts.debug) {
729
+ console.log(`${prefix} ${opName} attempt ${attemptNumber}/${opts.maxAttempts}`);
730
+ }
731
+ try {
732
+ return await operation();
733
+ } catch (err) {
734
+ lastError = err;
735
+ if (opts.debug) {
736
+ const msg = err instanceof Error ? err.message : String(err);
737
+ console.warn(
738
+ `${prefix} ${opName} attempt ${attemptNumber} failed: ${msg}${attemptNumber === opts.maxAttempts ? " (no more retries)" : ""}`
739
+ );
740
+ }
741
+ if (lastError && typeof lastError === "object" && "retryable" in lastError && !lastError.retryable)
742
+ break;
743
+ if (attemptNumber === opts.maxAttempts) break;
744
+ }
745
+ }
746
+ throw lastError instanceof Error ? lastError : new Error(String(lastError));
747
+ }
748
+ async function postJson(url, body, headers, opts) {
749
+ var _a;
750
+ const opName = `POST ${redactUrlForLog(url)}`;
751
+ const timeoutMs = (_a = opts.timeoutMs) != null ? _a : DEFAULT_REQUEST_TIMEOUT_MS;
752
+ await withRetry(
753
+ async () => {
754
+ const resp = await runWithTracingSuppressed(
755
+ () => fetch(url, {
756
+ method: "POST",
757
+ redirect: headers["X-Raindrop-Replay-Id"] !== void 0 ? "error" : "follow",
758
+ headers: {
759
+ "Content-Type": "application/json",
760
+ ...headers
761
+ },
762
+ body: JSON.stringify(body),
763
+ signal: AbortSignal.timeout(timeoutMs)
764
+ })
765
+ );
766
+ if (!resp.ok) {
767
+ const text = await resp.text().catch(() => "");
768
+ const err = new Error(
769
+ `HTTP ${resp.status} ${resp.statusText}${text ? `: ${text}` : ""}`
770
+ );
771
+ const retryAfterMs = parseRetryAfter(resp.headers);
772
+ if (typeof retryAfterMs === "number") err.retryAfterMs = retryAfterMs;
773
+ err.retryable = resp.status === 429 || resp.status >= 500;
774
+ throw err;
775
+ }
776
+ },
777
+ opName,
778
+ opts
779
+ );
780
+ }
781
+ var DEFAULT_MAX_TEXT_FIELD_CHARS = 1e6;
782
+ var TRUNCATION_MARKER = "...[truncated by raindrop]";
783
+ var BOUNDED_CLONE_MAX_DEPTH = 12;
784
+ var BOUNDED_CLONE_SLACK = 256;
785
+ var currentDefaultMaxTextFieldChars = DEFAULT_MAX_TEXT_FIELD_CHARS;
786
+ function resolveMaxTextFieldChars(value) {
787
+ if (typeof value === "number" && Number.isFinite(value) && value > 0) {
788
+ return Math.floor(value);
789
+ }
790
+ return currentDefaultMaxTextFieldChars;
791
+ }
792
+ function truncateToLimit(text, limit) {
793
+ if (limit > TRUNCATION_MARKER.length) {
794
+ return text.slice(0, limit - TRUNCATION_MARKER.length) + TRUNCATION_MARKER;
795
+ }
796
+ return text.slice(0, Math.max(0, limit));
797
+ }
798
+ function capText(value, limit) {
799
+ if (typeof value !== "string") return value;
800
+ const max = limit != null ? limit : currentDefaultMaxTextFieldChars;
801
+ if (value.length <= max) return value;
802
+ return truncateToLimit(value, max);
803
+ }
804
+ function boundedClone(obj, charBudget) {
805
+ let budget = charBudget;
806
+ const seen = /* @__PURE__ */ new WeakSet();
807
+ const walk = (node, depth) => {
808
+ if (budget <= 0) return TRUNCATION_MARKER;
809
+ if (typeof node === "string") {
810
+ if (node.length > budget) {
811
+ const taken = node.slice(0, Math.max(0, budget)) + TRUNCATION_MARKER;
812
+ budget = 0;
813
+ return taken;
814
+ }
815
+ budget -= Math.max(node.length, 1);
816
+ return node;
817
+ }
818
+ if (node === null || typeof node === "number" || typeof node === "boolean") {
819
+ budget -= 8;
820
+ return node;
821
+ }
822
+ if (typeof node !== "object") {
823
+ budget -= 8;
824
+ return node;
825
+ }
826
+ if (seen.has(node)) return "[CIRCULAR]";
827
+ if (depth >= BOUNDED_CLONE_MAX_DEPTH) {
828
+ budget -= 16;
829
+ return `<max depth>`;
830
+ }
831
+ seen.add(node);
832
+ if (Array.isArray(node)) {
833
+ const out2 = [];
834
+ for (const v of node) {
835
+ if (budget <= 0) {
836
+ out2.push(TRUNCATION_MARKER);
837
+ break;
838
+ }
839
+ out2.push(walk(v, depth + 1));
840
+ }
841
+ return out2;
842
+ }
843
+ if (typeof node.toJSON === "function") {
844
+ budget -= 16;
845
+ return node;
846
+ }
847
+ const out = {};
848
+ for (const k in node) {
849
+ if (!Object.prototype.hasOwnProperty.call(node, k)) continue;
850
+ if (budget <= 0) {
851
+ out["..."] = TRUNCATION_MARKER;
852
+ break;
853
+ }
854
+ const key = walk(k, depth + 1);
855
+ out[key] = walk(node[k], depth + 1);
856
+ }
857
+ return out;
858
+ };
859
+ return walk(obj, 0);
860
+ }
861
+ function stringifyBounded(value, limit) {
862
+ const max = limit != null ? limit : currentDefaultMaxTextFieldChars;
863
+ if (typeof value === "string") {
864
+ return capText(value, max);
865
+ }
866
+ const pruned = boundedClone(value, max + TRUNCATION_MARKER.length + BOUNDED_CLONE_SLACK);
867
+ let json;
868
+ try {
869
+ json = JSON.stringify(pruned);
870
+ } catch (e) {
871
+ json = void 0;
872
+ }
873
+ if (json === void 0) {
874
+ return capText(String(value), max);
875
+ }
876
+ return json.length <= max ? json : truncateToLimit(json, max);
877
+ }
878
+ var SpanStatusCode = {
879
+ UNSET: 0,
880
+ OK: 1,
881
+ ERROR: 2
882
+ };
883
+ function createSpanIds(parent) {
884
+ const traceId = parent ? parent.traceIdB64 : base64Encode(randomBytes(16));
885
+ const spanId = base64Encode(randomBytes(8));
886
+ return {
887
+ traceIdB64: traceId,
888
+ spanIdB64: spanId,
889
+ parentSpanIdB64: parent ? parent.spanIdB64 : void 0
890
+ };
891
+ }
892
+ function nowUnixNanoString() {
893
+ return Date.now().toString() + "000000";
894
+ }
895
+ function attrString(key, value) {
896
+ if (value === void 0) return void 0;
897
+ return { key, value: { stringValue: value } };
898
+ }
899
+ function attrInt(key, value) {
900
+ if (value === void 0) return void 0;
901
+ if (!Number.isFinite(value)) return void 0;
902
+ return { key, value: { intValue: String(Math.trunc(value)) } };
903
+ }
904
+ function attrDouble(key, value) {
905
+ if (value === void 0) return void 0;
906
+ if (!Number.isFinite(value)) return void 0;
907
+ return { key, value: { doubleValue: value } };
908
+ }
909
+ function buildOtlpSpan(args) {
910
+ const attrs = args.attributes.filter((x) => x !== void 0);
911
+ const span = {
912
+ traceId: args.ids.traceIdB64,
913
+ spanId: args.ids.spanIdB64,
914
+ name: args.name,
915
+ startTimeUnixNano: args.startTimeUnixNano,
916
+ endTimeUnixNano: args.endTimeUnixNano
917
+ };
918
+ if (args.ids.parentSpanIdB64) span.parentSpanId = args.ids.parentSpanIdB64;
919
+ if (attrs.length) span.attributes = attrs;
920
+ if (args.status) span.status = args.status;
921
+ return span;
922
+ }
923
+ function buildExportTraceServiceRequest(spans, serviceName = "raindrop.core", serviceVersion = "0.0.0") {
924
+ return {
925
+ resourceSpans: [
926
+ {
927
+ resource: {
928
+ attributes: [{ key: "service.name", value: { stringValue: serviceName } }]
929
+ },
930
+ scopeSpans: [
931
+ {
932
+ scope: { name: serviceName, version: serviceVersion },
933
+ spans
934
+ }
935
+ ]
936
+ }
937
+ ]
938
+ };
939
+ }
940
+ var LOCAL_DEBUGGER_ENV_VAR = "RAINDROP_LOCAL_DEBUGGER";
941
+ var WORKSHOP_ENV_VAR = "RAINDROP_WORKSHOP";
942
+ var DEFAULT_LOCAL_WORKSHOP_URL = "http://localhost:5899/v1/";
943
+ function readEnvVar(name) {
944
+ var _a;
945
+ try {
946
+ const env = (_a = globalThis == null ? void 0 : globalThis.process) == null ? void 0 : _a.env;
947
+ if (env && typeof env[name] === "string" && env[name].length > 0) {
948
+ return env[name];
949
+ }
950
+ } catch (e) {
951
+ }
952
+ return void 0;
953
+ }
954
+ function readWorkshopEnv() {
955
+ const raw = readEnvVar(WORKSHOP_ENV_VAR);
956
+ if (raw === void 0) return void 0;
957
+ const trimmed = raw.trim();
958
+ if (trimmed.length === 0) return void 0;
959
+ if (/^https?:\/\//i.test(trimmed)) return { url: trimmed };
960
+ if (/^(1|true|yes|on)$/i.test(trimmed)) return "enable";
961
+ if (/^(0|false|no|off)$/i.test(trimmed)) return "disable";
962
+ return void 0;
963
+ }
964
+ function isLocalDevHost(hostname) {
965
+ if (!hostname) return false;
966
+ if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "0.0.0.0" || hostname === "::1") {
967
+ return true;
968
+ }
969
+ if (hostname.endsWith(".localhost")) return true;
970
+ return false;
971
+ }
972
+ function readRuntimeHostname() {
973
+ try {
974
+ const loc = globalThis == null ? void 0 : globalThis.location;
975
+ if (loc && typeof loc.hostname === "string" && loc.hostname.length > 0) {
976
+ return loc.hostname;
977
+ }
978
+ } catch (e) {
979
+ }
980
+ return void 0;
981
+ }
982
+ function shouldAutoEnableLocalWorkshop() {
983
+ if (isLocalDevHost(readRuntimeHostname())) return true;
984
+ if (readEnvVar("NODE_ENV") === "development") return true;
985
+ return false;
986
+ }
987
+ function resolveLocalDebuggerBaseUrl(baseUrl) {
988
+ var _a, _b, _c;
989
+ if (baseUrl === null) return null;
990
+ if (typeof baseUrl === "string" && baseUrl.length > 0) {
991
+ return (_a = formatEndpoint(baseUrl)) != null ? _a : null;
992
+ }
993
+ const explicitUrlEnv = readEnvVar(LOCAL_DEBUGGER_ENV_VAR);
994
+ if (explicitUrlEnv) return (_b = formatEndpoint(explicitUrlEnv)) != null ? _b : null;
995
+ const workshopEnv = readWorkshopEnv();
996
+ if (workshopEnv === "disable") return null;
997
+ if (workshopEnv === "enable") return DEFAULT_LOCAL_WORKSHOP_URL;
998
+ if (workshopEnv && "url" in workshopEnv) return (_c = formatEndpoint(workshopEnv.url)) != null ? _c : null;
999
+ if (shouldAutoEnableLocalWorkshop()) return DEFAULT_LOCAL_WORKSHOP_URL;
1000
+ return null;
1001
+ }
1002
+ var LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS = 2e3;
1003
+ function mirrorTraceExportToLocalDebugger(body, options = {}) {
1004
+ var _a;
1005
+ const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
1006
+ if (!baseUrl) return Promise.resolve();
1007
+ return postJson(`${baseUrl}traces`, body, {}, {
1008
+ maxAttempts: 1,
1009
+ debug: (_a = options.debug) != null ? _a : false,
1010
+ sdkName: options.sdkName,
1011
+ timeoutMs: LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS
1012
+ }).catch(() => {
1013
+ });
1014
+ }
1015
+ function mirrorPartialEventToLocalDebugger(event, options = {}) {
1016
+ var _a;
1017
+ const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
1018
+ if (!baseUrl) return Promise.resolve();
1019
+ const headers = options.writeKey ? { Authorization: `Bearer ${options.writeKey}` } : {};
1020
+ return postJson(`${baseUrl}events/track_partial`, event, headers, {
1021
+ maxAttempts: 1,
1022
+ debug: (_a = options.debug) != null ? _a : false,
1023
+ sdkName: options.sdkName,
1024
+ timeoutMs: LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS
1025
+ }).catch(() => {
1026
+ });
1027
+ }
1028
+ var PROJECT_ID_HEADER = "X-Raindrop-Project-Id";
1029
+ var PROJECT_ID_SLUG_PATTERN = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
1030
+ function isValidProjectIdSlug(value) {
1031
+ return PROJECT_ID_SLUG_PATTERN.test(value);
1032
+ }
1033
+ function normalizeProjectId(raw, opts) {
1034
+ if (typeof raw !== "string") return void 0;
1035
+ const trimmed = raw.trim();
1036
+ if (!trimmed) return void 0;
1037
+ if (!isValidProjectIdSlug(trimmed) && opts.debug) {
1038
+ console.warn(
1039
+ `${opts.prefix} projectId "${trimmed}" does not match slug ${PROJECT_ID_SLUG_PATTERN.source}; sending anyway \u2014 backend may reject with HTTP 400`
1040
+ );
1041
+ }
1042
+ return trimmed;
1043
+ }
1044
+ function projectIdHeaders(projectId) {
1045
+ return projectId ? { [PROJECT_ID_HEADER]: projectId } : {};
1046
+ }
1047
+ var SHUTDOWN_DEADLINE_MS = 1e4;
1048
+ var POST_SHUTDOWN_TIMEOUT_MS = 5e3;
1049
+ function appGitOwnerId(prefix) {
1050
+ try {
1051
+ return `${prefix}:${randomUUID()}`;
1052
+ } catch (e) {
1053
+ return `${prefix}:${Date.now().toString(36)}:${Math.random().toString(36).slice(2)}`;
1054
+ }
1055
+ }
1056
+ function mergePatches(target, source) {
1057
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
1058
+ const out = { ...target, ...source };
1059
+ if (target.properties || source.properties) {
1060
+ out.properties = { ...(_a = target.properties) != null ? _a : {}, ...(_b = source.properties) != null ? _b : {} };
1061
+ }
1062
+ if (target.usage || source.usage) {
1063
+ out.usage = { ...(_c = target.usage) != null ? _c : {} };
1064
+ if (((_d = source.usage) == null ? void 0 : _d.promptTokens) !== void 0) {
1065
+ out.usage.promptTokens = source.usage.promptTokens;
1066
+ }
1067
+ if (((_e = source.usage) == null ? void 0 : _e.completionTokens) !== void 0) {
1068
+ out.usage.completionTokens = source.usage.completionTokens;
1069
+ }
1070
+ }
1071
+ if (source.error === void 0) {
1072
+ out.error = target.error;
1073
+ }
1074
+ if (target.featureFlags || source.featureFlags) {
1075
+ out.featureFlags = { ...(_f = target.featureFlags) != null ? _f : {}, ...(_g = source.featureFlags) != null ? _g : {} };
1076
+ }
1077
+ if (target.attachments || source.attachments) {
1078
+ out.attachments = [...(_h = target.attachments) != null ? _h : [], ...(_i = source.attachments) != null ? _i : []];
1079
+ }
1080
+ return out;
1081
+ }
1082
+ function isErrorLike(value) {
1083
+ return value !== null && typeof value === "object";
1084
+ }
1085
+ function eventTelemetryProperties(patch) {
1086
+ var _a, _b;
1087
+ const properties = {};
1088
+ if (((_a = patch.usage) == null ? void 0 : _a.promptTokens) !== void 0 && Number.isFinite(patch.usage.promptTokens)) {
1089
+ properties["ai.usage.prompt_tokens"] = patch.usage.promptTokens;
1090
+ }
1091
+ if (((_b = patch.usage) == null ? void 0 : _b.completionTokens) !== void 0 && Number.isFinite(patch.usage.completionTokens)) {
1092
+ properties["ai.usage.completion_tokens"] = patch.usage.completionTokens;
1093
+ }
1094
+ if (patch.error !== void 0 && patch.error !== null) {
1095
+ const constructorName = patch.error instanceof Error && patch.error.constructor !== Error ? patch.error.constructor.name : void 0;
1096
+ const errorType = patch.error instanceof Error ? patch.error.name && patch.error.name !== "Error" ? patch.error.name : constructorName || patch.error.name || "Error" : isErrorLike(patch.error) && typeof patch.error.name === "string" && patch.error.name.length > 0 ? patch.error.name : "Error";
1097
+ const errorMessage = patch.error instanceof Error ? patch.error.message : isErrorLike(patch.error) && typeof patch.error.message === "string" ? patch.error.message : String(patch.error);
1098
+ properties["error.type"] = errorType;
1099
+ properties["error.message"] = errorMessage;
1100
+ }
1101
+ return properties;
1102
+ }
1103
+ var EventShipper = class {
1104
+ constructor(opts) {
1105
+ this.appGitOwner = appGitOwnerId("event");
1106
+ this.buffers = /* @__PURE__ */ new Map();
1107
+ this.sticky = /* @__PURE__ */ new Map();
1108
+ this.timers = /* @__PURE__ */ new Map();
1109
+ this.inFlight = /* @__PURE__ */ new Set();
1110
+ this.hasShutdown = false;
1111
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
1112
+ this.appGitContext = (_a = opts.appGitContext) != null ? _a : createAppGitContext(opts.appGit);
1113
+ this.ownsAppGitContext = opts.appGitContext === void 0;
1114
+ this.writeKey = (_b = opts.writeKey) == null ? void 0 : _b.trim();
1115
+ this.baseUrl = (_c = formatEndpoint(opts.endpoint)) != null ? _c : "https://api.raindrop.ai/v1/";
1116
+ this.enabled = opts.enabled !== false;
1117
+ this.debug = opts.debug;
1118
+ this.partialFlushMs = (_d = opts.partialFlushMs) != null ? _d : 1e3;
1119
+ this.sdkName = (_e = opts.sdkName) != null ? _e : "core";
1120
+ this.prefix = `[raindrop-ai/${this.sdkName}]`;
1121
+ this.defaultEventName = (_f = opts.defaultEventName) != null ? _f : "ai_generation";
1122
+ this.maxTextFieldCharsOpt = opts.maxTextFieldChars;
1123
+ this.localDebuggerUrl = (_g = resolveLocalDebuggerBaseUrl(opts.localDebuggerUrl)) != null ? _g : void 0;
1124
+ if (this.debug && this.localDebuggerUrl) {
1125
+ console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
1126
+ }
1127
+ this.projectId = normalizeProjectId(opts.projectId, {
1128
+ debug: this.debug,
1129
+ prefix: this.prefix
1130
+ });
1131
+ const isNode = typeof process !== "undefined" && typeof process.version === "string";
1132
+ this.context = {
1133
+ library: {
1134
+ name: (_h = opts.libraryName) != null ? _h : "@raindrop-ai/core",
1135
+ version: (_i = opts.libraryVersion) != null ? _i : "0.0.0"
1136
+ },
1137
+ metadata: {
1138
+ jsRuntime: isNode ? "node" : "web",
1139
+ ...isNode ? { nodeVersion: process.version } : {}
1140
+ }
1141
+ };
1142
+ }
1143
+ ownAppGitContextForShutdown() {
1144
+ this.ownsAppGitContext = true;
1145
+ }
1146
+ isDebugEnabled() {
1147
+ return this.debug;
1148
+ }
1149
+ authHeaders() {
1150
+ return this.writeKey ? { Authorization: `Bearer ${this.writeKey}` } : {};
1151
+ }
1152
+ requestHeaders() {
1153
+ return { ...this.authHeaders(), ...projectIdHeaders(this.projectId) };
1154
+ }
1155
+ /**
1156
+ * Build the retry/timeout options for one POST, honoring the shutdown
1157
+ * deadline. Returns `null` when the shutdown drain window is exhausted —
1158
+ * the caller must drop the payload (with a rate-limited warning) instead
1159
+ * of issuing a request that could outlive process exit.
1160
+ *
1161
+ * Checked fresh on EVERY send, so a shutdown that begins while the flush
1162
+ * path is mid-drain takes effect immediately: no further retries, and the
1163
+ * per-attempt timeout is clamped to the remaining window. After
1164
+ * `shutdown()` returns (deadline cleared, `hasShutdown` still set),
1165
+ * sends — late callers, or flush work the deadline abandoned mid-drain —
1166
+ * run as a single short attempt rather than regaining the full retry
1167
+ * schedule.
1168
+ */
1169
+ requestOpts() {
1170
+ if (this.shutdownDeadlineAt !== void 0) {
1171
+ const remainingMs = this.shutdownDeadlineAt - Date.now();
1172
+ if (remainingMs <= 0) return null;
1173
+ return {
1174
+ maxAttempts: 1,
1175
+ debug: this.debug,
1176
+ sdkName: this.sdkName,
1177
+ timeoutMs: Math.min(DEFAULT_REQUEST_TIMEOUT_MS, remainingMs)
1178
+ };
1179
+ }
1180
+ if (this.hasShutdown) {
1181
+ return {
1182
+ maxAttempts: 1,
1183
+ debug: this.debug,
1184
+ sdkName: this.sdkName,
1185
+ timeoutMs: POST_SHUTDOWN_TIMEOUT_MS
1186
+ };
1187
+ }
1188
+ return { maxAttempts: 3, debug: this.debug, sdkName: this.sdkName };
1189
+ }
1190
+ async patch(eventId, patch) {
1191
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
1192
+ if (!this.enabled) return;
1193
+ if (!eventId || !eventId.trim()) return;
1194
+ const capturedSticky = this.sticky.get(eventId);
1195
+ const eventAlreadyKnown = capturedSticky !== void 0 || this.buffers.has(eventId);
1196
+ const destination = currentReplayTraceDestination();
1197
+ const cloudReplay = destination !== void 0 && destination.kind !== "workshop";
1198
+ if ((capturedSticky == null ? void 0 : capturedSticky.replayOnly) === true || !eventAlreadyKnown && cloudReplay) {
1199
+ if (patch.isPending === false) this.sticky.delete(eventId);
1200
+ else this.sticky.set(eventId, { ...capturedSticky, replayOnly: true });
1201
+ return;
1202
+ }
1203
+ const maxChars = resolveMaxTextFieldChars(this.maxTextFieldCharsOpt);
1204
+ if (typeof patch.input === "string" && patch.input.length > maxChars) {
1205
+ patch = { ...patch, input: capText(patch.input, maxChars) };
1206
+ }
1207
+ if (typeof patch.output === "string" && patch.output.length > maxChars) {
1208
+ patch = { ...patch, output: capText(patch.output, maxChars) };
1209
+ }
1210
+ if (this.debug) {
1211
+ console.log(`${this.prefix} queue patch`, {
1212
+ eventId,
1213
+ userId: patch.userId,
1214
+ convoId: patch.convoId,
1215
+ eventName: patch.eventName,
1216
+ hasInput: typeof patch.input === "string" && patch.input.length > 0,
1217
+ hasOutput: typeof patch.output === "string" && patch.output.length > 0,
1218
+ attachments: (_b = (_a = patch.attachments) == null ? void 0 : _a.length) != null ? _b : 0,
1219
+ isPending: patch.isPending
1220
+ });
1221
+ }
1222
+ const sticky = (_c = this.sticky.get(eventId)) != null ? _c : {};
1223
+ const existing = (_d = this.buffers.get(eventId)) != null ? _d : {};
1224
+ patch = {
1225
+ ...patch,
1226
+ properties: withAppGitProperties(
1227
+ patch.properties,
1228
+ this.appGitContext.forOperation(eventId, patch.properties, this.appGitOwner)
1229
+ )
1230
+ };
1231
+ const merged = mergePatches(existing, patch);
1232
+ merged.isPending = (_g = (_f = (_e = patch.isPending) != null ? _e : existing.isPending) != null ? _f : sticky.isPending) != null ? _g : true;
1233
+ this.buffers.set(eventId, merged);
1234
+ this.sticky.set(eventId, {
1235
+ userId: (_h = merged.userId) != null ? _h : sticky.userId,
1236
+ convoId: (_i = merged.convoId) != null ? _i : sticky.convoId,
1237
+ eventName: (_j = merged.eventName) != null ? _j : sticky.eventName,
1238
+ isPending: (_k = merged.isPending) != null ? _k : sticky.isPending
1239
+ });
1240
+ const t = this.timers.get(eventId);
1241
+ if (t) clearTimeout(t);
1242
+ if (merged.isPending === false) {
1243
+ await this.flushOne(eventId);
1244
+ if (this.appGitContext.releaseOperation) this.appGitContext.releaseOperation(eventId, this.appGitOwner);
1245
+ else this.appGitContext.finishOperation(eventId);
1246
+ return;
1247
+ }
1248
+ const timeout = setTimeout(() => {
1249
+ void this.flushOne(eventId).catch(() => {
1250
+ });
1251
+ }, this.partialFlushMs);
1252
+ this.timers.set(eventId, timeout);
1253
+ }
1254
+ async finish(eventId, patch) {
1255
+ await this.patch(eventId, { ...patch, isPending: false });
1256
+ }
1257
+ async flush() {
1258
+ if (!this.enabled) return;
1259
+ const ids = [...this.buffers.keys()];
1260
+ await Promise.all(ids.map((id) => this.flushOne(id)));
1261
+ await Promise.all([...this.inFlight].map((p) => p.catch(() => {
1262
+ })));
1263
+ }
1264
+ async shutdown() {
1265
+ this.hasShutdown = true;
1266
+ this.shutdownDeadlineAt = Date.now() + SHUTDOWN_DEADLINE_MS;
1267
+ try {
1268
+ for (const t of this.timers.values()) clearTimeout(t);
1269
+ this.timers.clear();
1270
+ for (const [eventId, sticky] of this.sticky) {
1271
+ if (sticky.replayOnly) this.sticky.delete(eventId);
1272
+ }
1273
+ const settled = await raceWithTimeout(this.flush(), SHUTDOWN_DEADLINE_MS);
1274
+ if (!settled) this.warnShutdownDrop("in-flight request(s) at shutdown");
1275
+ } finally {
1276
+ this.shutdownDeadlineAt = void 0;
1277
+ if (this.ownsAppGitContext) this.appGitContext.dispose();
1278
+ }
1279
+ }
1280
+ async trackSignal(signal) {
1281
+ var _a, _b;
1282
+ if (!this.enabled) return;
1283
+ const destination = currentReplayTraceDestination();
1284
+ if (destination && destination.kind !== "workshop") return;
1285
+ const body = [
1286
+ {
1287
+ event_id: signal.eventId,
1288
+ signal_name: signal.name,
1289
+ signal_type: (_a = signal.type) != null ? _a : "default",
1290
+ timestamp: signal.timestamp,
1291
+ sentiment: signal.sentiment,
1292
+ attachment_id: signal.attachmentId,
1293
+ properties: {
1294
+ ...(_b = signal.properties) != null ? _b : {},
1295
+ ...signal.comment ? { comment: signal.comment } : {},
1296
+ ...signal.after ? { after: signal.after } : {}
1297
+ }
1298
+ }
1299
+ ];
1300
+ if (!this.writeKey) return;
1301
+ const url = `${this.baseUrl}signals/track`;
1302
+ const opts = this.requestOpts();
1303
+ if (!opts) {
1304
+ this.warnShutdownDrop("signal");
1305
+ return;
1306
+ }
1307
+ try {
1308
+ await postJson(url, body, this.requestHeaders(), opts);
1309
+ } catch (err) {
1310
+ const msg = err instanceof Error ? err.message : String(err);
1311
+ rateLimitedLog(
1312
+ `${this.prefix}.send_signal_failed`,
1313
+ () => console.warn(`${this.prefix} failed to send signal (dropping): ${msg}`)
1314
+ );
1315
+ }
1316
+ }
1317
+ async identify(users) {
1318
+ if (!this.enabled) return;
1319
+ const destination = currentReplayTraceDestination();
1320
+ if (destination && destination.kind !== "workshop") return;
1321
+ const list = Array.isArray(users) ? users : [users];
1322
+ const body = list.filter((user) => {
1323
+ if (!(user == null ? void 0 : user.userId) || !user.userId.trim()) {
1324
+ if (this.debug) {
1325
+ console.warn(`${this.prefix} skipping identify: missing userId`);
1326
+ }
1327
+ return false;
1328
+ }
1329
+ return true;
1330
+ }).map((user) => {
1331
+ var _a;
1332
+ return {
1333
+ user_id: user.userId,
1334
+ traits: (_a = user.traits) != null ? _a : {}
1335
+ };
1336
+ });
1337
+ if (!this.writeKey) return;
1338
+ if (body.length === 0) return;
1339
+ const url = `${this.baseUrl}users/identify`;
1340
+ const opts = this.requestOpts();
1341
+ if (!opts) {
1342
+ this.warnShutdownDrop("identify");
1343
+ return;
1344
+ }
1345
+ try {
1346
+ await postJson(url, body, this.requestHeaders(), opts);
1347
+ } catch (err) {
1348
+ const msg = err instanceof Error ? err.message : String(err);
1349
+ rateLimitedLog(
1350
+ `${this.prefix}.send_identify_failed`,
1351
+ () => console.warn(`${this.prefix} failed to send identify (dropping): ${msg}`)
1352
+ );
1353
+ }
1354
+ }
1355
+ warnShutdownDrop(what) {
1356
+ rateLimitedLog(
1357
+ `${this.prefix}.shutdown_deadline`,
1358
+ () => console.warn(`${this.prefix} shutdown flush deadline exceeded; dropping ${what}`)
1359
+ );
1360
+ }
1361
+ async flushOne(eventId) {
1362
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
1363
+ if (!this.enabled) return;
1364
+ const timer = this.timers.get(eventId);
1365
+ if (timer) {
1366
+ clearTimeout(timer);
1367
+ this.timers.delete(eventId);
1368
+ }
1369
+ const accumulated = this.buffers.get(eventId);
1370
+ this.buffers.delete(eventId);
1371
+ if (!accumulated) return;
1372
+ const sticky = (_a = this.sticky.get(eventId)) != null ? _a : {};
1373
+ const isPending = (_c = (_b = accumulated.isPending) != null ? _b : sticky.isPending) != null ? _c : true;
1374
+ const eventName = (_e = (_d = accumulated.eventName) != null ? _d : sticky.eventName) != null ? _e : this.defaultEventName;
1375
+ const userId = (_f = accumulated.userId) != null ? _f : sticky.userId;
1376
+ if (!userId) {
1377
+ if (this.debug) {
1378
+ console.warn(`${this.prefix} skipping track_partial for ${eventId}: missing userId`);
1379
+ }
1380
+ this.sticky.delete(eventId);
1381
+ return;
1382
+ }
1383
+ const { wizardSession, ...restProperties } = (_g = accumulated.properties) != null ? _g : {};
1384
+ let telemetryProperties = {};
1385
+ try {
1386
+ telemetryProperties = eventTelemetryProperties(accumulated);
1387
+ } catch (e) {
1388
+ }
1389
+ const convoId = (_h = accumulated.convoId) != null ? _h : sticky.convoId;
1390
+ const payload = {
1391
+ event_id: eventId,
1392
+ user_id: userId,
1393
+ event: eventName,
1394
+ timestamp: (_i = accumulated.timestamp) != null ? _i : (/* @__PURE__ */ new Date()).toISOString(),
1395
+ ai_data: {
1396
+ input: accumulated.input,
1397
+ output: accumulated.error !== void 0 && accumulated.error !== null ? void 0 : accumulated.output,
1398
+ model: accumulated.model,
1399
+ convo_id: convoId
1400
+ },
1401
+ properties: {
1402
+ ...restProperties,
1403
+ ...telemetryProperties,
1404
+ ...wizardSession ? { "raindrop.wizardSession": wizardSession } : {},
1405
+ $context: this.context
1406
+ },
1407
+ ...accumulated.featureFlags && Object.keys(accumulated.featureFlags).length > 0 ? { feature_flags: accumulated.featureFlags } : {},
1408
+ attachments: accumulated.attachments,
1409
+ is_pending: isPending
1410
+ };
1411
+ const url = `${this.baseUrl}events/track_partial`;
1412
+ if (this.debug) {
1413
+ console.log(`${this.prefix} sending track_partial`, {
1414
+ eventId,
1415
+ eventName,
1416
+ userId,
1417
+ convoId,
1418
+ isPending,
1419
+ inputPreview: typeof accumulated.input === "string" ? accumulated.input.slice(0, 120) : void 0,
1420
+ outputPreview: typeof accumulated.output === "string" ? accumulated.output.slice(0, 120) : void 0,
1421
+ attachments: (_k = (_j = accumulated.attachments) == null ? void 0 : _j.length) != null ? _k : 0,
1422
+ attachmentKinds: (_m = (_l = accumulated.attachments) == null ? void 0 : _l.map((a) => ({
1423
+ type: a.type,
1424
+ role: a.role,
1425
+ name: a.name,
1426
+ valuePreview: a.value.slice(0, 60)
1427
+ }))) != null ? _m : [],
1428
+ endpoint: url
1429
+ });
1430
+ }
1431
+ const mirror = this.localDebuggerUrl ? mirrorPartialEventToLocalDebugger(payload, {
1432
+ baseUrl: this.localDebuggerUrl,
1433
+ writeKey: this.writeKey,
1434
+ debug: this.debug,
1435
+ sdkName: this.sdkName
1436
+ }) : void 0;
1437
+ if (!this.writeKey) {
1438
+ if (!isPending) this.sticky.delete(eventId);
1439
+ if (mirror) await mirror;
1440
+ return;
1441
+ }
1442
+ const opts = this.requestOpts();
1443
+ if (!opts) {
1444
+ this.warnShutdownDrop(`track_partial ${eventId}`);
1445
+ if (!isPending) this.sticky.delete(eventId);
1446
+ if (mirror) await mirror;
1447
+ return;
1448
+ }
1449
+ const p = postJson(url, payload, this.requestHeaders(), opts);
1450
+ const combined = mirror ? Promise.all([mirror, p]).then(() => void 0) : p;
1451
+ this.inFlight.add(combined);
1452
+ try {
1453
+ try {
1454
+ await combined;
1455
+ if (this.debug) {
1456
+ console.log(`${this.prefix} sent track_partial ${eventId} (${eventName})`);
1457
+ }
1458
+ } catch (err) {
1459
+ const msg = err instanceof Error ? err.message : String(err);
1460
+ rateLimitedLog(
1461
+ `${this.prefix}.send_track_partial_failed`,
1462
+ () => console.warn(`${this.prefix} failed to send track_partial (dropping): ${msg}`)
1463
+ );
1464
+ }
1465
+ } finally {
1466
+ this.inFlight.delete(combined);
1467
+ }
1468
+ if (!isPending) {
1469
+ this.sticky.delete(eventId);
1470
+ }
1471
+ }
1472
+ };
1473
+ var MODEL_USAGE_ATTRIBUTES = {
1474
+ usageSource: "raindrop.usage.source",
1475
+ providerName: "gen_ai.provider.name",
1476
+ requestModel: "gen_ai.request.model",
1477
+ responseModel: "gen_ai.response.model",
1478
+ inputTokens: "gen_ai.usage.input_tokens",
1479
+ outputTokens: "gen_ai.usage.output_tokens",
1480
+ reasoningTokens: "gen_ai.usage.reasoning_tokens",
1481
+ cacheReadInputTokens: "gen_ai.usage.cache_read_input_tokens",
1482
+ cacheWriteInputTokens: "gen_ai.usage.cache_write_input_tokens",
1483
+ providerReportedCost: "gen_ai.usage.provider_reported_cost",
1484
+ nonCachedInputTokens: "raindrop.usage.input_tokens.non_cached",
1485
+ nonReasoningOutputTokens: "raindrop.usage.output_tokens.non_reasoning",
1486
+ totalOutputTokens: "raindrop.usage.output_tokens.total",
1487
+ reasoningOutputTokens: "raindrop.usage.output_tokens.reasoning",
1488
+ cacheReadTokens: "raindrop.usage.input_tokens.cache_read",
1489
+ cacheWriteTokens: "raindrop.usage.input_tokens.cache_write"
1490
+ };
1491
+ var MODEL_PROVIDER_NAMES = [
1492
+ ["google.vertex.anthropic", "google-vertex"],
1493
+ ["google.vertex_ai", "google-vertex"],
1494
+ ["google.vertex", "google-vertex"],
1495
+ ["gcp.vertex_ai", "google-vertex"],
1496
+ ["gcp.gemini", "google"],
1497
+ ["google_vertexai", "google-vertex"],
1498
+ ["vertex.anthropic", "google-vertex"],
1499
+ ["amazon-bedrock", "amazon-bedrock"],
1500
+ ["aws.bedrock", "amazon-bedrock"],
1501
+ ["bedrock", "amazon-bedrock"],
1502
+ ["anthropic", "anthropic"],
1503
+ ["openai", "openai"],
1504
+ ["google", "google"],
1505
+ ["az.ai.openai", "azure"],
1506
+ ["azure", "azure"],
1507
+ ["openrouter", "openrouter"]
1508
+ ];
1509
+ function canonicalModelProvider(provider) {
1510
+ var _a;
1511
+ const normalizedProvider = provider.trim().toLowerCase();
1512
+ if (normalizedProvider === "gateway") return "vercel";
1513
+ const match = MODEL_PROVIDER_NAMES.find(
1514
+ ([family]) => normalizedProvider === family || normalizedProvider.startsWith(`${family}.`)
1515
+ );
1516
+ return (_a = match == null ? void 0 : match[1]) != null ? _a : normalizedProvider;
1517
+ }
1518
+ function tokenCount(value) {
1519
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : void 0;
1520
+ }
1521
+ function buildRawModelUsageAttributes(usage) {
1522
+ const providerReportedCost = typeof usage.providerReportedCost === "number" && Number.isFinite(usage.providerReportedCost) && usage.providerReportedCost >= 0 ? usage.providerReportedCost : void 0;
1523
+ return [
1524
+ attrInt(MODEL_USAGE_ATTRIBUTES.inputTokens, tokenCount(usage.inputTokens)),
1525
+ attrInt(MODEL_USAGE_ATTRIBUTES.outputTokens, tokenCount(usage.outputTokens)),
1526
+ attrInt(MODEL_USAGE_ATTRIBUTES.reasoningTokens, tokenCount(usage.reasoningTokens)),
1527
+ attrInt(MODEL_USAGE_ATTRIBUTES.cacheReadInputTokens, tokenCount(usage.cacheReadInputTokens)),
1528
+ attrInt(MODEL_USAGE_ATTRIBUTES.cacheWriteInputTokens, tokenCount(usage.cacheWriteInputTokens)),
1529
+ attrDouble(MODEL_USAGE_ATTRIBUTES.providerReportedCost, providerReportedCost)
1530
+ ].filter((attribute) => attribute !== void 0);
1531
+ }
1532
+ var STRING_ALIASES = {
1533
+ [MODEL_USAGE_ATTRIBUTES.requestModel]: ["ai.model.id", "ai.model"]
1534
+ };
1535
+ var NUMBER_ALIASES = {
1536
+ [MODEL_USAGE_ATTRIBUTES.inputTokens]: [
1537
+ "gen_ai.usage.prompt_tokens",
1538
+ "ai.usage.prompt_tokens",
1539
+ "ai.usage.promptTokens",
1540
+ "ai.usage.input_tokens",
1541
+ "ai.usage.inputTokens"
1542
+ ],
1543
+ [MODEL_USAGE_ATTRIBUTES.outputTokens]: [
1544
+ "gen_ai.usage.completion_tokens",
1545
+ "ai.usage.completion_tokens",
1546
+ "ai.usage.completionTokens",
1547
+ "ai.usage.output_tokens",
1548
+ "ai.usage.outputTokens"
1549
+ ],
1550
+ [MODEL_USAGE_ATTRIBUTES.reasoningTokens]: [
1551
+ "gen_ai.usage.reasoning.output_tokens",
1552
+ "ai.usage.reasoningTokens",
1553
+ "ai.usage.thoughts_tokens"
1554
+ ],
1555
+ [MODEL_USAGE_ATTRIBUTES.cacheReadInputTokens]: [
1556
+ "gen_ai.usage.cache_read_tokens",
1557
+ "gen_ai.usage.cache_read.input_tokens",
1558
+ "ai.usage.cachedInputTokens",
1559
+ "ai.usage.cached_tokens",
1560
+ "ai.usage.cache_read_tokens",
1561
+ "ai.usage.cache_read_input_tokens",
1562
+ "ai.usage.cacheReadInputTokens"
1563
+ ],
1564
+ [MODEL_USAGE_ATTRIBUTES.cacheWriteInputTokens]: [
1565
+ "gen_ai.usage.cache_creation_input_tokens",
1566
+ "gen_ai.usage.cache_creation.input_tokens",
1567
+ "ai.usage.cacheWriteInputTokens",
1568
+ "ai.usage.cache_creation_input_tokens",
1569
+ "ai.usage.cacheCreationInputTokens"
1570
+ ]
1571
+ };
1572
+ function hasAttribute(attributes, key) {
1573
+ return attributes.some((attribute) => attribute.key === key);
1574
+ }
1575
+ function findStringAttribute(attributes, keys) {
1576
+ return attributes.find(
1577
+ (attribute) => keys.includes(attribute.key) && typeof attribute.value.stringValue === "string" && attribute.value.stringValue.length > 0
1578
+ );
1579
+ }
1580
+ function findNumberAttribute(attributes, keys) {
1581
+ return attributes.find((attribute) => {
1582
+ if (!keys.includes(attribute.key)) return false;
1583
+ if (typeof attribute.value.doubleValue === "number" && Number.isSafeInteger(attribute.value.doubleValue) && attribute.value.doubleValue >= 0) {
1584
+ return true;
1585
+ }
1586
+ const intValue = attribute.value.intValue;
1587
+ return integerValue(intValue) !== void 0;
1588
+ });
1589
+ }
1590
+ function integerValue(value) {
1591
+ if (typeof value === "number") {
1592
+ return Number.isSafeInteger(value) && value >= 0 ? value : void 0;
1593
+ }
1594
+ if (typeof value !== "string") return void 0;
1595
+ const parsed = Number(value);
1596
+ return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : void 0;
1597
+ }
1598
+ function appendAlias(attributes, target, source) {
1599
+ if (!source || hasAttribute(attributes, target)) return attributes;
1600
+ return [...attributes, { key: target, value: { ...source.value } }];
1601
+ }
1602
+ function appendProviderAlias(attributes) {
1603
+ if (hasAttribute(attributes, MODEL_USAGE_ATTRIBUTES.providerName)) return attributes;
1604
+ const source = findStringAttribute(attributes, ["gen_ai.system", "ai.model.provider"]);
1605
+ if (!(source == null ? void 0 : source.value.stringValue)) return attributes;
1606
+ const attribute = attrString(
1607
+ MODEL_USAGE_ATTRIBUTES.providerName,
1608
+ canonicalModelProvider(source.value.stringValue)
1609
+ );
1610
+ return attribute ? [...attributes, attribute] : attributes;
1611
+ }
1612
+ function normalizeModelUsageSpan(span) {
1613
+ const original = span.attributes;
1614
+ if (!original || original.length === 0) return span;
1615
+ const responseModel = findStringAttribute(original, [
1616
+ MODEL_USAGE_ATTRIBUTES.responseModel,
1617
+ "ai.response.model"
1618
+ ]);
1619
+ if (!responseModel) return span;
1620
+ let attributes = appendAlias(original, MODEL_USAGE_ATTRIBUTES.responseModel, responseModel);
1621
+ attributes = appendProviderAlias(attributes);
1622
+ for (const [target, aliases] of Object.entries(STRING_ALIASES)) {
1623
+ attributes = appendAlias(attributes, target, findStringAttribute(attributes, aliases));
1624
+ }
1625
+ for (const [target, aliases] of Object.entries(NUMBER_ALIASES)) {
1626
+ attributes = appendAlias(attributes, target, findNumberAttribute(attributes, aliases));
1627
+ }
1628
+ return attributes === original ? span : { ...span, attributes };
1629
+ }
1630
+ var DEFAULT_SECRET_KEY_NAMES = [
1631
+ "apikey",
1632
+ "apisecret",
1633
+ "apitoken",
1634
+ "secretaccesskey",
1635
+ "sessiontoken",
1636
+ "privatekey",
1637
+ "privatekeyid",
1638
+ "clientsecret",
1639
+ "accesstoken",
1640
+ "refreshtoken",
1641
+ "oauthtoken",
1642
+ "bearertoken",
1643
+ "authorization",
1644
+ "password",
1645
+ "passphrase"
1646
+ ];
1647
+ var REDACTED_PLACEHOLDER = "[REDACTED]";
1648
+ function normalizeKeyName(name) {
1649
+ return name.toLowerCase().replace(/[-_.]/g, "");
1650
+ }
1651
+ function redactSecretsInObject(value, options) {
1652
+ var _a, _b;
1653
+ const normalizedSecretSet = buildSecretSet((_a = options == null ? void 0 : options.secretKeyNames) != null ? _a : DEFAULT_SECRET_KEY_NAMES);
1654
+ const placeholder = (_b = options == null ? void 0 : options.placeholder) != null ? _b : REDACTED_PLACEHOLDER;
1655
+ const seen = /* @__PURE__ */ new WeakSet();
1656
+ const walk = (node) => {
1657
+ if (node === null || typeof node !== "object") return node;
1658
+ if (seen.has(node)) return "[CIRCULAR]";
1659
+ seen.add(node);
1660
+ if (Array.isArray(node)) {
1661
+ return node.map((item) => walk(item));
1662
+ }
1663
+ const out = {};
1664
+ for (const [k, v] of Object.entries(node)) {
1665
+ if (normalizedSecretSet.has(normalizeKeyName(k))) {
1666
+ out[k] = placeholder;
1667
+ } else {
1668
+ out[k] = walk(v);
1669
+ }
1670
+ }
1671
+ return out;
1672
+ };
1673
+ return walk(value);
1674
+ }
1675
+ function buildSecretSet(names) {
1676
+ const set = /* @__PURE__ */ new Set();
1677
+ for (const name of names) set.add(normalizeKeyName(name));
1678
+ return set;
1679
+ }
1680
+ var DEFAULT_REDACT_ATTRIBUTE_KEYS = [
1681
+ "ai.request.providerOptions",
1682
+ "ai.response.providerMetadata"
1683
+ ];
1684
+ function defaultTransformSpan(span) {
1685
+ const attrs = span.attributes;
1686
+ if (!attrs || attrs.length === 0) return span;
1687
+ let nextAttrs;
1688
+ for (let i = 0; i < attrs.length; i++) {
1689
+ const attr = attrs[i];
1690
+ const redacted = redactJsonAttributeValue(attr.key, attr.value);
1691
+ if (redacted === void 0) continue;
1692
+ if (!nextAttrs) nextAttrs = attrs.slice();
1693
+ nextAttrs[i] = { key: attr.key, value: redacted };
1694
+ }
1695
+ if (!nextAttrs) return span;
1696
+ return { ...span, attributes: nextAttrs };
1697
+ }
1698
+ var REDACT_JSON_ATTRIBUTE_KEYS = new Set(DEFAULT_REDACT_ATTRIBUTE_KEYS);
1699
+ function redactJsonAttributeValue(key, value) {
1700
+ if (!REDACT_JSON_ATTRIBUTE_KEYS.has(key)) return void 0;
1701
+ const json = value.stringValue;
1702
+ if (typeof json !== "string" || json.length === 0) return void 0;
1703
+ let parsed;
1704
+ try {
1705
+ parsed = JSON.parse(json);
1706
+ } catch (e) {
1707
+ return void 0;
1708
+ }
1709
+ const scrubbed = redactSecretsInObject(parsed);
1710
+ let scrubbedJson;
1711
+ try {
1712
+ scrubbedJson = JSON.stringify(scrubbed);
1713
+ } catch (e) {
1714
+ return void 0;
1715
+ }
1716
+ if (scrubbedJson === json) return void 0;
1717
+ return { stringValue: scrubbedJson };
1718
+ }
1719
+ function appGitOwnerId2(prefix) {
1720
+ try {
1721
+ return `${prefix}:${randomUUID()}`;
1722
+ } catch (e) {
1723
+ return `${prefix}:${Date.now().toString(36)}:${Math.random().toString(36).slice(2)}`;
1724
+ }
1725
+ }
1726
+ function identityAttrs(args) {
1727
+ return [
1728
+ attrString("ai.telemetry.metadata.raindrop.ai.userId", args.userId),
1729
+ attrString("ai.telemetry.metadata.raindrop.convoId", args.convoId),
1730
+ attrString("ai.telemetry.metadata.raindrop.eventName", args.eventName)
1731
+ ];
1732
+ }
1733
+ function applyOtelSpanAttributeLimit(limit) {
1734
+ var _a, _b;
1735
+ try {
1736
+ const raw = (_b = (_a = globalThis == null ? void 0 : globalThis.process) == null ? void 0 : _a.env) == null ? void 0 : _b.OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT;
1737
+ if (!raw) return limit;
1738
+ const parsed = Number.parseInt(raw, 10);
1739
+ if (Number.isFinite(parsed) && parsed > 0) {
1740
+ return Math.min(limit, parsed);
1741
+ }
1742
+ } catch (e) {
1743
+ }
1744
+ return limit;
1745
+ }
1746
+ var TraceShipper = class {
1747
+ constructor(opts) {
1748
+ this.appGitOwner = appGitOwnerId2("trace");
1749
+ this.appGitEventIds = /* @__PURE__ */ new WeakMap();
1750
+ this.appGitActiveSpans = /* @__PURE__ */ new Map();
1751
+ this.appGitCaptured = /* @__PURE__ */ new WeakSet();
1752
+ this.appGitAdded = /* @__PURE__ */ new WeakMap();
1753
+ this.queue = [];
1754
+ this.inFlight = /* @__PURE__ */ new Set();
1755
+ this.hasShutdown = false;
1756
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
1757
+ this.appGitContext = (_a = opts.appGitContext) != null ? _a : createAppGitContext(opts.appGit);
1758
+ this.ownsAppGitContext = opts.appGitContext === void 0;
1759
+ this.writeKey = (_b = opts.writeKey) == null ? void 0 : _b.trim();
1760
+ this.baseUrl = (_c = formatEndpoint(opts.endpoint)) != null ? _c : "https://api.raindrop.ai/v1/";
1761
+ this.enabled = opts.enabled !== false;
1762
+ this.debug = opts.debug;
1763
+ this.debugSpans = opts.debugSpans === true;
1764
+ this.flushIntervalMs = (_d = opts.flushIntervalMs) != null ? _d : 1e3;
1765
+ this.maxBatchSize = (_e = opts.maxBatchSize) != null ? _e : 50;
1766
+ this.maxQueueSize = (_f = opts.maxQueueSize) != null ? _f : 5e3;
1767
+ this.sdkName = (_g = opts.sdkName) != null ? _g : "core";
1768
+ this.prefix = `[raindrop-ai/${this.sdkName}]`;
1769
+ this.serviceName = (_h = opts.serviceName) != null ? _h : "raindrop.core";
1770
+ this.serviceVersion = (_i = opts.serviceVersion) != null ? _i : "0.0.0";
1771
+ this.localDebuggerUrl = (_j = resolveLocalDebuggerBaseUrl(opts.localDebuggerUrl)) != null ? _j : void 0;
1772
+ if (this.debug && this.localDebuggerUrl) {
1773
+ console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
1774
+ }
1775
+ this.projectId = normalizeProjectId(opts.projectId, {
1776
+ debug: this.debug,
1777
+ prefix: this.prefix
1778
+ });
1779
+ this.transformSpanHook = opts.transformSpan;
1780
+ this.disableDefaultRedaction = opts.disableDefaultRedaction === true;
1781
+ this.maxTextFieldCharsOpt = opts.maxTextFieldChars;
1782
+ }
1783
+ /**
1784
+ * Cap every string attribute value on the span. O(#attributes) length
1785
+ * checks; only oversized values pay a slice. Runs AFTER the redaction
1786
+ * pipeline so the default secret-scrub still sees parseable JSON in
1787
+ * `ai.request.providerOptions` / `ai.response.providerMetadata` (capping
1788
+ * first could cut a JSON blob mid-way, fail the parse, and ship secrets
1789
+ * in the surviving prefix).
1790
+ *
1791
+ * A stricter `OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT` env var is honored
1792
+ * for span content, matching the Python SDK and the OTel SDK convention.
1793
+ */
1794
+ capSpanAttributes(span) {
1795
+ var _a;
1796
+ const maxChars = applyOtelSpanAttributeLimit(
1797
+ resolveMaxTextFieldChars(this.maxTextFieldCharsOpt)
1798
+ );
1799
+ const attrs = span.attributes;
1800
+ if (!attrs || attrs.length === 0) return span;
1801
+ let nextAttrs;
1802
+ for (let i = 0; i < attrs.length; i++) {
1803
+ const attr = attrs[i];
1804
+ const value = (_a = attr.value) == null ? void 0 : _a.stringValue;
1805
+ if (typeof value !== "string" || value.length <= maxChars) continue;
1806
+ if (!nextAttrs) nextAttrs = attrs.slice();
1807
+ nextAttrs[i] = {
1808
+ key: attr.key,
1809
+ value: { ...attr.value, stringValue: capText(value, maxChars) }
1810
+ };
1811
+ }
1812
+ if (!nextAttrs) return span;
1813
+ return { ...span, attributes: nextAttrs };
1814
+ }
1815
+ /**
1816
+ * Apply the user `transformSpan` hook (if any) followed by the default
1817
+ * redactor (unless disabled). Returns either the (possibly new) span to
1818
+ * ship, or `null` to drop the span entirely.
1819
+ *
1820
+ * Ordering: user hook runs first so callers can rewrite the span freely
1821
+ * (rename attrs, add new ones, scrub things the default doesn't know
1822
+ * about). The default redactor then runs on whatever the user produced,
1823
+ * acting as the always-on floor for documented BYOK secrets. If the user
1824
+ * sets `disableDefaultRedaction: true`, the floor is skipped.
1825
+ *
1826
+ * Fail-closed: if the user hook throws, the span is dropped — a buggy
1827
+ * hook can never accidentally ship raw, un-redacted spans.
1828
+ */
1829
+ redactSpan(span) {
1830
+ let current = span;
1831
+ if (this.transformSpanHook) {
1832
+ try {
1833
+ const result = this.transformSpanHook(current);
1834
+ if (result === null) return null;
1835
+ if (result !== void 0) {
1836
+ copyReplayTraceDestination(current, result);
1837
+ current = result;
1838
+ }
1839
+ } catch (err) {
1840
+ if (this.debug) {
1841
+ const msg = err instanceof Error ? err.message : String(err);
1842
+ console.warn(`${this.prefix} transformSpan hook threw: ${msg}`);
1843
+ }
1844
+ return null;
1845
+ }
1846
+ }
1847
+ try {
1848
+ const normalized = normalizeModelUsageSpan(current);
1849
+ copyReplayTraceDestination(current, normalized);
1850
+ current = normalized;
1851
+ } catch (e) {
1852
+ }
1853
+ if (!this.disableDefaultRedaction) {
1854
+ const redacted = defaultTransformSpan(current);
1855
+ copyReplayTraceDestination(current, redacted);
1856
+ current = redacted;
1857
+ }
1858
+ const capped = this.capSpanAttributes(current);
1859
+ copyReplayTraceDestination(current, capped);
1860
+ return capped;
1861
+ }
1862
+ isDebugEnabled() {
1863
+ return this.debug;
1864
+ }
1865
+ authHeaders() {
1866
+ return this.writeKey ? { Authorization: `Bearer ${this.writeKey}` } : {};
1867
+ }
1868
+ requestHeaders() {
1869
+ return { ...this.authHeaders(), ...projectIdHeaders(this.projectId) };
1870
+ }
1871
+ startSpan(args) {
1872
+ var _a, _b, _c;
1873
+ const ids = createSpanIds(args.parent);
1874
+ const started = (_a = args.startTimeUnixNano) != null ? _a : nowUnixNanoString();
1875
+ const attrs = [
1876
+ attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId),
1877
+ ...identityAttrs(args),
1878
+ attrString("ai.operationId", args.operationId),
1879
+ ...Object.entries(evalScopeAttributes()).map(([key, value]) => attrString(key, value))
1880
+ ];
1881
+ if ((_b = args.attributes) == null ? void 0 : _b.length) attrs.push(...args.attributes);
1882
+ const tracksAppGit = this.appGitActiveSpans.has(args.eventId) || this.appGitActiveSpans.size < 1e4;
1883
+ const appGitOverrides = appGitPropertiesFromAttributes(attrs);
1884
+ const span = {
1885
+ ids,
1886
+ name: args.name,
1887
+ startTimeUnixNano: started,
1888
+ attributes: withAppGitAttributes(
1889
+ attrs,
1890
+ this.appGitContext.forOperation(args.eventId, appGitOverrides, this.appGitOwner)
1891
+ )
1892
+ };
1893
+ rememberReplayTraceDestination(span);
1894
+ this.appGitCaptured.add(span);
1895
+ this.appGitEventIds.set(span, args.eventId);
1896
+ if (tracksAppGit) {
1897
+ this.appGitActiveSpans.set(args.eventId, ((_c = this.appGitActiveSpans.get(args.eventId)) != null ? _c : 0) + 1);
1898
+ }
1899
+ this.appGitAdded.set(span, new Set(span.attributes.filter((attr) => !attrs.includes(attr))));
1900
+ const openSpan = buildOtlpSpan({
1901
+ ids: span.ids,
1902
+ name: span.name,
1903
+ startTimeUnixNano: span.startTimeUnixNano,
1904
+ endTimeUnixNano: span.startTimeUnixNano,
1905
+ // placeholder — will be updated on endSpan
1906
+ attributes: span.attributes,
1907
+ status: { code: SpanStatusCode.UNSET }
1908
+ });
1909
+ copyReplayTraceDestination(span, openSpan);
1910
+ this.mirrorToLocalDebugger(openSpan);
1911
+ return span;
1912
+ }
1913
+ mirrorToLocalDebugger(span, completed = false) {
1914
+ const destination = replayTraceDestinationFor(span);
1915
+ if (destination && destination.kind !== "workshop") return;
1916
+ const localDebuggerUrl = (destination == null ? void 0 : destination.kind) === "workshop" ? destination.url : this.localDebuggerUrl;
1917
+ if (!localDebuggerUrl) return;
1918
+ const redacted = this.redactSpan(span);
1919
+ if (redacted === null) return;
1920
+ if (completed && (destination == null ? void 0 : destination.kind) === "workshop") {
1921
+ recordReplayExportedSpan(
1922
+ destination,
1923
+ base64ToHex(redacted.spanId),
1924
+ base64ToHex(redacted.traceId)
1925
+ );
1926
+ }
1927
+ const body = buildExportTraceServiceRequest([redacted], this.serviceName, this.serviceVersion);
1928
+ const p = mirrorTraceExportToLocalDebugger(body, {
1929
+ baseUrl: localDebuggerUrl,
1930
+ debug: false,
1931
+ sdkName: this.sdkName
1932
+ });
1933
+ this.inFlight.add(p);
1934
+ void p.finally(() => {
1935
+ this.inFlight.delete(p);
1936
+ });
1937
+ }
1938
+ endSpan(span, extra) {
1939
+ var _a, _b, _c;
1940
+ if (span.endTimeUnixNano) return;
1941
+ span.endTimeUnixNano = (_a = extra == null ? void 0 : extra.endTimeUnixNano) != null ? _a : nowUnixNanoString();
1942
+ if ((_b = extra == null ? void 0 : extra.attributes) == null ? void 0 : _b.length) {
1943
+ const overrides = appGitPropertiesFromAttributes(extra.attributes);
1944
+ const eventId2 = this.appGitEventIds.get(span);
1945
+ const snapshot = eventId2 ? this.appGitContext.forOperation(eventId2, overrides, this.appGitOwner) : overrides;
1946
+ const added = this.appGitAdded.get(span);
1947
+ 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));
1948
+ span.attributes.push(...extra.attributes);
1949
+ span.attributes = withAppGitAttributes(span.attributes, snapshot);
1950
+ }
1951
+ let status = extra == null ? void 0 : extra.status;
1952
+ if (!status && (extra == null ? void 0 : extra.error) !== void 0) {
1953
+ const message = extra.error instanceof Error ? extra.error.message : String(extra.error);
1954
+ status = { code: SpanStatusCode.ERROR, message };
1955
+ }
1956
+ const otlp = buildOtlpSpan({
1957
+ ids: span.ids,
1958
+ name: span.name,
1959
+ startTimeUnixNano: span.startTimeUnixNano,
1960
+ endTimeUnixNano: span.endTimeUnixNano,
1961
+ attributes: span.attributes,
1962
+ status
1963
+ });
1964
+ copyReplayTraceDestination(span, otlp);
1965
+ this.appGitCaptured.add(otlp);
1966
+ this.enqueue(otlp);
1967
+ this.mirrorToLocalDebugger(otlp, true);
1968
+ const eventId = this.appGitEventIds.get(span);
1969
+ if (eventId && this.appGitActiveSpans.has(eventId)) {
1970
+ const remaining = ((_c = this.appGitActiveSpans.get(eventId)) != null ? _c : 1) - 1;
1971
+ if (remaining > 0) this.appGitActiveSpans.set(eventId, remaining);
1972
+ else {
1973
+ this.appGitActiveSpans.delete(eventId);
1974
+ if (this.appGitContext.releaseOperation) this.appGitContext.releaseOperation(eventId, this.appGitOwner);
1975
+ else if (this.ownsAppGitContext) this.appGitContext.finishOperation(eventId);
1976
+ }
1977
+ }
1978
+ }
1979
+ createSpan(args) {
1980
+ var _a;
1981
+ const ids = createSpanIds(args.parent);
1982
+ const attrs = [
1983
+ attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId),
1984
+ ...identityAttrs(args),
1985
+ ...Object.entries(evalScopeAttributes()).map(([key, value]) => attrString(key, value))
1986
+ ];
1987
+ if ((_a = args.attributes) == null ? void 0 : _a.length) attrs.push(...args.attributes);
1988
+ const tracksAppGit = !this.appGitActiveSpans.has(args.eventId);
1989
+ const otlp = buildOtlpSpan({
1990
+ ids,
1991
+ name: args.name,
1992
+ startTimeUnixNano: args.startTimeUnixNano,
1993
+ endTimeUnixNano: args.endTimeUnixNano,
1994
+ attributes: withAppGitAttributes(
1995
+ attrs,
1996
+ this.appGitContext.forOperation(
1997
+ args.eventId,
1998
+ appGitPropertiesFromAttributes(attrs),
1999
+ this.appGitOwner
2000
+ )
2001
+ ),
2002
+ status: args.status
2003
+ });
2004
+ rememberReplayTraceDestination(otlp);
2005
+ this.appGitCaptured.add(otlp);
2006
+ if (tracksAppGit) {
2007
+ if (this.appGitContext.releaseOperation) this.appGitContext.releaseOperation(args.eventId, this.appGitOwner);
2008
+ else if (this.ownsAppGitContext) this.appGitContext.finishOperation(args.eventId);
2009
+ }
2010
+ this.enqueue(otlp);
2011
+ this.mirrorToLocalDebugger(otlp, true);
2012
+ }
2013
+ enqueue(span) {
2014
+ var _a;
2015
+ if (!this.enabled) return;
2016
+ const attributes = (_a = span.attributes) != null ? _a : [];
2017
+ const enriched = this.appGitCaptured.has(span) ? attributes : withAppGitAttributes(attributes, this.appGitContext.snapshot(appGitPropertiesFromAttributes(attributes)));
2018
+ if (enriched !== attributes) {
2019
+ const original = span;
2020
+ span = { ...span, attributes: enriched.filter((attr) => attr !== void 0) };
2021
+ copyReplayTraceDestination(original, span);
2022
+ }
2023
+ if (this.debugSpans) {
2024
+ const short = (s) => s ? s.slice(-8) : "none";
2025
+ console.log(
2026
+ `${this.prefix}[span] name=${span.name} trace=${short(span.traceId)} span=${short(span.spanId)} parent=${short(
2027
+ span.parentSpanId
2028
+ )}`
2029
+ );
2030
+ }
2031
+ const redacted = this.redactSpan(span);
2032
+ if (redacted === null) return;
2033
+ const destination = replayTraceDestinationFor(redacted);
2034
+ recordReplayExportedSpan(
2035
+ destination,
2036
+ base64ToHex(redacted.spanId),
2037
+ base64ToHex(redacted.traceId)
2038
+ );
2039
+ if ((destination == null ? void 0 : destination.kind) === "workshop") return;
2040
+ if (this.queue.length >= this.maxQueueSize) {
2041
+ this.queue.shift();
2042
+ }
2043
+ this.queue.push(redacted);
2044
+ if (this.queue.length >= this.maxBatchSize) {
2045
+ void this.flush().catch(() => {
2046
+ });
2047
+ return;
2048
+ }
2049
+ if (!this.timer) {
2050
+ this.timer = setTimeout(() => {
2051
+ this.timer = void 0;
2052
+ void this.flush().catch(() => {
2053
+ });
2054
+ }, this.flushIntervalMs);
2055
+ }
2056
+ }
2057
+ async flush() {
2058
+ var _a;
2059
+ if (!this.enabled) {
2060
+ await Promise.all([...this.inFlight].map((p) => p.catch(() => {
2061
+ })));
2062
+ return;
2063
+ }
2064
+ if (this.timer) {
2065
+ clearTimeout(this.timer);
2066
+ this.timer = void 0;
2067
+ }
2068
+ while (this.queue.length > 0) {
2069
+ const batch = this.queue.splice(0, this.maxBatchSize);
2070
+ const groups = /* @__PURE__ */ new Map();
2071
+ for (const span of batch) {
2072
+ const destination = replayTraceDestinationFor(span);
2073
+ const spans = groups.get(destination);
2074
+ if (spans) spans.push(span);
2075
+ else groups.set(destination, [span]);
2076
+ }
2077
+ for (const [destination, spans] of groups) {
2078
+ if (!destination && !this.writeKey) continue;
2079
+ if ((destination == null ? void 0 : destination.kind) === "workshop") continue;
2080
+ const opts = this.requestOpts();
2081
+ if (!opts) {
2082
+ rateLimitedLog(
2083
+ `${this.prefix}.shutdown_deadline`,
2084
+ () => console.warn(
2085
+ `${this.prefix} shutdown flush deadline exceeded; dropping ${spans.length} spans`
2086
+ )
2087
+ );
2088
+ continue;
2089
+ }
2090
+ const body = buildExportTraceServiceRequest(spans, this.serviceName, this.serviceVersion);
2091
+ const url = destination ? replayTraceUrl(destination.url) : `${this.baseUrl}traces`;
2092
+ const headers = destination ? {
2093
+ Authorization: `Bearer ${destination.apiKey}`,
2094
+ "X-Raindrop-Replay-Id": destination.replayId,
2095
+ "X-Raindrop-Project-Id": (_a = destination.projectId) != null ? _a : "default"
2096
+ } : this.requestHeaders();
2097
+ if (this.debug) {
2098
+ console.log(`${this.prefix} sending traces batch`, {
2099
+ spans: spans.length,
2100
+ endpoint: url
2101
+ });
2102
+ }
2103
+ const p = postJson(url, body, headers, opts);
2104
+ this.inFlight.add(p);
2105
+ try {
2106
+ try {
2107
+ await p;
2108
+ if (this.debug) console.log(`${this.prefix} sent ${spans.length} spans`);
2109
+ } catch (err) {
2110
+ const msg = err instanceof Error ? err.message : String(err);
2111
+ rateLimitedLog(
2112
+ `${this.prefix}.send_spans_failed`,
2113
+ () => console.warn(`${this.prefix} failed to send ${spans.length} spans: ${msg}`)
2114
+ );
2115
+ }
2116
+ } finally {
2117
+ this.inFlight.delete(p);
2118
+ }
2119
+ }
2120
+ }
2121
+ }
2122
+ /** See EventShipper.requestOpts — same shutdown-budget semantics. */
2123
+ requestOpts() {
2124
+ if (this.shutdownDeadlineAt !== void 0) {
2125
+ const remainingMs = this.shutdownDeadlineAt - Date.now();
2126
+ if (remainingMs <= 0) return null;
2127
+ return {
2128
+ maxAttempts: 1,
2129
+ debug: this.debug,
2130
+ sdkName: this.sdkName,
2131
+ timeoutMs: Math.min(DEFAULT_REQUEST_TIMEOUT_MS, remainingMs)
2132
+ };
2133
+ }
2134
+ if (this.hasShutdown) {
2135
+ return {
2136
+ maxAttempts: 1,
2137
+ debug: this.debug,
2138
+ sdkName: this.sdkName,
2139
+ timeoutMs: POST_SHUTDOWN_TIMEOUT_MS
2140
+ };
2141
+ }
2142
+ return { maxAttempts: 3, debug: this.debug, sdkName: this.sdkName };
2143
+ }
2144
+ async shutdown() {
2145
+ this.hasShutdown = true;
2146
+ this.shutdownDeadlineAt = Date.now() + SHUTDOWN_DEADLINE_MS;
2147
+ try {
2148
+ if (this.timer) {
2149
+ clearTimeout(this.timer);
2150
+ this.timer = void 0;
2151
+ }
2152
+ const drain = async () => {
2153
+ await this.flush();
2154
+ await Promise.all([...this.inFlight].map((p) => p.catch(() => {
2155
+ })));
2156
+ };
2157
+ const settled = await raceWithTimeout(drain(), SHUTDOWN_DEADLINE_MS);
2158
+ if (!settled) {
2159
+ rateLimitedLog(
2160
+ `${this.prefix}.shutdown_deadline`,
2161
+ () => console.warn(
2162
+ `${this.prefix} shutdown flush deadline exceeded; abandoning in-flight spans`
2163
+ )
2164
+ );
2165
+ }
2166
+ } finally {
2167
+ this.shutdownDeadlineAt = void 0;
2168
+ if (this.ownsAppGitContext) this.appGitContext.dispose();
2169
+ }
2170
+ }
2171
+ };
2172
+
2173
+ // ../core/dist/index.node.js
2174
+ var import_async_hooks = require("async_hooks");
2175
+ var import_child_process = require("child_process");
2176
+ var import_path = require("path");
2177
+ var resolveLocal = (sourceDirectory, detectBranch, completed) => {
2178
+ const cwd = sourceDirectory ? (0, import_path.resolve)(sourceDirectory) : process.cwd();
2179
+ let cancelled = false;
2180
+ let active;
2181
+ let deadlineTimer;
2182
+ const deadline = Date.now() + 1e3;
2183
+ const run = (args, done) => {
2184
+ if (cancelled) return;
2185
+ const remaining = deadline - Date.now();
2186
+ if (remaining <= 0) {
2187
+ done(void 0);
2188
+ return;
2189
+ }
2190
+ try {
2191
+ active = (0, import_child_process.execFile)(
2192
+ "git",
2193
+ args,
2194
+ {
2195
+ cwd,
2196
+ encoding: "utf8",
2197
+ maxBuffer: 4096,
2198
+ windowsHide: true,
2199
+ env: {
2200
+ ...process.env,
2201
+ // The selected application cwd, not the invoking shell's Git plumbing, owns identity.
2202
+ GIT_DIR: void 0,
2203
+ GIT_WORK_TREE: void 0,
2204
+ GIT_COMMON_DIR: void 0,
2205
+ GIT_NAMESPACE: void 0,
2206
+ GIT_INDEX_FILE: void 0,
2207
+ GIT_OBJECT_DIRECTORY: void 0,
2208
+ GIT_ALTERNATE_OBJECT_DIRECTORIES: void 0,
2209
+ GIT_CONFIG_PARAMETERS: void 0,
2210
+ GIT_CONFIG_COUNT: "0",
2211
+ GIT_TERMINAL_PROMPT: "0",
2212
+ GIT_OPTIONAL_LOCKS: "0"
2213
+ }
2214
+ },
2215
+ (error, stdout) => {
2216
+ clearTimeout(deadlineTimer);
2217
+ deadlineTimer = void 0;
2218
+ active = void 0;
2219
+ if (!cancelled) {
2220
+ try {
2221
+ done(error ? void 0 : stdout.trim());
2222
+ } catch (e) {
2223
+ }
2224
+ }
2225
+ }
2226
+ );
2227
+ active.unref();
2228
+ if (active.stdout && "unref" in active.stdout && typeof active.stdout.unref === "function")
2229
+ active.stdout.unref();
2230
+ if (active.stderr && "unref" in active.stderr && typeof active.stderr.unref === "function")
2231
+ active.stderr.unref();
2232
+ deadlineTimer = setTimeout(() => {
2233
+ try {
2234
+ active == null ? void 0 : active.kill("SIGKILL");
2235
+ } catch (e) {
2236
+ }
2237
+ }, remaining);
2238
+ deadlineTimer.unref();
2239
+ } catch (e) {
2240
+ try {
2241
+ done(void 0);
2242
+ } catch (e2) {
2243
+ }
2244
+ }
2245
+ };
2246
+ const scheduled = setTimeout(() => {
2247
+ try {
2248
+ run(["rev-parse", "HEAD"], (rawSha) => {
2249
+ const commitSha = validAppCommitSha(rawSha);
2250
+ if (!commitSha) {
2251
+ completed({});
2252
+ return;
2253
+ }
2254
+ run(["-c", "core.fsmonitor=false", "status", "--porcelain"], (status) => {
2255
+ const finish = (branch) => {
2256
+ run(["rev-parse", "HEAD"], (finalSha) => {
2257
+ const coherent = validAppCommitSha(finalSha) === commitSha;
2258
+ completed({
2259
+ commitSha,
2260
+ ...coherent && status !== void 0 ? { commitDirty: status !== "" } : {},
2261
+ ...coherent && branch && branch !== "HEAD" ? { branch } : {}
2262
+ });
2263
+ });
2264
+ };
2265
+ if (detectBranch) run(["symbolic-ref", "--quiet", "--short", "HEAD"], finish);
2266
+ else finish();
2267
+ });
2268
+ });
2269
+ } catch (e) {
2270
+ completed({});
2271
+ }
2272
+ }, 0);
2273
+ scheduled.unref();
2274
+ return () => {
2275
+ cancelled = true;
2276
+ clearTimeout(scheduled);
2277
+ clearTimeout(deadlineTimer);
2278
+ try {
2279
+ active == null ? void 0 : active.kill("SIGKILL");
2280
+ } catch (e) {
2281
+ }
2282
+ };
2283
+ };
2284
+ function createAppGitContext2(options, runtime = {}) {
2285
+ return new AppGitContext(options, { ...runtime, resolveLocal });
2286
+ }
2287
+ function hasDestination(options) {
2288
+ var _a;
2289
+ if (options.enabled === false) return false;
2290
+ return Boolean(((_a = options.writeKey) == null ? void 0 : _a.trim()) || resolveLocalDebuggerBaseUrl(options.localDebuggerUrl));
2291
+ }
2292
+ var EventShipper2 = class extends EventShipper {
2293
+ constructor(options) {
2294
+ var _a;
2295
+ const ownsAppGitContext = options.appGitContext === void 0;
2296
+ const appGitContext = (_a = options.appGitContext) != null ? _a : createAppGitContext2(options.appGit, { allowDiscovery: hasDestination(options) });
2297
+ try {
2298
+ super({ ...options, appGitContext });
2299
+ } catch (error) {
2300
+ if (ownsAppGitContext) appGitContext.dispose();
2301
+ throw error;
2302
+ }
2303
+ if (ownsAppGitContext) this.ownAppGitContextForShutdown();
2304
+ }
2305
+ };
2306
+ var TraceShipper2 = class extends TraceShipper {
2307
+ constructor(options) {
2308
+ var _a;
2309
+ const ownsAppGitContext = options.appGitContext === void 0;
2310
+ const appGitContext = (_a = options.appGitContext) != null ? _a : createAppGitContext2(options.appGit, { allowDiscovery: hasDestination(options) });
2311
+ try {
2312
+ super({ ...options, appGitContext });
2313
+ } catch (error) {
2314
+ if (ownsAppGitContext) appGitContext.dispose();
2315
+ throw error;
2316
+ }
2317
+ this.ownsAppGitContext = ownsAppGitContext;
2318
+ }
2319
+ };
2320
+ globalThis.RAINDROP_ASYNC_LOCAL_STORAGE = import_async_hooks.AsyncLocalStorage;
2321
+ var SUPPRESS_TRACING_KEY = /* @__PURE__ */ Symbol.for(
2322
+ "OpenTelemetry SDK Context Key SUPPRESS_TRACING"
2323
+ );
2324
+ function findOtelContextManager() {
2325
+ var _a;
2326
+ for (const sym of Object.getOwnPropertySymbols(globalThis)) {
2327
+ if (!((_a = sym.description) == null ? void 0 : _a.startsWith("opentelemetry.js.api."))) continue;
2328
+ const api = globalThis[sym];
2329
+ const cm = api == null ? void 0 : api.context;
2330
+ if (cm && typeof cm.with === "function" && typeof cm.active === "function") {
2331
+ return cm;
2332
+ }
2333
+ }
2334
+ return void 0;
2335
+ }
2336
+ function installTracingSuppressionHook() {
2337
+ if (typeof globalThis.RAINDROP_SUPPRESS_TRACING === "function") return;
2338
+ const hook = (fn) => {
2339
+ const cm = findOtelContextManager();
2340
+ if (!cm) return fn();
2341
+ return cm.with(cm.active().setValue(SUPPRESS_TRACING_KEY, true), fn);
2342
+ };
2343
+ globalThis.RAINDROP_SUPPRESS_TRACING = hook;
2344
+ }
2345
+ installTracingSuppressionHook();
2346
+
2347
+ // src/handler.ts
2348
+ var RaindropManagedAgentsHandler = class {
2349
+ constructor(events, traces, opts) {
2350
+ this.events = events;
2351
+ this.traces = traces;
2352
+ this.opts = opts;
2353
+ this.sessions = /* @__PURE__ */ new Map();
2354
+ this.idleSessions = /* @__PURE__ */ new Set();
2355
+ this.completed = /* @__PURE__ */ new Set();
2356
+ }
2357
+ text(value) {
2358
+ const text = typeof value === "string" ? value : stringifyBounded(value, this.opts.maxTextFieldChars);
2359
+ return capText(this.opts.redact ? this.opts.redact(text) : text, this.opts.maxTextFieldChars);
2360
+ }
2361
+ setAttributes(span, attributes) {
2362
+ for (const attribute of attributes) {
2363
+ if (!attribute) continue;
2364
+ const index = span.attributes.findIndex((current) => (current == null ? void 0 : current.key) === attribute.key);
2365
+ if (index < 0) span.attributes.push(attribute);
2366
+ else span.attributes[index] = attribute;
2367
+ }
2368
+ }
2369
+ sessionCapture(sessionId) {
2370
+ const existing = this.sessions.get(sessionId);
2371
+ if (existing) return existing;
2372
+ const session = { context: this.opts, turns: /* @__PURE__ */ new Map() };
2373
+ this.sessions.set(sessionId, session);
2374
+ return session;
2375
+ }
2376
+ cacheSession(sessionId, session) {
2377
+ this.idleSessions.delete(sessionId);
2378
+ if (session.turns.size > 0) return;
2379
+ this.idleSessions.add(sessionId);
2380
+ if (this.idleSessions.size <= 1e4) return;
2381
+ const oldest = this.idleSessions.values().next().value;
2382
+ if (oldest !== void 0) {
2383
+ this.idleSessions.delete(oldest);
2384
+ this.sessions.delete(oldest);
2385
+ }
2386
+ }
2387
+ onSession(session, context = {}) {
2388
+ try {
2389
+ const capture = this.sessionCapture(session.id);
2390
+ capture.model = session.agent.model;
2391
+ capture.context = { ...this.opts, ...capture.context, ...context };
2392
+ this.cacheSession(session.id, capture);
2393
+ } catch (e) {
2394
+ }
2395
+ }
2396
+ onInput(sessionId, input) {
2397
+ try {
2398
+ const session = this.sessionCapture(sessionId);
2399
+ const message = Array.isArray(input) ? [...input].reverse().find((item) => item.role === "user") : void 0;
2400
+ session.input = typeof input === "string" ? this.text(input) : message ? this.text(
2401
+ message.content.flatMap((part) => part.type === "input_text" ? [part.text] : []).join("\n")
2402
+ ) : void 0;
2403
+ this.cacheSession(sessionId, session);
2404
+ } catch (e) {
2405
+ }
2406
+ }
2407
+ capture(sessionId, turnId) {
2408
+ var _a, _b, _c, _d, _e;
2409
+ const key = `${sessionId}:${turnId}`;
2410
+ if (this.completed.has(key)) return void 0;
2411
+ const session = this.sessionCapture(sessionId);
2412
+ const existing = session.turns.get(turnId);
2413
+ if (existing) return existing;
2414
+ const context = session.context;
2415
+ const eventId = (_c = (_b = (_a = this.opts).eventId) == null ? void 0 : _b.call(_a, turnId)) != null ? _c : randomUUID();
2416
+ const patch = {
2417
+ userId: context.userId,
2418
+ convoId: (_d = context.convoId) != null ? _d : sessionId,
2419
+ eventName: (_e = context.eventName) != null ? _e : "ai_generation",
2420
+ input: void 0,
2421
+ model: void 0,
2422
+ properties: {
2423
+ ...context.properties,
2424
+ "ai.provider": "openai",
2425
+ "openai.session.id": sessionId,
2426
+ "openai.turn.id": turnId
2427
+ },
2428
+ isPending: true
2429
+ };
2430
+ const root = this.traces.startSpan({
2431
+ name: "openai.agent.turn",
2432
+ eventId,
2433
+ userId: patch.userId,
2434
+ convoId: patch.convoId,
2435
+ eventName: patch.eventName,
2436
+ operationId: "ai.generateText",
2437
+ attributes: [
2438
+ attrString("gen_ai.provider.name", "openai"),
2439
+ attrString("openai.session.id", sessionId),
2440
+ attrString("openai.turn.id", turnId)
2441
+ ]
2442
+ });
2443
+ const capture = {
2444
+ eventId,
2445
+ patch,
2446
+ root,
2447
+ tools: /* @__PURE__ */ new Map(),
2448
+ completedTools: /* @__PURE__ */ new Set(),
2449
+ inputFromItem: false
2450
+ };
2451
+ session.turns.set(turnId, capture);
2452
+ this.cacheSession(sessionId, session);
2453
+ void this.events.patch(eventId, patch).catch(() => {
2454
+ });
2455
+ return capture;
2456
+ }
2457
+ onTurn(turn) {
2458
+ var _a, _b, _c, _d;
2459
+ try {
2460
+ const capture = this.capture(turn.session_id, turn.id);
2461
+ if (!capture) return;
2462
+ capture.patch.timestamp = new Date(turn.created_at * 1e3).toISOString();
2463
+ this.setAttributes(capture.root, [
2464
+ attrInt("openai.turn.created_at", turn.created_at),
2465
+ attrInt("openai.turn.started_at", (_a = turn.started_at) != null ? _a : void 0),
2466
+ attrInt("openai.turn.completed_at", (_b = turn.completed_at) != null ? _b : void 0)
2467
+ ]);
2468
+ if (turn.subagent_id === null) {
2469
+ const session = this.sessions.get(turn.session_id);
2470
+ capture.patch.model = session == null ? void 0 : session.model;
2471
+ if (!capture.inputFromItem) capture.patch.input = session == null ? void 0 : session.input;
2472
+ this.setAttributes(capture.root, [
2473
+ attrString("ai.model.id", session == null ? void 0 : session.model),
2474
+ attrString("gen_ai.request.model", session == null ? void 0 : session.model),
2475
+ attrString("gen_ai.response.model", session == null ? void 0 : session.model)
2476
+ ]);
2477
+ }
2478
+ if (turn.subagent_id)
2479
+ capture.patch.properties = {
2480
+ ...capture.patch.properties,
2481
+ "openai.subagent.id": turn.subagent_id
2482
+ };
2483
+ if (!["completed", "failed", "cancelled"].includes(turn.status)) {
2484
+ void this.events.patch(capture.eventId, capture.patch).catch(() => {
2485
+ });
2486
+ return;
2487
+ }
2488
+ const usage = turn.usage;
2489
+ if (usage)
2490
+ capture.root.attributes.push(
2491
+ ...buildRawModelUsageAttributes({
2492
+ inputTokens: usage.input_tokens,
2493
+ outputTokens: usage.output_tokens,
2494
+ cacheReadInputTokens: usage.input_tokens_details.cached_tokens,
2495
+ reasoningTokens: usage.output_tokens_details.reasoning_tokens
2496
+ })
2497
+ );
2498
+ capture.patch.usage = usage ? { promptTokens: usage.input_tokens, completionTokens: usage.output_tokens } : void 0;
2499
+ capture.patch.properties = {
2500
+ ...capture.patch.properties,
2501
+ "ai.finish_reason": turn.status,
2502
+ "ai.usage.cached_tokens": usage == null ? void 0 : usage.input_tokens_details.cached_tokens,
2503
+ "ai.usage.thoughts_tokens": usage == null ? void 0 : usage.output_tokens_details.reasoning_tokens
2504
+ };
2505
+ const error = turn.error ? new Error(this.text(turn.error.message)) : turn.status === "cancelled" ? new Error("Agent turn cancelled") : turn.status === "failed" ? new Error("Agent turn failed") : void 0;
2506
+ if (error)
2507
+ error.name = (_d = (_c = turn.error) == null ? void 0 : _c.code) != null ? _d : turn.status === "cancelled" ? "AgentTurnCancelled" : "AgentTurnFailed";
2508
+ this.complete(turn.session_id, turn.id, error);
2509
+ } catch (e) {
2510
+ }
2511
+ }
2512
+ onItem(sessionId, item) {
2513
+ try {
2514
+ const capture = this.capture(sessionId, item.turn_id);
2515
+ if (!capture) return;
2516
+ if (item.type === "message") {
2517
+ const text = this.text(
2518
+ item.content.flatMap(
2519
+ (part) => part.type === "input_text" || part.type === "output_text" ? [part.text] : []
2520
+ ).join("\n")
2521
+ );
2522
+ if (item.role === "user") {
2523
+ capture.patch.input = text;
2524
+ capture.inputFromItem = true;
2525
+ } else if (item.phase === "final_answer" && item.status === "completed")
2526
+ capture.patch.output = text;
2527
+ void this.events.patch(capture.eventId, capture.patch).catch(() => {
2528
+ });
2529
+ return;
2530
+ }
2531
+ if (item.type === "reasoning" || item.type === "agent_message") return;
2532
+ const key = item.type === "function_call_output" || item.type === "function_call" ? item.call_id : item.id;
2533
+ if (capture.completedTools.has(key)) return;
2534
+ let span = capture.tools.get(key);
2535
+ if (!span) {
2536
+ span = this.traces.startSpan({
2537
+ name: "ai.toolCall",
2538
+ operationId: "ai.toolCall",
2539
+ eventId: capture.eventId,
2540
+ parent: {
2541
+ traceIdB64: capture.root.ids.traceIdB64,
2542
+ spanIdB64: capture.root.ids.spanIdB64
2543
+ },
2544
+ attributes: [
2545
+ attrString("openai.item.id", item.id),
2546
+ attrString("openai.item.type", item.type)
2547
+ ]
2548
+ });
2549
+ capture.tools.set(key, span);
2550
+ }
2551
+ let name = item.type === "function_call_output" ? void 0 : item.type;
2552
+ let input;
2553
+ let output;
2554
+ let error;
2555
+ if (item.type === "command_execution") {
2556
+ name = "bash";
2557
+ input = item.command;
2558
+ output = item.output;
2559
+ if (item.exit_code !== null && item.exit_code !== 0)
2560
+ error = new Error(`Command exited with code ${item.exit_code}`);
2561
+ } else if (item.type === "function_call" || item.type === "mcp_call") {
2562
+ name = item.name;
2563
+ input = item.arguments;
2564
+ if (item.type === "mcp_call") {
2565
+ output = item.output;
2566
+ if (item.error) error = new Error(this.text(item.error));
2567
+ }
2568
+ } else if (item.type === "function_call_output") {
2569
+ output = item.output;
2570
+ if (item.error) error = new Error(this.text(item.error));
2571
+ } else {
2572
+ input = item;
2573
+ }
2574
+ this.setAttributes(span, [
2575
+ attrString("ai.toolCall.name", name),
2576
+ attrString("ai.toolCall.args", input === void 0 ? void 0 : this.text(input))
2577
+ ]);
2578
+ if (item.status !== "in_progress" && (item.type !== "function_call" || item.status === "failed" || item.status === "incomplete")) {
2579
+ capture.tools.delete(key);
2580
+ capture.completedTools.add(key);
2581
+ this.traces.endSpan(span, {
2582
+ attributes: [
2583
+ attrString("ai.toolCall.result", output === void 0 ? void 0 : this.text(output))
2584
+ ],
2585
+ error: error != null ? error : item.status === "failed" || item.status === "incomplete" ? new Error(`Agent tool ${item.status}`) : void 0
2586
+ });
2587
+ }
2588
+ } catch (e) {
2589
+ }
2590
+ }
2591
+ onInputEvents(sessionId, events) {
2592
+ var _a, _b;
2593
+ try {
2594
+ for (const event of events) {
2595
+ if (event.type === "agent.session.input.message") this.onInput(sessionId, event.input);
2596
+ else if (event.type === "agent.session.input.tool_result") {
2597
+ const capture = (_a = this.sessions.get(sessionId)) == null ? void 0 : _a.turns.get(event.turn_id);
2598
+ const span = capture == null ? void 0 : capture.tools.get(event.call_id);
2599
+ if (capture && span) {
2600
+ capture.tools.delete(event.call_id);
2601
+ capture.completedTools.add(event.call_id);
2602
+ this.traces.endSpan(span, {
2603
+ attributes: [attrString("ai.toolCall.result", this.text(event.output))],
2604
+ error: event.success ? void 0 : new Error(this.text((_b = event.error) != null ? _b : "Function tool failed"))
2605
+ });
2606
+ }
2607
+ }
2608
+ }
2609
+ } catch (e) {
2610
+ }
2611
+ }
2612
+ onEvent(event) {
2613
+ var _a;
2614
+ try {
2615
+ switch (event.type) {
2616
+ case "agent.session.created":
2617
+ this.onSession(event.session);
2618
+ break;
2619
+ case "agent.session.turn.created":
2620
+ case "agent.session.turn.in_progress":
2621
+ case "agent.session.turn.completed":
2622
+ case "agent.session.turn.failed":
2623
+ case "agent.session.turn.cancelled":
2624
+ this.onTurn(event.turn);
2625
+ break;
2626
+ case "agent.session.turn.item.added":
2627
+ case "agent.session.turn.item.done":
2628
+ this.onItem(event.session_id, event.item);
2629
+ break;
2630
+ case "agent.session.failed":
2631
+ this.forgetSession(
2632
+ event.session.id,
2633
+ new Error(this.text((_a = event.session.error) != null ? _a : "Agent session failed"))
2634
+ );
2635
+ break;
2636
+ case "agent.session.environment.failed":
2637
+ this.forgetSession(event.session_id, new Error("Agent environment failed"));
2638
+ break;
2639
+ case "error":
2640
+ this.closeSessionTurns(event.session_id, new Error(this.text(event.error.message)));
2641
+ break;
2642
+ }
2643
+ } catch (e) {
2644
+ }
2645
+ }
2646
+ complete(sessionId, turnId, error) {
2647
+ var _a, _b;
2648
+ const key = `${sessionId}:${turnId}`;
2649
+ const session = this.sessions.get(sessionId);
2650
+ const capture = session == null ? void 0 : session.turns.get(turnId);
2651
+ if (!session || !capture) return;
2652
+ session.turns.delete(turnId);
2653
+ this.completed.add(key);
2654
+ if (this.completed.size > 1e4) {
2655
+ const oldest = this.completed.values().next().value;
2656
+ if (oldest !== void 0) this.completed.delete(oldest);
2657
+ }
2658
+ for (const span of capture.tools.values()) {
2659
+ try {
2660
+ this.traces.endSpan(span, {
2661
+ error: error != null ? error : new Error("Capture ended before tool completed")
2662
+ });
2663
+ } catch (e) {
2664
+ }
2665
+ }
2666
+ try {
2667
+ this.traces.endSpan(capture.root, {
2668
+ error,
2669
+ attributes: [
2670
+ attrString("ai.prompt", capture.patch.input),
2671
+ attrString("ai.response.text", capture.patch.output),
2672
+ attrInt("ai.usage.prompt_tokens", (_a = capture.patch.usage) == null ? void 0 : _a.promptTokens),
2673
+ attrInt("ai.usage.completion_tokens", (_b = capture.patch.usage) == null ? void 0 : _b.completionTokens)
2674
+ ]
2675
+ });
2676
+ } catch (e) {
2677
+ }
2678
+ try {
2679
+ void this.events.finish(capture.eventId, { ...capture.patch, error }).catch(() => {
2680
+ });
2681
+ } catch (e) {
2682
+ }
2683
+ this.cacheSession(sessionId, session);
2684
+ }
2685
+ closeSessionTurns(sessionId, error) {
2686
+ try {
2687
+ const session = this.sessions.get(sessionId);
2688
+ if (!session) return;
2689
+ for (const turnId of session.turns.keys())
2690
+ this.complete(
2691
+ sessionId,
2692
+ turnId,
2693
+ error != null ? error : new Error("Agent capture closed before turn completed")
2694
+ );
2695
+ session.input = void 0;
2696
+ this.cacheSession(sessionId, session);
2697
+ } catch (e) {
2698
+ }
2699
+ }
2700
+ forgetSession(sessionId, error) {
2701
+ try {
2702
+ this.closeSessionTurns(sessionId, error);
2703
+ this.sessions.delete(sessionId);
2704
+ this.idleSessions.delete(sessionId);
2705
+ } catch (e) {
2706
+ }
2707
+ }
2708
+ shutdown() {
2709
+ for (const sessionId of this.sessions.keys()) this.forgetSession(sessionId);
2710
+ this.completed.clear();
2711
+ }
2712
+ };
2713
+
2714
+ // package.json
2715
+ var package_default = {
2716
+ name: "@raindrop-ai/openai-managed-agents",
2717
+ version: "0.0.1",
2718
+ description: "Raindrop tracing for the OpenAI Agents API",
2719
+ main: "dist/index.js",
2720
+ module: "dist/index.mjs",
2721
+ types: "dist/index.d.ts",
2722
+ license: "MIT",
2723
+ homepage: "https://docs.raindrop.ai/integrations/openai-managed-agents",
2724
+ bugs: {
2725
+ url: "https://docs.raindrop.ai/support"
2726
+ },
2727
+ exports: {
2728
+ ".": {
2729
+ import: {
2730
+ types: "./dist/index.d.mts",
2731
+ default: "./dist/index.mjs"
2732
+ },
2733
+ require: {
2734
+ types: "./dist/index.d.ts",
2735
+ default: "./dist/index.js"
2736
+ }
2737
+ }
2738
+ },
2739
+ sideEffects: false,
2740
+ files: [
2741
+ "dist/**",
2742
+ "RELEASING.md"
2743
+ ],
2744
+ scripts: {
2745
+ build: "tsup",
2746
+ dev: "tsup --watch",
2747
+ clean: "trash dist",
2748
+ test: "vitest run",
2749
+ "test:types": "tsc -p tests/consumers/tsconfig.json",
2750
+ lint: "eslint src tests --ext .ts"
2751
+ },
2752
+ peerDependencies: {
2753
+ openai: ">=7.15.0 <8"
2754
+ },
2755
+ devDependencies: {
2756
+ "@raindrop-ai/core": "workspace:*",
2757
+ "@types/node": "^20.11.17",
2758
+ msw: "^2.12.7",
2759
+ tsup: "^8.4.0",
2760
+ typescript: "^5.3.3",
2761
+ vitest: "^2.1.9",
2762
+ openai: "7.15.0",
2763
+ zod: "^3.23.8"
2764
+ },
2765
+ tsup: {
2766
+ entry: [
2767
+ "src/index.ts"
2768
+ ],
2769
+ format: [
2770
+ "cjs",
2771
+ "esm"
2772
+ ],
2773
+ dts: {
2774
+ resolve: true
2775
+ },
2776
+ clean: true,
2777
+ noExternal: [
2778
+ "@raindrop-ai/core"
2779
+ ]
2780
+ },
2781
+ publishConfig: {
2782
+ access: "public"
2783
+ },
2784
+ engines: {
2785
+ node: ">=22"
2786
+ }
2787
+ };
2788
+
2789
+ // src/version.ts
2790
+ var libraryName = package_default.name;
2791
+ var libraryVersion = package_default.version;
2792
+
2793
+ // src/wrap.ts
2794
+ var import_streaming = require("openai/core/streaming");
2795
+ async function* observe(events, handler, sessionId) {
2796
+ try {
2797
+ for await (const event of events) {
2798
+ if (event.type === "agent.session.created") sessionId = event.session.id;
2799
+ handler.onEvent(event);
2800
+ yield event;
2801
+ }
2802
+ } finally {
2803
+ if (sessionId) handler.closeSessionTurns(sessionId);
2804
+ }
2805
+ }
2806
+ function wrapManagedAgents(client, handler, context) {
2807
+ const sessions = client.beta.agents.sessions;
2808
+ const wrappedEvents = new Proxy(sessions.events, {
2809
+ get(target, prop) {
2810
+ if (prop === "stream")
2811
+ return (sessionId, options) => target.stream(sessionId, options)._thenUnwrap(
2812
+ (events) => new import_streaming.Stream(() => observe(events, handler, sessionId), events.controller)
2813
+ );
2814
+ if (prop === "create")
2815
+ return (sessionId, params, options) => target.create(sessionId, params, options)._thenUnwrap((result) => {
2816
+ handler.onInputEvents(sessionId, params.events);
2817
+ return result;
2818
+ });
2819
+ const value = Reflect.get(target, prop, target);
2820
+ return typeof value === "function" ? value.bind(target) : value;
2821
+ }
2822
+ });
2823
+ const wrappedSessions = new Proxy(sessions, {
2824
+ get(target, prop) {
2825
+ if (prop === "events") return wrappedEvents;
2826
+ if (prop === "create")
2827
+ return (params, options) => target.create(params, options)._thenUnwrap((result) => {
2828
+ if (result instanceof import_streaming.Stream) {
2829
+ const source = result;
2830
+ async function* initialEvents() {
2831
+ let sessionId;
2832
+ try {
2833
+ for await (const event of source) {
2834
+ if (event.type === "agent.session.created") {
2835
+ sessionId = event.session.id;
2836
+ handler.onSession(event.session, context);
2837
+ handler.onInput(event.session.id, params.input);
2838
+ }
2839
+ handler.onEvent(event);
2840
+ yield event;
2841
+ }
2842
+ } finally {
2843
+ if (sessionId) handler.closeSessionTurns(sessionId);
2844
+ }
2845
+ }
2846
+ return new import_streaming.Stream(initialEvents, result.controller);
2847
+ }
2848
+ handler.onSession(result, context);
2849
+ handler.onInput(result.id, params.input);
2850
+ return result;
2851
+ });
2852
+ if (prop === "retrieve")
2853
+ return (sessionId, options) => target.retrieve(sessionId, options)._thenUnwrap((session) => {
2854
+ handler.onSession(session, context);
2855
+ return session;
2856
+ });
2857
+ if (prop === "stream")
2858
+ return (sessionId, params, options) => {
2859
+ const stream = target.stream(sessionId, params, options);
2860
+ return new Proxy(stream, {
2861
+ get(obj, key) {
2862
+ if (key === Symbol.asyncIterator)
2863
+ return () => {
2864
+ handler.onInput(sessionId, params.input);
2865
+ return observe(stream, handler, sessionId);
2866
+ };
2867
+ const value2 = Reflect.get(obj, key, obj);
2868
+ return typeof value2 === "function" ? value2.bind(obj) : value2;
2869
+ }
2870
+ });
2871
+ };
2872
+ const value = Reflect.get(target, prop, target);
2873
+ return typeof value === "function" ? value.bind(target) : value;
2874
+ }
2875
+ });
2876
+ const agents = new Proxy(client.beta.agents, {
2877
+ get(target, prop) {
2878
+ if (prop === "sessions") return wrappedSessions;
2879
+ const value = Reflect.get(target, prop, target);
2880
+ return typeof value === "function" ? value.bind(target) : value;
2881
+ }
2882
+ });
2883
+ const beta = new Proxy(client.beta, {
2884
+ get(target, prop) {
2885
+ if (prop === "agents") return agents;
2886
+ const value = Reflect.get(target, prop, target);
2887
+ return typeof value === "function" ? value.bind(target) : value;
2888
+ }
2889
+ });
2890
+ return new Proxy(client, {
2891
+ get(target, prop) {
2892
+ if (prop === "beta") return beta;
2893
+ const value = Reflect.get(target, prop, target);
2894
+ return typeof value === "function" ? value.bind(target) : value;
2895
+ }
2896
+ });
2897
+ }
2898
+
2899
+ // src/index.ts
2900
+ function createRaindropOpenAIManagedAgents(opts = {}) {
2901
+ var _a, _b;
2902
+ const enabled = Boolean((_a = opts.writeKey) == null ? void 0 : _a.trim());
2903
+ if (!enabled)
2904
+ console.warn(
2905
+ "[raindrop-ai/openai-managed-agents] writeKey not provided; cloud telemetry disabled"
2906
+ );
2907
+ const appGitContext = createAppGitContext2(enabled ? opts.appGit : false, {
2908
+ allowLocalGit: false
2909
+ });
2910
+ const shipperOptions = {
2911
+ writeKey: opts.writeKey,
2912
+ endpoint: opts.endpoint,
2913
+ projectId: opts.projectId,
2914
+ enabled,
2915
+ debug: (_b = opts.debug) != null ? _b : false,
2916
+ sdkName: "openai-managed-agents",
2917
+ libraryName,
2918
+ libraryVersion,
2919
+ appGitContext,
2920
+ maxTextFieldChars: opts.maxTextFieldChars,
2921
+ localDebuggerUrl: opts.localWorkshopUrl === false ? null : opts.localWorkshopUrl
2922
+ };
2923
+ const events = new EventShipper2(shipperOptions);
2924
+ const traces = new TraceShipper2({
2925
+ ...shipperOptions,
2926
+ serviceName: "raindrop.openai-managed-agents",
2927
+ serviceVersion: libraryVersion
2928
+ });
2929
+ const handler = new RaindropManagedAgentsHandler(events, traces, opts);
2930
+ return {
2931
+ handler,
2932
+ wrap: (client, context) => wrapManagedAgents(client, handler, context),
2933
+ events: {
2934
+ patch: (id, patch) => events.patch(id, patch),
2935
+ finish: (id, patch) => events.finish(id, patch),
2936
+ addAttachments: (id, attachments) => events.patch(id, { attachments }),
2937
+ setProperties: (id, properties) => events.patch(id, { properties })
2938
+ },
2939
+ users: { identify: (users) => events.identify(users) },
2940
+ signals: { track: (signal) => events.trackSignal(signal) },
2941
+ async flush() {
2942
+ await Promise.all([events.flush(), traces.flush()]);
2943
+ },
2944
+ async shutdown() {
2945
+ try {
2946
+ handler.shutdown();
2947
+ await Promise.all([events.shutdown(), traces.shutdown()]);
2948
+ } finally {
2949
+ appGitContext.dispose();
2950
+ }
2951
+ }
2952
+ };
2953
+ }
2954
+ // Annotate the CommonJS export names for ESM import in node:
2955
+ 0 && (module.exports = {
2956
+ RaindropManagedAgentsHandler,
2957
+ createRaindropOpenAIManagedAgents
2958
+ });