@raindrop-ai/ai-sdk 0.0.28 → 0.0.30

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,4 @@
1
- // ../core/dist/chunk-LMIWKHOH.js
1
+ // ../core/dist/chunk-VUNUOE2X.js
2
2
  function getCrypto() {
3
3
  const c = globalThis.crypto;
4
4
  return c;
@@ -221,6 +221,114 @@ function buildExportTraceServiceRequest(spans, serviceName = "raindrop.core", se
221
221
  ]
222
222
  };
223
223
  }
224
+ var LOCAL_DEBUGGER_ENV_VAR = "RAINDROP_LOCAL_DEBUGGER";
225
+ var WORKSHOP_ENV_VAR = "RAINDROP_WORKSHOP";
226
+ var DEFAULT_LOCAL_WORKSHOP_URL = "http://localhost:5899/v1/";
227
+ function readEnvVar(name) {
228
+ var _a;
229
+ try {
230
+ const env = (_a = globalThis == null ? void 0 : globalThis.process) == null ? void 0 : _a.env;
231
+ if (env && typeof env[name] === "string" && env[name].length > 0) {
232
+ return env[name];
233
+ }
234
+ } catch (e) {
235
+ }
236
+ return void 0;
237
+ }
238
+ function readWorkshopEnv() {
239
+ const raw = readEnvVar(WORKSHOP_ENV_VAR);
240
+ if (raw === void 0) return void 0;
241
+ const trimmed = raw.trim();
242
+ if (trimmed.length === 0) return void 0;
243
+ if (/^https?:\/\//i.test(trimmed)) return { url: trimmed };
244
+ if (/^(1|true|yes|on)$/i.test(trimmed)) return "enable";
245
+ if (/^(0|false|no|off)$/i.test(trimmed)) return "disable";
246
+ return void 0;
247
+ }
248
+ function isLocalDevHost(hostname) {
249
+ if (!hostname) return false;
250
+ if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "0.0.0.0" || hostname === "::1") {
251
+ return true;
252
+ }
253
+ if (hostname.endsWith(".localhost")) return true;
254
+ return false;
255
+ }
256
+ function readRuntimeHostname() {
257
+ try {
258
+ const loc = globalThis == null ? void 0 : globalThis.location;
259
+ if (loc && typeof loc.hostname === "string" && loc.hostname.length > 0) {
260
+ return loc.hostname;
261
+ }
262
+ } catch (e) {
263
+ }
264
+ return void 0;
265
+ }
266
+ function shouldAutoEnableLocalWorkshop() {
267
+ if (isLocalDevHost(readRuntimeHostname())) return true;
268
+ if (readEnvVar("NODE_ENV") === "development") return true;
269
+ return false;
270
+ }
271
+ function resolveLocalDebuggerBaseUrl(baseUrl) {
272
+ var _a, _b, _c;
273
+ if (baseUrl === null) return null;
274
+ if (typeof baseUrl === "string" && baseUrl.length > 0) {
275
+ return (_a = formatEndpoint(baseUrl)) != null ? _a : null;
276
+ }
277
+ const explicitUrlEnv = readEnvVar(LOCAL_DEBUGGER_ENV_VAR);
278
+ if (explicitUrlEnv) return (_b = formatEndpoint(explicitUrlEnv)) != null ? _b : null;
279
+ const workshopEnv = readWorkshopEnv();
280
+ if (workshopEnv === "disable") return null;
281
+ if (workshopEnv === "enable") return DEFAULT_LOCAL_WORKSHOP_URL;
282
+ if (workshopEnv && "url" in workshopEnv) return (_c = formatEndpoint(workshopEnv.url)) != null ? _c : null;
283
+ if (shouldAutoEnableLocalWorkshop()) return DEFAULT_LOCAL_WORKSHOP_URL;
284
+ return null;
285
+ }
286
+ function localDebuggerEnabled(baseUrl) {
287
+ return resolveLocalDebuggerBaseUrl(baseUrl) !== null;
288
+ }
289
+ function mirrorTraceExportToLocalDebugger(body, options = {}) {
290
+ var _a;
291
+ const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
292
+ if (!baseUrl) return;
293
+ void postJson(`${baseUrl}traces`, body, {}, {
294
+ maxAttempts: 1,
295
+ debug: (_a = options.debug) != null ? _a : false,
296
+ sdkName: options.sdkName
297
+ }).catch(() => {
298
+ });
299
+ }
300
+ function mirrorPartialEventToLocalDebugger(event, options = {}) {
301
+ var _a;
302
+ const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
303
+ if (!baseUrl) return;
304
+ const headers = options.writeKey ? { Authorization: `Bearer ${options.writeKey}` } : {};
305
+ void postJson(`${baseUrl}events/track_partial`, event, headers, {
306
+ maxAttempts: 1,
307
+ debug: (_a = options.debug) != null ? _a : false,
308
+ sdkName: options.sdkName
309
+ }).catch(() => {
310
+ });
311
+ }
312
+ function sendLocalDebuggerLiveEvent(event, options = {}) {
313
+ var _a, _b;
314
+ const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
315
+ if (!baseUrl) return;
316
+ void postJson(
317
+ `${baseUrl}live`,
318
+ {
319
+ ...event,
320
+ type: event.type,
321
+ timestamp: (_a = event.timestamp) != null ? _a : Date.now()
322
+ },
323
+ {},
324
+ {
325
+ maxAttempts: 1,
326
+ debug: (_b = options.debug) != null ? _b : false,
327
+ sdkName: options.sdkName
328
+ }
329
+ ).catch(() => {
330
+ });
331
+ }
224
332
  function mergePatches(target, source) {
225
333
  var _a, _b, _c, _d;
226
334
  const out = { ...target, ...source };
@@ -238,7 +346,7 @@ var EventShipper = class {
238
346
  this.sticky = /* @__PURE__ */ new Map();
239
347
  this.timers = /* @__PURE__ */ new Map();
240
348
  this.inFlight = /* @__PURE__ */ new Set();
241
- var _a, _b, _c, _d, _e, _f, _g;
349
+ var _a, _b, _c, _d, _e, _f, _g, _h;
242
350
  this.writeKey = (_a = opts.writeKey) == null ? void 0 : _a.trim();
243
351
  this.baseUrl = (_b = formatEndpoint(opts.endpoint)) != null ? _b : "https://api.raindrop.ai/v1/";
244
352
  this.enabled = opts.enabled !== false;
@@ -247,11 +355,15 @@ var EventShipper = class {
247
355
  this.sdkName = (_d = opts.sdkName) != null ? _d : "core";
248
356
  this.prefix = `[raindrop-ai/${this.sdkName}]`;
249
357
  this.defaultEventName = (_e = opts.defaultEventName) != null ? _e : "ai_generation";
358
+ this.localDebuggerUrl = (_f = resolveLocalDebuggerBaseUrl(opts.localDebuggerUrl)) != null ? _f : void 0;
359
+ if (this.debug && this.localDebuggerUrl) {
360
+ console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
361
+ }
250
362
  const isNode = typeof process !== "undefined" && typeof process.version === "string";
251
363
  this.context = {
252
364
  library: {
253
- name: (_f = opts.libraryName) != null ? _f : "@raindrop-ai/core",
254
- version: (_g = opts.libraryVersion) != null ? _g : "0.0.0"
365
+ name: (_g = opts.libraryName) != null ? _g : "@raindrop-ai/core",
366
+ version: (_h = opts.libraryVersion) != null ? _h : "0.0.0"
255
367
  },
256
368
  metadata: {
257
369
  jsRuntime: isNode ? "node" : "web",
@@ -337,6 +449,7 @@ var EventShipper = class {
337
449
  }
338
450
  }
339
451
  ];
452
+ if (!this.writeKey) return;
340
453
  const url = `${this.baseUrl}signals/track`;
341
454
  try {
342
455
  await postJson(url, body, this.authHeaders(), {
@@ -367,6 +480,7 @@ var EventShipper = class {
367
480
  traits: (_a = user.traits) != null ? _a : {}
368
481
  };
369
482
  });
483
+ if (!this.writeKey) return;
370
484
  if (body.length === 0) return;
371
485
  const url = `${this.baseUrl}users/identify`;
372
486
  try {
@@ -443,6 +557,18 @@ var EventShipper = class {
443
557
  endpoint: url
444
558
  });
445
559
  }
560
+ if (this.localDebuggerUrl) {
561
+ mirrorPartialEventToLocalDebugger(payload, {
562
+ baseUrl: this.localDebuggerUrl,
563
+ writeKey: this.writeKey,
564
+ debug: this.debug,
565
+ sdkName: this.sdkName
566
+ });
567
+ }
568
+ if (!this.writeKey) {
569
+ if (!isPending) this.sticky.delete(eventId);
570
+ return;
571
+ }
446
572
  const p = postJson(url, payload, this.authHeaders(), {
447
573
  maxAttempts: 3,
448
574
  debug: this.debug,
@@ -467,101 +593,94 @@ var EventShipper = class {
467
593
  }
468
594
  }
469
595
  };
470
- var LOCAL_DEBUGGER_ENV_VAR = "RAINDROP_LOCAL_DEBUGGER";
471
- var WORKSHOP_ENV_VAR = "RAINDROP_WORKSHOP";
472
- var DEFAULT_LOCAL_WORKSHOP_URL = "http://localhost:5899/v1/";
473
- function readEnvVar(name) {
474
- var _a;
475
- try {
476
- const env = (_a = globalThis == null ? void 0 : globalThis.process) == null ? void 0 : _a.env;
477
- if (env && typeof env[name] === "string" && env[name].length > 0) {
478
- return env[name];
596
+ var DEFAULT_SECRET_KEY_NAMES = [
597
+ "apikey",
598
+ "apisecret",
599
+ "apitoken",
600
+ "secretaccesskey",
601
+ "sessiontoken",
602
+ "privatekey",
603
+ "privatekeyid",
604
+ "clientsecret",
605
+ "accesstoken",
606
+ "refreshtoken",
607
+ "oauthtoken",
608
+ "bearertoken",
609
+ "authorization",
610
+ "password",
611
+ "passphrase"
612
+ ];
613
+ var REDACTED_PLACEHOLDER = "[REDACTED]";
614
+ function normalizeKeyName(name) {
615
+ return name.toLowerCase().replace(/[-_.]/g, "");
616
+ }
617
+ function redactSecretsInObject(value, options) {
618
+ var _a, _b;
619
+ const normalizedSecretSet = buildSecretSet((_a = options == null ? void 0 : options.secretKeyNames) != null ? _a : DEFAULT_SECRET_KEY_NAMES);
620
+ const placeholder = (_b = options == null ? void 0 : options.placeholder) != null ? _b : REDACTED_PLACEHOLDER;
621
+ const seen = /* @__PURE__ */ new WeakSet();
622
+ const walk = (node) => {
623
+ if (node === null || typeof node !== "object") return node;
624
+ if (seen.has(node)) return "[CIRCULAR]";
625
+ seen.add(node);
626
+ if (Array.isArray(node)) {
627
+ return node.map((item) => walk(item));
479
628
  }
629
+ const out = {};
630
+ for (const [k, v] of Object.entries(node)) {
631
+ if (normalizedSecretSet.has(normalizeKeyName(k))) {
632
+ out[k] = placeholder;
633
+ } else {
634
+ out[k] = walk(v);
635
+ }
636
+ }
637
+ return out;
638
+ };
639
+ return walk(value);
640
+ }
641
+ function buildSecretSet(names) {
642
+ const set = /* @__PURE__ */ new Set();
643
+ for (const name of names) set.add(normalizeKeyName(name));
644
+ return set;
645
+ }
646
+ var DEFAULT_REDACT_ATTRIBUTE_KEYS = [
647
+ "ai.request.providerOptions",
648
+ "ai.response.providerMetadata"
649
+ ];
650
+ function defaultTransformSpan(span) {
651
+ const attrs = span.attributes;
652
+ if (!attrs || attrs.length === 0) return span;
653
+ let nextAttrs;
654
+ for (let i = 0; i < attrs.length; i++) {
655
+ const attr = attrs[i];
656
+ const redacted = redactJsonAttributeValue(attr.key, attr.value);
657
+ if (redacted === void 0) continue;
658
+ if (!nextAttrs) nextAttrs = attrs.slice();
659
+ nextAttrs[i] = { key: attr.key, value: redacted };
660
+ }
661
+ if (!nextAttrs) return span;
662
+ return { ...span, attributes: nextAttrs };
663
+ }
664
+ var REDACT_JSON_ATTRIBUTE_KEYS = new Set(DEFAULT_REDACT_ATTRIBUTE_KEYS);
665
+ function redactJsonAttributeValue(key, value) {
666
+ if (!REDACT_JSON_ATTRIBUTE_KEYS.has(key)) return void 0;
667
+ const json = value.stringValue;
668
+ if (typeof json !== "string" || json.length === 0) return void 0;
669
+ let parsed;
670
+ try {
671
+ parsed = JSON.parse(json);
480
672
  } catch (e) {
673
+ return void 0;
481
674
  }
482
- return void 0;
483
- }
484
- function readWorkshopEnv() {
485
- const raw = readEnvVar(WORKSHOP_ENV_VAR);
486
- if (raw === void 0) return void 0;
487
- const trimmed = raw.trim();
488
- if (trimmed.length === 0) return void 0;
489
- if (/^https?:\/\//i.test(trimmed)) return { url: trimmed };
490
- if (/^(1|true|yes|on)$/i.test(trimmed)) return "enable";
491
- if (/^(0|false|no|off)$/i.test(trimmed)) return "disable";
492
- return void 0;
493
- }
494
- function isLocalDevHost(hostname) {
495
- if (!hostname) return false;
496
- if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "0.0.0.0" || hostname === "::1") {
497
- return true;
498
- }
499
- if (hostname.endsWith(".localhost")) return true;
500
- return false;
501
- }
502
- function readRuntimeHostname() {
675
+ const scrubbed = redactSecretsInObject(parsed);
676
+ let scrubbedJson;
503
677
  try {
504
- const loc = globalThis == null ? void 0 : globalThis.location;
505
- if (loc && typeof loc.hostname === "string" && loc.hostname.length > 0) {
506
- return loc.hostname;
507
- }
678
+ scrubbedJson = JSON.stringify(scrubbed);
508
679
  } catch (e) {
680
+ return void 0;
509
681
  }
510
- return void 0;
511
- }
512
- function shouldAutoEnableLocalWorkshop() {
513
- if (isLocalDevHost(readRuntimeHostname())) return true;
514
- if (readEnvVar("NODE_ENV") === "development") return true;
515
- return false;
516
- }
517
- function resolveLocalDebuggerBaseUrl(baseUrl) {
518
- var _a, _b, _c;
519
- if (baseUrl === null) return null;
520
- if (typeof baseUrl === "string" && baseUrl.length > 0) {
521
- return (_a = formatEndpoint(baseUrl)) != null ? _a : null;
522
- }
523
- const explicitUrlEnv = readEnvVar(LOCAL_DEBUGGER_ENV_VAR);
524
- if (explicitUrlEnv) return (_b = formatEndpoint(explicitUrlEnv)) != null ? _b : null;
525
- const workshopEnv = readWorkshopEnv();
526
- if (workshopEnv === "disable") return null;
527
- if (workshopEnv === "enable") return DEFAULT_LOCAL_WORKSHOP_URL;
528
- if (workshopEnv && "url" in workshopEnv) return (_c = formatEndpoint(workshopEnv.url)) != null ? _c : null;
529
- if (shouldAutoEnableLocalWorkshop()) return DEFAULT_LOCAL_WORKSHOP_URL;
530
- return null;
531
- }
532
- function localDebuggerEnabled(baseUrl) {
533
- return resolveLocalDebuggerBaseUrl(baseUrl) !== null;
534
- }
535
- function mirrorTraceExportToLocalDebugger(body, options = {}) {
536
- var _a;
537
- const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
538
- if (!baseUrl) return;
539
- void postJson(`${baseUrl}traces`, body, {}, {
540
- maxAttempts: 1,
541
- debug: (_a = options.debug) != null ? _a : false,
542
- sdkName: options.sdkName
543
- }).catch(() => {
544
- });
545
- }
546
- function sendLocalDebuggerLiveEvent(event, options = {}) {
547
- var _a, _b;
548
- const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
549
- if (!baseUrl) return;
550
- void postJson(
551
- `${baseUrl}live`,
552
- {
553
- ...event,
554
- type: event.type,
555
- timestamp: (_a = event.timestamp) != null ? _a : Date.now()
556
- },
557
- {},
558
- {
559
- maxAttempts: 1,
560
- debug: (_b = options.debug) != null ? _b : false,
561
- sdkName: options.sdkName
562
- }
563
- ).catch(() => {
564
- });
682
+ if (scrubbedJson === json) return void 0;
683
+ return { stringValue: scrubbedJson };
565
684
  }
566
685
  var TraceShipper = class {
567
686
  constructor(opts) {
@@ -584,6 +703,42 @@ var TraceShipper = class {
584
703
  if (this.debug && this.localDebuggerUrl) {
585
704
  console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
586
705
  }
706
+ this.transformSpanHook = opts.transformSpan;
707
+ this.disableDefaultRedaction = opts.disableDefaultRedaction === true;
708
+ }
709
+ /**
710
+ * Apply the user `transformSpan` hook (if any) followed by the default
711
+ * redactor (unless disabled). Returns either the (possibly new) span to
712
+ * ship, or `null` to drop the span entirely.
713
+ *
714
+ * Ordering: user hook runs first so callers can rewrite the span freely
715
+ * (rename attrs, add new ones, scrub things the default doesn't know
716
+ * about). The default redactor then runs on whatever the user produced,
717
+ * acting as the always-on floor for documented BYOK secrets. If the user
718
+ * sets `disableDefaultRedaction: true`, the floor is skipped.
719
+ *
720
+ * Fail-closed: if the user hook throws, the span is dropped — a buggy
721
+ * hook can never accidentally ship raw, un-redacted spans.
722
+ */
723
+ redactSpan(span) {
724
+ let current = span;
725
+ if (this.transformSpanHook) {
726
+ try {
727
+ const result = this.transformSpanHook(current);
728
+ if (result === null) return null;
729
+ if (result !== void 0) current = result;
730
+ } catch (err) {
731
+ if (this.debug) {
732
+ const msg = err instanceof Error ? err.message : String(err);
733
+ console.warn(`${this.prefix} transformSpan hook threw: ${msg}`);
734
+ }
735
+ return null;
736
+ }
737
+ }
738
+ if (!this.disableDefaultRedaction) {
739
+ current = defaultTransformSpan(current);
740
+ }
741
+ return current;
587
742
  }
588
743
  isDebugEnabled() {
589
744
  return this.debug;
@@ -601,8 +756,8 @@ var TraceShipper = class {
601
756
  ];
602
757
  if ((_b = args.attributes) == null ? void 0 : _b.length) attrs.push(...args.attributes);
603
758
  const span = { ids, name: args.name, startTimeUnixNano: started, attributes: attrs };
604
- if (this.localDebuggerUrl) {
605
- const openSpan = buildOtlpSpan({
759
+ this.mirrorToLocalDebugger(
760
+ buildOtlpSpan({
606
761
  ids: span.ids,
607
762
  name: span.name,
608
763
  startTimeUnixNano: span.startTimeUnixNano,
@@ -610,16 +765,21 @@ var TraceShipper = class {
610
765
  // placeholder — will be updated on endSpan
611
766
  attributes: span.attributes,
612
767
  status: { code: SpanStatusCode.UNSET }
613
- });
614
- const body = buildExportTraceServiceRequest([openSpan], this.serviceName, this.serviceVersion);
615
- mirrorTraceExportToLocalDebugger(body, {
616
- baseUrl: this.localDebuggerUrl,
617
- debug: false,
618
- sdkName: this.sdkName
619
- });
620
- }
768
+ })
769
+ );
621
770
  return span;
622
771
  }
772
+ mirrorToLocalDebugger(span) {
773
+ if (!this.localDebuggerUrl) return;
774
+ const redacted = this.redactSpan(span);
775
+ if (redacted === null) return;
776
+ const body = buildExportTraceServiceRequest([redacted], this.serviceName, this.serviceVersion);
777
+ mirrorTraceExportToLocalDebugger(body, {
778
+ baseUrl: this.localDebuggerUrl,
779
+ debug: false,
780
+ sdkName: this.sdkName
781
+ });
782
+ }
623
783
  endSpan(span, extra) {
624
784
  var _a, _b;
625
785
  if (span.endTimeUnixNano) return;
@@ -641,14 +801,7 @@ var TraceShipper = class {
641
801
  status
642
802
  });
643
803
  this.enqueue(otlp);
644
- if (this.localDebuggerUrl) {
645
- const body = buildExportTraceServiceRequest([otlp], this.serviceName, this.serviceVersion);
646
- mirrorTraceExportToLocalDebugger(body, {
647
- baseUrl: this.localDebuggerUrl,
648
- debug: false,
649
- sdkName: this.sdkName
650
- });
651
- }
804
+ this.mirrorToLocalDebugger(otlp);
652
805
  }
653
806
  createSpan(args) {
654
807
  var _a;
@@ -666,14 +819,7 @@ var TraceShipper = class {
666
819
  status: args.status
667
820
  });
668
821
  this.enqueue(otlp);
669
- if (this.localDebuggerUrl) {
670
- const body = buildExportTraceServiceRequest([otlp], this.serviceName, this.serviceVersion);
671
- mirrorTraceExportToLocalDebugger(body, {
672
- baseUrl: this.localDebuggerUrl,
673
- debug: false,
674
- sdkName: this.sdkName
675
- });
676
- }
822
+ this.mirrorToLocalDebugger(otlp);
677
823
  }
678
824
  enqueue(span) {
679
825
  if (!this.enabled) return;
@@ -685,10 +831,12 @@ var TraceShipper = class {
685
831
  )}`
686
832
  );
687
833
  }
834
+ const redacted = this.redactSpan(span);
835
+ if (redacted === null) return;
688
836
  if (this.queue.length >= this.maxQueueSize) {
689
837
  this.queue.shift();
690
838
  }
691
- this.queue.push(span);
839
+ this.queue.push(redacted);
692
840
  if (this.queue.length >= this.maxBatchSize) {
693
841
  void this.flush().catch(() => {
694
842
  });
@@ -710,6 +858,7 @@ var TraceShipper = class {
710
858
  }
711
859
  while (this.queue.length > 0) {
712
860
  const batch = this.queue.splice(0, this.maxBatchSize);
861
+ if (!this.writeKey) continue;
713
862
  const body = buildExportTraceServiceRequest(batch, this.serviceName, this.serviceVersion);
714
863
  const url = `${this.baseUrl}traces`;
715
864
  if (this.debug) {
@@ -868,7 +1017,7 @@ async function* asyncGeneratorWithCurrent(span, gen) {
868
1017
  // package.json
869
1018
  var package_default = {
870
1019
  name: "@raindrop-ai/ai-sdk",
871
- version: "0.0.28"};
1020
+ version: "0.0.30"};
872
1021
 
873
1022
  // src/internal/version.ts
874
1023
  var libraryName = package_default.name;
@@ -1584,13 +1733,76 @@ function readRaindropCallMetadataFromArgs(args) {
1584
1733
  return meta;
1585
1734
  }
1586
1735
 
1736
+ // src/internal/parent-tool-context.ts
1737
+ var SyncFallbackStorage2 = class {
1738
+ constructor() {
1739
+ this._stack = [];
1740
+ }
1741
+ getStore() {
1742
+ return this._stack[this._stack.length - 1];
1743
+ }
1744
+ run(store, callback) {
1745
+ this._stack.push(store);
1746
+ try {
1747
+ return callback();
1748
+ } finally {
1749
+ this._stack.pop();
1750
+ }
1751
+ }
1752
+ // `enterWith` is intentionally absent on the sync fallback — the
1753
+ // event-driven enter/clear pattern only makes sense when the runtime
1754
+ // can propagate state across awaits, which the sync stack cannot.
1755
+ };
1756
+ var _storage2 = null;
1757
+ function getStorage2() {
1758
+ if (_storage2) return _storage2;
1759
+ const Ctor = globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
1760
+ _storage2 = Ctor ? new Ctor() : new SyncFallbackStorage2();
1761
+ return _storage2;
1762
+ }
1763
+ function _resetParentToolContextStorage() {
1764
+ _storage2 = null;
1765
+ }
1766
+ function getCurrentParentToolContext() {
1767
+ return getStorage2().getStore();
1768
+ }
1769
+ function enterParentToolContext(ctx) {
1770
+ var _a;
1771
+ const storage = getStorage2();
1772
+ (_a = storage.enterWith) == null ? void 0 : _a.call(storage, ctx);
1773
+ }
1774
+ function clearParentToolContext() {
1775
+ var _a;
1776
+ const storage = getStorage2();
1777
+ (_a = storage.enterWith) == null ? void 0 : _a.call(storage, void 0);
1778
+ }
1779
+ function runWithParentToolContext(ctx, fn) {
1780
+ return getStorage2().run(ctx, fn);
1781
+ }
1782
+
1587
1783
  // src/internal/raindrop-telemetry-integration.ts
1588
1784
  var RaindropTelemetryIntegration = class {
1589
1785
  constructor(opts) {
1590
1786
  this.callStates = /* @__PURE__ */ new Map();
1787
+ /**
1788
+ * Per-tool-call snapshot of the parent-tool ALS context taken right
1789
+ * before `enterParentToolContext` overwrites it in `toolExecutionStart`.
1790
+ * Kept at the integration level (rather than on `CallState`) so the
1791
+ * snapshot survives even when the parent generation has no tracked
1792
+ * `CallState` — e.g. the AI SDK dispatches a tool callback for a
1793
+ * `callId` we never registered via `onStart`. Without this, the
1794
+ * unconditional ALS enter in `toolExecutionStart` would leave
1795
+ * `toolExecutionEnd` no way to restore the prior context, so it would
1796
+ * clear and wipe whatever the outer scope had set.
1797
+ *
1798
+ * Keyed by `toolCallId` because that's the only identifier guaranteed
1799
+ * to round-trip between `toolExecutionStart` and `toolExecutionEnd`
1800
+ * (the `event.callId` can be the same for parallel sibling tools).
1801
+ */
1802
+ this.priorParentContexts = /* @__PURE__ */ new Map();
1591
1803
  // ── onStart ─────────────────────────────────────────────────────────────
1592
1804
  this.onStart = (event) => {
1593
- var _a, _b, _c, _d;
1805
+ var _a, _b, _c, _d, _e;
1594
1806
  if (event.isEnabled === false) return;
1595
1807
  const isEmbed = event.operationId === "ai.embed" || event.operationId === "ai.embedMany";
1596
1808
  const recordInputs = event.recordInputs !== false;
@@ -1609,6 +1821,47 @@ var RaindropTelemetryIntegration = class {
1609
1821
  event.operationId,
1610
1822
  functionId
1611
1823
  );
1824
+ const parentToolContext = !isEmbed && this.subagentWrapping ? getCurrentParentToolContext() : void 0;
1825
+ const metadataSubagentName = !isEmbed && this.subagentWrapping && parentToolContext === void 0 ? typeof (metadata == null ? void 0 : metadata["ash.subagent.name"]) === "string" ? metadata["ash.subagent.name"] : void 0 : void 0;
1826
+ const subagentName = (_e = parentToolContext == null ? void 0 : parentToolContext.toolName) != null ? _e : metadataSubagentName;
1827
+ let subagentToolCallSpan;
1828
+ let rootParentOverride;
1829
+ if (subagentName && this.sendTraces) {
1830
+ const parentAttrs = parentToolContext ? [
1831
+ attrString("raindrop.parent.callId", parentToolContext.parentCallId),
1832
+ attrString("raindrop.parent.toolCallId", parentToolContext.toolCallId),
1833
+ attrString("raindrop.parent.toolName", parentToolContext.toolName)
1834
+ ] : [];
1835
+ subagentToolCallSpan = this.traceShipper.startSpan({
1836
+ name: subagentName,
1837
+ parent: inheritedParent,
1838
+ eventId,
1839
+ operationId: "ai.toolCall",
1840
+ attributes: [
1841
+ attrString("operation.name", "ai.toolCall"),
1842
+ attrString("resource.name", subagentName),
1843
+ attrString("raindrop.span.kind", "tool_call"),
1844
+ attrString("ai.toolCall.name", subagentName),
1845
+ attrString("raindrop.subagent.name", subagentName),
1846
+ attrString("raindrop.agent.role", "subagent"),
1847
+ ...parentAttrs
1848
+ ]
1849
+ });
1850
+ const subagentParentRef = this.spanParentRef(subagentToolCallSpan);
1851
+ const markerSpan = this.traceShipper.startSpan({
1852
+ name: "agent.subagent",
1853
+ parent: subagentParentRef,
1854
+ eventId,
1855
+ operationId: "agent.subagent",
1856
+ attributes: [
1857
+ attrString("operation.name", "agent.subagent"),
1858
+ attrString("raindrop.span.kind", "llm_call"),
1859
+ attrString("raindrop.subagent.name", subagentName)
1860
+ ]
1861
+ });
1862
+ this.traceShipper.endSpan(markerSpan);
1863
+ rootParentOverride = subagentParentRef;
1864
+ }
1612
1865
  let rootSpan;
1613
1866
  if (this.sendTraces) {
1614
1867
  const promptAttrs = !isEmbed && recordInputs ? [
@@ -1629,7 +1882,7 @@ var RaindropTelemetryIntegration = class {
1629
1882
  ] : [attrString("ai.value", safeJsonWithUint8(event.value))] : [];
1630
1883
  rootSpan = this.traceShipper.startSpan({
1631
1884
  name: event.operationId,
1632
- parent: inheritedParent,
1885
+ parent: rootParentOverride != null ? rootParentOverride : inheritedParent,
1633
1886
  eventId,
1634
1887
  operationId: event.operationId,
1635
1888
  attributes: [
@@ -1657,18 +1910,21 @@ var RaindropTelemetryIntegration = class {
1657
1910
  operationId: event.operationId,
1658
1911
  eventId,
1659
1912
  rootSpan,
1660
- rootParent: rootSpan ? this.spanParentRef(rootSpan) : inheritedParent,
1913
+ rootParent: rootSpan ? this.spanParentRef(rootSpan) : rootParentOverride != null ? rootParentOverride : inheritedParent,
1661
1914
  stepSpan: void 0,
1662
1915
  stepParent: void 0,
1663
1916
  toolSpans: /* @__PURE__ */ new Map(),
1664
1917
  embedSpans: /* @__PURE__ */ new Map(),
1918
+ parentContextToolCallIds: /* @__PURE__ */ new Set(),
1665
1919
  recordInputs,
1666
1920
  recordOutputs,
1667
1921
  functionId,
1668
1922
  metadata,
1669
1923
  accumulatedText: "",
1670
1924
  inputText: isEmbed ? void 0 : this.extractInputText(event),
1671
- toolCallCount: 0
1925
+ toolCallCount: 0,
1926
+ subagentName,
1927
+ subagentToolCallSpan
1672
1928
  });
1673
1929
  };
1674
1930
  // ── onStepStart ─────────────────────────────────────────────────────────
@@ -1892,6 +2148,9 @@ var RaindropTelemetryIntegration = class {
1892
2148
  } else {
1893
2149
  this.finishGenerate(event, state);
1894
2150
  }
2151
+ if (state.subagentToolCallSpan) {
2152
+ this.traceShipper.endSpan(state.subagentToolCallSpan);
2153
+ }
1895
2154
  this.cleanup(event.callId);
1896
2155
  };
1897
2156
  // ── onError ─────────────────────────────────────────────────────────────
@@ -1909,6 +2168,10 @@ var RaindropTelemetryIntegration = class {
1909
2168
  this.traceShipper.endSpan(embedSpan, { error: actualError });
1910
2169
  }
1911
2170
  state.embedSpans.clear();
2171
+ for (const toolCallId of state.parentContextToolCallIds) {
2172
+ this.priorParentContexts.delete(toolCallId);
2173
+ }
2174
+ state.parentContextToolCallIds.clear();
1912
2175
  for (const toolSpan of state.toolSpans.values()) {
1913
2176
  this.traceShipper.endSpan(toolSpan, { error: actualError });
1914
2177
  }
@@ -1916,6 +2179,9 @@ var RaindropTelemetryIntegration = class {
1916
2179
  if (state.rootSpan) {
1917
2180
  this.traceShipper.endSpan(state.rootSpan, { error: actualError });
1918
2181
  }
2182
+ if (state.subagentToolCallSpan) {
2183
+ this.traceShipper.endSpan(state.subagentToolCallSpan, { error: actualError });
2184
+ }
1919
2185
  this.cleanup(event.callId);
1920
2186
  };
1921
2187
  // ── executeTool ─────────────────────────────────────────────────────────
@@ -1940,6 +2206,7 @@ var RaindropTelemetryIntegration = class {
1940
2206
  this.eventShipper = opts.eventShipper;
1941
2207
  this.sendTraces = opts.sendTraces !== false;
1942
2208
  this.sendEvents = opts.sendEvents !== false;
2209
+ this.subagentWrapping = opts.subagentWrapping !== false;
1943
2210
  this.debug = opts.debug === true;
1944
2211
  this.defaultContext = opts.context;
1945
2212
  }
@@ -2021,9 +2288,20 @@ var RaindropTelemetryIntegration = class {
2021
2288
  // (see https://github.com/vercel/ai/pull/14589). Event shape is identical.
2022
2289
  // Both names are exposed and forward to a single implementation.
2023
2290
  toolExecutionStart(event) {
2291
+ const { toolCall } = event;
2292
+ const priorParent = getCurrentParentToolContext();
2293
+ this.priorParentContexts.set(
2294
+ toolCall.toolCallId,
2295
+ priorParent != null ? priorParent : null
2296
+ );
2297
+ enterParentToolContext({
2298
+ parentCallId: event.callId,
2299
+ toolCallId: toolCall.toolCallId,
2300
+ toolName: toolCall.toolName
2301
+ });
2024
2302
  const state = this.getState(event.callId);
2303
+ state == null ? void 0 : state.parentContextToolCallIds.add(toolCall.toolCallId);
2025
2304
  if (!(state == null ? void 0 : state.stepParent)) return;
2026
- const { toolCall } = event;
2027
2305
  const { operationName, resourceName } = opName(
2028
2306
  "ai.toolCall",
2029
2307
  state.functionId
@@ -2047,6 +2325,17 @@ var RaindropTelemetryIntegration = class {
2047
2325
  this.emitLive(state, "tool_start", toolCall.toolName, { args: toolCall.input });
2048
2326
  }
2049
2327
  toolExecutionEnd(event) {
2328
+ var _a;
2329
+ const toolCallId = (_a = event.toolCall) == null ? void 0 : _a.toolCallId;
2330
+ if (toolCallId && this.priorParentContexts.has(toolCallId)) {
2331
+ const prior = this.priorParentContexts.get(toolCallId);
2332
+ this.priorParentContexts.delete(toolCallId);
2333
+ if (prior) {
2334
+ enterParentToolContext(prior);
2335
+ } else {
2336
+ clearParentToolContext();
2337
+ }
2338
+ }
2050
2339
  const state = this.getState(event.callId);
2051
2340
  if (!state) return;
2052
2341
  const toolSpan = state.toolSpans.get(event.toolCall.toolCallId);
@@ -2110,7 +2399,8 @@ var RaindropTelemetryIntegration = class {
2110
2399
  );
2111
2400
  this.traceShipper.endSpan(state.rootSpan, { attributes: outputAttrs });
2112
2401
  }
2113
- if (this.sendEvents) {
2402
+ const suppressSubagentEvent = state.subagentName !== void 0 && state.subagentToolCallSpan !== void 0;
2403
+ if (this.sendEvents && !suppressSubagentEvent) {
2114
2404
  const callMeta = this.extractRaindropMetadata(state.metadata);
2115
2405
  const userId = (_f = callMeta.userId) != null ? _f : (_e = this.defaultContext) == null ? void 0 : _e.userId;
2116
2406
  if (userId) {
@@ -4268,16 +4558,20 @@ function envDebugEnabled() {
4268
4558
  return flag === "1" || flag === "true";
4269
4559
  }
4270
4560
  function createRaindropAISDK(opts) {
4271
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
4561
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
4272
4562
  const writeKey = opts.writeKey;
4273
4563
  const eventsRequested = ((_a = opts.events) == null ? void 0 : _a.enabled) !== false;
4274
4564
  const tracesRequested = ((_b = opts.traces) == null ? void 0 : _b.enabled) !== false;
4275
- const eventsEnabled = eventsRequested && !!writeKey;
4276
- const tracesEnabled = tracesRequested && !!writeKey;
4277
4565
  const envDebug = envDebugEnabled();
4278
- if (!writeKey && (eventsRequested || tracesRequested)) {
4566
+ const localWorkshopInput = opts.localWorkshopUrl === false ? null : opts.localWorkshopUrl;
4567
+ const resolvedLocalDebuggerUrl = resolveLocalDebuggerBaseUrl(localWorkshopInput);
4568
+ const localDebuggerUrl = localWorkshopInput === null ? null : resolvedLocalDebuggerUrl != null ? resolvedLocalDebuggerUrl : void 0;
4569
+ const hasDestination = !!writeKey || !!resolvedLocalDebuggerUrl;
4570
+ const eventsEnabled = eventsRequested && hasDestination;
4571
+ const tracesEnabled = tracesRequested && hasDestination;
4572
+ if (!hasDestination && (eventsRequested || tracesRequested)) {
4279
4573
  console.warn(
4280
- "[raindrop-ai/ai-sdk] writeKey not provided; telemetry shipping is disabled"
4574
+ "[raindrop-ai/ai-sdk] writeKey not provided and no local Workshop reachable; telemetry shipping is disabled"
4281
4575
  );
4282
4576
  }
4283
4577
  const eventShipper = new EventShipper2({
@@ -4285,9 +4579,9 @@ function createRaindropAISDK(opts) {
4285
4579
  endpoint: opts.endpoint,
4286
4580
  enabled: eventsEnabled,
4287
4581
  debug: ((_c = opts.events) == null ? void 0 : _c.debug) === true || envDebug,
4288
- partialFlushMs: (_d = opts.events) == null ? void 0 : _d.partialFlushMs
4582
+ partialFlushMs: (_d = opts.events) == null ? void 0 : _d.partialFlushMs,
4583
+ localDebuggerUrl
4289
4584
  });
4290
- const localDebuggerUrl = opts.localWorkshopUrl === false ? null : opts.localWorkshopUrl;
4291
4585
  const traceShipper = new TraceShipper2({
4292
4586
  writeKey,
4293
4587
  endpoint: opts.endpoint,
@@ -4297,7 +4591,9 @@ function createRaindropAISDK(opts) {
4297
4591
  flushIntervalMs: (_g = opts.traces) == null ? void 0 : _g.flushIntervalMs,
4298
4592
  maxBatchSize: (_h = opts.traces) == null ? void 0 : _h.maxBatchSize,
4299
4593
  maxQueueSize: (_i = opts.traces) == null ? void 0 : _i.maxQueueSize,
4300
- localDebuggerUrl
4594
+ localDebuggerUrl,
4595
+ transformSpan: (_j = opts.traces) == null ? void 0 : _j.transformSpan,
4596
+ disableDefaultRedaction: (_k = opts.traces) == null ? void 0 : _k.disableDefaultRedaction
4301
4597
  });
4302
4598
  return {
4303
4599
  wrap(aiSDK, options) {
@@ -4307,12 +4603,30 @@ function createRaindropAISDK(opts) {
4307
4603
  traceShipper
4308
4604
  });
4309
4605
  },
4310
- createTelemetryIntegration(context) {
4606
+ createTelemetryIntegration(contextOrOptions) {
4607
+ const FLAT_CONTEXT_KEYS = [
4608
+ "userId",
4609
+ "eventId",
4610
+ "eventName",
4611
+ "convoId",
4612
+ "properties"
4613
+ ];
4614
+ let context;
4615
+ let subagentWrapping;
4616
+ if (contextOrOptions === void 0) ; else if ("context" in contextOrOptions) {
4617
+ context = contextOrOptions.context;
4618
+ subagentWrapping = contextOrOptions.subagentWrapping;
4619
+ } else if ("subagentWrapping" in contextOrOptions && !FLAT_CONTEXT_KEYS.some((k) => k in contextOrOptions)) {
4620
+ subagentWrapping = contextOrOptions.subagentWrapping;
4621
+ } else {
4622
+ context = contextOrOptions;
4623
+ }
4311
4624
  return new RaindropTelemetryIntegration({
4312
4625
  traceShipper,
4313
4626
  eventShipper,
4314
4627
  sendTraces: tracesEnabled,
4315
4628
  sendEvents: eventsEnabled,
4629
+ subagentWrapping,
4316
4630
  debug: envDebug,
4317
4631
  context
4318
4632
  });
@@ -4420,4 +4734,4 @@ function createRaindropAISDK(opts) {
4420
4734
  };
4421
4735
  }
4422
4736
 
4423
- export { RaindropTelemetryIntegration, _resetRaindropCallMetadataStorage, _resetWarnedMissingUserId, createRaindropAISDK, currentSpan, eventMetadata, eventMetadataFromChatRequest, getContextManager, getCurrentRaindropCallMetadata, readRaindropCallMetadataFromArgs, runWithRaindropCallMetadata, withCurrent };
4737
+ export { DEFAULT_REDACT_ATTRIBUTE_KEYS, DEFAULT_SECRET_KEY_NAMES, REDACTED_PLACEHOLDER, RaindropTelemetryIntegration, _resetParentToolContextStorage, _resetRaindropCallMetadataStorage, _resetWarnedMissingUserId, clearParentToolContext, createRaindropAISDK, currentSpan, defaultTransformSpan, enterParentToolContext, eventMetadata, eventMetadataFromChatRequest, getContextManager, getCurrentParentToolContext, getCurrentRaindropCallMetadata, readRaindropCallMetadataFromArgs, redactJsonAttributeValue, redactSecretsInObject, runWithParentToolContext, runWithRaindropCallMetadata, withCurrent };