@raindrop-ai/ai-sdk 0.3.1 → 0.3.3

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.
@@ -1,4 +1,633 @@
1
- // ../core/dist/chunk-3V4MIA75.js
1
+ // ../core/dist/chunk-BYBMRLZM.js
2
+ var EVAL_CORRELATION_ID_ATTRIBUTE = "raindrop.eval_correlation_id";
3
+ var PROBE_SCOPE = { correlationId: "" };
4
+ var EvalScopeStorage = class {
5
+ constructor() {
6
+ this._als = null;
7
+ this._probed = false;
8
+ }
9
+ maybeAdoptAsyncLocalStorage() {
10
+ if (this._probed) return;
11
+ this._probed = true;
12
+ try {
13
+ const Ctor = globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
14
+ if (!Ctor) return;
15
+ const als = new Ctor();
16
+ als.run(PROBE_SCOPE, () => {
17
+ });
18
+ this._als = als;
19
+ } catch (e) {
20
+ this._als = null;
21
+ }
22
+ }
23
+ run(scope, callback) {
24
+ this.maybeAdoptAsyncLocalStorage();
25
+ if (this._als) return this._als.run(scope, callback);
26
+ const previous = this._syncScope;
27
+ this._syncScope = scope;
28
+ try {
29
+ return callback();
30
+ } finally {
31
+ this._syncScope = previous;
32
+ }
33
+ }
34
+ current() {
35
+ this.maybeAdoptAsyncLocalStorage();
36
+ if (this._als) return this._als.getStore();
37
+ return this._syncScope;
38
+ }
39
+ };
40
+ var EVAL_SCOPE_STORAGE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.evalScopeStorage");
41
+ function evalScopeStorage() {
42
+ const holder = globalThis;
43
+ let storage = holder[EVAL_SCOPE_STORAGE_KEY];
44
+ if (!storage) {
45
+ storage = new EvalScopeStorage();
46
+ holder[EVAL_SCOPE_STORAGE_KEY] = storage;
47
+ }
48
+ return storage;
49
+ }
50
+ function currentEvalScope() {
51
+ try {
52
+ return evalScopeStorage().current();
53
+ } catch (e) {
54
+ return void 0;
55
+ }
56
+ }
57
+ function evalScopeAttributes() {
58
+ const scope = currentEvalScope();
59
+ if (!scope) return {};
60
+ return { [EVAL_CORRELATION_ID_ATTRIBUTE]: scope.correlationId };
61
+ }
62
+
63
+ // ../core/dist/chunk-WJOR6M7H.js
64
+ var STATE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.replayTraceRoutingState");
65
+ function state() {
66
+ const holder = globalThis;
67
+ let current = holder[STATE_KEY];
68
+ if (!current) {
69
+ let storage = null;
70
+ try {
71
+ const Ctor = globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
72
+ if (Ctor) storage = new Ctor();
73
+ } catch (e) {
74
+ storage = null;
75
+ }
76
+ current = {
77
+ storage,
78
+ syncDestination: void 0,
79
+ spanDestinations: /* @__PURE__ */ new WeakMap()
80
+ };
81
+ holder[STATE_KEY] = current;
82
+ }
83
+ return current;
84
+ }
85
+ function currentReplayTraceDestination() {
86
+ var _a, _b;
87
+ const routing = state();
88
+ return (_b = (_a = routing.storage) == null ? void 0 : _a.getStore()) != null ? _b : routing.syncDestination;
89
+ }
90
+ function rememberReplayTraceDestination(span) {
91
+ const destination = currentReplayTraceDestination();
92
+ if (destination) state().spanDestinations.set(span, destination);
93
+ }
94
+ function copyReplayTraceDestination(source, target) {
95
+ const destination = state().spanDestinations.get(source);
96
+ if (destination) state().spanDestinations.set(target, destination);
97
+ }
98
+ function replayTraceDestinationFor(value) {
99
+ if (typeof value !== "object" && typeof value !== "function" || value === null) {
100
+ return void 0;
101
+ }
102
+ return state().spanDestinations.get(value);
103
+ }
104
+ function recordReplayExportedSpan(destination, spanId, traceId) {
105
+ var _a, _b;
106
+ if (!destination || !spanId || !traceId) return;
107
+ (_a = destination.exportedSpanIds) == null ? void 0 : _a.add(spanId);
108
+ (_b = destination.exportedTraceIds) == null ? void 0 : _b.add(traceId);
109
+ }
110
+ function replayTraceUrl(baseUrl) {
111
+ return `${baseUrl.replace(/\/+$/, "")}/v1/traces`;
112
+ }
113
+ var NOOP_SPAN = {
114
+ traceIdB64: "",
115
+ spanIdB64: "",
116
+ eventId: "",
117
+ log() {
118
+ }
119
+ };
120
+ function getAsyncLocalStorageCtor() {
121
+ return globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
122
+ }
123
+ var SynchronousContextStorage = class {
124
+ constructor() {
125
+ this._stack = [];
126
+ }
127
+ isEmpty() {
128
+ return this._stack.length === 0;
129
+ }
130
+ getStore() {
131
+ return this._stack[this._stack.length - 1];
132
+ }
133
+ run(store, callback) {
134
+ this._stack.push(store);
135
+ try {
136
+ return callback();
137
+ } finally {
138
+ this._stack.pop();
139
+ }
140
+ }
141
+ };
142
+ var ContextManager = class {
143
+ };
144
+ var RaindropContextManager = class extends ContextManager {
145
+ constructor() {
146
+ super();
147
+ this._fallback = null;
148
+ const Ctor = getAsyncLocalStorageCtor();
149
+ if (Ctor) {
150
+ this._storage = new Ctor();
151
+ return;
152
+ }
153
+ this._fallback = new SynchronousContextStorage();
154
+ this._storage = this._fallback;
155
+ }
156
+ maybeAdoptAsyncLocalStorage() {
157
+ if (!this._fallback || !this._fallback.isEmpty()) return;
158
+ const Ctor = getAsyncLocalStorageCtor();
159
+ if (!Ctor) return;
160
+ this._storage = new Ctor();
161
+ this._fallback = null;
162
+ }
163
+ isReady() {
164
+ return true;
165
+ }
166
+ getParentSpanIds() {
167
+ this.maybeAdoptAsyncLocalStorage();
168
+ const span = this._storage.getStore();
169
+ if (!span || span === NOOP_SPAN) return void 0;
170
+ return {
171
+ traceIdB64: span.traceIdB64,
172
+ spanIdB64: span.spanIdB64,
173
+ eventId: span.eventId
174
+ };
175
+ }
176
+ runInContext(span, callback) {
177
+ this.maybeAdoptAsyncLocalStorage();
178
+ return this._storage.run(span, callback);
179
+ }
180
+ getCurrentSpan() {
181
+ this.maybeAdoptAsyncLocalStorage();
182
+ return this._storage.getStore();
183
+ }
184
+ };
185
+ var _contextManager = null;
186
+ function getContextManager() {
187
+ if (!_contextManager) {
188
+ _contextManager = globalThis.RAINDROP_CONTEXT_MANAGER ? new globalThis.RAINDROP_CONTEXT_MANAGER() : new RaindropContextManager();
189
+ }
190
+ return _contextManager;
191
+ }
192
+ function currentSpan() {
193
+ var _a;
194
+ return (_a = getContextManager().getCurrentSpan()) != null ? _a : NOOP_SPAN;
195
+ }
196
+ function withCurrent(span, callback) {
197
+ return getContextManager().runInContext(span, callback);
198
+ }
199
+ async function getCurrentParentSpanContext() {
200
+ var _a, _b;
201
+ return (_b = getContextManager().getParentSpanIds()) != null ? _b : (_a = currentReplayTraceDestination()) == null ? void 0 : _a.parentSpanContext;
202
+ }
203
+ async function runWithParentSpanContext(ctx, fn) {
204
+ const cm = getContextManager();
205
+ const span = {
206
+ traceIdB64: ctx.traceIdB64,
207
+ spanIdB64: ctx.spanIdB64,
208
+ eventId: ctx.eventId
209
+ };
210
+ return cm.runInContext(span, fn);
211
+ }
212
+ async function* asyncGeneratorWithCurrent(span, gen) {
213
+ let nextValue;
214
+ while (true) {
215
+ const result = await withCurrent(span, async () => {
216
+ try {
217
+ return await gen.next(nextValue);
218
+ } catch (e) {
219
+ return { value: void 0, done: true, error: e };
220
+ }
221
+ });
222
+ if ("error" in result && result.error !== void 0) {
223
+ throw result.error;
224
+ }
225
+ if (result.done) {
226
+ return result.value;
227
+ }
228
+ nextValue = yield result.value;
229
+ }
230
+ }
231
+ var MAX_BINDING_STACK = 128;
232
+ var EMPTY_STACK = [];
233
+ var ContextStackStorage = class {
234
+ /** Emitted once when this runtime cannot support an ambient push. */
235
+ constructor(noAmbientBindWarning) {
236
+ this.noAmbientBindWarning = noAmbientBindWarning;
237
+ this._als = null;
238
+ this._enterWithUsable = false;
239
+ this._syncStack = EMPTY_STACK;
240
+ this._adoptionChecked = false;
241
+ this._warnedNoAmbientBind = false;
242
+ }
243
+ maybeAdoptAsyncLocalStorage() {
244
+ if (this._adoptionChecked) return;
245
+ this._adoptionChecked = true;
246
+ const Ctor = getAsyncLocalStorageCtor();
247
+ if (!Ctor) return;
248
+ const als = new Ctor();
249
+ try {
250
+ als.run(EMPTY_STACK, () => {
251
+ });
252
+ } catch (e) {
253
+ return;
254
+ }
255
+ this._als = als;
256
+ if (typeof als.enterWith === "function") {
257
+ try {
258
+ als.enterWith(EMPTY_STACK);
259
+ this._enterWithUsable = true;
260
+ } catch (e) {
261
+ this._enterWithUsable = false;
262
+ }
263
+ }
264
+ }
265
+ getStack() {
266
+ var _a;
267
+ this.maybeAdoptAsyncLocalStorage();
268
+ if (this._als) return (_a = this._als.getStore()) != null ? _a : this._syncStack;
269
+ return this._syncStack;
270
+ }
271
+ /**
272
+ * Persist an ambient stack mutation. Returns false when an ALS is adopted but
273
+ * `enterWith` is unusable (workerd): callers must NOT fall back to the
274
+ * process-shared sync stack, since concurrent isolates would cross-stamp.
275
+ */
276
+ setAmbientStack(stack) {
277
+ if (this._als) {
278
+ if (!this._enterWithUsable) return false;
279
+ this._als.enterWith(stack);
280
+ return true;
281
+ }
282
+ this._syncStack = stack;
283
+ return true;
284
+ }
285
+ push(binding) {
286
+ this.maybeAdoptAsyncLocalStorage();
287
+ if (this._als && !this._enterWithUsable) {
288
+ this.warnNoAmbientBindOnce();
289
+ return;
290
+ }
291
+ let stack = this.getStack();
292
+ if (stack.length >= MAX_BINDING_STACK) {
293
+ stack = stack.filter((b) => b.isLive());
294
+ if (stack.length >= MAX_BINDING_STACK) {
295
+ stack = stack.slice(stack.length - (MAX_BINDING_STACK - 1));
296
+ }
297
+ }
298
+ this.setAmbientStack([...stack, binding]);
299
+ }
300
+ remove(binding) {
301
+ binding.markDead();
302
+ const stack = this.getStack();
303
+ const pruned = stack.filter((b) => b !== binding && b.isLive());
304
+ if (pruned.length !== stack.length) {
305
+ this.setAmbientStack(pruned);
306
+ }
307
+ }
308
+ runWith(binding, callback) {
309
+ this.maybeAdoptAsyncLocalStorage();
310
+ if (this._als) {
311
+ return this._als.run([...this.getStack(), binding], callback);
312
+ }
313
+ const previous = this._syncStack;
314
+ this._syncStack = [...previous, binding];
315
+ try {
316
+ return callback();
317
+ } finally {
318
+ this._syncStack = previous;
319
+ }
320
+ }
321
+ current() {
322
+ const stack = this.getStack();
323
+ if (stack.length === 0) return void 0;
324
+ const top = stack[stack.length - 1];
325
+ if (top.isLive()) return top;
326
+ const pruned = stack.filter((b) => b.isLive());
327
+ this.setAmbientStack(pruned);
328
+ return pruned.length > 0 ? pruned[pruned.length - 1] : void 0;
329
+ }
330
+ warnNoAmbientBindOnce() {
331
+ if (this._warnedNoAmbientBind) return;
332
+ this._warnedNoAmbientBind = true;
333
+ console.warn(this.noAmbientBindWarning);
334
+ }
335
+ };
336
+ 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.";
337
+ var ROUTING_STORAGE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.routingContextStorage");
338
+ function routingStorage() {
339
+ const holder = globalThis;
340
+ let storage = holder[ROUTING_STORAGE_KEY];
341
+ if (!storage) {
342
+ storage = new ContextStackStorage(NO_AMBIENT_ROUTING_BIND_WARNING);
343
+ holder[ROUTING_STORAGE_KEY] = storage;
344
+ }
345
+ return storage;
346
+ }
347
+ function currentRoutingBinding() {
348
+ const bound = routingStorage().current();
349
+ if (!bound) return void 0;
350
+ return {
351
+ projectId: bound.projectId,
352
+ authHint: bound.authHint,
353
+ ...bound.appGit ? { appGit: bound.appGit } : {},
354
+ ...bound.appGitSource ? { appGitSource: bound.appGitSource } : {}
355
+ };
356
+ }
357
+ var APP_COMMIT_SHA = "raindrop.app.commit_sha";
358
+ var APP_COMMIT_DIRTY = "raindrop.app.commit_dirty";
359
+ var APP_BRANCH = "raindrop.app.branch";
360
+ var APP_GIT_KEYS = [APP_COMMIT_SHA, APP_COMMIT_DIRTY, APP_BRANCH];
361
+ var own = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
362
+ function appGitExplicitKeys(properties) {
363
+ const keys = /* @__PURE__ */ new Set();
364
+ if (!properties) return keys;
365
+ for (const key of APP_GIT_KEYS) {
366
+ if (own(properties, key)) keys.add(key);
367
+ }
368
+ return keys;
369
+ }
370
+ function mergeAppGitSnapshot(base, properties, explicitKeys = /* @__PURE__ */ new Set()) {
371
+ try {
372
+ const result = { ...base };
373
+ if (properties && own(properties, APP_COMMIT_SHA) && properties[APP_COMMIT_SHA] !== result[APP_COMMIT_SHA]) {
374
+ if (!explicitKeys.has(APP_COMMIT_DIRTY) && !own(properties, APP_COMMIT_DIRTY)) {
375
+ delete result[APP_COMMIT_DIRTY];
376
+ }
377
+ if (!explicitKeys.has(APP_BRANCH) && !own(properties, APP_BRANCH)) {
378
+ delete result[APP_BRANCH];
379
+ }
380
+ }
381
+ for (const key of APP_GIT_KEYS) {
382
+ if (properties && own(properties, key)) result[key] = properties[key];
383
+ }
384
+ return Object.freeze(result);
385
+ } catch (e) {
386
+ return Object.freeze({});
387
+ }
388
+ }
389
+ function validAppCommitSha(value) {
390
+ if (typeof value !== "string" || value.length > 128) return void 0;
391
+ const cleaned = value.trim();
392
+ return /^(?:[a-fA-F0-9]{40}|[a-fA-F0-9]{64})$/.test(cleaned) ? cleaned.toLowerCase() : void 0;
393
+ }
394
+ function shortString(value) {
395
+ if (typeof value !== "string" || value.length > 1024) return void 0;
396
+ const cleaned = value.trim();
397
+ return cleaned.length > 0 ? cleaned : void 0;
398
+ }
399
+ function flag(value) {
400
+ if (value === true || value === "true" || value === "1") return true;
401
+ if (value === false || value === "false" || value === "0") return false;
402
+ return void 0;
403
+ }
404
+ function environment() {
405
+ try {
406
+ return typeof process === "undefined" ? {} : process.env;
407
+ } catch (e) {
408
+ return {};
409
+ }
410
+ }
411
+ var DEPLOYMENTS = [
412
+ ["VERCEL", "VERCEL_GIT_COMMIT_SHA", "VERCEL_GIT_COMMIT_REF"],
413
+ ["NETLIFY", "COMMIT_REF", "BRANCH"],
414
+ ["RAILWAY_ENVIRONMENT_NAME", "RAILWAY_GIT_COMMIT_SHA", "RAILWAY_GIT_BRANCH"],
415
+ ["RAILWAY_ENVIRONMENT", "RAILWAY_GIT_COMMIT_SHA", "RAILWAY_GIT_BRANCH"],
416
+ ["RENDER", "RENDER_GIT_COMMIT", "RENDER_GIT_BRANCH"],
417
+ ["DYNO", "HEROKU_BUILD_COMMIT", ""],
418
+ ["DYNO", "HEROKU_SLUG_COMMIT", ""],
419
+ ["AWS_APP_ID", "AWS_COMMIT_ID", "AWS_BRANCH"],
420
+ ["WORKERS_CI", "WORKERS_CI_COMMIT_SHA", "WORKERS_CI_BRANCH"]
421
+ ];
422
+ var CI_SOURCES = [
423
+ ["GITHUB_ACTIONS", "GITHUB_SHA", "GITHUB_REF_NAME"],
424
+ ["GITLAB_CI", "CI_COMMIT_SHA", "CI_COMMIT_REF_NAME"],
425
+ ["CIRCLECI", "CIRCLE_SHA1", "CIRCLE_BRANCH"]
426
+ ];
427
+ function detectedSource(env, table, detectBranch) {
428
+ for (const row of table) {
429
+ const [marker, shaKey, branchKey] = row;
430
+ if (!marker || !shaKey || !shortString(env[marker]) || flag(env[marker]) === false) continue;
431
+ const commitSha = validAppCommitSha(env[shaKey]);
432
+ if (commitSha)
433
+ return {
434
+ commitSha,
435
+ ...detectBranch && branchKey ? { branch: shortString(env[branchKey]) } : {}
436
+ };
437
+ }
438
+ return {};
439
+ }
440
+ var AppGitContextImpl = class {
441
+ constructor(options, runtime = {}) {
442
+ this.defaults = {};
443
+ this.explicit = {};
444
+ this.explicitKeys = /* @__PURE__ */ new Set();
445
+ this.disposed = false;
446
+ this.operations = /* @__PURE__ */ new Map();
447
+ this.operationOverflow = false;
448
+ this.detectBranch = false;
449
+ this.disabled = false;
450
+ var _a, _b, _c, _d, _e, _f;
451
+ try {
452
+ if (options === false) {
453
+ this.disabled = true;
454
+ return;
455
+ }
456
+ const opts = options != null ? options : {};
457
+ const env = (_a = runtime.env) != null ? _a : environment();
458
+ const detectBranch = (_c = (_b = flag(opts.detectBranch)) != null ? _b : flag(env.RAINDROP_GIT_DETECT_BRANCH)) != null ? _c : false;
459
+ this.detectBranch = detectBranch;
460
+ const collectBranch = detectBranch || runtime.captureLegacyReplayBranch === true;
461
+ const autoDetect = runtime.allowDiscovery === false ? false : (_e = (_d = flag(opts.autoDetect)) != null ? _d : flag(env.RAINDROP_GIT_AUTO_DETECT)) != null ? _e : true;
462
+ const configuredSha = opts.commitSha;
463
+ const explicitSha = configuredSha === void 0 ? env.RAINDROP_COMMIT_SHA : configuredSha;
464
+ if (explicitSha === null) this.explicit[APP_COMMIT_SHA] = null;
465
+ else if (typeof explicitSha === "string" && validAppCommitSha(explicitSha))
466
+ this.explicit[APP_COMMIT_SHA] = explicitSha;
467
+ const configuredDirty = opts.commitDirty;
468
+ const explicitDirty = configuredDirty === void 0 ? flag(env.RAINDROP_COMMIT_DIRTY) : configuredDirty;
469
+ if (explicitDirty === null || typeof explicitDirty === "boolean")
470
+ this.explicit[APP_COMMIT_DIRTY] = explicitDirty;
471
+ const configuredBranch = opts.branch;
472
+ const explicitBranch = configuredBranch === void 0 ? env.RAINDROP_BRANCH : configuredBranch;
473
+ if (explicitBranch === null) this.explicit[APP_BRANCH] = null;
474
+ else if (typeof explicitBranch === "string" && explicitBranch.length <= 1024)
475
+ this.explicit[APP_BRANCH] = explicitBranch;
476
+ this.explicitKeys = appGitExplicitKeys(this.explicit);
477
+ this.defaults = { ...this.explicit };
478
+ if (!autoDetect || explicitSha !== void 0) return;
479
+ const sourceDirectory = (_f = shortString(opts.sourceDirectory)) != null ? _f : shortString(env.RAINDROP_GIT_SOURCE_DIRECTORY);
480
+ if (runtime.allowLocalGit === false && !sourceDirectory) return;
481
+ const deploy = sourceDirectory ? {} : detectedSource(env, DEPLOYMENTS, collectBranch);
482
+ if (deploy.commitSha) {
483
+ this.accept(deploy);
484
+ return;
485
+ }
486
+ const fallback = sourceDirectory ? {} : detectedSource(env, CI_SOURCES, collectBranch);
487
+ if (runtime.resolveLocal && (runtime.allowLocalGit !== false || sourceDirectory)) {
488
+ this.cancel = runtime.resolveLocal(sourceDirectory, collectBranch, (result) => {
489
+ try {
490
+ if (!this.disposed) this.accept(result.commitSha ? result : fallback);
491
+ } catch (e) {
492
+ }
493
+ });
494
+ } else this.accept(fallback);
495
+ } catch (e) {
496
+ }
497
+ }
498
+ accept(result) {
499
+ const sha = validAppCommitSha(result.commitSha);
500
+ if (!sha) return;
501
+ this.replayBranch = shortString(result.branch);
502
+ this.defaults = {
503
+ [APP_COMMIT_SHA]: sha,
504
+ ...typeof result.commitDirty === "boolean" ? { [APP_COMMIT_DIRTY]: result.commitDirty } : {},
505
+ ...this.detectBranch && this.replayBranch ? { [APP_BRANCH]: this.replayBranch } : {},
506
+ ...this.explicit
507
+ };
508
+ }
509
+ snapshot(properties) {
510
+ var _a;
511
+ try {
512
+ const binding = currentRoutingBinding();
513
+ const base = this.disabled && (binding == null ? void 0 : binding.appGitSource) !== "replay-override" ? {} : (_a = binding == null ? void 0 : binding.appGit) != null ? _a : this.defaults;
514
+ return this.mergeSnapshot(base, properties);
515
+ } catch (e) {
516
+ return Object.freeze({});
517
+ }
518
+ }
519
+ /** Safe defaults when no operation/span start was observed; never infer identity. */
520
+ snapshotExplicit(properties, eventId) {
521
+ try {
522
+ const base = { ...this.explicit };
523
+ const operation = eventId ? this.operations.get(eventId) : void 0;
524
+ if (operation) {
525
+ for (const key of operation.explicitKeys) base[key] = operation.snapshot[key];
526
+ }
527
+ return this.mergeSnapshot(base, properties, new Set(Object.keys(base)));
528
+ } catch (e) {
529
+ return mergeAppGitSnapshot({}, properties);
530
+ }
531
+ }
532
+ /** Existing replay branch reporting stays separate from opt-in event properties. */
533
+ snapshotForReplay() {
534
+ const snapshot = this.snapshot();
535
+ if (this.replayBranch && !own(snapshot, APP_BRANCH) && snapshot[APP_COMMIT_SHA] === this.defaults[APP_COMMIT_SHA]) {
536
+ return Object.freeze({ ...snapshot, [APP_BRANCH]: this.replayBranch });
537
+ }
538
+ return snapshot;
539
+ }
540
+ /** Merge a frozen span snapshot without losing client-authored provenance. */
541
+ mergeSnapshot(base, properties, explicitKeys = this.explicitKeys) {
542
+ return mergeAppGitSnapshot(base, properties, /* @__PURE__ */ new Set([...this.explicitKeys, ...explicitKeys]));
543
+ }
544
+ /** Shippers belonging to one client share this bounded operation registry. */
545
+ forOperation(eventId, properties, owner) {
546
+ if (!eventId) return this.snapshot(properties);
547
+ let operation = this.operations.get(eventId);
548
+ if (!operation) {
549
+ if (this.operations.size >= 1e4) this.operationOverflow = true;
550
+ if (this.operationOverflow) return this.mergeSnapshot({}, properties);
551
+ operation = {
552
+ snapshot: this.snapshot(properties),
553
+ owners: /* @__PURE__ */ new Set(),
554
+ unowned: owner === void 0,
555
+ explicitKeys: appGitExplicitKeys(properties)
556
+ };
557
+ this.operations.set(eventId, operation);
558
+ } else if (properties && APP_GIT_KEYS.some((key) => own(properties, key))) {
559
+ const explicitKeys = /* @__PURE__ */ new Set([...this.explicitKeys, ...operation.explicitKeys]);
560
+ operation.snapshot = this.mergeSnapshot(operation.snapshot, properties, explicitKeys);
561
+ for (const key of appGitExplicitKeys(properties)) operation.explicitKeys.add(key);
562
+ }
563
+ if (!owner) operation.unowned = true;
564
+ if (owner) operation.owners.add(owner);
565
+ return operation.snapshot;
566
+ }
567
+ releaseOperation(eventId, owner) {
568
+ const operation = this.operations.get(eventId);
569
+ if (!operation) return;
570
+ operation.owners.delete(owner);
571
+ if (operation.owners.size === 0 && !operation.unowned) this.operations.delete(eventId);
572
+ }
573
+ finishOperation(eventId) {
574
+ this.operations.delete(eventId);
575
+ }
576
+ dispose() {
577
+ var _a;
578
+ this.disposed = true;
579
+ try {
580
+ (_a = this.cancel) == null ? void 0 : _a.call(this);
581
+ } catch (e) {
582
+ }
583
+ }
584
+ };
585
+ var AppGitContext = AppGitContextImpl;
586
+ function createAppGitContext(options, runtime = {}) {
587
+ return new AppGitContext(options, runtime);
588
+ }
589
+ function withAppGitProperties(properties, snapshot) {
590
+ try {
591
+ const merged = { ...properties };
592
+ for (const key of APP_GIT_KEYS)
593
+ if (!own(merged, key) && own(snapshot, key)) merged[key] = snapshot[key];
594
+ return merged;
595
+ } catch (e) {
596
+ return properties != null ? properties : {};
597
+ }
598
+ }
599
+ function withAppGitAttributes(attributes, snapshot) {
600
+ try {
601
+ const present = new Set(attributes.flatMap((attr) => attr ? [attr.key] : []));
602
+ const added = [];
603
+ for (const key of APP_GIT_KEYS) {
604
+ if (present.has(key) || present.has(`ai.telemetry.metadata.${key}`) || present.has(`traceloop.association.properties.${key}`))
605
+ continue;
606
+ const value = snapshot[key];
607
+ if (typeof value === "string") added.push({ key, value: { stringValue: value } });
608
+ else if (typeof value === "boolean") added.push({ key, value: { boolValue: value } });
609
+ }
610
+ return added.length ? [...attributes, ...added] : attributes;
611
+ } catch (e) {
612
+ return attributes;
613
+ }
614
+ }
615
+ function appGitPropertiesFromAttributes(attributes) {
616
+ var _a, _b, _c;
617
+ const properties = {};
618
+ try {
619
+ for (const attr of attributes) {
620
+ if (!attr) continue;
621
+ for (const key of APP_GIT_KEYS) {
622
+ if (attr.key === key || attr.key === `ai.telemetry.metadata.${key}` || attr.key === `traceloop.association.properties.${key}`) {
623
+ properties[key] = (_c = (_b = (_a = attr.value.stringValue) != null ? _a : attr.value.boolValue) != null ? _b : attr.value.intValue) != null ? _c : null;
624
+ }
625
+ }
626
+ }
627
+ } catch (e) {
628
+ }
629
+ return properties;
630
+ }
2
631
  function normalizeFeatureFlags(input) {
3
632
  if (Array.isArray(input)) {
4
633
  return Object.fromEntries(input.map((name) => [name, "true"]));
@@ -493,6 +1122,7 @@ async function postJson(url, body, headers, opts) {
493
1122
  const resp = await runWithTracingSuppressed(
494
1123
  () => fetch(url, {
495
1124
  method: "POST",
1125
+ redirect: headers["X-Raindrop-Replay-Id"] !== void 0 ? "error" : "follow",
496
1126
  headers: {
497
1127
  "Content-Type": "application/json",
498
1128
  ...headers
@@ -681,31 +1311,36 @@ function resolveLocalDebuggerBaseUrl(baseUrl) {
681
1311
  function localDebuggerEnabled(baseUrl) {
682
1312
  return resolveLocalDebuggerBaseUrl(baseUrl) !== null;
683
1313
  }
1314
+ var LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS = 2e3;
684
1315
  function mirrorTraceExportToLocalDebugger(body, options = {}) {
685
1316
  var _a;
686
1317
  const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
687
- if (!baseUrl) return;
688
- void postJson(`${baseUrl}traces`, body, {}, {
1318
+ if (!baseUrl) return Promise.resolve();
1319
+ return postJson(`${baseUrl}traces`, body, {}, {
689
1320
  maxAttempts: 1,
690
1321
  debug: (_a = options.debug) != null ? _a : false,
691
- sdkName: options.sdkName
1322
+ sdkName: options.sdkName,
1323
+ timeoutMs: LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS
692
1324
  }).catch(() => {
693
1325
  });
694
1326
  }
695
1327
  function mirrorPartialEventToLocalDebugger(event, options = {}) {
696
1328
  var _a;
697
1329
  const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
698
- if (!baseUrl) return;
1330
+ if (!baseUrl) return Promise.resolve();
699
1331
  const headers = options.writeKey ? { Authorization: `Bearer ${options.writeKey}` } : {};
700
- void postJson(`${baseUrl}events/track_partial`, event, headers, {
1332
+ return postJson(`${baseUrl}events/track_partial`, event, headers, {
701
1333
  maxAttempts: 1,
702
1334
  debug: (_a = options.debug) != null ? _a : false,
703
- sdkName: options.sdkName
1335
+ sdkName: options.sdkName,
1336
+ timeoutMs: LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS
704
1337
  }).catch(() => {
705
1338
  });
706
1339
  }
707
1340
  function sendLocalDebuggerLiveEvent(event, options = {}) {
708
1341
  var _a, _b;
1342
+ const destination = currentReplayTraceDestination();
1343
+ if (destination && destination.kind !== "workshop") return;
709
1344
  const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
710
1345
  if (!baseUrl) return;
711
1346
  void postJson(
@@ -745,6 +1380,13 @@ function projectIdHeaders(projectId) {
745
1380
  }
746
1381
  var SHUTDOWN_DEADLINE_MS = 1e4;
747
1382
  var POST_SHUTDOWN_TIMEOUT_MS = 5e3;
1383
+ function appGitOwnerId(prefix) {
1384
+ try {
1385
+ return `${prefix}:${randomUUID()}`;
1386
+ } catch (e) {
1387
+ return `${prefix}:${Date.now().toString(36)}:${Math.random().toString(36).slice(2)}`;
1388
+ }
1389
+ }
748
1390
  function mergePatches(target, source) {
749
1391
  var _a, _b, _c, _d, _e, _f, _g, _h, _i;
750
1392
  const out = { ...target, ...source };
@@ -794,22 +1436,25 @@ function eventTelemetryProperties(patch) {
794
1436
  }
795
1437
  var EventShipper = class {
796
1438
  constructor(opts) {
1439
+ this.appGitOwner = appGitOwnerId("event");
797
1440
  this.buffers = /* @__PURE__ */ new Map();
798
1441
  this.sticky = /* @__PURE__ */ new Map();
799
1442
  this.timers = /* @__PURE__ */ new Map();
800
1443
  this.inFlight = /* @__PURE__ */ new Set();
801
1444
  this.hasShutdown = false;
802
- var _a, _b, _c, _d, _e, _f, _g, _h;
803
- this.writeKey = (_a = opts.writeKey) == null ? void 0 : _a.trim();
804
- this.baseUrl = (_b = formatEndpoint(opts.endpoint)) != null ? _b : "https://api.raindrop.ai/v1/";
1445
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
1446
+ this.appGitContext = (_a = opts.appGitContext) != null ? _a : createAppGitContext(opts.appGit);
1447
+ this.ownsAppGitContext = opts.appGitContext === void 0;
1448
+ this.writeKey = (_b = opts.writeKey) == null ? void 0 : _b.trim();
1449
+ this.baseUrl = (_c = formatEndpoint(opts.endpoint)) != null ? _c : "https://api.raindrop.ai/v1/";
805
1450
  this.enabled = opts.enabled !== false;
806
1451
  this.debug = opts.debug;
807
- this.partialFlushMs = (_c = opts.partialFlushMs) != null ? _c : 1e3;
808
- this.sdkName = (_d = opts.sdkName) != null ? _d : "core";
1452
+ this.partialFlushMs = (_d = opts.partialFlushMs) != null ? _d : 1e3;
1453
+ this.sdkName = (_e = opts.sdkName) != null ? _e : "core";
809
1454
  this.prefix = `[raindrop-ai/${this.sdkName}]`;
810
- this.defaultEventName = (_e = opts.defaultEventName) != null ? _e : "ai_generation";
1455
+ this.defaultEventName = (_f = opts.defaultEventName) != null ? _f : "ai_generation";
811
1456
  this.maxTextFieldCharsOpt = opts.maxTextFieldChars;
812
- this.localDebuggerUrl = (_f = resolveLocalDebuggerBaseUrl(opts.localDebuggerUrl)) != null ? _f : void 0;
1457
+ this.localDebuggerUrl = (_g = resolveLocalDebuggerBaseUrl(opts.localDebuggerUrl)) != null ? _g : void 0;
813
1458
  if (this.debug && this.localDebuggerUrl) {
814
1459
  console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
815
1460
  }
@@ -820,8 +1465,8 @@ var EventShipper = class {
820
1465
  const isNode = typeof process !== "undefined" && typeof process.version === "string";
821
1466
  this.context = {
822
1467
  library: {
823
- name: (_g = opts.libraryName) != null ? _g : "@raindrop-ai/core",
824
- version: (_h = opts.libraryVersion) != null ? _h : "0.0.0"
1468
+ name: (_h = opts.libraryName) != null ? _h : "@raindrop-ai/core",
1469
+ version: (_i = opts.libraryVersion) != null ? _i : "0.0.0"
825
1470
  },
826
1471
  metadata: {
827
1472
  jsRuntime: isNode ? "node" : "web",
@@ -829,6 +1474,9 @@ var EventShipper = class {
829
1474
  }
830
1475
  };
831
1476
  }
1477
+ ownAppGitContextForShutdown() {
1478
+ this.ownsAppGitContext = true;
1479
+ }
832
1480
  isDebugEnabled() {
833
1481
  return this.debug;
834
1482
  }
@@ -877,6 +1525,15 @@ var EventShipper = class {
877
1525
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
878
1526
  if (!this.enabled) return;
879
1527
  if (!eventId || !eventId.trim()) return;
1528
+ const capturedSticky = this.sticky.get(eventId);
1529
+ const eventAlreadyKnown = capturedSticky !== void 0 || this.buffers.has(eventId);
1530
+ const destination = currentReplayTraceDestination();
1531
+ const cloudReplay = destination !== void 0 && destination.kind !== "workshop";
1532
+ if ((capturedSticky == null ? void 0 : capturedSticky.replayOnly) === true || !eventAlreadyKnown && cloudReplay) {
1533
+ if (patch.isPending === false) this.sticky.delete(eventId);
1534
+ else this.sticky.set(eventId, { ...capturedSticky, replayOnly: true });
1535
+ return;
1536
+ }
880
1537
  const maxChars = resolveMaxTextFieldChars(this.maxTextFieldCharsOpt);
881
1538
  if (typeof patch.input === "string" && patch.input.length > maxChars) {
882
1539
  patch = { ...patch, input: capText(patch.input, maxChars) };
@@ -898,6 +1555,13 @@ var EventShipper = class {
898
1555
  }
899
1556
  const sticky = (_c = this.sticky.get(eventId)) != null ? _c : {};
900
1557
  const existing = (_d = this.buffers.get(eventId)) != null ? _d : {};
1558
+ patch = {
1559
+ ...patch,
1560
+ properties: withAppGitProperties(
1561
+ patch.properties,
1562
+ this.appGitContext.forOperation(eventId, patch.properties, this.appGitOwner)
1563
+ )
1564
+ };
901
1565
  const merged = mergePatches(existing, patch);
902
1566
  merged.isPending = (_g = (_f = (_e = patch.isPending) != null ? _e : existing.isPending) != null ? _f : sticky.isPending) != null ? _g : true;
903
1567
  this.buffers.set(eventId, merged);
@@ -911,6 +1575,8 @@ var EventShipper = class {
911
1575
  if (t) clearTimeout(t);
912
1576
  if (merged.isPending === false) {
913
1577
  await this.flushOne(eventId);
1578
+ if (this.appGitContext.releaseOperation) this.appGitContext.releaseOperation(eventId, this.appGitOwner);
1579
+ else this.appGitContext.finishOperation(eventId);
914
1580
  return;
915
1581
  }
916
1582
  const timeout = setTimeout(() => {
@@ -935,15 +1601,21 @@ var EventShipper = class {
935
1601
  try {
936
1602
  for (const t of this.timers.values()) clearTimeout(t);
937
1603
  this.timers.clear();
1604
+ for (const [eventId, sticky] of this.sticky) {
1605
+ if (sticky.replayOnly) this.sticky.delete(eventId);
1606
+ }
938
1607
  const settled = await raceWithTimeout(this.flush(), SHUTDOWN_DEADLINE_MS);
939
1608
  if (!settled) this.warnShutdownDrop("in-flight request(s) at shutdown");
940
1609
  } finally {
941
1610
  this.shutdownDeadlineAt = void 0;
1611
+ if (this.ownsAppGitContext) this.appGitContext.dispose();
942
1612
  }
943
1613
  }
944
1614
  async trackSignal(signal) {
945
1615
  var _a, _b;
946
1616
  if (!this.enabled) return;
1617
+ const destination = currentReplayTraceDestination();
1618
+ if (destination && destination.kind !== "workshop") return;
947
1619
  const body = [
948
1620
  {
949
1621
  event_id: signal.eventId,
@@ -978,6 +1650,8 @@ var EventShipper = class {
978
1650
  }
979
1651
  async identify(users) {
980
1652
  if (!this.enabled) return;
1653
+ const destination = currentReplayTraceDestination();
1654
+ if (destination && destination.kind !== "workshop") return;
981
1655
  const list = Array.isArray(users) ? users : [users];
982
1656
  const body = list.filter((user) => {
983
1657
  if (!(user == null ? void 0 : user.userId) || !user.userId.trim()) {
@@ -1030,8 +1704,9 @@ var EventShipper = class {
1030
1704
  this.buffers.delete(eventId);
1031
1705
  if (!accumulated) return;
1032
1706
  const sticky = (_a = this.sticky.get(eventId)) != null ? _a : {};
1033
- const eventName = (_c = (_b = accumulated.eventName) != null ? _b : sticky.eventName) != null ? _c : this.defaultEventName;
1034
- const userId = (_d = accumulated.userId) != null ? _d : sticky.userId;
1707
+ const isPending = (_c = (_b = accumulated.isPending) != null ? _b : sticky.isPending) != null ? _c : true;
1708
+ const eventName = (_e = (_d = accumulated.eventName) != null ? _d : sticky.eventName) != null ? _e : this.defaultEventName;
1709
+ const userId = (_f = accumulated.userId) != null ? _f : sticky.userId;
1035
1710
  if (!userId) {
1036
1711
  if (this.debug) {
1037
1712
  console.warn(`${this.prefix} skipping track_partial for ${eventId}: missing userId`);
@@ -1039,14 +1714,13 @@ var EventShipper = class {
1039
1714
  this.sticky.delete(eventId);
1040
1715
  return;
1041
1716
  }
1042
- const { wizardSession, ...restProperties } = (_e = accumulated.properties) != null ? _e : {};
1717
+ const { wizardSession, ...restProperties } = (_g = accumulated.properties) != null ? _g : {};
1043
1718
  let telemetryProperties = {};
1044
1719
  try {
1045
1720
  telemetryProperties = eventTelemetryProperties(accumulated);
1046
1721
  } catch (e) {
1047
1722
  }
1048
- const convoId = (_f = accumulated.convoId) != null ? _f : sticky.convoId;
1049
- const isPending = (_h = (_g = accumulated.isPending) != null ? _g : sticky.isPending) != null ? _h : true;
1723
+ const convoId = (_h = accumulated.convoId) != null ? _h : sticky.convoId;
1050
1724
  const payload = {
1051
1725
  event_id: eventId,
1052
1726
  user_id: userId,
@@ -1088,29 +1762,30 @@ var EventShipper = class {
1088
1762
  endpoint: url
1089
1763
  });
1090
1764
  }
1091
- if (this.localDebuggerUrl) {
1092
- mirrorPartialEventToLocalDebugger(payload, {
1093
- baseUrl: this.localDebuggerUrl,
1094
- writeKey: this.writeKey,
1095
- debug: this.debug,
1096
- sdkName: this.sdkName
1097
- });
1098
- }
1765
+ const mirror = this.localDebuggerUrl ? mirrorPartialEventToLocalDebugger(payload, {
1766
+ baseUrl: this.localDebuggerUrl,
1767
+ writeKey: this.writeKey,
1768
+ debug: this.debug,
1769
+ sdkName: this.sdkName
1770
+ }) : void 0;
1099
1771
  if (!this.writeKey) {
1100
1772
  if (!isPending) this.sticky.delete(eventId);
1773
+ if (mirror) await mirror;
1101
1774
  return;
1102
1775
  }
1103
1776
  const opts = this.requestOpts();
1104
1777
  if (!opts) {
1105
1778
  this.warnShutdownDrop(`track_partial ${eventId}`);
1106
1779
  if (!isPending) this.sticky.delete(eventId);
1780
+ if (mirror) await mirror;
1107
1781
  return;
1108
1782
  }
1109
1783
  const p = postJson(url, payload, this.requestHeaders(), opts);
1110
- this.inFlight.add(p);
1784
+ const combined = mirror ? Promise.all([mirror, p]).then(() => void 0) : p;
1785
+ this.inFlight.add(combined);
1111
1786
  try {
1112
1787
  try {
1113
- await p;
1788
+ await combined;
1114
1789
  if (this.debug) {
1115
1790
  console.log(`${this.prefix} sent track_partial ${eventId} (${eventName})`);
1116
1791
  }
@@ -1122,7 +1797,7 @@ var EventShipper = class {
1122
1797
  );
1123
1798
  }
1124
1799
  } finally {
1125
- this.inFlight.delete(p);
1800
+ this.inFlight.delete(combined);
1126
1801
  }
1127
1802
  if (!isPending) {
1128
1803
  this.sticky.delete(eventId);
@@ -1368,6 +2043,13 @@ function redactJsonAttributeValue(key, value) {
1368
2043
  if (scrubbedJson === json) return void 0;
1369
2044
  return { stringValue: scrubbedJson };
1370
2045
  }
2046
+ function appGitOwnerId2(prefix) {
2047
+ try {
2048
+ return `${prefix}:${randomUUID()}`;
2049
+ } catch (e) {
2050
+ return `${prefix}:${Date.now().toString(36)}:${Math.random().toString(36).slice(2)}`;
2051
+ }
2052
+ }
1371
2053
  function identityAttrs(args) {
1372
2054
  return [
1373
2055
  attrString("ai.telemetry.metadata.raindrop.ai.userId", args.userId),
@@ -1390,23 +2072,30 @@ function applyOtelSpanAttributeLimit(limit) {
1390
2072
  }
1391
2073
  var TraceShipper = class {
1392
2074
  constructor(opts) {
2075
+ this.appGitOwner = appGitOwnerId2("trace");
2076
+ this.appGitEventIds = /* @__PURE__ */ new WeakMap();
2077
+ this.appGitActiveSpans = /* @__PURE__ */ new Map();
2078
+ this.appGitCaptured = /* @__PURE__ */ new WeakSet();
2079
+ this.appGitAdded = /* @__PURE__ */ new WeakMap();
1393
2080
  this.queue = [];
1394
2081
  this.inFlight = /* @__PURE__ */ new Set();
1395
2082
  this.hasShutdown = false;
1396
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
1397
- this.writeKey = (_a = opts.writeKey) == null ? void 0 : _a.trim();
1398
- this.baseUrl = (_b = formatEndpoint(opts.endpoint)) != null ? _b : "https://api.raindrop.ai/v1/";
2083
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
2084
+ this.appGitContext = (_a = opts.appGitContext) != null ? _a : createAppGitContext(opts.appGit);
2085
+ this.ownsAppGitContext = opts.appGitContext === void 0;
2086
+ this.writeKey = (_b = opts.writeKey) == null ? void 0 : _b.trim();
2087
+ this.baseUrl = (_c = formatEndpoint(opts.endpoint)) != null ? _c : "https://api.raindrop.ai/v1/";
1399
2088
  this.enabled = opts.enabled !== false;
1400
2089
  this.debug = opts.debug;
1401
2090
  this.debugSpans = opts.debugSpans === true;
1402
- this.flushIntervalMs = (_c = opts.flushIntervalMs) != null ? _c : 1e3;
1403
- this.maxBatchSize = (_d = opts.maxBatchSize) != null ? _d : 50;
1404
- this.maxQueueSize = (_e = opts.maxQueueSize) != null ? _e : 5e3;
1405
- this.sdkName = (_f = opts.sdkName) != null ? _f : "core";
2091
+ this.flushIntervalMs = (_d = opts.flushIntervalMs) != null ? _d : 1e3;
2092
+ this.maxBatchSize = (_e = opts.maxBatchSize) != null ? _e : 50;
2093
+ this.maxQueueSize = (_f = opts.maxQueueSize) != null ? _f : 5e3;
2094
+ this.sdkName = (_g = opts.sdkName) != null ? _g : "core";
1406
2095
  this.prefix = `[raindrop-ai/${this.sdkName}]`;
1407
- this.serviceName = (_g = opts.serviceName) != null ? _g : "raindrop.core";
1408
- this.serviceVersion = (_h = opts.serviceVersion) != null ? _h : "0.0.0";
1409
- this.localDebuggerUrl = (_i = resolveLocalDebuggerBaseUrl(opts.localDebuggerUrl)) != null ? _i : void 0;
2096
+ this.serviceName = (_h = opts.serviceName) != null ? _h : "raindrop.core";
2097
+ this.serviceVersion = (_i = opts.serviceVersion) != null ? _i : "0.0.0";
2098
+ this.localDebuggerUrl = (_j = resolveLocalDebuggerBaseUrl(opts.localDebuggerUrl)) != null ? _j : void 0;
1410
2099
  if (this.debug && this.localDebuggerUrl) {
1411
2100
  console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
1412
2101
  }
@@ -1470,7 +2159,10 @@ var TraceShipper = class {
1470
2159
  try {
1471
2160
  const result = this.transformSpanHook(current);
1472
2161
  if (result === null) return null;
1473
- if (result !== void 0) current = result;
2162
+ if (result !== void 0) {
2163
+ copyReplayTraceDestination(current, result);
2164
+ current = result;
2165
+ }
1474
2166
  } catch (err) {
1475
2167
  if (this.debug) {
1476
2168
  const msg = err instanceof Error ? err.message : String(err);
@@ -1480,13 +2172,19 @@ var TraceShipper = class {
1480
2172
  }
1481
2173
  }
1482
2174
  try {
1483
- current = normalizeModelUsageSpan(current);
2175
+ const normalized = normalizeModelUsageSpan(current);
2176
+ copyReplayTraceDestination(current, normalized);
2177
+ current = normalized;
1484
2178
  } catch (e) {
1485
2179
  }
1486
2180
  if (!this.disableDefaultRedaction) {
1487
- current = defaultTransformSpan(current);
2181
+ const redacted = defaultTransformSpan(current);
2182
+ copyReplayTraceDestination(current, redacted);
2183
+ current = redacted;
1488
2184
  }
1489
- return this.capSpanAttributes(current);
2185
+ const capped = this.capSpanAttributes(current);
2186
+ copyReplayTraceDestination(current, capped);
2187
+ return capped;
1490
2188
  }
1491
2189
  isDebugEnabled() {
1492
2190
  return this.debug;
@@ -1498,46 +2196,84 @@ var TraceShipper = class {
1498
2196
  return { ...this.authHeaders(), ...projectIdHeaders(this.projectId) };
1499
2197
  }
1500
2198
  startSpan(args) {
1501
- var _a, _b;
2199
+ var _a, _b, _c;
1502
2200
  const ids = createSpanIds(args.parent);
1503
2201
  const started = (_a = args.startTimeUnixNano) != null ? _a : nowUnixNanoString();
1504
2202
  const attrs = [
1505
2203
  attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId),
1506
2204
  ...identityAttrs(args),
1507
- attrString("ai.operationId", args.operationId)
2205
+ attrString("ai.operationId", args.operationId),
2206
+ ...Object.entries(evalScopeAttributes()).map(([key, value]) => attrString(key, value))
1508
2207
  ];
1509
2208
  if ((_b = args.attributes) == null ? void 0 : _b.length) attrs.push(...args.attributes);
1510
- const span = { ids, name: args.name, startTimeUnixNano: started, attributes: attrs };
1511
- this.mirrorToLocalDebugger(
1512
- buildOtlpSpan({
1513
- ids: span.ids,
1514
- name: span.name,
1515
- startTimeUnixNano: span.startTimeUnixNano,
1516
- endTimeUnixNano: span.startTimeUnixNano,
1517
- // placeholder — will be updated on endSpan
1518
- attributes: span.attributes,
1519
- status: { code: SpanStatusCode.UNSET }
1520
- })
1521
- );
2209
+ const tracksAppGit = this.appGitActiveSpans.has(args.eventId) || this.appGitActiveSpans.size < 1e4;
2210
+ const appGitOverrides = appGitPropertiesFromAttributes(attrs);
2211
+ const span = {
2212
+ ids,
2213
+ name: args.name,
2214
+ startTimeUnixNano: started,
2215
+ attributes: withAppGitAttributes(
2216
+ attrs,
2217
+ this.appGitContext.forOperation(args.eventId, appGitOverrides, this.appGitOwner)
2218
+ )
2219
+ };
2220
+ rememberReplayTraceDestination(span);
2221
+ this.appGitCaptured.add(span);
2222
+ this.appGitEventIds.set(span, args.eventId);
2223
+ if (tracksAppGit) {
2224
+ this.appGitActiveSpans.set(args.eventId, ((_c = this.appGitActiveSpans.get(args.eventId)) != null ? _c : 0) + 1);
2225
+ }
2226
+ this.appGitAdded.set(span, new Set(span.attributes.filter((attr) => !attrs.includes(attr))));
2227
+ const openSpan = buildOtlpSpan({
2228
+ ids: span.ids,
2229
+ name: span.name,
2230
+ startTimeUnixNano: span.startTimeUnixNano,
2231
+ endTimeUnixNano: span.startTimeUnixNano,
2232
+ // placeholder — will be updated on endSpan
2233
+ attributes: span.attributes,
2234
+ status: { code: SpanStatusCode.UNSET }
2235
+ });
2236
+ copyReplayTraceDestination(span, openSpan);
2237
+ this.mirrorToLocalDebugger(openSpan);
1522
2238
  return span;
1523
2239
  }
1524
- mirrorToLocalDebugger(span) {
1525
- if (!this.localDebuggerUrl) return;
2240
+ mirrorToLocalDebugger(span, completed = false) {
2241
+ const destination = replayTraceDestinationFor(span);
2242
+ if (destination && destination.kind !== "workshop") return;
2243
+ const localDebuggerUrl = (destination == null ? void 0 : destination.kind) === "workshop" ? destination.url : this.localDebuggerUrl;
2244
+ if (!localDebuggerUrl) return;
1526
2245
  const redacted = this.redactSpan(span);
1527
2246
  if (redacted === null) return;
2247
+ if (completed && (destination == null ? void 0 : destination.kind) === "workshop") {
2248
+ recordReplayExportedSpan(
2249
+ destination,
2250
+ base64ToHex(redacted.spanId),
2251
+ base64ToHex(redacted.traceId)
2252
+ );
2253
+ }
1528
2254
  const body = buildExportTraceServiceRequest([redacted], this.serviceName, this.serviceVersion);
1529
- mirrorTraceExportToLocalDebugger(body, {
1530
- baseUrl: this.localDebuggerUrl,
2255
+ const p = mirrorTraceExportToLocalDebugger(body, {
2256
+ baseUrl: localDebuggerUrl,
1531
2257
  debug: false,
1532
2258
  sdkName: this.sdkName
1533
2259
  });
2260
+ this.inFlight.add(p);
2261
+ void p.finally(() => {
2262
+ this.inFlight.delete(p);
2263
+ });
1534
2264
  }
1535
2265
  endSpan(span, extra) {
1536
- var _a, _b;
2266
+ var _a, _b, _c;
1537
2267
  if (span.endTimeUnixNano) return;
1538
2268
  span.endTimeUnixNano = (_a = extra == null ? void 0 : extra.endTimeUnixNano) != null ? _a : nowUnixNanoString();
1539
2269
  if ((_b = extra == null ? void 0 : extra.attributes) == null ? void 0 : _b.length) {
2270
+ const overrides = appGitPropertiesFromAttributes(extra.attributes);
2271
+ const eventId2 = this.appGitEventIds.get(span);
2272
+ const snapshot = eventId2 ? this.appGitContext.forOperation(eventId2, overrides, this.appGitOwner) : overrides;
2273
+ const added = this.appGitAdded.get(span);
2274
+ 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));
1540
2275
  span.attributes.push(...extra.attributes);
2276
+ span.attributes = withAppGitAttributes(span.attributes, snapshot);
1541
2277
  }
1542
2278
  let status = extra == null ? void 0 : extra.status;
1543
2279
  if (!status && (extra == null ? void 0 : extra.error) !== void 0) {
@@ -1552,30 +2288,65 @@ var TraceShipper = class {
1552
2288
  attributes: span.attributes,
1553
2289
  status
1554
2290
  });
2291
+ copyReplayTraceDestination(span, otlp);
2292
+ this.appGitCaptured.add(otlp);
1555
2293
  this.enqueue(otlp);
1556
- this.mirrorToLocalDebugger(otlp);
2294
+ this.mirrorToLocalDebugger(otlp, true);
2295
+ const eventId = this.appGitEventIds.get(span);
2296
+ if (eventId && this.appGitActiveSpans.has(eventId)) {
2297
+ const remaining = ((_c = this.appGitActiveSpans.get(eventId)) != null ? _c : 1) - 1;
2298
+ if (remaining > 0) this.appGitActiveSpans.set(eventId, remaining);
2299
+ else {
2300
+ this.appGitActiveSpans.delete(eventId);
2301
+ if (this.appGitContext.releaseOperation) this.appGitContext.releaseOperation(eventId, this.appGitOwner);
2302
+ else if (this.ownsAppGitContext) this.appGitContext.finishOperation(eventId);
2303
+ }
2304
+ }
1557
2305
  }
1558
2306
  createSpan(args) {
1559
2307
  var _a;
1560
2308
  const ids = createSpanIds(args.parent);
1561
2309
  const attrs = [
1562
2310
  attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId),
1563
- ...identityAttrs(args)
2311
+ ...identityAttrs(args),
2312
+ ...Object.entries(evalScopeAttributes()).map(([key, value]) => attrString(key, value))
1564
2313
  ];
1565
2314
  if ((_a = args.attributes) == null ? void 0 : _a.length) attrs.push(...args.attributes);
2315
+ const tracksAppGit = !this.appGitActiveSpans.has(args.eventId);
1566
2316
  const otlp = buildOtlpSpan({
1567
2317
  ids,
1568
2318
  name: args.name,
1569
2319
  startTimeUnixNano: args.startTimeUnixNano,
1570
2320
  endTimeUnixNano: args.endTimeUnixNano,
1571
- attributes: attrs,
2321
+ attributes: withAppGitAttributes(
2322
+ attrs,
2323
+ this.appGitContext.forOperation(
2324
+ args.eventId,
2325
+ appGitPropertiesFromAttributes(attrs),
2326
+ this.appGitOwner
2327
+ )
2328
+ ),
1572
2329
  status: args.status
1573
2330
  });
2331
+ rememberReplayTraceDestination(otlp);
2332
+ this.appGitCaptured.add(otlp);
2333
+ if (tracksAppGit) {
2334
+ if (this.appGitContext.releaseOperation) this.appGitContext.releaseOperation(args.eventId, this.appGitOwner);
2335
+ else if (this.ownsAppGitContext) this.appGitContext.finishOperation(args.eventId);
2336
+ }
1574
2337
  this.enqueue(otlp);
1575
- this.mirrorToLocalDebugger(otlp);
2338
+ this.mirrorToLocalDebugger(otlp, true);
1576
2339
  }
1577
2340
  enqueue(span) {
2341
+ var _a;
1578
2342
  if (!this.enabled) return;
2343
+ const attributes = (_a = span.attributes) != null ? _a : [];
2344
+ const enriched = this.appGitCaptured.has(span) ? attributes : withAppGitAttributes(attributes, this.appGitContext.snapshot(appGitPropertiesFromAttributes(attributes)));
2345
+ if (enriched !== attributes) {
2346
+ const original = span;
2347
+ span = { ...span, attributes: enriched.filter((attr) => attr !== void 0) };
2348
+ copyReplayTraceDestination(original, span);
2349
+ }
1579
2350
  if (this.debugSpans) {
1580
2351
  const short = (s) => s ? s.slice(-8) : "none";
1581
2352
  console.log(
@@ -1586,6 +2357,13 @@ var TraceShipper = class {
1586
2357
  }
1587
2358
  const redacted = this.redactSpan(span);
1588
2359
  if (redacted === null) return;
2360
+ const destination = replayTraceDestinationFor(redacted);
2361
+ recordReplayExportedSpan(
2362
+ destination,
2363
+ base64ToHex(redacted.spanId),
2364
+ base64ToHex(redacted.traceId)
2365
+ );
2366
+ if ((destination == null ? void 0 : destination.kind) === "workshop") return;
1589
2367
  if (this.queue.length >= this.maxQueueSize) {
1590
2368
  this.queue.shift();
1591
2369
  }
@@ -1604,47 +2382,67 @@ var TraceShipper = class {
1604
2382
  }
1605
2383
  }
1606
2384
  async flush() {
1607
- if (!this.enabled) return;
2385
+ var _a;
2386
+ if (!this.enabled) {
2387
+ await Promise.all([...this.inFlight].map((p) => p.catch(() => {
2388
+ })));
2389
+ return;
2390
+ }
1608
2391
  if (this.timer) {
1609
2392
  clearTimeout(this.timer);
1610
2393
  this.timer = void 0;
1611
2394
  }
1612
2395
  while (this.queue.length > 0) {
1613
2396
  const batch = this.queue.splice(0, this.maxBatchSize);
1614
- if (!this.writeKey) continue;
1615
- const opts = this.requestOpts();
1616
- if (!opts) {
1617
- rateLimitedLog(
1618
- `${this.prefix}.shutdown_deadline`,
1619
- () => console.warn(
1620
- `${this.prefix} shutdown flush deadline exceeded; dropping ${batch.length} spans`
1621
- )
1622
- );
1623
- continue;
1624
- }
1625
- const body = buildExportTraceServiceRequest(batch, this.serviceName, this.serviceVersion);
1626
- const url = `${this.baseUrl}traces`;
1627
- if (this.debug) {
1628
- console.log(`${this.prefix} sending traces batch`, {
1629
- spans: batch.length,
1630
- endpoint: url
1631
- });
2397
+ const groups = /* @__PURE__ */ new Map();
2398
+ for (const span of batch) {
2399
+ const destination = replayTraceDestinationFor(span);
2400
+ const spans = groups.get(destination);
2401
+ if (spans) spans.push(span);
2402
+ else groups.set(destination, [span]);
1632
2403
  }
1633
- const p = postJson(url, body, this.requestHeaders(), opts);
1634
- this.inFlight.add(p);
1635
- try {
1636
- try {
1637
- await p;
1638
- if (this.debug) console.log(`${this.prefix} sent ${batch.length} spans`);
1639
- } catch (err) {
1640
- const msg = err instanceof Error ? err.message : String(err);
2404
+ for (const [destination, spans] of groups) {
2405
+ if (!destination && !this.writeKey) continue;
2406
+ if ((destination == null ? void 0 : destination.kind) === "workshop") continue;
2407
+ const opts = this.requestOpts();
2408
+ if (!opts) {
1641
2409
  rateLimitedLog(
1642
- `${this.prefix}.send_spans_failed`,
1643
- () => console.warn(`${this.prefix} failed to send ${batch.length} spans: ${msg}`)
2410
+ `${this.prefix}.shutdown_deadline`,
2411
+ () => console.warn(
2412
+ `${this.prefix} shutdown flush deadline exceeded; dropping ${spans.length} spans`
2413
+ )
1644
2414
  );
2415
+ continue;
2416
+ }
2417
+ const body = buildExportTraceServiceRequest(spans, this.serviceName, this.serviceVersion);
2418
+ const url = destination ? replayTraceUrl(destination.url) : `${this.baseUrl}traces`;
2419
+ const headers = destination ? {
2420
+ Authorization: `Bearer ${destination.apiKey}`,
2421
+ "X-Raindrop-Replay-Id": destination.replayId,
2422
+ "X-Raindrop-Project-Id": (_a = destination.projectId) != null ? _a : "default"
2423
+ } : this.requestHeaders();
2424
+ if (this.debug) {
2425
+ console.log(`${this.prefix} sending traces batch`, {
2426
+ spans: spans.length,
2427
+ endpoint: url
2428
+ });
2429
+ }
2430
+ const p = postJson(url, body, headers, opts);
2431
+ this.inFlight.add(p);
2432
+ try {
2433
+ try {
2434
+ await p;
2435
+ if (this.debug) console.log(`${this.prefix} sent ${spans.length} spans`);
2436
+ } catch (err) {
2437
+ const msg = err instanceof Error ? err.message : String(err);
2438
+ rateLimitedLog(
2439
+ `${this.prefix}.send_spans_failed`,
2440
+ () => console.warn(`${this.prefix} failed to send ${spans.length} spans: ${msg}`)
2441
+ );
2442
+ }
2443
+ } finally {
2444
+ this.inFlight.delete(p);
1645
2445
  }
1646
- } finally {
1647
- this.inFlight.delete(p);
1648
2446
  }
1649
2447
  }
1650
2448
  }
@@ -1687,136 +2485,22 @@ var TraceShipper = class {
1687
2485
  if (!settled) {
1688
2486
  rateLimitedLog(
1689
2487
  `${this.prefix}.shutdown_deadline`,
1690
- () => console.warn(`${this.prefix} shutdown flush deadline exceeded; abandoning in-flight spans`)
2488
+ () => console.warn(
2489
+ `${this.prefix} shutdown flush deadline exceeded; abandoning in-flight spans`
2490
+ )
1691
2491
  );
1692
2492
  }
1693
2493
  } finally {
1694
2494
  this.shutdownDeadlineAt = void 0;
2495
+ if (this.ownsAppGitContext) this.appGitContext.dispose();
1695
2496
  }
1696
2497
  }
1697
2498
  };
1698
- var NOOP_SPAN = {
1699
- traceIdB64: "",
1700
- spanIdB64: "",
1701
- eventId: "",
1702
- log() {
1703
- }
1704
- };
1705
- function getAsyncLocalStorageCtor() {
1706
- return globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
1707
- }
1708
- var SynchronousContextStorage = class {
1709
- constructor() {
1710
- this._stack = [];
1711
- }
1712
- isEmpty() {
1713
- return this._stack.length === 0;
1714
- }
1715
- getStore() {
1716
- return this._stack[this._stack.length - 1];
1717
- }
1718
- run(store, callback) {
1719
- this._stack.push(store);
1720
- try {
1721
- return callback();
1722
- } finally {
1723
- this._stack.pop();
1724
- }
1725
- }
1726
- };
1727
- var ContextManager = class {
1728
- };
1729
- var RaindropContextManager = class extends ContextManager {
1730
- constructor() {
1731
- super();
1732
- this._fallback = null;
1733
- const Ctor = getAsyncLocalStorageCtor();
1734
- if (Ctor) {
1735
- this._storage = new Ctor();
1736
- return;
1737
- }
1738
- this._fallback = new SynchronousContextStorage();
1739
- this._storage = this._fallback;
1740
- }
1741
- maybeAdoptAsyncLocalStorage() {
1742
- if (!this._fallback || !this._fallback.isEmpty()) return;
1743
- const Ctor = getAsyncLocalStorageCtor();
1744
- if (!Ctor) return;
1745
- this._storage = new Ctor();
1746
- this._fallback = null;
1747
- }
1748
- isReady() {
1749
- return true;
1750
- }
1751
- getParentSpanIds() {
1752
- this.maybeAdoptAsyncLocalStorage();
1753
- const span = this._storage.getStore();
1754
- if (!span || span === NOOP_SPAN) return void 0;
1755
- return {
1756
- traceIdB64: span.traceIdB64,
1757
- spanIdB64: span.spanIdB64,
1758
- eventId: span.eventId
1759
- };
1760
- }
1761
- runInContext(span, callback) {
1762
- this.maybeAdoptAsyncLocalStorage();
1763
- return this._storage.run(span, callback);
1764
- }
1765
- getCurrentSpan() {
1766
- this.maybeAdoptAsyncLocalStorage();
1767
- return this._storage.getStore();
1768
- }
1769
- };
1770
- var _contextManager = null;
1771
- function getContextManager() {
1772
- if (!_contextManager) {
1773
- _contextManager = globalThis.RAINDROP_CONTEXT_MANAGER ? new globalThis.RAINDROP_CONTEXT_MANAGER() : new RaindropContextManager();
1774
- }
1775
- return _contextManager;
1776
- }
1777
- function currentSpan() {
1778
- var _a;
1779
- return (_a = getContextManager().getCurrentSpan()) != null ? _a : NOOP_SPAN;
1780
- }
1781
- function withCurrent(span, callback) {
1782
- return getContextManager().runInContext(span, callback);
1783
- }
1784
- async function getCurrentParentSpanContext() {
1785
- return getContextManager().getParentSpanIds();
1786
- }
1787
- async function runWithParentSpanContext(ctx, fn) {
1788
- const cm = getContextManager();
1789
- const span = {
1790
- traceIdB64: ctx.traceIdB64,
1791
- spanIdB64: ctx.spanIdB64,
1792
- eventId: ctx.eventId
1793
- };
1794
- return cm.runInContext(span, fn);
1795
- }
1796
- async function* asyncGeneratorWithCurrent(span, gen) {
1797
- let nextValue;
1798
- while (true) {
1799
- const result = await withCurrent(span, async () => {
1800
- try {
1801
- return await gen.next(nextValue);
1802
- } catch (e) {
1803
- return { value: void 0, done: true, error: e };
1804
- }
1805
- });
1806
- if ("error" in result && result.error !== void 0) {
1807
- throw result.error;
1808
- }
1809
- if (result.done) {
1810
- return result.value;
1811
- }
1812
- nextValue = yield result.value;
1813
- }
1814
- }
1815
2499
 
1816
2500
  // package.json
1817
2501
  var package_default = {
1818
2502
  name: "@raindrop-ai/ai-sdk",
1819
- version: "0.3.1"};
2503
+ version: "0.3.3"};
1820
2504
 
1821
2505
  // src/internal/version.ts
1822
2506
  var libraryName = package_default.name;
@@ -3342,13 +4026,13 @@ var RaindropTelemetryIntegration = class {
3342
4026
  };
3343
4027
  // ── onStepStart ─────────────────────────────────────────────────────────
3344
4028
  this.onStepStart = (event) => {
3345
- const state = this.getState(event.callId);
3346
- if (!(state == null ? void 0 : state.rootSpan) || !state.rootParent) return;
3347
- const isStream = state.operationId === "ai.streamText" || state.operationId === "ai.streamObject";
3348
- const stepOperationId = isStream ? `${state.operationId}.doStream` : `${state.operationId}.doGenerate`;
3349
- const { operationName, resourceName } = opName(stepOperationId, state.functionId);
4029
+ const state2 = this.getState(event.callId);
4030
+ if (!(state2 == null ? void 0 : state2.rootSpan) || !state2.rootParent) return;
4031
+ const isStream = state2.operationId === "ai.streamText" || state2.operationId === "ai.streamObject";
4032
+ const stepOperationId = isStream ? `${state2.operationId}.doStream` : `${state2.operationId}.doGenerate`;
4033
+ const { operationName, resourceName } = opName(stepOperationId, state2.functionId);
3350
4034
  const inputAttrs = [];
3351
- if (state.recordInputs) {
4035
+ if (state2.recordInputs) {
3352
4036
  if (event.promptMessages) {
3353
4037
  inputAttrs.push(attrString("ai.prompt.messages", safeJsonWithUint8(event.promptMessages)));
3354
4038
  }
@@ -3371,25 +4055,25 @@ var RaindropTelemetryIntegration = class {
3371
4055
  }
3372
4056
  const stepSpan = this.traceShipper.startSpan({
3373
4057
  name: stepOperationId,
3374
- parent: state.rootParent,
3375
- eventId: state.eventId,
3376
- ...state.identity,
4058
+ parent: state2.rootParent,
4059
+ eventId: state2.eventId,
4060
+ ...state2.identity,
3377
4061
  operationId: stepOperationId,
3378
4062
  attributes: [
3379
4063
  attrString("operation.name", operationName),
3380
4064
  attrString("resource.name", resourceName),
3381
- attrString("ai.telemetry.functionId", state.functionId),
4065
+ attrString("ai.telemetry.functionId", state2.functionId),
3382
4066
  ...attrsFromModelProvider(event.provider),
3383
4067
  attrString("ai.model.id", event.modelId),
3384
4068
  attrString(MODEL_USAGE_ATTRIBUTES.requestModel, event.modelId),
3385
4069
  ...inputAttrs,
3386
- ...handoffSpanAttrs(state.handoff)
4070
+ ...handoffSpanAttrs(state2.handoff)
3387
4071
  ]
3388
4072
  });
3389
- state.stepSpan = stepSpan;
3390
- state.stepParent = this.spanParentRef(stepSpan);
3391
- state.stepProvider = event.provider;
3392
- state.stepModelId = event.modelId;
4073
+ state2.stepSpan = stepSpan;
4074
+ state2.stepParent = this.spanParentRef(stepSpan);
4075
+ state2.stepProvider = event.provider;
4076
+ state2.stepModelId = event.modelId;
3393
4077
  };
3394
4078
  this.onToolExecutionStart = (event) => this.toolExecutionStart(event);
3395
4079
  this.onToolExecutionEnd = (event) => this.toolExecutionEnd(event);
@@ -3416,33 +4100,33 @@ var RaindropTelemetryIntegration = class {
3416
4100
  var _a, _b, _c, _d, _e;
3417
4101
  const callId = (_b = event.callId) != null ? _b : (_a = event.chunk) == null ? void 0 : _a.callId;
3418
4102
  if (!callId) return;
3419
- const state = this.getState(callId);
3420
- if (!state) return;
4103
+ const state2 = this.getState(callId);
4104
+ if (!state2) return;
3421
4105
  const chunk = event.chunk;
3422
4106
  if (!chunk || typeof chunk !== "object") return;
3423
4107
  if (chunk.type === "text-delta") {
3424
4108
  const delta = (_c = chunk.textDelta) != null ? _c : chunk.delta;
3425
4109
  if (typeof delta === "string") {
3426
- if (state.accumulatedText.length <= effectiveMaxTextFieldChars()) {
3427
- state.accumulatedText += delta;
4110
+ if (state2.accumulatedText.length <= effectiveMaxTextFieldChars()) {
4111
+ state2.accumulatedText += delta;
3428
4112
  }
3429
- this.emitLive(state, "text_delta", delta);
4113
+ this.emitLive(state2, "text_delta", delta);
3430
4114
  }
3431
4115
  } else if (chunk.type === "reasoning" || chunk.type === "reasoning-delta") {
3432
4116
  const text = (_e = (_d = chunk.textDelta) != null ? _d : chunk.text) != null ? _e : chunk.delta;
3433
4117
  if (typeof text === "string") {
3434
- this.emitLive(state, "reasoning_delta", text);
4118
+ this.emitLive(state2, "reasoning_delta", text);
3435
4119
  }
3436
4120
  }
3437
4121
  };
3438
4122
  // ── onStepFinish ────────────────────────────────────────────────────────
3439
4123
  this.onStepFinish = (event) => {
3440
4124
  var _a, _b, _c, _d, _e, _f, _g, _h, _i;
3441
- const state = this.getState(event.callId);
3442
- if (!(state == null ? void 0 : state.stepSpan)) return;
3443
- const responseModelId = (_b = (_a = event.response) == null ? void 0 : _a.modelId) != null ? _b : state.stepModelId;
4125
+ const state2 = this.getState(event.callId);
4126
+ if (!(state2 == null ? void 0 : state2.stepSpan)) return;
4127
+ const responseModelId = (_b = (_a = event.response) == null ? void 0 : _a.modelId) != null ? _b : state2.stepModelId;
3444
4128
  const outputAttrs = [];
3445
- if (state.recordOutputs) {
4129
+ if (state2.recordOutputs) {
3446
4130
  outputAttrs.push(
3447
4131
  attrString("ai.response.finishReason", event.finishReason),
3448
4132
  attrString("ai.response.text", capText2((_c = event.text) != null ? _c : void 0)),
@@ -3487,7 +4171,7 @@ var RaindropTelemetryIntegration = class {
3487
4171
  if (usage) {
3488
4172
  const usageMetrics = extractUsageMetricsFromUsage(
3489
4173
  usage,
3490
- state.stepProvider,
4174
+ state2.stepProvider,
3491
4175
  event.providerMetadata
3492
4176
  );
3493
4177
  outputAttrs.push(
@@ -3500,51 +4184,51 @@ var RaindropTelemetryIntegration = class {
3500
4184
  ...buildRawModelUsageAttributes(usageMetrics)
3501
4185
  );
3502
4186
  }
3503
- this.emitProviderExecutedToolSpans(event, state);
3504
- this.traceShipper.endSpan(state.stepSpan, { attributes: outputAttrs });
3505
- state.stepSpan = void 0;
3506
- state.stepParent = void 0;
3507
- state.stepProvider = void 0;
3508
- state.stepModelId = void 0;
4187
+ this.emitProviderExecutedToolSpans(event, state2);
4188
+ this.traceShipper.endSpan(state2.stepSpan, { attributes: outputAttrs });
4189
+ state2.stepSpan = void 0;
4190
+ state2.stepParent = void 0;
4191
+ state2.stepProvider = void 0;
4192
+ state2.stepModelId = void 0;
3509
4193
  };
3510
4194
  // ── onEmbedStart ────────────────────────────────────────────────────────
3511
4195
  this.onEmbedStart = (event) => {
3512
- const state = this.getState(event.callId);
3513
- if (!(state == null ? void 0 : state.rootSpan) || !state.rootParent) return;
3514
- const { operationName, resourceName } = opName(event.operationId, state.functionId);
3515
- const inputAttrs = state.recordInputs ? [attrString("ai.values", safeJsonWithUint8(event.values))] : [];
4196
+ const state2 = this.getState(event.callId);
4197
+ if (!(state2 == null ? void 0 : state2.rootSpan) || !state2.rootParent) return;
4198
+ const { operationName, resourceName } = opName(event.operationId, state2.functionId);
4199
+ const inputAttrs = state2.recordInputs ? [attrString("ai.values", safeJsonWithUint8(event.values))] : [];
3516
4200
  const embedSpan = this.traceShipper.startSpan({
3517
4201
  name: event.operationId,
3518
- parent: state.rootParent,
3519
- eventId: state.eventId,
3520
- ...state.identity,
4202
+ parent: state2.rootParent,
4203
+ eventId: state2.eventId,
4204
+ ...state2.identity,
3521
4205
  operationId: event.operationId,
3522
4206
  attributes: [
3523
4207
  attrString("operation.name", operationName),
3524
4208
  attrString("resource.name", resourceName),
3525
- attrString("ai.telemetry.functionId", state.functionId),
4209
+ attrString("ai.telemetry.functionId", state2.functionId),
3526
4210
  ...inputAttrs,
3527
- ...handoffSpanAttrs(state.handoff)
4211
+ ...handoffSpanAttrs(state2.handoff)
3528
4212
  ]
3529
4213
  });
3530
- state.embedSpans.set(event.embedCallId, embedSpan);
4214
+ state2.embedSpans.set(event.embedCallId, embedSpan);
3531
4215
  };
3532
4216
  // ── onEmbedFinish ───────────────────────────────────────────────────────
3533
4217
  this.onEmbedFinish = (event) => {
3534
4218
  var _a;
3535
- const state = this.getState(event.callId);
3536
- if (!state) return;
3537
- const embedSpan = state.embedSpans.get(event.embedCallId);
4219
+ const state2 = this.getState(event.callId);
4220
+ if (!state2) return;
4221
+ const embedSpan = state2.embedSpans.get(event.embedCallId);
3538
4222
  if (!embedSpan) return;
3539
4223
  const outputAttrs = [];
3540
- if (state.recordOutputs) {
4224
+ if (state2.recordOutputs) {
3541
4225
  outputAttrs.push(attrString("ai.embeddings", safeJsonWithUint8(event.embeddings)));
3542
4226
  }
3543
4227
  if (((_a = event.usage) == null ? void 0 : _a.tokens) != null) {
3544
4228
  outputAttrs.push(attrInt("ai.usage.tokens", event.usage.tokens));
3545
4229
  }
3546
4230
  this.traceShipper.endSpan(embedSpan, { attributes: outputAttrs });
3547
- state.embedSpans.delete(event.embedCallId);
4231
+ state2.embedSpans.delete(event.embedCallId);
3548
4232
  };
3549
4233
  // v7 canary.159 renamed `onEmbedFinish` -> `onEmbedEnd`. Both names forward
3550
4234
  // to the same implementation; the installed SDK only wires up whichever it
@@ -3552,16 +4236,16 @@ var RaindropTelemetryIntegration = class {
3552
4236
  this.onEmbedEnd = (event) => this.onEmbedFinish(event);
3553
4237
  // ── onFinish ────────────────────────────────────────────────────────────
3554
4238
  this.onFinish = (event) => {
3555
- const state = this.getState(event.callId);
3556
- if (!state) return;
3557
- const isEmbed = state.operationId === "ai.embed" || state.operationId === "ai.embedMany";
4239
+ const state2 = this.getState(event.callId);
4240
+ if (!state2) return;
4241
+ const isEmbed = state2.operationId === "ai.embed" || state2.operationId === "ai.embedMany";
3558
4242
  if (isEmbed) {
3559
- this.finishEmbed(event, state);
4243
+ this.finishEmbed(event, state2);
3560
4244
  } else {
3561
- this.finishGenerate(event, state);
4245
+ this.finishGenerate(event, state2);
3562
4246
  }
3563
- if (state.subagentToolCallSpan) {
3564
- this.traceShipper.endSpan(state.subagentToolCallSpan);
4247
+ if (state2.subagentToolCallSpan) {
4248
+ this.traceShipper.endSpan(state2.subagentToolCallSpan);
3565
4249
  }
3566
4250
  this.cleanup(event.callId);
3567
4251
  };
@@ -3576,42 +4260,42 @@ var RaindropTelemetryIntegration = class {
3576
4260
  var _a;
3577
4261
  const event = error;
3578
4262
  if (!(event == null ? void 0 : event.callId)) return;
3579
- const state = this.getState(event.callId);
3580
- if (!state) return;
4263
+ const state2 = this.getState(event.callId);
4264
+ if (!state2) return;
3581
4265
  const actualError = (_a = event.error) != null ? _a : error;
3582
- if (state.stepSpan) {
3583
- this.traceShipper.endSpan(state.stepSpan, { error: actualError });
3584
- state.stepProvider = void 0;
3585
- state.stepModelId = void 0;
4266
+ if (state2.stepSpan) {
4267
+ this.traceShipper.endSpan(state2.stepSpan, { error: actualError });
4268
+ state2.stepProvider = void 0;
4269
+ state2.stepModelId = void 0;
3586
4270
  }
3587
- for (const embedSpan of state.embedSpans.values()) {
4271
+ for (const embedSpan of state2.embedSpans.values()) {
3588
4272
  this.traceShipper.endSpan(embedSpan, { error: actualError });
3589
4273
  }
3590
- state.embedSpans.clear();
3591
- for (const toolCallId of state.parentContextToolCallIds) {
4274
+ state2.embedSpans.clear();
4275
+ for (const toolCallId of state2.parentContextToolCallIds) {
3592
4276
  this.priorParentContexts.delete(toolCallId);
3593
4277
  }
3594
- state.parentContextToolCallIds.clear();
3595
- for (const toolSpan of state.toolSpans.values()) {
4278
+ state2.parentContextToolCallIds.clear();
4279
+ for (const toolSpan of state2.toolSpans.values()) {
3596
4280
  this.traceShipper.endSpan(toolSpan, { error: actualError });
3597
4281
  }
3598
- state.toolSpans.clear();
4282
+ state2.toolSpans.clear();
3599
4283
  const abortReason = describeAbortReason(actualError);
3600
- if (state.rootSpan) {
3601
- this.traceShipper.endSpan(state.rootSpan, {
4284
+ if (state2.rootSpan) {
4285
+ this.traceShipper.endSpan(state2.rootSpan, {
3602
4286
  error: actualError,
3603
- attributes: this.abortOutcomeAttrs(state, abortReason, "error")
4287
+ attributes: this.abortOutcomeAttrs(state2, abortReason, "error")
3604
4288
  });
3605
4289
  }
3606
- if (state.subagentToolCallSpan) {
3607
- this.traceShipper.endSpan(state.subagentToolCallSpan, { error: actualError });
4290
+ if (state2.subagentToolCallSpan) {
4291
+ this.traceShipper.endSpan(state2.subagentToolCallSpan, { error: actualError });
3608
4292
  }
3609
- const isEmbed = state.operationId === "ai.embed" || state.operationId === "ai.embedMany";
4293
+ const isEmbed = state2.operationId === "ai.embed" || state2.operationId === "ai.embedMany";
3610
4294
  if (!isEmbed) {
3611
- const errorIsTheRunsOutcome = state.handoff !== void 0 && !state.nestedInEvent;
4295
+ const errorIsTheRunsOutcome = state2.handoff !== void 0 && !state2.nestedInEvent;
3612
4296
  this.finalizeGenerateEvent(
3613
- state,
3614
- state.accumulatedText || void 0,
4297
+ state2,
4298
+ state2.accumulatedText || void 0,
3615
4299
  void 0,
3616
4300
  false,
3617
4301
  errorIsTheRunsOutcome ? { fallbackOutput: abortReason } : void 0
@@ -3630,51 +4314,51 @@ var RaindropTelemetryIntegration = class {
3630
4314
  this.onAbort = (event) => {
3631
4315
  const callId = event == null ? void 0 : event.callId;
3632
4316
  if (!callId) return;
3633
- const state = this.getState(callId);
3634
- if (!state) return;
4317
+ const state2 = this.getState(callId);
4318
+ if (!state2) return;
3635
4319
  const abortedAttr = attrString("ai.response.aborted", "true");
3636
- if (state.stepSpan) {
3637
- this.traceShipper.endSpan(state.stepSpan, { attributes: [abortedAttr] });
3638
- state.stepSpan = void 0;
3639
- state.stepParent = void 0;
3640
- state.stepProvider = void 0;
3641
- state.stepModelId = void 0;
4320
+ if (state2.stepSpan) {
4321
+ this.traceShipper.endSpan(state2.stepSpan, { attributes: [abortedAttr] });
4322
+ state2.stepSpan = void 0;
4323
+ state2.stepParent = void 0;
4324
+ state2.stepProvider = void 0;
4325
+ state2.stepModelId = void 0;
3642
4326
  }
3643
- for (const embedSpan of state.embedSpans.values()) {
4327
+ for (const embedSpan of state2.embedSpans.values()) {
3644
4328
  this.traceShipper.endSpan(embedSpan, { attributes: [abortedAttr] });
3645
4329
  }
3646
- state.embedSpans.clear();
3647
- for (const toolCallId of state.parentContextToolCallIds) {
4330
+ state2.embedSpans.clear();
4331
+ for (const toolCallId of state2.parentContextToolCallIds) {
3648
4332
  this.priorParentContexts.delete(toolCallId);
3649
4333
  }
3650
- state.parentContextToolCallIds.clear();
3651
- for (const toolSpan of state.toolSpans.values()) {
4334
+ state2.parentContextToolCallIds.clear();
4335
+ for (const toolSpan of state2.toolSpans.values()) {
3652
4336
  this.traceShipper.endSpan(toolSpan, { attributes: [abortedAttr] });
3653
4337
  }
3654
- state.toolSpans.clear();
3655
- const abortIsTheRunsOutcome = state.handoff !== void 0 && !state.nestedInEvent;
3656
- if (state.rootSpan) {
3657
- this.traceShipper.endSpan(state.rootSpan, {
4338
+ state2.toolSpans.clear();
4339
+ const abortIsTheRunsOutcome = state2.handoff !== void 0 && !state2.nestedInEvent;
4340
+ if (state2.rootSpan) {
4341
+ this.traceShipper.endSpan(state2.rootSpan, {
3658
4342
  attributes: [
3659
4343
  abortedAttr,
3660
- attrInt("ai.toolCall.count", state.toolCallCount),
4344
+ attrInt("ai.toolCall.count", state2.toolCallCount),
3661
4345
  // An aborted detached child IS a cancelled sub-agent, and a cancelled
3662
4346
  // run is span-for-span identical to a finished one — spans close,
3663
4347
  // nothing errors, there is just no answer. So it is the one outcome
3664
4348
  // that has to be stated, and the child states it on itself.
3665
4349
  ...abortIsTheRunsOutcome ? cancelledSpanAttrs() : [],
3666
- ...abortIsTheRunsOutcome ? this.abortOutcomeAttrs(state, SUBAGENT_CANCELLED_OUTPUT, "stop") : []
4350
+ ...abortIsTheRunsOutcome ? this.abortOutcomeAttrs(state2, SUBAGENT_CANCELLED_OUTPUT, "stop") : []
3667
4351
  ]
3668
4352
  });
3669
4353
  }
3670
- if (state.subagentToolCallSpan) {
3671
- this.traceShipper.endSpan(state.subagentToolCallSpan, {
4354
+ if (state2.subagentToolCallSpan) {
4355
+ this.traceShipper.endSpan(state2.subagentToolCallSpan, {
3672
4356
  attributes: [abortedAttr]
3673
4357
  });
3674
4358
  }
3675
4359
  this.finalizeGenerateEvent(
3676
- state,
3677
- state.accumulatedText || void 0,
4360
+ state2,
4361
+ state2.accumulatedText || void 0,
3678
4362
  void 0,
3679
4363
  false,
3680
4364
  abortIsTheRunsOutcome ? {
@@ -3682,7 +4366,7 @@ var RaindropTelemetryIntegration = class {
3682
4366
  properties: { [HANDOFF_TERMINAL_PROPERTY_KEY]: HANDOFF_TERMINAL_CANCELLED }
3683
4367
  } : void 0
3684
4368
  );
3685
- if (abortIsTheRunsOutcome) this.subagents.noteSettled(state.eventId);
4369
+ if (abortIsTheRunsOutcome) this.subagents.noteSettled(state2.eventId);
3686
4370
  this.cleanup(callId);
3687
4371
  };
3688
4372
  // ── executeTool ─────────────────────────────────────────────────────────
@@ -3691,14 +4375,14 @@ var RaindropTelemetryIntegration = class {
3691
4375
  toolCallId,
3692
4376
  execute
3693
4377
  }) => {
3694
- const state = this.getState(callId);
3695
- const toolSpan = state == null ? void 0 : state.toolSpans.get(toolCallId);
4378
+ const state2 = this.getState(callId);
4379
+ const toolSpan = state2 == null ? void 0 : state2.toolSpans.get(toolCallId);
3696
4380
  if (!toolSpan) return execute();
3697
4381
  return runWithParentSpanContext(
3698
4382
  {
3699
4383
  traceIdB64: toolSpan.ids.traceIdB64,
3700
4384
  spanIdB64: toolSpan.ids.spanIdB64,
3701
- eventId: state.eventId
4385
+ eventId: state2.eventId
3702
4386
  },
3703
4387
  () => execute()
3704
4388
  );
@@ -3747,35 +4431,35 @@ var RaindropTelemetryIntegration = class {
3747
4431
  activeDispatch() {
3748
4432
  var _a;
3749
4433
  const parentTool = getCurrentParentToolContext();
3750
- let state = parentTool ? this.getState(parentTool.parentCallId) : void 0;
4434
+ let state2 = parentTool ? this.getState(parentTool.parentCallId) : void 0;
3751
4435
  const inheritedEventId = (_a = getContextManager().getParentSpanIds()) == null ? void 0 : _a.eventId;
3752
- if (!state && inheritedEventId) {
4436
+ if (!state2 && inheritedEventId) {
3753
4437
  for (const candidate of this.callStates.values()) {
3754
4438
  if (candidate.eventId === inheritedEventId) {
3755
- state = candidate;
4439
+ state2 = candidate;
3756
4440
  break;
3757
4441
  }
3758
4442
  }
3759
4443
  }
3760
- if (!state) return void 0;
4444
+ if (!state2) return void 0;
3761
4445
  return {
3762
- eventId: state.eventId,
3763
- userId: state.identity.userId,
3764
- convoId: state.identity.convoId,
3765
- dispatchSpan: parentTool ? state.toolSpans.get(parentTool.toolCallId) : void 0,
3766
- turnSpans: [state.rootSpan, state.stepSpan].filter(
4446
+ eventId: state2.eventId,
4447
+ userId: state2.identity.userId,
4448
+ convoId: state2.identity.convoId,
4449
+ dispatchSpan: parentTool ? state2.toolSpans.get(parentTool.toolCallId) : void 0,
4450
+ turnSpans: [state2.rootSpan, state2.stepSpan].filter(
3767
4451
  (span) => span !== void 0
3768
4452
  ),
3769
- recordInputs: state.recordInputs
4453
+ recordInputs: state2.recordInputs
3770
4454
  };
3771
4455
  }
3772
4456
  /** Spans still open for an event, so a late outcome can still be stated. */
3773
4457
  openSpansForEvent(eventId) {
3774
4458
  const spans = [];
3775
- for (const state of this.callStates.values()) {
3776
- if (state.eventId !== eventId) continue;
3777
- if (state.rootSpan) spans.push(state.rootSpan);
3778
- if (state.stepSpan) spans.push(state.stepSpan);
4459
+ for (const state2 of this.callStates.values()) {
4460
+ if (state2.eventId !== eventId) continue;
4461
+ if (state2.rootSpan) spans.push(state2.rootSpan);
4462
+ if (state2.stepSpan) spans.push(state2.stepSpan);
3779
4463
  }
3780
4464
  return spans;
3781
4465
  }
@@ -3795,10 +4479,10 @@ var RaindropTelemetryIntegration = class {
3795
4479
  * created from an LLM span with output, `ai.response.text` here would state
3796
4480
  * the run's outcome through the span while the turn is still working.
3797
4481
  */
3798
- abortOutcomeAttrs(state, reason, finishReason) {
3799
- if (!state.handoff || state.nestedInEvent) return [];
4482
+ abortOutcomeAttrs(state2, reason, finishReason) {
4483
+ if (!state2.handoff || state2.nestedInEvent) return [];
3800
4484
  return [
3801
- attrString("ai.response.text", capText2(state.accumulatedText || reason)),
4485
+ attrString("ai.response.text", capText2(state2.accumulatedText || reason)),
3802
4486
  attrString("ai.response.finishReason", finishReason)
3803
4487
  ];
3804
4488
  }
@@ -3812,19 +4496,19 @@ var RaindropTelemetryIntegration = class {
3812
4496
  spanParentRef(span) {
3813
4497
  return { traceIdB64: span.ids.traceIdB64, spanIdB64: span.ids.spanIdB64 };
3814
4498
  }
3815
- emitLive(state, type, content, extra) {
4499
+ emitLive(state2, type, content, extra) {
3816
4500
  var _a, _b, _c, _d, _e, _f;
3817
- if (!localDebuggerEnabled() || !state.rootSpan) return;
3818
- const callMeta = this.extractRaindropMetadata(state.metadata);
4501
+ if (!localDebuggerEnabled() || !state2.rootSpan) return;
4502
+ const callMeta = this.extractRaindropMetadata(state2.metadata);
3819
4503
  sendLocalDebuggerLiveEvent({
3820
- traceId: state.rootSpan.ids.traceIdB64,
4504
+ traceId: state2.rootSpan.ids.traceIdB64,
3821
4505
  type,
3822
4506
  content,
3823
4507
  metadata: {
3824
4508
  userId: (_b = callMeta.userId) != null ? _b : (_a = this.defaultContext) == null ? void 0 : _a.userId,
3825
4509
  convoId: (_d = callMeta.convoId) != null ? _d : (_c = this.defaultContext) == null ? void 0 : _c.convoId,
3826
4510
  eventName: (_f = callMeta.eventName) != null ? _f : (_e = this.defaultContext) == null ? void 0 : _e.eventName,
3827
- eventId: state.eventId,
4511
+ eventId: state2.eventId,
3828
4512
  ...extra
3829
4513
  }
3830
4514
  });
@@ -3902,29 +4586,29 @@ var RaindropTelemetryIntegration = class {
3902
4586
  toolCallId: toolCall.toolCallId,
3903
4587
  toolName: toolCall.toolName
3904
4588
  });
3905
- const state = this.getState(event.callId);
3906
- state == null ? void 0 : state.parentContextToolCallIds.add(toolCall.toolCallId);
3907
- if (!(state == null ? void 0 : state.stepParent)) return;
3908
- const { operationName, resourceName } = opName("ai.toolCall", state.functionId);
3909
- const inputAttrs = state.recordInputs ? [attrString("ai.toolCall.args", safeJsonWithUint8(toolCall.input))] : [];
4589
+ const state2 = this.getState(event.callId);
4590
+ state2 == null ? void 0 : state2.parentContextToolCallIds.add(toolCall.toolCallId);
4591
+ if (!(state2 == null ? void 0 : state2.stepParent)) return;
4592
+ const { operationName, resourceName } = opName("ai.toolCall", state2.functionId);
4593
+ const inputAttrs = state2.recordInputs ? [attrString("ai.toolCall.args", safeJsonWithUint8(toolCall.input))] : [];
3910
4594
  const toolSpan = this.traceShipper.startSpan({
3911
4595
  name: "ai.toolCall",
3912
- parent: state.stepParent,
3913
- eventId: state.eventId,
3914
- ...state.identity,
4596
+ parent: state2.stepParent,
4597
+ eventId: state2.eventId,
4598
+ ...state2.identity,
3915
4599
  operationId: "ai.toolCall",
3916
4600
  attributes: [
3917
4601
  attrString("operation.name", operationName),
3918
4602
  attrString("resource.name", resourceName),
3919
- attrString("ai.telemetry.functionId", state.functionId),
4603
+ attrString("ai.telemetry.functionId", state2.functionId),
3920
4604
  attrString("ai.toolCall.name", toolCall.toolName),
3921
4605
  attrString("ai.toolCall.id", toolCall.toolCallId),
3922
4606
  ...inputAttrs,
3923
- ...handoffSpanAttrs(state.handoff)
4607
+ ...handoffSpanAttrs(state2.handoff)
3924
4608
  ]
3925
4609
  });
3926
- state.toolSpans.set(toolCall.toolCallId, toolSpan);
3927
- this.emitLive(state, "tool_start", toolCall.toolName, { args: toolCall.input });
4610
+ state2.toolSpans.set(toolCall.toolCallId, toolSpan);
4611
+ this.emitLive(state2, "tool_start", toolCall.toolName, { args: toolCall.input });
3928
4612
  }
3929
4613
  toolExecutionEnd(event) {
3930
4614
  var _a;
@@ -3938,20 +4622,20 @@ var RaindropTelemetryIntegration = class {
3938
4622
  clearParentToolContext();
3939
4623
  }
3940
4624
  }
3941
- const state = this.getState(event.callId);
3942
- if (!state) return;
3943
- const toolSpan = state.toolSpans.get(event.toolCall.toolCallId);
4625
+ const state2 = this.getState(event.callId);
4626
+ if (!state2) return;
4627
+ const toolSpan = state2.toolSpans.get(event.toolCall.toolCallId);
3944
4628
  if (!toolSpan) return;
3945
- state.toolCallCount += 1;
4629
+ state2.toolCallCount += 1;
3946
4630
  const outcome = "toolOutput" in event ? event.toolOutput.type === "tool-result" ? { success: true, output: event.toolOutput.output } : { success: false, error: event.toolOutput.error } : event.success ? { success: true, output: event.output } : { success: false, error: event.error };
3947
4631
  if (outcome.success) {
3948
- const outputAttrs = state.recordOutputs ? [attrString("ai.toolCall.result", safeJsonWithUint8(outcome.output))] : [];
4632
+ const outputAttrs = state2.recordOutputs ? [attrString("ai.toolCall.result", safeJsonWithUint8(outcome.output))] : [];
3949
4633
  this.traceShipper.endSpan(toolSpan, { attributes: outputAttrs });
3950
4634
  } else {
3951
4635
  this.traceShipper.endSpan(toolSpan, { error: outcome.error });
3952
4636
  }
3953
- this.emitLive(state, "tool_result", event.toolCall.toolName);
3954
- state.toolSpans.delete(event.toolCall.toolCallId);
4637
+ this.emitLive(state2, "tool_result", event.toolCall.toolName);
4638
+ state2.toolSpans.delete(event.toolCall.toolCallId);
3955
4639
  }
3956
4640
  // ── provider-executed tool calls ─────────────────────────────────────────
3957
4641
  //
@@ -3970,8 +4654,8 @@ var RaindropTelemetryIntegration = class {
3970
4654
  //
3971
4655
  // Client-executed tools are excluded (`providerExecuted` falsy) — they were
3972
4656
  // already spanned during execution, so this never double-emits.
3973
- emitProviderExecutedToolSpans(event, state) {
3974
- if (!state.stepParent) return;
4657
+ emitProviderExecutedToolSpans(event, state2) {
4658
+ if (!state2.stepParent) return;
3975
4659
  const content = Array.isArray(event.content) ? event.content : [];
3976
4660
  const providerToolCalls = content.filter(
3977
4661
  (part) => (part == null ? void 0 : part.type) === "tool-call" && part.providerExecuted === true
@@ -3984,42 +4668,42 @@ var RaindropTelemetryIntegration = class {
3984
4668
  }
3985
4669
  }
3986
4670
  for (const call of providerToolCalls) {
3987
- const { operationName, resourceName } = opName("ai.toolCall", state.functionId);
3988
- const inputAttrs = state.recordInputs ? [attrString("ai.toolCall.args", safeJsonWithUint8(call.input))] : [];
4671
+ const { operationName, resourceName } = opName("ai.toolCall", state2.functionId);
4672
+ const inputAttrs = state2.recordInputs ? [attrString("ai.toolCall.args", safeJsonWithUint8(call.input))] : [];
3989
4673
  const toolSpan = this.traceShipper.startSpan({
3990
4674
  name: "ai.toolCall",
3991
- parent: state.stepParent,
3992
- eventId: state.eventId,
3993
- ...state.identity,
4675
+ parent: state2.stepParent,
4676
+ eventId: state2.eventId,
4677
+ ...state2.identity,
3994
4678
  operationId: "ai.toolCall",
3995
4679
  attributes: [
3996
4680
  attrString("operation.name", operationName),
3997
4681
  attrString("resource.name", resourceName),
3998
- attrString("ai.telemetry.functionId", state.functionId),
4682
+ attrString("ai.telemetry.functionId", state2.functionId),
3999
4683
  attrString("ai.toolCall.name", call.toolName),
4000
4684
  attrString("ai.toolCall.id", call.toolCallId),
4001
4685
  attrString("ai.toolCall.providerExecuted", "true"),
4002
4686
  ...inputAttrs,
4003
- ...handoffSpanAttrs(state.handoff)
4687
+ ...handoffSpanAttrs(state2.handoff)
4004
4688
  ]
4005
4689
  });
4006
- state.toolCallCount += 1;
4007
- this.emitLive(state, "tool_start", call.toolName, { args: call.input });
4690
+ state2.toolCallCount += 1;
4691
+ this.emitLive(state2, "tool_start", call.toolName, { args: call.input });
4008
4692
  const resultPart = resultsByCallId.get(call.toolCallId);
4009
4693
  if ((resultPart == null ? void 0 : resultPart.type) === "tool-error") {
4010
4694
  this.traceShipper.endSpan(toolSpan, { error: resultPart.error });
4011
4695
  } else {
4012
- const outputAttrs = state.recordOutputs && resultPart && "output" in resultPart ? [attrString("ai.toolCall.result", safeJsonWithUint8(resultPart.output))] : [];
4696
+ const outputAttrs = state2.recordOutputs && resultPart && "output" in resultPart ? [attrString("ai.toolCall.result", safeJsonWithUint8(resultPart.output))] : [];
4013
4697
  this.traceShipper.endSpan(toolSpan, { attributes: outputAttrs });
4014
4698
  }
4015
- this.emitLive(state, "tool_result", call.toolName);
4699
+ this.emitLive(state2, "tool_result", call.toolName);
4016
4700
  }
4017
4701
  }
4018
- finishGenerate(event, state) {
4702
+ finishGenerate(event, state2) {
4019
4703
  var _a, _b, _c, _d, _e, _f;
4020
- if (state.rootSpan) {
4704
+ if (state2.rootSpan) {
4021
4705
  const outputAttrs = [];
4022
- if (state.recordOutputs) {
4706
+ if (state2.recordOutputs) {
4023
4707
  outputAttrs.push(
4024
4708
  attrString("ai.response.finishReason", event.finishReason),
4025
4709
  attrString("ai.response.text", capText2((_a = event.text) != null ? _a : void 0)),
@@ -4060,12 +4744,12 @@ var RaindropTelemetryIntegration = class {
4060
4744
  attrInt("ai.usage.cachedInputTokens", usageMetrics.cachedInputTokens)
4061
4745
  );
4062
4746
  }
4063
- outputAttrs.push(attrInt("ai.toolCall.count", state.toolCallCount));
4064
- this.traceShipper.endSpan(state.rootSpan, { attributes: outputAttrs });
4747
+ outputAttrs.push(attrInt("ai.toolCall.count", state2.toolCallCount));
4748
+ this.traceShipper.endSpan(state2.rootSpan, { attributes: outputAttrs });
4065
4749
  }
4066
4750
  this.finalizeGenerateEvent(
4067
- state,
4068
- (_e = event.text) != null ? _e : state.accumulatedText || void 0,
4751
+ state2,
4752
+ (_e = event.text) != null ? _e : state2.accumulatedText || void 0,
4069
4753
  (_f = event.response) == null ? void 0 : _f.modelId,
4070
4754
  hasUnresolvedToolApproval(event)
4071
4755
  );
@@ -4081,29 +4765,29 @@ var RaindropTelemetryIntegration = class {
4081
4765
  * is finalized by that resume — otherwise each execution would finalize the
4082
4766
  * same event ID into a separate canonical row.
4083
4767
  */
4084
- finalizeGenerateEvent(state, output, model, keepPending = false, detachedOutcome) {
4768
+ finalizeGenerateEvent(state2, output, model, keepPending = false, detachedOutcome) {
4085
4769
  var _a, _b, _c, _d, _e, _f, _g, _h, _i;
4086
- const suppressSubagentEvent = state.subagentName !== void 0 && state.subagentToolCallSpan !== void 0;
4770
+ const suppressSubagentEvent = state2.subagentName !== void 0 && state2.subagentToolCallSpan !== void 0;
4087
4771
  if (!this.sendEvents || suppressSubagentEvent) return;
4088
- if (this.subagents.wasSettledExplicitly(state.eventId)) return;
4089
- const callMeta = this.extractRaindropMetadata(state.metadata);
4772
+ if (this.subagents.wasSettledExplicitly(state2.eventId)) return;
4773
+ const callMeta = this.extractRaindropMetadata(state2.metadata);
4090
4774
  const userId = (_b = callMeta.userId) != null ? _b : (_a = this.defaultContext) == null ? void 0 : _a.userId;
4091
4775
  if (!userId) return;
4092
- const eventName = (_e = (_d = callMeta.eventName) != null ? _d : (_c = this.defaultContext) == null ? void 0 : _c.eventName) != null ? _e : state.operationId;
4776
+ const eventName = (_e = (_d = callMeta.eventName) != null ? _d : (_c = this.defaultContext) == null ? void 0 : _c.eventName) != null ? _e : state2.operationId;
4093
4777
  const cappedOutput = capText2(output);
4094
- const reportedOutput = state.handoff && detachedOutcome && !(cappedOutput == null ? void 0 : cappedOutput.trim()) ? detachedOutcome.fallbackOutput : cappedOutput;
4095
- const input = capText2(state.inputText);
4778
+ const reportedOutput = state2.handoff && detachedOutcome && !(cappedOutput == null ? void 0 : cappedOutput.trim()) ? detachedOutcome.fallbackOutput : cappedOutput;
4779
+ const input = capText2(state2.inputText);
4096
4780
  const properties = {
4097
4781
  ...(_f = this.defaultContext) == null ? void 0 : _f.properties,
4098
4782
  ...callMeta.properties,
4099
- ...state.handoff ? detachedOutcome == null ? void 0 : detachedOutcome.properties : void 0
4783
+ ...state2.handoff ? detachedOutcome == null ? void 0 : detachedOutcome.properties : void 0
4100
4784
  };
4101
4785
  const featureFlags = {
4102
4786
  ...((_g = this.defaultContext) == null ? void 0 : _g.featureFlags) ? normalizeFeatureFlags(this.defaultContext.featureFlags) : {},
4103
4787
  ...callMeta.featureFlags
4104
4788
  };
4105
4789
  const convoId = (_i = callMeta.convoId) != null ? _i : (_h = this.defaultContext) == null ? void 0 : _h.convoId;
4106
- void this.eventShipper.patch(state.eventId, {
4790
+ void this.eventShipper.patch(state2.eventId, {
4107
4791
  eventName,
4108
4792
  userId,
4109
4793
  convoId,
@@ -4121,12 +4805,12 @@ var RaindropTelemetryIntegration = class {
4121
4805
  }
4122
4806
  });
4123
4807
  }
4124
- finishEmbed(event, state) {
4808
+ finishEmbed(event, state2) {
4125
4809
  var _a;
4126
- if (!state.rootSpan) return;
4810
+ if (!state2.rootSpan) return;
4127
4811
  const outputAttrs = [];
4128
- const isMany = state.operationId === "ai.embedMany";
4129
- if (state.recordOutputs) {
4812
+ const isMany = state2.operationId === "ai.embedMany";
4813
+ if (state2.recordOutputs) {
4130
4814
  if (isMany) {
4131
4815
  outputAttrs.push(attrString("ai.embeddings", safeJsonWithUint8(event.embedding)));
4132
4816
  } else {
@@ -4136,7 +4820,7 @@ var RaindropTelemetryIntegration = class {
4136
4820
  if (((_a = event.usage) == null ? void 0 : _a.tokens) != null) {
4137
4821
  outputAttrs.push(attrInt("ai.usage.tokens", event.usage.tokens));
4138
4822
  }
4139
- this.traceShipper.endSpan(state.rootSpan, { attributes: outputAttrs });
4823
+ this.traceShipper.endSpan(state2.rootSpan, { attributes: outputAttrs });
4140
4824
  }
4141
4825
  };
4142
4826
 
@@ -6314,11 +6998,11 @@ function userAttrsToOtlp(attrs) {
6314
6998
  function envDebugEnabled() {
6315
6999
  var _a;
6316
7000
  if (typeof process === "undefined") return false;
6317
- const flag = (_a = process.env) == null ? void 0 : _a.RAINDROP_AI_DEBUG;
6318
- return flag === "1" || flag === "true";
7001
+ const flag2 = (_a = process.env) == null ? void 0 : _a.RAINDROP_AI_DEBUG;
7002
+ return flag2 === "1" || flag2 === "true";
6319
7003
  }
6320
7004
  function createRaindropAISDK(opts) {
6321
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
7005
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
6322
7006
  const writeKey = opts.writeKey;
6323
7007
  const eventsRequested = ((_a = opts.events) == null ? void 0 : _a.enabled) !== false;
6324
7008
  const tracesRequested = ((_b = opts.traces) == null ? void 0 : _b.enabled) !== false;
@@ -6327,37 +7011,53 @@ function createRaindropAISDK(opts) {
6327
7011
  const localWorkshopInput = opts.localWorkshopUrl === false ? null : opts.localWorkshopUrl;
6328
7012
  const resolvedLocalDebuggerUrl = resolveLocalDebuggerBaseUrl(localWorkshopInput);
6329
7013
  const localDebuggerUrl = localWorkshopInput === null ? null : resolvedLocalDebuggerUrl != null ? resolvedLocalDebuggerUrl : void 0;
6330
- const hasDestination = !!writeKey || !!resolvedLocalDebuggerUrl;
7014
+ const hasDestination = Boolean(writeKey == null ? void 0 : writeKey.trim()) || Boolean(resolvedLocalDebuggerUrl);
6331
7015
  const eventsEnabled = eventsRequested && hasDestination;
6332
7016
  const tracesEnabled = tracesRequested && hasDestination;
7017
+ const appGitContext = (_c = opts.appGitContext) != null ? _c : createAppGitContext(
7018
+ eventsEnabled || tracesEnabled ? opts.appGit : false,
7019
+ { allowLocalGit: true }
7020
+ );
6333
7021
  if (!hasDestination && (eventsRequested || tracesRequested)) {
6334
7022
  console.warn(
6335
7023
  "[raindrop-ai/ai-sdk] writeKey not provided and no local Workshop reachable; telemetry shipping is disabled"
6336
7024
  );
6337
7025
  }
6338
- const eventShipper = new EventShipper2({
6339
- writeKey,
6340
- endpoint: opts.endpoint,
6341
- enabled: eventsEnabled,
6342
- debug: ((_c = opts.events) == null ? void 0 : _c.debug) === true || envDebug,
6343
- partialFlushMs: (_d = opts.events) == null ? void 0 : _d.partialFlushMs,
6344
- projectId: opts.projectId,
6345
- localDebuggerUrl
6346
- });
6347
- const traceShipper = new TraceShipper2({
6348
- writeKey,
6349
- endpoint: opts.endpoint,
6350
- enabled: tracesEnabled,
6351
- debug: ((_e = opts.traces) == null ? void 0 : _e.debug) === true || envDebug,
6352
- debugSpans: ((_f = opts.traces) == null ? void 0 : _f.debugSpans) === true || envDebug,
6353
- flushIntervalMs: (_g = opts.traces) == null ? void 0 : _g.flushIntervalMs,
6354
- maxBatchSize: (_h = opts.traces) == null ? void 0 : _h.maxBatchSize,
6355
- maxQueueSize: (_i = opts.traces) == null ? void 0 : _i.maxQueueSize,
6356
- projectId: opts.projectId,
6357
- localDebuggerUrl,
6358
- transformSpan: (_j = opts.traces) == null ? void 0 : _j.transformSpan,
6359
- disableDefaultRedaction: (_k = opts.traces) == null ? void 0 : _k.disableDefaultRedaction
6360
- });
7026
+ let eventShipper;
7027
+ let traceShipper;
7028
+ try {
7029
+ eventShipper = new EventShipper2({
7030
+ writeKey,
7031
+ endpoint: opts.endpoint,
7032
+ enabled: eventsEnabled,
7033
+ debug: ((_d = opts.events) == null ? void 0 : _d.debug) === true || envDebug,
7034
+ partialFlushMs: (_e = opts.events) == null ? void 0 : _e.partialFlushMs,
7035
+ projectId: opts.projectId,
7036
+ localDebuggerUrl,
7037
+ appGitContext
7038
+ });
7039
+ traceShipper = new TraceShipper2({
7040
+ writeKey,
7041
+ endpoint: opts.endpoint,
7042
+ enabled: tracesEnabled,
7043
+ debug: ((_f = opts.traces) == null ? void 0 : _f.debug) === true || envDebug,
7044
+ debugSpans: ((_g = opts.traces) == null ? void 0 : _g.debugSpans) === true || envDebug,
7045
+ flushIntervalMs: (_h = opts.traces) == null ? void 0 : _h.flushIntervalMs,
7046
+ maxBatchSize: (_i = opts.traces) == null ? void 0 : _i.maxBatchSize,
7047
+ maxQueueSize: (_j = opts.traces) == null ? void 0 : _j.maxQueueSize,
7048
+ projectId: opts.projectId,
7049
+ localDebuggerUrl,
7050
+ transformSpan: (_k = opts.traces) == null ? void 0 : _k.transformSpan,
7051
+ disableDefaultRedaction: (_l = opts.traces) == null ? void 0 : _l.disableDefaultRedaction,
7052
+ appGitContext
7053
+ });
7054
+ } catch (error) {
7055
+ try {
7056
+ appGitContext.dispose();
7057
+ } catch (e) {
7058
+ }
7059
+ throw error;
7060
+ }
6361
7061
  const settledEventIds = /* @__PURE__ */ new Set();
6362
7062
  const subagentApi = new SubagentApi({
6363
7063
  traceShipper,
@@ -6525,7 +7225,14 @@ function createRaindropAISDK(opts) {
6525
7225
  await Promise.all([eventShipper.flush(), traceShipper.flush()]);
6526
7226
  },
6527
7227
  async shutdown() {
6528
- await Promise.all([eventShipper.shutdown(), traceShipper.shutdown()]);
7228
+ try {
7229
+ await Promise.all([eventShipper.shutdown(), traceShipper.shutdown()]);
7230
+ } finally {
7231
+ try {
7232
+ appGitContext.dispose();
7233
+ } catch (e) {
7234
+ }
7235
+ }
6529
7236
  }
6530
7237
  };
6531
7238
  }