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