braintrust 3.20.0 → 3.21.0

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.
Files changed (88) hide show
  1. package/NOTICE +20 -0
  2. package/README.md +2 -0
  3. package/dev/dist/index.d.mts +309 -199
  4. package/dev/dist/index.d.ts +309 -199
  5. package/dev/dist/index.js +2826 -983
  6. package/dev/dist/index.mjs +2286 -443
  7. package/dist/apply-auto-instrumentation.js +781 -199
  8. package/dist/apply-auto-instrumentation.mjs +588 -6
  9. package/dist/auto-instrumentations/bundler/esbuild.cjs +594 -2
  10. package/dist/auto-instrumentations/bundler/esbuild.d.mts +2 -2
  11. package/dist/auto-instrumentations/bundler/esbuild.d.ts +2 -2
  12. package/dist/auto-instrumentations/bundler/esbuild.mjs +3 -3
  13. package/dist/auto-instrumentations/bundler/next.cjs +594 -2
  14. package/dist/auto-instrumentations/bundler/next.mjs +4 -4
  15. package/dist/auto-instrumentations/bundler/rollup.cjs +594 -2
  16. package/dist/auto-instrumentations/bundler/rollup.d.mts +2 -2
  17. package/dist/auto-instrumentations/bundler/rollup.d.ts +2 -2
  18. package/dist/auto-instrumentations/bundler/rollup.mjs +3 -3
  19. package/dist/auto-instrumentations/bundler/vite.cjs +594 -2
  20. package/dist/auto-instrumentations/bundler/vite.d.mts +2 -2
  21. package/dist/auto-instrumentations/bundler/vite.d.ts +2 -2
  22. package/dist/auto-instrumentations/bundler/vite.mjs +3 -3
  23. package/dist/auto-instrumentations/bundler/webpack-loader.cjs +593 -9
  24. package/dist/auto-instrumentations/bundler/webpack-loader.d.ts +68 -1
  25. package/dist/auto-instrumentations/bundler/webpack.cjs +594 -2
  26. package/dist/auto-instrumentations/bundler/webpack.d.mts +2 -2
  27. package/dist/auto-instrumentations/bundler/webpack.d.ts +2 -2
  28. package/dist/auto-instrumentations/bundler/webpack.mjs +4 -4
  29. package/dist/auto-instrumentations/{chunk-W4E36GIW.mjs → chunk-BRQX23KL.mjs} +16 -0
  30. package/dist/auto-instrumentations/chunk-M6DLIJ2Z.mjs +784 -0
  31. package/dist/auto-instrumentations/{chunk-K74TZGGM.mjs → chunk-T6J4C7LX.mjs} +1 -1
  32. package/dist/auto-instrumentations/{chunk-S4374IP6.mjs → chunk-TKRPRPGD.mjs} +4 -6
  33. package/dist/auto-instrumentations/chunk-VT6DDNKM.mjs +856 -0
  34. package/dist/auto-instrumentations/hook.mjs +749 -45
  35. package/dist/auto-instrumentations/index.cjs +16 -0
  36. package/dist/auto-instrumentations/index.d.mts +2 -3
  37. package/dist/auto-instrumentations/index.d.ts +2 -3
  38. package/dist/auto-instrumentations/index.mjs +1 -1
  39. package/dist/auto-instrumentations/loader/cjs-patch.cjs +578 -4
  40. package/dist/auto-instrumentations/loader/cjs-patch.d.mts +1 -1
  41. package/dist/auto-instrumentations/loader/cjs-patch.d.ts +1 -1
  42. package/dist/auto-instrumentations/loader/cjs-patch.mjs +3 -7
  43. package/dist/auto-instrumentations/loader/esm-hook.mjs +2 -6
  44. package/dist/auto-instrumentations/{plugin-D7nDswtC.d.mts → plugin-D0KHwSJv.d.mts} +1 -1
  45. package/dist/auto-instrumentations/{plugin-D7nDswtC.d.ts → plugin-G6fgxk1b.d.ts} +1 -1
  46. package/dist/auto-instrumentations/types-RNPaKi9o.d.mts +70 -0
  47. package/dist/auto-instrumentations/types-RNPaKi9o.d.ts +70 -0
  48. package/dist/browser.d.mts +1357 -847
  49. package/dist/browser.d.ts +1357 -847
  50. package/dist/browser.js +2726 -469
  51. package/dist/browser.mjs +2726 -469
  52. package/dist/{chunk-LPC4W2WX.js → chunk-BFGIH2ZJ.js} +4 -0
  53. package/dist/{chunk-POCCIJAL.js → chunk-FY7DAKA5.js} +3141 -1269
  54. package/dist/{chunk-Y7W7WP6H.mjs → chunk-KMGUTPB7.mjs} +4 -0
  55. package/dist/{chunk-F73OMF66.mjs → chunk-O2P765XK.mjs} +2391 -519
  56. package/dist/cli.js +2260 -408
  57. package/dist/edge-light.d.mts +1 -1
  58. package/dist/edge-light.d.ts +1 -1
  59. package/dist/edge-light.js +2726 -469
  60. package/dist/edge-light.mjs +2726 -469
  61. package/dist/index.d.mts +1837 -1327
  62. package/dist/index.d.ts +1837 -1327
  63. package/dist/index.js +752 -353
  64. package/dist/index.mjs +445 -46
  65. package/dist/instrumentation/index.d.mts +107 -19
  66. package/dist/instrumentation/index.d.ts +107 -19
  67. package/dist/instrumentation/index.js +2337 -509
  68. package/dist/instrumentation/index.mjs +2337 -509
  69. package/dist/vitest-evals-reporter.js +16 -16
  70. package/dist/vitest-evals-reporter.mjs +2 -2
  71. package/dist/workerd.d.mts +1 -1
  72. package/dist/workerd.d.ts +1 -1
  73. package/dist/workerd.js +2726 -469
  74. package/dist/workerd.mjs +2726 -469
  75. package/licenses/import-in-the-middle/LICENSE +201 -0
  76. package/licenses/import-in-the-middle/LICENSE-3rdparty.csv +4 -0
  77. package/licenses/import-in-the-middle/NOTICE +34 -0
  78. package/licenses/orchestrion-js/LICENSE +202 -0
  79. package/licenses/orchestrion-js/LICENSE-3rdparty.csv +8 -0
  80. package/licenses/orchestrion-js/NOTICE +3 -0
  81. package/licenses/require-in-the-middle/LICENSE +23 -0
  82. package/package.json +13 -4
  83. package/util/dist/index.d.mts +1 -0
  84. package/util/dist/index.d.ts +1 -0
  85. package/util/dist/index.js +4 -4
  86. package/util/dist/index.mjs +2 -2
  87. package/dist/auto-instrumentations/chunk-J57YF7WS.mjs +0 -208
  88. package/dist/auto-instrumentations/chunk-QFMACSOL.mjs +0 -280
package/dist/browser.js CHANGED
@@ -32,8 +32,10 @@ var browser_exports = {};
32
32
  __export(browser_exports, {
33
33
  Attachment: () => Attachment,
34
34
  AttachmentReference: () => AttachmentReference,
35
+ BAGGAGE_HEADER: () => BAGGAGE_HEADER,
35
36
  BRAINTRUST_CURRENT_SPAN_STORE: () => BRAINTRUST_CURRENT_SPAN_STORE,
36
37
  BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME: () => BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME,
38
+ BRAINTRUST_PARENT_KEY: () => BRAINTRUST_PARENT_KEY,
37
39
  BaseAttachment: () => BaseAttachment,
38
40
  BaseExperiment: () => BaseExperiment,
39
41
  BraintrustLangChainCallbackHandler: () => BraintrustLangChainCallbackHandler,
@@ -66,6 +68,7 @@ __export(browser_exports, {
66
68
  NOOP_SPAN: () => NOOP_SPAN,
67
69
  NOOP_SPAN_PERMALINK: () => NOOP_SPAN_PERMALINK,
68
70
  NoopSpan: () => NoopSpan,
71
+ OTELIDGenerator: () => OTELIDGenerator,
69
72
  ObjectFetcher: () => ObjectFetcher,
70
73
  Project: () => Project2,
71
74
  ProjectNameIdMap: () => ProjectNameIdMap,
@@ -77,6 +80,8 @@ __export(browser_exports, {
77
80
  ScorerBuilder: () => ScorerBuilder,
78
81
  SpanFetcher: () => SpanFetcher,
79
82
  SpanImpl: () => SpanImpl,
83
+ TRACEPARENT_HEADER: () => TRACEPARENT_HEADER,
84
+ TRACESTATE_HEADER: () => TRACESTATE_HEADER,
80
85
  TestBackgroundLogger: () => TestBackgroundLogger,
81
86
  ToolBuilder: () => ToolBuilder,
82
87
  UUIDGenerator: () => UUIDGenerator,
@@ -86,6 +91,7 @@ __export(browser_exports, {
86
91
  _internalIso: () => isomorph_default,
87
92
  _internalSetInitialState: () => _internalSetInitialState,
88
93
  addAzureBlobHeaders: () => addAzureBlobHeaders,
94
+ agentAssertionScorer: () => agentAssertionScorer,
89
95
  braintrustAISDKTelemetry: () => braintrustAISDKTelemetry,
90
96
  braintrustFlueInstrumentation: () => braintrustFlueInstrumentation,
91
97
  braintrustFlueObserver: () => braintrustFlueObserver,
@@ -104,6 +110,7 @@ __export(browser_exports, {
104
110
  devNullWritableStream: () => devNullWritableStream,
105
111
  evaluatorDefinitionSchema: () => evaluatorDefinitionSchema,
106
112
  evaluatorDefinitionsSchema: () => evaluatorDefinitionsSchema,
113
+ extractTraceContextFromHeaders: () => extractTraceContextFromHeaders,
107
114
  flush: () => flush,
108
115
  getContextManager: () => getContextManager,
109
116
  getIdGenerator: () => getIdGenerator,
@@ -117,6 +124,7 @@ __export(browser_exports, {
117
124
  initFunction: () => initFunction,
118
125
  initLogger: () => initLogger,
119
126
  initNodeTestSuite: () => initNodeTestSuite,
127
+ injectTraceContext: () => injectTraceContext,
120
128
  invoke: () => invoke,
121
129
  isTemplateFormat: () => isTemplateFormat,
122
130
  loadParameters: () => loadParameters,
@@ -155,7 +163,7 @@ __export(browser_exports, {
155
163
  traced: () => traced,
156
164
  updateSpan: () => updateSpan,
157
165
  uploadLogs3OverflowPayload: () => uploadLogs3OverflowPayload,
158
- utf8ByteLength: () => utf8ByteLength,
166
+ utf8ByteLength: () => utf8ByteLength2,
159
167
  withCurrent: () => withCurrent,
160
168
  withDataset: () => withDataset,
161
169
  withExperiment: () => withExperiment,
@@ -473,8 +481,291 @@ var UUIDGenerator = class extends IDGenerator {
473
481
  return true;
474
482
  }
475
483
  };
484
+ function generateHexId(bytes) {
485
+ let result = "";
486
+ for (let i = 0; i < bytes; i++) {
487
+ result += Math.floor(Math.random() * 256).toString(16).padStart(2, "0");
488
+ }
489
+ return result;
490
+ }
491
+ var OTELIDGenerator = class extends IDGenerator {
492
+ getSpanId() {
493
+ return generateHexId(8);
494
+ }
495
+ getTraceId() {
496
+ return generateHexId(16);
497
+ }
498
+ shareRootSpanId() {
499
+ return false;
500
+ }
501
+ };
502
+ function parseEnvBool(name) {
503
+ const raw = isomorph_default.getEnv(name);
504
+ if (raw === void 0 || raw === null) {
505
+ return false;
506
+ }
507
+ const normalized = raw.trim().toLowerCase();
508
+ return normalized === "true" || normalized === "1" || normalized === "yes" || normalized === "y" || normalized === "on";
509
+ }
510
+ var _warnedLegacyUuidConflict = false;
511
+ function resolveUseLegacyUuidIds() {
512
+ const legacy = parseEnvBool("BRAINTRUST_LEGACY_IDS");
513
+ if (parseEnvBool("BRAINTRUST_OTEL_COMPAT")) {
514
+ if (legacy && !_warnedLegacyUuidConflict) {
515
+ _warnedLegacyUuidConflict = true;
516
+ debugLogger.warn(
517
+ "BRAINTRUST_LEGACY_IDS is ignored because BRAINTRUST_OTEL_COMPAT requires OpenTelemetry-compatible hex span IDs. Using hex IDs."
518
+ );
519
+ }
520
+ return false;
521
+ }
522
+ return legacy;
523
+ }
476
524
  function getIdGenerator() {
477
- return globalThis.BRAINTRUST_ID_GENERATOR !== void 0 ? new globalThis.BRAINTRUST_ID_GENERATOR() : new UUIDGenerator();
525
+ if (globalThis.BRAINTRUST_ID_GENERATOR !== void 0) {
526
+ return new globalThis.BRAINTRUST_ID_GENERATOR();
527
+ }
528
+ return resolveUseLegacyUuidIds() ? new UUIDGenerator() : new OTELIDGenerator();
529
+ }
530
+
531
+ // src/propagation.ts
532
+ var TRACEPARENT_HEADER = "traceparent";
533
+ var TRACESTATE_HEADER = "tracestate";
534
+ var BAGGAGE_HEADER = "baggage";
535
+ var BRAINTRUST_PARENT_KEY = "braintrust.parent";
536
+ var DEFAULT_TRACE_FLAGS = "01";
537
+ var TRACEPARENT_RE = /^00-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$/;
538
+ var ZERO_TRACE_ID = "0".repeat(32);
539
+ var ZERO_SPAN_ID = "0".repeat(16);
540
+ var MAX_BAGGAGE_LENGTH = 8192;
541
+ var MAX_BAGGAGE_MEMBERS = 64;
542
+ var _utf8Encoder = new TextEncoder();
543
+ function utf8ByteLength(value) {
544
+ return _utf8Encoder.encode(value).length;
545
+ }
546
+ function capBaggageToMemberBoundary(value) {
547
+ const totalBytes = utf8ByteLength(value);
548
+ const withinBytes = totalBytes <= MAX_BAGGAGE_LENGTH;
549
+ let commaCount = 0;
550
+ for (let i = 0; i < value.length; i++) {
551
+ if (value.charCodeAt(i) === 44) {
552
+ commaCount++;
553
+ }
554
+ }
555
+ const withinMembers = commaCount < MAX_BAGGAGE_MEMBERS;
556
+ if (withinBytes && withinMembers) {
557
+ return value;
558
+ }
559
+ const kept = [];
560
+ let length = 0;
561
+ for (const rawMember of value.split(",")) {
562
+ if (kept.length >= MAX_BAGGAGE_MEMBERS) {
563
+ break;
564
+ }
565
+ const cost = utf8ByteLength(rawMember) + (kept.length ? 1 : 0);
566
+ if (length + cost > MAX_BAGGAGE_LENGTH) {
567
+ break;
568
+ }
569
+ kept.push(rawMember);
570
+ length += cost;
571
+ }
572
+ if (!kept.length) {
573
+ return "";
574
+ }
575
+ return kept.join(",");
576
+ }
577
+ function isTraceContextHeaderTupleArray(value) {
578
+ return Array.isArray(value) && value.every(
579
+ (item) => Array.isArray(item) && typeof item[0] === "string" && typeof item[1] === "string"
580
+ );
581
+ }
582
+ function isListHeader(name) {
583
+ const lowered = name.toLowerCase();
584
+ return lowered === BAGGAGE_HEADER || lowered === TRACESTATE_HEADER;
585
+ }
586
+ function headerValueToString(value, name) {
587
+ if (value === void 0 || value === null) {
588
+ return void 0;
589
+ }
590
+ if (Array.isArray(value)) {
591
+ const stringValues = value.filter((item) => {
592
+ return typeof item === "string";
593
+ });
594
+ if (!stringValues.length) {
595
+ return void 0;
596
+ }
597
+ return isListHeader(name) ? stringValues.join(",") : stringValues[0];
598
+ }
599
+ return typeof value === "string" ? value : String(value);
600
+ }
601
+ function getHeader(headers, name) {
602
+ if (!headers) {
603
+ return void 0;
604
+ }
605
+ if (isTraceContextHeaderTupleArray(headers)) {
606
+ const lowered2 = name.toLowerCase();
607
+ const matches = headers.filter(([key]) => key.toLowerCase() === lowered2).map(([, value]) => value);
608
+ if (!matches.length) {
609
+ return void 0;
610
+ }
611
+ return headerValueToString(matches, name);
612
+ }
613
+ const getter = headers.get;
614
+ if (typeof getter === "function") {
615
+ try {
616
+ const value = headerValueToString(getter.call(headers, name), name);
617
+ if (value !== void 0) {
618
+ return value;
619
+ }
620
+ } catch {
621
+ }
622
+ }
623
+ const nodeGetter = headers.getHeader;
624
+ if (typeof nodeGetter === "function") {
625
+ try {
626
+ const value = headerValueToString(nodeGetter.call(headers, name), name);
627
+ if (value !== void 0) {
628
+ return value;
629
+ }
630
+ } catch {
631
+ }
632
+ }
633
+ const headerBag = headers;
634
+ const exact = headerValueToString(headerBag[name], name);
635
+ if (exact !== void 0) {
636
+ return exact;
637
+ }
638
+ const lowered = name.toLowerCase();
639
+ for (const key of Object.keys(headers)) {
640
+ if (key !== name && key.toLowerCase() === lowered) {
641
+ const value = headerValueToString(headerBag[key], name);
642
+ if (value !== void 0) {
643
+ return value;
644
+ }
645
+ }
646
+ }
647
+ return void 0;
648
+ }
649
+ function isHex(value, length) {
650
+ if (typeof value !== "string" || value.length !== length) {
651
+ return false;
652
+ }
653
+ for (let i = 0; i < value.length; i++) {
654
+ const c = value[i];
655
+ const isDigit = c >= "0" && c <= "9";
656
+ const isLowerHex = c >= "a" && c <= "f";
657
+ if (!isDigit && !isLowerHex) {
658
+ return false;
659
+ }
660
+ }
661
+ return true;
662
+ }
663
+ function parseTraceparent(value) {
664
+ if (!value || typeof value !== "string") {
665
+ return void 0;
666
+ }
667
+ const match = TRACEPARENT_RE.exec(value.trim());
668
+ if (!match) {
669
+ return void 0;
670
+ }
671
+ const traceId = match[1];
672
+ const spanId = match[2];
673
+ const traceFlags = match[3];
674
+ if (traceId === ZERO_TRACE_ID || spanId === ZERO_SPAN_ID) {
675
+ return void 0;
676
+ }
677
+ return { traceId, spanId, traceFlags };
678
+ }
679
+ function formatTraceparent(traceId, spanId, traceFlags = DEFAULT_TRACE_FLAGS) {
680
+ if (!isHex(traceId, 32) || traceId === ZERO_TRACE_ID) {
681
+ return void 0;
682
+ }
683
+ if (!isHex(spanId, 16) || spanId === ZERO_SPAN_ID) {
684
+ return void 0;
685
+ }
686
+ const flags = isHex(traceFlags, 2) ? traceFlags : DEFAULT_TRACE_FLAGS;
687
+ return `00-${traceId}-${spanId}-${flags}`;
688
+ }
689
+ function percentEncode(value) {
690
+ return encodeURIComponent(value);
691
+ }
692
+ function percentDecode(value) {
693
+ if (!value.includes("%")) {
694
+ return value;
695
+ }
696
+ try {
697
+ return decodeURIComponent(value);
698
+ } catch {
699
+ return value;
700
+ }
701
+ }
702
+ function parseBaggage(value) {
703
+ const result = {};
704
+ if (!value || typeof value !== "string") {
705
+ return result;
706
+ }
707
+ const bounded = capBaggageToMemberBoundary(value);
708
+ for (let member of bounded.split(",")) {
709
+ member = member.trim();
710
+ if (!member || !member.includes("=")) {
711
+ continue;
712
+ }
713
+ member = member.split(";", 1)[0];
714
+ const eq = member.indexOf("=");
715
+ const key = percentDecode(member.slice(0, eq).trim());
716
+ const val = member.slice(eq + 1).trim();
717
+ if (!key) {
718
+ continue;
719
+ }
720
+ result[key] = percentDecode(val);
721
+ }
722
+ return result;
723
+ }
724
+ function mergeBaggage(existing, braintrustParent) {
725
+ let btMember = void 0;
726
+ if (braintrustParent) {
727
+ const encodedKey = percentEncode(BRAINTRUST_PARENT_KEY);
728
+ const encodedVal = percentEncode(String(braintrustParent));
729
+ btMember = `${encodedKey}=${encodedVal}`;
730
+ if (utf8ByteLength(btMember) > MAX_BAGGAGE_LENGTH) {
731
+ btMember = void 0;
732
+ }
733
+ }
734
+ let byteBudget = MAX_BAGGAGE_LENGTH;
735
+ let memberBudget = MAX_BAGGAGE_MEMBERS;
736
+ if (btMember !== void 0) {
737
+ byteBudget -= utf8ByteLength(btMember) + 1;
738
+ memberBudget -= 1;
739
+ }
740
+ const relayed = [];
741
+ let length = 0;
742
+ if (existing && typeof existing === "string") {
743
+ for (const rawMember of existing.split(",")) {
744
+ const member = rawMember.trim();
745
+ if (!member || !member.includes("=")) {
746
+ continue;
747
+ }
748
+ const keyPart = member.split(";", 1)[0].split("=", 1)[0];
749
+ const key = percentDecode(keyPart.trim());
750
+ if (key === BRAINTRUST_PARENT_KEY) {
751
+ continue;
752
+ }
753
+ if (relayed.length >= memberBudget) {
754
+ break;
755
+ }
756
+ const cost = utf8ByteLength(member) + (relayed.length ? 1 : 0);
757
+ if (length + cost > byteBudget) {
758
+ break;
759
+ }
760
+ relayed.push(member);
761
+ length += cost;
762
+ }
763
+ }
764
+ const members = btMember !== void 0 ? [...relayed, btMember] : relayed;
765
+ if (!members.length) {
766
+ return void 0;
767
+ }
768
+ return members.join(",");
478
769
  }
479
770
 
480
771
  // util/db_fields.ts
@@ -1082,7 +1373,7 @@ var SpanComponentsV3 = class _SpanComponentsV3 {
1082
1373
  case 3 /* PLAYGROUND_LOGS */:
1083
1374
  return { prompt_session_id: this.data.object_id, log_id: "x" };
1084
1375
  default:
1085
- const _ = this.data.object_type;
1376
+ this.data.object_type;
1086
1377
  throw new Error("Impossible");
1087
1378
  }
1088
1379
  }
@@ -1611,7 +1902,7 @@ var SpanComponentsV4 = class _SpanComponentsV4 {
1611
1902
  case 3 /* PLAYGROUND_LOGS */:
1612
1903
  return { prompt_session_id: this.data.object_id, log_id: "x" };
1613
1904
  default:
1614
- const _ = this.data.object_type;
1905
+ this.data.object_type;
1615
1906
  throw new Error(`Invalid object_type ${this.data.object_type}`);
1616
1907
  }
1617
1908
  }
@@ -1790,7 +2081,8 @@ var AclObjectType = import_v36.z.union([
1790
2081
  "role",
1791
2082
  "org_member",
1792
2083
  "project_log",
1793
- "org_project"
2084
+ "org_project",
2085
+ "org_audit_logs"
1794
2086
  ]),
1795
2087
  import_v36.z.null()
1796
2088
  ]);
@@ -1816,6 +2108,17 @@ var Acl = import_v36.z.object({
1816
2108
  _object_org_id: import_v36.z.string().uuid(),
1817
2109
  created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional()
1818
2110
  });
2111
+ var Agent = import_v36.z.object({
2112
+ id: import_v36.z.string().uuid(),
2113
+ project_id: import_v36.z.string().uuid(),
2114
+ user_id: import_v36.z.string().uuid(),
2115
+ created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2116
+ name: import_v36.z.string(),
2117
+ slug: import_v36.z.string(),
2118
+ kind: import_v36.z.string(),
2119
+ description: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2120
+ metadata: import_v36.z.union([import_v36.z.object({}).partial().passthrough(), import_v36.z.null()]).optional()
2121
+ });
1819
2122
  var AISecret = import_v36.z.object({
1820
2123
  id: import_v36.z.string().uuid(),
1821
2124
  created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
@@ -1962,6 +2265,7 @@ var AttachmentStatus = import_v36.z.object({
1962
2265
  upload_status: UploadStatus,
1963
2266
  error_message: import_v36.z.string().optional()
1964
2267
  });
2268
+ var AutomationStatus = import_v36.z.enum(["active", "paused"]);
1965
2269
  var FunctionTypeEnum = import_v36.z.enum([
1966
2270
  "llm",
1967
2271
  "scorer",
@@ -2007,7 +2311,9 @@ var TopicMapData = import_v36.z.object({
2007
2311
  topic_names: import_v36.z.record(import_v36.z.string()).optional(),
2008
2312
  generation_settings: TopicMapGenerationSettings.optional(),
2009
2313
  disable_reconciliation: import_v36.z.boolean().optional(),
2010
- distance_threshold: import_v36.z.number().optional()
2314
+ distance_threshold: import_v36.z.number().optional(),
2315
+ btql_filter: import_v36.z.string().optional(),
2316
+ automation_btql_filter: import_v36.z.string().optional()
2011
2317
  });
2012
2318
  var BatchedFacetData = import_v36.z.object({
2013
2319
  type: import_v36.z.literal("batched_facet"),
@@ -2290,7 +2596,7 @@ var DatasetEvent = import_v36.z.object({
2290
2596
  origin: ObjectReferenceNullish.optional(),
2291
2597
  comments: import_v36.z.union([import_v36.z.array(import_v36.z.unknown()), import_v36.z.null()]).optional(),
2292
2598
  audit_data: import_v36.z.union([import_v36.z.array(import_v36.z.unknown()), import_v36.z.null()]).optional(),
2293
- facets: import_v36.z.union([import_v36.z.object({}).partial().passthrough(), import_v36.z.null()]).optional(),
2599
+ facets: import_v36.z.union([import_v36.z.record(import_v36.z.union([import_v36.z.string(), import_v36.z.null()])), import_v36.z.null()]).optional(),
2294
2600
  classifications: import_v36.z.union([
2295
2601
  import_v36.z.record(
2296
2602
  import_v36.z.array(
@@ -2442,7 +2748,7 @@ var ExperimentEvent = import_v36.z.object({
2442
2748
  origin: ObjectReferenceNullish.optional(),
2443
2749
  comments: import_v36.z.union([import_v36.z.array(import_v36.z.unknown()), import_v36.z.null()]).optional(),
2444
2750
  audit_data: import_v36.z.union([import_v36.z.array(import_v36.z.unknown()), import_v36.z.null()]).optional(),
2445
- facets: import_v36.z.union([import_v36.z.object({}).partial().passthrough(), import_v36.z.null()]).optional(),
2751
+ facets: import_v36.z.union([import_v36.z.record(import_v36.z.union([import_v36.z.string(), import_v36.z.null()])), import_v36.z.null()]).optional(),
2446
2752
  classifications: import_v36.z.union([
2447
2753
  import_v36.z.record(
2448
2754
  import_v36.z.array(
@@ -2580,7 +2886,8 @@ var PromptParserNullish = import_v36.z.union([
2580
2886
  use_cot: import_v36.z.boolean(),
2581
2887
  choice_scores: import_v36.z.record(import_v36.z.number().gte(0).lte(1)).optional(),
2582
2888
  choice: import_v36.z.array(import_v36.z.string()).optional(),
2583
- allow_no_match: import_v36.z.boolean().optional()
2889
+ allow_no_match: import_v36.z.boolean().optional(),
2890
+ allow_skip: import_v36.z.boolean().optional()
2584
2891
  }),
2585
2892
  import_v36.z.null()
2586
2893
  ]);
@@ -2910,6 +3217,9 @@ var Group = import_v36.z.object({
2910
3217
  var GroupScope = import_v36.z.object({
2911
3218
  type: import_v36.z.literal("group"),
2912
3219
  group_by: import_v36.z.string(),
3220
+ interval_seconds: import_v36.z.number().gte(1).optional(),
3221
+ max_traces: import_v36.z.number().int().gte(1).lte(64).optional(),
3222
+ placement: import_v36.z.enum(["first", "each"]),
2913
3223
  idle_seconds: import_v36.z.number().optional()
2914
3224
  });
2915
3225
  var IfExists = import_v36.z.enum(["error", "ignore", "replace"]);
@@ -3058,6 +3368,10 @@ var RetentionObjectType = import_v36.z.enum([
3058
3368
  "experiment",
3059
3369
  "dataset"
3060
3370
  ]);
3371
+ var TopicAutomationFacetModel = import_v36.z.union([
3372
+ import_v36.z.enum(["brain-facet-latest", "brain-facet-1", "brain-facet-2"]),
3373
+ import_v36.z.null()
3374
+ ]);
3061
3375
  var TopicMapFunctionAutomation = import_v36.z.object({
3062
3376
  function: SavedFunctionId.and(import_v36.z.unknown()),
3063
3377
  btql_filter: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional()
@@ -3070,7 +3384,9 @@ var TopicAutomationDataScope = import_v36.z.union([
3070
3384
  ]);
3071
3385
  var TopicAutomationConfig = import_v36.z.object({
3072
3386
  event_type: import_v36.z.literal("topic"),
3387
+ status: AutomationStatus.optional(),
3073
3388
  sampling_rate: import_v36.z.number().gte(0).lte(1),
3389
+ facet_model: TopicAutomationFacetModel.optional(),
3074
3390
  facet_functions: import_v36.z.array(SavedFunctionId),
3075
3391
  topic_map_functions: import_v36.z.array(TopicMapFunctionAutomation),
3076
3392
  scope: import_v36.z.union([SpanScope, TraceScope, GroupScope, import_v36.z.null()]).optional(),
@@ -3084,6 +3400,19 @@ var TopicAutomationConfig = import_v36.z.object({
3084
3400
  import_v36.z.null()
3085
3401
  ]).optional()
3086
3402
  });
3403
+ var TopicDigestAutomationConfig = import_v36.z.object({
3404
+ event_type: import_v36.z.literal("topic_digest"),
3405
+ status: AutomationStatus.optional(),
3406
+ window_seconds: import_v36.z.number().int().gte(3600).lte(2592e3).optional().default(86400),
3407
+ scheduled_time_minutes_utc: import_v36.z.number().int().gte(0).lte(1439),
3408
+ action: import_v36.z.object({
3409
+ type: import_v36.z.literal("slack"),
3410
+ workspace_id: import_v36.z.string(),
3411
+ channel: import_v36.z.string(),
3412
+ message_template: import_v36.z.string().optional()
3413
+ }),
3414
+ topic_map_function_ids: import_v36.z.array(import_v36.z.string()).max(10).optional()
3415
+ });
3087
3416
  var ProjectAutomation = import_v36.z.object({
3088
3417
  id: import_v36.z.string().uuid(),
3089
3418
  project_id: import_v36.z.string().uuid(),
@@ -3108,6 +3437,7 @@ var ProjectAutomation = import_v36.z.object({
3108
3437
  }),
3109
3438
  import_v36.z.object({
3110
3439
  event_type: import_v36.z.literal("btql_export"),
3440
+ status: AutomationStatus.optional(),
3111
3441
  export_definition: import_v36.z.union([
3112
3442
  import_v36.z.object({ type: import_v36.z.literal("log_traces") }),
3113
3443
  import_v36.z.object({ type: import_v36.z.literal("log_spans") }),
@@ -3130,6 +3460,21 @@ var ProjectAutomation = import_v36.z.object({
3130
3460
  ]),
3131
3461
  batch_size: import_v36.z.union([import_v36.z.number(), import_v36.z.null()]).optional()
3132
3462
  }),
3463
+ import_v36.z.object({
3464
+ event_type: import_v36.z.literal("async_query"),
3465
+ status: AutomationStatus.optional(),
3466
+ created_by_user_id: import_v36.z.string().uuid(),
3467
+ object_type: import_v36.z.enum([
3468
+ "project_logs",
3469
+ "experiment",
3470
+ "dataset",
3471
+ "playground_logs"
3472
+ ]),
3473
+ object_id: import_v36.z.string(),
3474
+ query: import_v36.z.string(),
3475
+ format: import_v36.z.literal("jsonl"),
3476
+ batch_size: import_v36.z.union([import_v36.z.number(), import_v36.z.null()]).optional()
3477
+ }),
3133
3478
  import_v36.z.object({
3134
3479
  event_type: import_v36.z.literal("retention"),
3135
3480
  object_type: RetentionObjectType,
@@ -3148,7 +3493,8 @@ var ProjectAutomation = import_v36.z.object({
3148
3493
  })
3149
3494
  ])
3150
3495
  }),
3151
- TopicAutomationConfig
3496
+ TopicAutomationConfig,
3497
+ TopicDigestAutomationConfig
3152
3498
  ])
3153
3499
  });
3154
3500
  var ProjectLogsEvent = import_v36.z.object({
@@ -3187,7 +3533,7 @@ var ProjectLogsEvent = import_v36.z.object({
3187
3533
  comments: import_v36.z.union([import_v36.z.array(import_v36.z.unknown()), import_v36.z.null()]).optional(),
3188
3534
  audit_data: import_v36.z.union([import_v36.z.array(import_v36.z.unknown()), import_v36.z.null()]).optional(),
3189
3535
  _async_scoring_state: import_v36.z.unknown().optional(),
3190
- facets: import_v36.z.union([import_v36.z.object({}).partial().passthrough(), import_v36.z.null()]).optional(),
3536
+ facets: import_v36.z.union([import_v36.z.record(import_v36.z.union([import_v36.z.string(), import_v36.z.null()])), import_v36.z.null()]).optional(),
3191
3537
  classifications: import_v36.z.union([
3192
3538
  import_v36.z.record(
3193
3539
  import_v36.z.array(
@@ -3236,11 +3582,34 @@ var ProjectScoreCategories = import_v36.z.union([
3236
3582
  import_v36.z.array(import_v36.z.string()),
3237
3583
  import_v36.z.null()
3238
3584
  ]);
3585
+ var ProjectScoreCondition = import_v36.z.union([
3586
+ import_v36.z.object({
3587
+ when: import_v36.z.object({
3588
+ clauses: import_v36.z.union([import_v36.z.array(import_v36.z.string()), import_v36.z.null()]),
3589
+ subspan_clauses: import_v36.z.union([import_v36.z.array(import_v36.z.string()), import_v36.z.null()]),
3590
+ trace_clauses: import_v36.z.union([import_v36.z.array(import_v36.z.string()), import_v36.z.null()])
3591
+ }).partial(),
3592
+ behavior: import_v36.z.literal("hidden").optional().default("hidden")
3593
+ }),
3594
+ import_v36.z.null()
3595
+ ]);
3239
3596
  var ProjectScoreConfig = import_v36.z.union([
3240
3597
  import_v36.z.object({
3241
3598
  multi_select: import_v36.z.union([import_v36.z.boolean(), import_v36.z.null()]),
3242
3599
  destination: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
3243
- online: OnlineScoreConfig
3600
+ visibility: import_v36.z.union([
3601
+ import_v36.z.object({
3602
+ users: import_v36.z.union([import_v36.z.array(import_v36.z.string()), import_v36.z.null()]),
3603
+ groups: import_v36.z.union([import_v36.z.array(import_v36.z.string()), import_v36.z.null()])
3604
+ }).partial(),
3605
+ import_v36.z.null()
3606
+ ]),
3607
+ online: OnlineScoreConfig,
3608
+ condition: ProjectScoreCondition,
3609
+ object_types: import_v36.z.union([
3610
+ import_v36.z.array(import_v36.z.enum(["project_logs", "dataset", "experiment"])),
3611
+ import_v36.z.null()
3612
+ ])
3244
3613
  }).partial(),
3245
3614
  import_v36.z.null()
3246
3615
  ]);
@@ -3425,8 +3794,7 @@ var User = import_v36.z.object({
3425
3794
  family_name: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3426
3795
  email: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3427
3796
  avatar_url: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3428
- created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3429
- last_active_at: import_v36.z.union([import_v36.z.number(), import_v36.z.null()]).optional()
3797
+ created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional()
3430
3798
  });
3431
3799
  var ViewDataSearch = import_v36.z.union([
3432
3800
  import_v36.z.object({
@@ -4713,7 +5081,10 @@ var BraintrustContextManager = class extends ContextManager {
4713
5081
  }
4714
5082
  };
4715
5083
  function getSpanComponentsClass() {
4716
- return globalThis.BRAINTRUST_SPAN_COMPONENT ? globalThis.BRAINTRUST_SPAN_COMPONENT : SpanComponentsV3;
5084
+ if (globalThis.BRAINTRUST_SPAN_COMPONENT) {
5085
+ return globalThis.BRAINTRUST_SPAN_COMPONENT;
5086
+ }
5087
+ return resolveUseLegacyUuidIds() ? SpanComponentsV3 : SpanComponentsV4;
4717
5088
  }
4718
5089
  function getContextManager() {
4719
5090
  return globalThis.BRAINTRUST_CONTEXT_MANAGER ? new globalThis.BRAINTRUST_CONTEXT_MANAGER() : new BraintrustContextManager();
@@ -4749,6 +5120,9 @@ var NoopSpan = class {
4749
5120
  async export() {
4750
5121
  return "";
4751
5122
  }
5123
+ inject(carrier) {
5124
+ return carrier ?? {};
5125
+ }
4752
5126
  async permalink() {
4753
5127
  return NOOP_SPAN_PERMALINK;
4754
5128
  }
@@ -4799,6 +5173,10 @@ var loginSchema = import_v38.z.strictObject({
4799
5173
  debugLogLevelDisabled: import_v38.z.boolean().optional()
4800
5174
  });
4801
5175
  var stateNonce = 0;
5176
+ var V1_PROXY_SUFFIX = "/v1/proxy";
5177
+ function normalizeProxyConnUrl(proxyUrl) {
5178
+ return proxyUrl.endsWith(V1_PROXY_SUFFIX) ? proxyUrl.slice(0, proxyUrl.length - V1_PROXY_SUFFIX.length) : proxyUrl;
5179
+ }
4802
5180
  var BraintrustState = class _BraintrustState {
4803
5181
  constructor(loginParams) {
4804
5182
  this.loginParams = loginParams;
@@ -5069,7 +5447,10 @@ var BraintrustState = class _BraintrustState {
5069
5447
  if (!this.proxyUrl) {
5070
5448
  throw new Error("Must initialize proxyUrl before requesting proxyConn");
5071
5449
  }
5072
- this._proxyConn = new HTTPConnection(this.proxyUrl, this.fetch);
5450
+ this._proxyConn = new HTTPConnection(
5451
+ normalizeProxyConnUrl(this.proxyUrl),
5452
+ this.fetch
5453
+ );
5073
5454
  }
5074
5455
  return this._proxyConn;
5075
5456
  }
@@ -5827,7 +6208,7 @@ function updateSpan({
5827
6208
  ...event
5828
6209
  }) {
5829
6210
  const resolvedState = state ?? _globalState;
5830
- const components = getSpanComponentsClass().fromStr(exported);
6211
+ const components = SpanComponentsV4.fromStr(exported);
5831
6212
  if (!components.data.row_id) {
5832
6213
  throw new Error("Exported span must have a row id");
5833
6214
  }
@@ -5927,7 +6308,7 @@ async function permalink(slug, opts) {
5927
6308
  return state.appUrl;
5928
6309
  };
5929
6310
  try {
5930
- const components = getSpanComponentsClass().fromStr(slug);
6311
+ const components = SpanComponentsV4.fromStr(slug);
5931
6312
  const object_type = spanObjectTypeV3ToString(components.data.object_type);
5932
6313
  const [orgName, appUrl, object_id] = await Promise.all([
5933
6314
  getOrgName(),
@@ -5951,35 +6332,47 @@ function startSpanParentArgs(args) {
5951
6332
  let argParentObjectId = void 0;
5952
6333
  let argParentSpanIds = void 0;
5953
6334
  let argPropagatedEvent = void 0;
5954
- if (args.parent) {
6335
+ let argPropagatedState = void 0;
6336
+ const { parentSlug, propagatedState: parentPropagatedState } = normalizeParent(args.parent, args.state);
6337
+ if (parentSlug) {
5955
6338
  if (args.parentSpanIds) {
5956
6339
  throw new Error("Cannot specify both parent and parentSpanIds");
5957
6340
  }
5958
- const parentComponents = getSpanComponentsClass().fromStr(args.parent);
6341
+ const parentComponents = SpanComponentsV4.fromStr(parentSlug);
5959
6342
  if (args.parentObjectType !== parentComponents.data.object_type) {
5960
6343
  throw new Error(
5961
6344
  `Mismatch between expected span parent object type ${args.parentObjectType} and provided type ${parentComponents.data.object_type}`
5962
6345
  );
5963
6346
  }
5964
6347
  argParentObjectId = args.parentObjectId;
5965
- if (parentComponents.data.row_id) {
6348
+ if (parentComponents.data.row_id && parentSpanIdsUsable(
6349
+ parentComponents.data.span_id,
6350
+ parentComponents.data.root_span_id
6351
+ )) {
5966
6352
  argParentSpanIds = {
5967
6353
  spanId: parentComponents.data.span_id,
5968
6354
  rootSpanId: parentComponents.data.root_span_id
5969
6355
  };
5970
6356
  }
5971
6357
  argPropagatedEvent = args.propagatedEvent ?? (parentComponents.data.propagated_event ?? void 0);
6358
+ const propagatedState = args.propagatedState ?? parentPropagatedState;
6359
+ if (propagatedState) {
6360
+ const { braintrustParent: _ignoredBraintrustParent, ...w3cState } = propagatedState;
6361
+ argPropagatedState = w3cState;
6362
+ }
5972
6363
  } else {
5973
6364
  argParentObjectId = args.parentObjectId;
5974
6365
  argParentSpanIds = args.parentSpanIds;
5975
6366
  argPropagatedEvent = args.propagatedEvent;
6367
+ argPropagatedState = args.propagatedState;
5976
6368
  }
5977
6369
  return {
5978
6370
  parentObjectType: args.parentObjectType,
5979
6371
  parentObjectId: argParentObjectId,
5980
6372
  parentComputeObjectMetadataArgs: args.parentComputeObjectMetadataArgs,
5981
6373
  parentSpanIds: argParentSpanIds,
5982
- propagatedEvent: argPropagatedEvent
6374
+ propagatedEvent: argPropagatedEvent,
6375
+ propagatedState: argPropagatedState
5983
6376
  };
5984
6377
  }
5985
6378
  var Logger = class {
@@ -6180,6 +6573,22 @@ var Logger = class {
6180
6573
  _getLinkBaseUrl() {
6181
6574
  return _getLinkBaseUrl(this.state, this._linkArgs);
6182
6575
  }
6576
+ /**
6577
+ * Return this logger's Braintrust parent string (`project_id:<id>` or
6578
+ * `project_name:<name>`) for the `braintrust.parent` baggage entry, or
6579
+ * undefined when it cannot be determined synchronously.
6580
+ */
6581
+ _getOtelParent() {
6582
+ const id = this.computeMetadataArgs?.project_id || this.lazyId.getSync().value;
6583
+ if (id) {
6584
+ return `project_id:${id}`;
6585
+ }
6586
+ const name = this.computeMetadataArgs?.project_name;
6587
+ if (name) {
6588
+ return `project_name:${name}`;
6589
+ }
6590
+ return void 0;
6591
+ }
6183
6592
  };
6184
6593
  function castLogger(logger, asyncFlush) {
6185
6594
  if (logger === void 0) return void 0;
@@ -6274,12 +6683,12 @@ function stringifyWithOverflowMeta(item) {
6274
6683
  object_ids: pickLogs3OverflowObjectIds(record),
6275
6684
  is_delete: record[OBJECT_DELETE_FIELD] === true,
6276
6685
  input_row: {
6277
- byte_size: utf8ByteLength(str)
6686
+ byte_size: utf8ByteLength2(str)
6278
6687
  }
6279
6688
  }
6280
6689
  };
6281
6690
  }
6282
- function utf8ByteLength(value) {
6691
+ function utf8ByteLength2(value) {
6283
6692
  if (typeof TextEncoder !== "undefined") {
6284
6693
  return new TextEncoder().encode(value).length;
6285
6694
  }
@@ -6667,7 +7076,7 @@ var HTTPBackgroundLogger = class _HTTPBackgroundLogger {
6667
7076
  }) {
6668
7077
  const conn = await this.apiConn.get();
6669
7078
  const dataStr = constructLogs3Data(items);
6670
- const payloadBytes = utf8ByteLength(dataStr);
7079
+ const payloadBytes = utf8ByteLength2(dataStr);
6671
7080
  const useOverflow = canUseOverflow && payloadBytes > maxRequestSize;
6672
7081
  if (this.allPublishPayloadsDir) {
6673
7082
  await _HTTPBackgroundLogger.writePayloadToDir({
@@ -7288,6 +7697,8 @@ function initDataset(projectOrOptions, optionalOptions) {
7288
7697
  const normalizedVersion = selection.version;
7289
7698
  const normalizedEnvironment = selection.environment;
7290
7699
  const normalizedSnapshotName = selection.snapshotName;
7700
+ const cliInternalBtql = globalThis.__bt_eval_internal_btql;
7701
+ const internalBtql = cliInternalBtql === void 0 ? _internal_btql : _internal_btql === void 0 ? cliInternalBtql : isObject(_internal_btql) ? { ...cliInternalBtql, ..._internal_btql } : _internal_btql;
7291
7702
  const state = stateArg ?? _globalState;
7292
7703
  const lazyMetadata = new LazyValue(
7293
7704
  async () => {
@@ -7339,7 +7750,7 @@ function initDataset(projectOrOptions, optionalOptions) {
7339
7750
  lazyMetadata,
7340
7751
  typeof resolvedVersion === "string" ? resolvedVersion : void 0,
7341
7752
  legacy,
7342
- _internal_btql,
7753
+ internalBtql,
7343
7754
  resolvedVersion instanceof LazyValue || normalizedEnvironment !== void 0 || normalizedSnapshotName !== void 0 ? {
7344
7755
  ...resolvedVersion instanceof LazyValue ? {
7345
7756
  lazyPinnedVersion: resolvedVersion
@@ -7803,23 +8214,285 @@ function currentSpan(options) {
7803
8214
  const state = options?.state ?? _globalState;
7804
8215
  return state.contextManager.getCurrentSpan() ?? NOOP_SPAN;
7805
8216
  }
7806
- function getSpanParentObject(options) {
8217
+ function getSpanParentObjectAndPropagatedState(options) {
7807
8218
  const state = options?.state ?? _globalState;
7808
8219
  const parentSpan = currentSpan({ state });
7809
8220
  if (!Object.is(parentSpan, NOOP_SPAN)) {
7810
- return parentSpan;
8221
+ return { parentObject: parentSpan, propagatedState: void 0 };
8222
+ }
8223
+ const parent = options?.parent ?? state.currentParent.getStore();
8224
+ const { parentSlug, propagatedState } = normalizeParent(parent, state);
8225
+ if (parentSlug) {
8226
+ return {
8227
+ parentObject: SpanComponentsV4.fromStr(parentSlug),
8228
+ propagatedState
8229
+ };
7811
8230
  }
7812
- const parentStr = options?.parent ?? state.currentParent.getStore();
7813
- if (parentStr) return getSpanComponentsClass().fromStr(parentStr);
7814
8231
  const experiment = currentExperiment();
7815
8232
  if (experiment) {
7816
- return experiment;
8233
+ return { parentObject: experiment, propagatedState: void 0 };
7817
8234
  }
7818
8235
  const logger = currentLogger(options);
7819
8236
  if (logger) {
7820
- return logger;
8237
+ return { parentObject: logger, propagatedState: void 0 };
8238
+ }
8239
+ return { parentObject: NOOP_SPAN, propagatedState: void 0 };
8240
+ }
8241
+ function getSpanParentObject(options) {
8242
+ return getSpanParentObjectAndPropagatedState(options).parentObject;
8243
+ }
8244
+ function currentBraintrustParent(state) {
8245
+ const resolvedState = state ?? _globalState;
8246
+ const experiment = currentExperiment({ state: resolvedState });
8247
+ if (experiment) {
8248
+ try {
8249
+ return experiment._getOtelParent() ?? void 0;
8250
+ } catch {
8251
+ return void 0;
8252
+ }
8253
+ }
8254
+ const logger = currentLogger({ state: resolvedState });
8255
+ if (logger) {
8256
+ try {
8257
+ return logger._getOtelParent() ?? void 0;
8258
+ } catch {
8259
+ return void 0;
8260
+ }
8261
+ }
8262
+ return void 0;
8263
+ }
8264
+ function braintrustParentToComponents(braintrustParent) {
8265
+ if (!braintrustParent) {
8266
+ return void 0;
8267
+ }
8268
+ if (braintrustParent.startsWith("project_id:")) {
8269
+ const objectId = braintrustParent.slice("project_id:".length);
8270
+ return objectId ? {
8271
+ objectType: 2 /* PROJECT_LOGS */,
8272
+ objectId,
8273
+ computeArgs: void 0
8274
+ } : void 0;
8275
+ }
8276
+ if (braintrustParent.startsWith("project_name:")) {
8277
+ const name = braintrustParent.slice("project_name:".length);
8278
+ return name ? {
8279
+ objectType: 2 /* PROJECT_LOGS */,
8280
+ objectId: void 0,
8281
+ computeArgs: { project_name: name }
8282
+ } : void 0;
8283
+ }
8284
+ if (braintrustParent.startsWith("experiment_id:")) {
8285
+ const objectId = braintrustParent.slice("experiment_id:".length);
8286
+ return objectId ? {
8287
+ objectType: 1 /* EXPERIMENT */,
8288
+ objectId,
8289
+ computeArgs: void 0
8290
+ } : void 0;
8291
+ }
8292
+ return void 0;
8293
+ }
8294
+ function isMutableHeaderTupleArray(carrier) {
8295
+ return Array.isArray(carrier) && carrier.every((item) => Array.isArray(item) && typeof item[0] === "string");
8296
+ }
8297
+ function setHeader(carrier, name, value) {
8298
+ if (isMutableHeaderTupleArray(carrier)) {
8299
+ const lowered2 = name.toLowerCase();
8300
+ for (let i = carrier.length - 1; i >= 0; i--) {
8301
+ if (carrier[i][0].toLowerCase() === lowered2) {
8302
+ carrier.splice(i, 1);
8303
+ }
8304
+ }
8305
+ carrier.push([name, value]);
8306
+ return;
8307
+ }
8308
+ const setter = carrier.set;
8309
+ if (typeof setter === "function") {
8310
+ const deleter = carrier.delete;
8311
+ if (typeof deleter === "function") {
8312
+ try {
8313
+ deleter.call(carrier, name);
8314
+ } catch {
8315
+ }
8316
+ }
8317
+ setter.call(carrier, name, value);
8318
+ return;
8319
+ }
8320
+ const nodeSetter = carrier.setHeader;
8321
+ if (typeof nodeSetter === "function") {
8322
+ const remover = carrier.removeHeader;
8323
+ if (typeof remover === "function") {
8324
+ try {
8325
+ remover.call(carrier, name);
8326
+ } catch {
8327
+ }
8328
+ }
8329
+ nodeSetter.call(carrier, name, value);
8330
+ return;
8331
+ }
8332
+ const headerSetter = carrier.header;
8333
+ if (typeof headerSetter === "function") {
8334
+ const deleter = carrier.delete;
8335
+ if (typeof deleter === "function") {
8336
+ try {
8337
+ deleter.call(carrier, name);
8338
+ } catch {
8339
+ }
8340
+ }
8341
+ const remover = carrier.removeHeader;
8342
+ if (typeof remover === "function") {
8343
+ try {
8344
+ remover.call(carrier, name);
8345
+ } catch {
8346
+ }
8347
+ }
8348
+ headerSetter.call(carrier, name, value);
8349
+ return;
8350
+ }
8351
+ const headerBag = carrier;
8352
+ const lowered = name.toLowerCase();
8353
+ for (const key of Object.keys(headerBag)) {
8354
+ if (key !== name && key.toLowerCase() === lowered) {
8355
+ delete headerBag[key];
8356
+ }
8357
+ }
8358
+ headerBag[name] = value;
8359
+ }
8360
+ function deleteHeader(carrier, name) {
8361
+ const lowered = name.toLowerCase();
8362
+ if (isMutableHeaderTupleArray(carrier)) {
8363
+ for (let i = carrier.length - 1; i >= 0; i--) {
8364
+ if (carrier[i][0].toLowerCase() === lowered) {
8365
+ carrier.splice(i, 1);
8366
+ }
8367
+ }
8368
+ return;
8369
+ }
8370
+ const deleter = carrier.delete;
8371
+ if (typeof deleter === "function") {
8372
+ try {
8373
+ deleter.call(carrier, name);
8374
+ return;
8375
+ } catch {
8376
+ }
8377
+ }
8378
+ const remover = carrier.removeHeader;
8379
+ if (typeof remover === "function") {
8380
+ try {
8381
+ remover.call(carrier, name);
8382
+ return;
8383
+ } catch {
8384
+ }
7821
8385
  }
7822
- return NOOP_SPAN;
8386
+ const headerBag = carrier;
8387
+ for (const key of Object.keys(headerBag)) {
8388
+ if (key.toLowerCase() === lowered) {
8389
+ delete headerBag[key];
8390
+ }
8391
+ }
8392
+ }
8393
+ function _injectIntoCarrier(carrier, args) {
8394
+ const traceFlags = args.propagatedState?.traceFlags;
8395
+ const traceparent = traceFlags ? formatTraceparent(args.traceId, args.spanId, traceFlags) : formatTraceparent(args.traceId, args.spanId);
8396
+ if (traceparent === void 0) {
8397
+ return;
8398
+ }
8399
+ setHeader(carrier, TRACEPARENT_HEADER, traceparent);
8400
+ const tracestate = args.propagatedState?.tracestate;
8401
+ if (tracestate) {
8402
+ setHeader(carrier, TRACESTATE_HEADER, tracestate);
8403
+ }
8404
+ const existing = getHeader(carrier, BAGGAGE_HEADER);
8405
+ const baggageValue = mergeBaggage(existing, args.braintrustParent);
8406
+ if (baggageValue !== void 0) {
8407
+ setHeader(carrier, BAGGAGE_HEADER, baggageValue);
8408
+ } else if (existing !== void 0) {
8409
+ deleteHeader(carrier, BAGGAGE_HEADER);
8410
+ }
8411
+ }
8412
+ function injectTraceContext(carrier, options) {
8413
+ const resolvedCarrier = carrier ?? {};
8414
+ const span = options?.span ?? currentSpan({ state: options?.state });
8415
+ try {
8416
+ return span.inject(resolvedCarrier);
8417
+ } catch (e) {
8418
+ debugLogger.warn(`Error injecting trace context: ${e}`);
8419
+ return resolvedCarrier;
8420
+ }
8421
+ }
8422
+ function extractTraceContextFromHeaders(headers) {
8423
+ if (!headers) {
8424
+ return void 0;
8425
+ }
8426
+ const traceparent = getHeader(headers, TRACEPARENT_HEADER);
8427
+ if (!traceparent || parseTraceparent(traceparent) === void 0) {
8428
+ return void 0;
8429
+ }
8430
+ const context = { [TRACEPARENT_HEADER]: traceparent };
8431
+ const baggageValue = getHeader(headers, BAGGAGE_HEADER);
8432
+ if (baggageValue) {
8433
+ context[BAGGAGE_HEADER] = baggageValue;
8434
+ }
8435
+ const tracestate = getHeader(headers, TRACESTATE_HEADER);
8436
+ if (tracestate) {
8437
+ context[TRACESTATE_HEADER] = tracestate;
8438
+ }
8439
+ return context;
8440
+ }
8441
+ function resolveW3cParent(context, state) {
8442
+ const traceparent = getHeader(context, TRACEPARENT_HEADER);
8443
+ const parsed = traceparent ? parseTraceparent(traceparent) : void 0;
8444
+ if (parsed === void 0) {
8445
+ return { parentSlug: void 0, propagatedState: void 0 };
8446
+ }
8447
+ const { traceId, spanId, traceFlags } = parsed;
8448
+ let braintrustParent = void 0;
8449
+ const baggageValue = getHeader(context, BAGGAGE_HEADER);
8450
+ if (baggageValue) {
8451
+ braintrustParent = parseBaggage(baggageValue)[BRAINTRUST_PARENT_KEY];
8452
+ }
8453
+ if (!braintrustParent) {
8454
+ braintrustParent = currentBraintrustParent(state);
8455
+ }
8456
+ if (!braintrustParent) {
8457
+ debugLogger.warn(
8458
+ "Received traceparent without a braintrust.parent and no active logger/experiment; cannot route the trace. Starting a fresh local span instead."
8459
+ );
8460
+ return { parentSlug: void 0, propagatedState: void 0 };
8461
+ }
8462
+ const parsedParent = braintrustParentToComponents(braintrustParent);
8463
+ if (parsedParent === void 0) {
8464
+ debugLogger.warn(
8465
+ `Invalid braintrust.parent: ${JSON.stringify(braintrustParent)}`
8466
+ );
8467
+ return { parentSlug: void 0, propagatedState: void 0 };
8468
+ }
8469
+ const { objectType, objectId, computeArgs } = parsedParent;
8470
+ const tracestate = getHeader(context, TRACESTATE_HEADER);
8471
+ const slug = new SpanComponentsV4({
8472
+ object_type: objectType,
8473
+ ...computeArgs ? { compute_object_metadata_args: computeArgs } : { object_id: objectId },
8474
+ row_id: "bt-propagation",
8475
+ // non-empty to enable span_id/root_span_id
8476
+ span_id: spanId,
8477
+ root_span_id: traceId
8478
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
8479
+ }).toStr();
8480
+ return {
8481
+ parentSlug: slug,
8482
+ propagatedState: { tracestate, traceFlags, braintrustParent }
8483
+ };
8484
+ }
8485
+ function normalizeParent(parent, state) {
8486
+ if (parent && typeof parent === "object") {
8487
+ return resolveW3cParent(parent, state);
8488
+ }
8489
+ return {
8490
+ parentSlug: parent ?? void 0,
8491
+ propagatedState: void 0
8492
+ };
8493
+ }
8494
+ function parentSpanIdsUsable(spanId, rootSpanId) {
8495
+ return Boolean(spanId) && Boolean(rootSpanId);
7823
8496
  }
7824
8497
  function logError(span, error) {
7825
8498
  let errorMessage = "<error>";
@@ -8027,19 +8700,23 @@ function setFetch(fetch2) {
8027
8700
  }
8028
8701
  function startSpanAndIsLogger(args) {
8029
8702
  const state = args?.state ?? _globalState;
8030
- const parentObject = getSpanParentObject({
8703
+ const { parentObject, propagatedState } = getSpanParentObjectAndPropagatedState({
8031
8704
  asyncFlush: args?.asyncFlush,
8032
8705
  parent: args?.parent,
8033
8706
  state
8034
8707
  });
8035
8708
  if (parentObject instanceof SpanComponentsV3 || parentObject instanceof SpanComponentsV4) {
8036
- const parentSpanIds = parentObject.data.row_id ? {
8709
+ const parentSpanIds = parentObject.data.row_id && parentSpanIdsUsable(
8710
+ parentObject.data.span_id,
8711
+ parentObject.data.root_span_id
8712
+ ) ? {
8037
8713
  spanId: parentObject.data.span_id,
8038
8714
  rootSpanId: parentObject.data.root_span_id
8039
8715
  } : void 0;
8716
+ const { parent: _ignoredParent, ...spanArgs } = args ?? {};
8040
8717
  const span = new SpanImpl({
8041
8718
  state,
8042
- ...args,
8719
+ ...spanArgs,
8043
8720
  parentObjectType: parentObject.data.object_type,
8044
8721
  parentObjectId: new LazyValue(
8045
8722
  spanComponentsToObjectIdLambda(state, parentObject)
@@ -8047,7 +8724,8 @@ function startSpanAndIsLogger(args) {
8047
8724
  parentComputeObjectMetadataArgs: parentObject.data.compute_object_metadata_args ?? void 0,
8048
8725
  parentSpanIds,
8049
8726
  propagatedEvent: args?.propagatedEvent ?? // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
8050
- (parentObject.data.propagated_event ?? void 0)
8727
+ (parentObject.data.propagated_event ?? void 0),
8728
+ propagatedState
8051
8729
  });
8052
8730
  return {
8053
8731
  span,
@@ -8336,11 +9014,12 @@ function validateAndSanitizeExperimentLogFullArgs(event, hasDataset) {
8336
9014
  var DEFAULT_FETCH_BATCH_SIZE = 1e3;
8337
9015
  var MAX_BTQL_ITERATIONS = 1e4;
8338
9016
  var ObjectFetcher = class {
8339
- constructor(objectType, pinnedVersion, mutateRecord, _internal_btql) {
9017
+ constructor(objectType, pinnedVersion, mutateRecord, _internal_btql, _internalBrainstoreRealtime = true) {
8340
9018
  this.objectType = objectType;
8341
9019
  this.pinnedVersion = pinnedVersion;
8342
9020
  this.mutateRecord = mutateRecord;
8343
9021
  this._internal_btql = _internal_btql;
9022
+ this._internalBrainstoreRealtime = _internalBrainstoreRealtime;
8344
9023
  }
8345
9024
  _fetchedData = void 0;
8346
9025
  get id() {
@@ -8399,7 +9078,7 @@ var ObjectFetcher = class {
8399
9078
  ...internalBtqlWithoutReservedQueryKeys
8400
9079
  },
8401
9080
  use_columnstore: false,
8402
- brainstore_realtime: true,
9081
+ brainstore_realtime: this._internalBrainstoreRealtime,
8403
9082
  query_source: `js_sdk_object_fetcher_${this.objectType}`,
8404
9083
  ...this.pinnedVersion !== void 0 ? {
8405
9084
  version: this.pinnedVersion
@@ -8748,6 +9427,15 @@ View complete results in Braintrust or run experiment.summarize() again.`
8748
9427
  object_id: await this.id
8749
9428
  }).toStr();
8750
9429
  }
9430
+ /**
9431
+ * Return this experiment's Braintrust parent string (`experiment_id:<id>`) for
9432
+ * the `braintrust.parent` baggage entry, or undefined when it cannot be
9433
+ * determined synchronously.
9434
+ */
9435
+ _getOtelParent() {
9436
+ const id = this.lazyId.getSync().value;
9437
+ return id ? `experiment_id:${id}` : void 0;
9438
+ }
8751
9439
  /**
8752
9440
  * Flush any pending rows to the server.
8753
9441
  */
@@ -8790,7 +9478,8 @@ var ReadonlyExperiment = class extends ObjectFetcher {
8790
9478
  async *asDataset(options) {
8791
9479
  const records = this.fetch(options);
8792
9480
  for await (const record of records) {
8793
- if (record.root_span_id !== record.span_id) {
9481
+ const isRoot = record.is_root ?? record.root_span_id === record.span_id;
9482
+ if (!isRoot) {
8794
9483
  continue;
8795
9484
  }
8796
9485
  const { output, expected: expectedRecord, metadata } = record;
@@ -8852,9 +9541,16 @@ var SpanImpl = class _SpanImpl {
8852
9541
  _spanId;
8853
9542
  _rootSpanId;
8854
9543
  _spanParents;
9544
+ // Inbound W3C trace-context state (tracestate + raw traceparent flags) to
9545
+ // forward on outbound propagation. Captured at the span that received it (via
9546
+ // extractTraceContextFromHeaders) and inherited by all subspans, so that any
9547
+ // inject() within the trace re-emits the upstream state unchanged, per the W3C
9548
+ // Trace Context spec. Not interpreted.
9549
+ _propagatedState;
8855
9550
  kind = "span";
8856
9551
  constructor(args) {
8857
9552
  this._state = args.state;
9553
+ this._propagatedState = args.propagatedState;
8858
9554
  const spanAttributes = args.spanAttributes ?? {};
8859
9555
  const rawEvent = args.event ?? {};
8860
9556
  const type = args.type ?? (args.parentSpanIds ? void 0 : args.defaultRootType);
@@ -8970,7 +9666,7 @@ var SpanImpl = class _SpanImpl {
8970
9666
  tags: partialRecord.tags,
8971
9667
  span_id: this._spanId,
8972
9668
  span_parents: this._spanParents,
8973
- is_root: this._spanId === this._rootSpanId,
9669
+ is_root: !this._spanParents || this._spanParents.length === 0,
8974
9670
  span_attributes: partialRecord.span_attributes
8975
9671
  };
8976
9672
  this._state.spanCache.queueWrite(
@@ -9032,7 +9728,8 @@ var SpanImpl = class _SpanImpl {
9032
9728
  parentObjectId: this.parentObjectId,
9033
9729
  parentComputeObjectMetadataArgs: this.parentComputeObjectMetadataArgs,
9034
9730
  parentSpanIds,
9035
- propagatedEvent: args?.propagatedEvent ?? this.propagatedEvent
9731
+ propagatedEvent: args?.propagatedEvent ?? this.propagatedEvent,
9732
+ propagatedState: this._propagatedState
9036
9733
  })
9037
9734
  });
9038
9735
  }
@@ -9051,7 +9748,8 @@ var SpanImpl = class _SpanImpl {
9051
9748
  parentObjectId: this.parentObjectId,
9052
9749
  parentComputeObjectMetadataArgs: this.parentComputeObjectMetadataArgs,
9053
9750
  parentSpanIds,
9054
- propagatedEvent: args?.propagatedEvent ?? this.propagatedEvent
9751
+ propagatedEvent: args?.propagatedEvent ?? this.propagatedEvent,
9752
+ propagatedState: this._propagatedState
9055
9753
  }),
9056
9754
  spanId
9057
9755
  });
@@ -9079,6 +9777,42 @@ var SpanImpl = class _SpanImpl {
9079
9777
  propagated_event: this.propagatedEvent
9080
9778
  }).toStr();
9081
9779
  }
9780
+ /**
9781
+ * Return this span's Braintrust parent string (`project_id:<id>`,
9782
+ * `project_name:<name>`, or `experiment_id:<id>`) for the `braintrust.parent`
9783
+ * baggage entry, or undefined when it cannot be determined synchronously.
9784
+ */
9785
+ _getOtelParent() {
9786
+ if (this.parentObjectType === 2 /* PROJECT_LOGS */) {
9787
+ const id = this.parentComputeObjectMetadataArgs?.project_id || this.parentObjectId.getSync().value;
9788
+ const name = this.parentComputeObjectMetadataArgs?.project_name;
9789
+ if (id) {
9790
+ return `project_id:${id}`;
9791
+ } else if (name) {
9792
+ return `project_name:${name}`;
9793
+ }
9794
+ } else if (this.parentObjectType === 1 /* EXPERIMENT */) {
9795
+ const id = this.parentComputeObjectMetadataArgs?.experiment_id || this.parentObjectId.getSync().value;
9796
+ if (id) {
9797
+ return `experiment_id:${id}`;
9798
+ }
9799
+ }
9800
+ return void 0;
9801
+ }
9802
+ inject(carrier) {
9803
+ const resolvedCarrier = carrier ?? {};
9804
+ try {
9805
+ _injectIntoCarrier(resolvedCarrier, {
9806
+ traceId: this._rootSpanId,
9807
+ spanId: this._spanId,
9808
+ braintrustParent: this._getOtelParent() ?? this._propagatedState?.braintrustParent,
9809
+ propagatedState: this._propagatedState
9810
+ });
9811
+ } catch (e) {
9812
+ debugLogger.warn(`Error injecting trace context: ${e}`);
9813
+ }
9814
+ return resolvedCarrier;
9815
+ }
9082
9816
  async permalink() {
9083
9817
  return await permalink(await this.export(), {
9084
9818
  state: this._state
@@ -9214,6 +9948,7 @@ var Dataset2 = class extends ObjectFetcher {
9214
9948
  _internal_btql
9215
9949
  );
9216
9950
  this.state = state;
9951
+ void this.__braintrust_dataset_marker;
9217
9952
  this.lazyMetadata = lazyMetadata;
9218
9953
  this.lazyPinnedVersion = pinState?.lazyPinnedVersion;
9219
9954
  this.pinnedEnvironment = pinState?.pinnedEnvironment;
@@ -9731,6 +10466,7 @@ var Prompt2 = class _Prompt {
9731
10466
  this.metadata = metadata;
9732
10467
  this.defaults = defaults;
9733
10468
  this.noTrace = noTrace;
10469
+ void this.__braintrust_prompt_marker;
9734
10470
  }
9735
10471
  parsedPromptData;
9736
10472
  hasParsedPromptData = false;
@@ -9967,6 +10703,7 @@ var Prompt2 = class _Prompt {
9967
10703
  var RemoteEvalParameters = class {
9968
10704
  constructor(metadata) {
9969
10705
  this.metadata = metadata;
10706
+ void this.__braintrust_parameters_marker;
9970
10707
  }
9971
10708
  __braintrust_parameters_marker = true;
9972
10709
  get id() {
@@ -10103,6 +10840,7 @@ var _exportsForTestingOnly = {
10103
10840
  isAsyncGeneratorFunction,
10104
10841
  resetIdGenStateForTests,
10105
10842
  validateTags,
10843
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
10106
10844
  isomorph: isomorph_default
10107
10845
  // Expose isomorph for build type detection
10108
10846
  };
@@ -10931,6 +11669,22 @@ function runStreamingCompletionHook(args) {
10931
11669
  );
10932
11670
  }
10933
11671
  }
11672
+ function runStreamingErrorHook(args) {
11673
+ if (!args.config.onError) {
11674
+ return;
11675
+ }
11676
+ try {
11677
+ args.config.onError({
11678
+ channelName: args.channelName,
11679
+ error: args.error,
11680
+ event: args.event,
11681
+ span: args.span,
11682
+ startTime: args.startTime
11683
+ });
11684
+ } catch (error) {
11685
+ debugLogger.error(`Error in onError hook for ${args.channelName}:`, error);
11686
+ }
11687
+ }
10934
11688
  function traceAsyncChannel(channel2, config) {
10935
11689
  const tracingChannel2 = channel2.tracingChannel();
10936
11690
  const states = /* @__PURE__ */ new WeakMap();
@@ -11092,6 +11846,14 @@ function traceStreamingChannel(channel2, config) {
11092
11846
  }
11093
11847
  },
11094
11848
  onError: (error) => {
11849
+ runStreamingErrorHook({
11850
+ channelName,
11851
+ config,
11852
+ error,
11853
+ event: asyncEndEvent,
11854
+ span,
11855
+ startTime
11856
+ });
11095
11857
  span.log({
11096
11858
  error: error.message
11097
11859
  });
@@ -11149,6 +11911,17 @@ function traceStreamingChannel(channel2, config) {
11149
11911
  }
11150
11912
  },
11151
11913
  error: (event) => {
11914
+ const spanData = states.get(event);
11915
+ if (spanData) {
11916
+ runStreamingErrorHook({
11917
+ channelName,
11918
+ config,
11919
+ error: event.error,
11920
+ event,
11921
+ span: spanData.span,
11922
+ startTime: spanData.startTime
11923
+ });
11924
+ }
11152
11925
  logErrorAndEnd(states, event);
11153
11926
  }
11154
11927
  };
@@ -13511,14 +14284,45 @@ function serializeAISDKToolsForLogging(tools) {
13511
14284
  return serialized;
13512
14285
  }
13513
14286
 
14287
+ // src/vendor-sdk-types/ai-sdk-v7-telemetry.ts
14288
+ var BRAINTRUST_AI_SDK_V7_OPERATION_KEY = /* @__PURE__ */ Symbol.for(
14289
+ "braintrust.ai-sdk.v7.telemetry-operation-key"
14290
+ );
14291
+
14292
+ // src/wrappers/ai-sdk/workflow-agent-context.ts
14293
+ var workflowAgentWrapperSpans = /* @__PURE__ */ new Map();
14294
+ function registerWorkflowAgentWrapperSpan(span) {
14295
+ if (span.spanId) {
14296
+ workflowAgentWrapperSpans.set(span.spanId, span);
14297
+ }
14298
+ }
14299
+ function unregisterWorkflowAgentWrapperSpan(span) {
14300
+ if (span.spanId) {
14301
+ workflowAgentWrapperSpans.delete(span.spanId);
14302
+ }
14303
+ }
14304
+ function currentWorkflowAgentWrapperSpan() {
14305
+ const parentSpanIds = _internalGetGlobalState().contextManager.getParentSpanIds()?.spanParents ?? [];
14306
+ for (const parentSpanId of parentSpanIds) {
14307
+ const span = workflowAgentWrapperSpans.get(parentSpanId);
14308
+ if (span) {
14309
+ return span;
14310
+ }
14311
+ }
14312
+ return void 0;
14313
+ }
14314
+
13514
14315
  // src/wrappers/ai-sdk/telemetry.ts
13515
14316
  function braintrustAISDKTelemetry() {
13516
14317
  const operations = /* @__PURE__ */ new Map();
14318
+ const operationKeysByCallId = /* @__PURE__ */ new Map();
14319
+ const workflowOperationKeyStore = isomorph_default.newAsyncLocalStorage();
13517
14320
  const modelSpans = /* @__PURE__ */ new Map();
13518
14321
  const objectSpans = /* @__PURE__ */ new Map();
13519
14322
  const embedSpans = /* @__PURE__ */ new Map();
13520
14323
  const rerankSpans = /* @__PURE__ */ new Map();
13521
14324
  const toolSpans = /* @__PURE__ */ new Map();
14325
+ let workflowAgentOperationCounter = 0;
13522
14326
  const runSafely = (name, callback) => {
13523
14327
  try {
13524
14328
  callback();
@@ -13526,42 +14330,333 @@ function braintrustAISDKTelemetry() {
13526
14330
  console.error(`Error in Braintrust AI SDK telemetry ${name}:`, error);
13527
14331
  }
13528
14332
  };
13529
- const startChildSpan = (callId, name, type, event) => {
13530
- const parent = operations.get(callId)?.span;
14333
+ const startChildSpan = (operationKey, name, type, event) => {
14334
+ const parent = operations.get(operationKey)?.span;
13531
14335
  const spanArgs = {
13532
14336
  name,
13533
14337
  spanAttributes: { type },
13534
14338
  ...event ? { event } : {}
13535
14339
  };
13536
14340
  const span = parent ? parent.startSpan(spanArgs) : startSpan(spanArgs);
13537
- const state = operations.get(callId);
14341
+ const state = operations.get(operationKey);
13538
14342
  if (state && type === "llm" /* LLM */) {
13539
14343
  state.hadModelChild = true;
13540
14344
  }
13541
14345
  return span;
13542
14346
  };
14347
+ const registerOperation = (state) => {
14348
+ operations.set(state.operationKey, state);
14349
+ const keys = operationKeysByCallId.get(state.callId) ?? [];
14350
+ keys.push(state.operationKey);
14351
+ operationKeysByCallId.set(state.callId, keys);
14352
+ };
14353
+ const deleteOperation = (operationKey) => {
14354
+ const state = operations.get(operationKey);
14355
+ if (!state) {
14356
+ return;
14357
+ }
14358
+ operations.delete(operationKey);
14359
+ if (workflowOperationKeyStore.getStore() === operationKey) {
14360
+ workflowOperationKeyStore.enterWith(void 0);
14361
+ }
14362
+ const keys = operationKeysByCallId.get(state.callId);
14363
+ if (!keys) {
14364
+ return;
14365
+ }
14366
+ const index = keys.indexOf(operationKey);
14367
+ if (index >= 0) {
14368
+ keys.splice(index, 1);
14369
+ }
14370
+ if (keys.length === 0) {
14371
+ operationKeysByCallId.delete(state.callId);
14372
+ }
14373
+ };
14374
+ const explicitOperationKey = (event) => {
14375
+ if (!isObject(event)) {
14376
+ return void 0;
14377
+ }
14378
+ const key = event[BRAINTRUST_AI_SDK_V7_OPERATION_KEY];
14379
+ return typeof key === "string" ? key : void 0;
14380
+ };
14381
+ const createOperationKey = (event, operationName) => {
14382
+ const explicit = explicitOperationKey(event);
14383
+ if (explicit) {
14384
+ return explicit;
14385
+ }
14386
+ if (operationName === "WorkflowAgent.stream") {
14387
+ workflowAgentOperationCounter += 1;
14388
+ return `${event.callId}:${workflowAgentOperationCounter}`;
14389
+ }
14390
+ return event.callId;
14391
+ };
14392
+ const operationKeyForCallId = (callId, mode = "active") => {
14393
+ const keys = operationKeysByCallId.get(callId);
14394
+ if (!keys || keys.length === 0) {
14395
+ return operations.has(callId) ? callId : void 0;
14396
+ }
14397
+ if (keys.length === 1) {
14398
+ return keys[0];
14399
+ }
14400
+ const wrapperSpan = currentWorkflowAgentWrapperSpan();
14401
+ if (wrapperSpan?.spanId) {
14402
+ const key = keys.find(
14403
+ (candidate) => operations.get(candidate)?.span.spanId === wrapperSpan.spanId
14404
+ );
14405
+ if (key) {
14406
+ return key;
14407
+ }
14408
+ }
14409
+ const workflowOperationKey = workflowOperationKeyStore.getStore();
14410
+ if (workflowOperationKey && keys.includes(workflowOperationKey)) {
14411
+ return workflowOperationKey;
14412
+ }
14413
+ if (callId === "workflow-agent") {
14414
+ return void 0;
14415
+ }
14416
+ return mode === "finish" ? keys[0] : keys[keys.length - 1];
14417
+ };
14418
+ const operationKeyFromEvent = (event, mode = "active") => {
14419
+ const explicit = explicitOperationKey(event);
14420
+ if (explicit && operations.has(explicit)) {
14421
+ return explicit;
14422
+ }
14423
+ if (isObject(event)) {
14424
+ const callId = event.callId;
14425
+ if (typeof callId === "string") {
14426
+ const operationKey = operationKeyForCallId(callId, mode);
14427
+ if (operationKey) {
14428
+ return operationKey;
14429
+ }
14430
+ const workflowOperationKey2 = workflowOperationKeyStore.getStore();
14431
+ if (workflowOperationKey2 && operations.has(workflowOperationKey2)) {
14432
+ return workflowOperationKey2;
14433
+ }
14434
+ return callId === "workflow-agent" ? void 0 : callId;
14435
+ }
14436
+ }
14437
+ const workflowOperationKey = workflowOperationKeyStore.getStore();
14438
+ if (workflowOperationKey && operations.has(workflowOperationKey)) {
14439
+ return workflowOperationKey;
14440
+ }
14441
+ const wrapperSpan = currentWorkflowAgentWrapperSpan();
14442
+ if (wrapperSpan?.spanId) {
14443
+ for (const [operationKey, state] of operations) {
14444
+ if (state.operationName === "WorkflowAgent.stream" && state.span.spanId === wrapperSpan.spanId) {
14445
+ return operationKey;
14446
+ }
14447
+ }
14448
+ }
14449
+ const workflowAgentKeys = operationKeysByCallId.get("workflow-agent");
14450
+ if (workflowAgentKeys?.length === 1) {
14451
+ return workflowAgentKeys[0];
14452
+ }
14453
+ if (operations.size === 1) {
14454
+ return operations.keys().next().value;
14455
+ }
14456
+ return void 0;
14457
+ };
14458
+ const closeOpenChildSpans = (operationKey, error) => {
14459
+ const openModelSpans = modelSpans.get(operationKey);
14460
+ if (openModelSpans) {
14461
+ for (const span of openModelSpans) {
14462
+ if (error !== void 0) {
14463
+ logError(span, error);
14464
+ }
14465
+ span.end();
14466
+ }
14467
+ modelSpans.delete(operationKey);
14468
+ }
14469
+ const openObjectSpan = objectSpans.get(operationKey);
14470
+ if (openObjectSpan) {
14471
+ if (error !== void 0) {
14472
+ logError(openObjectSpan, error);
14473
+ }
14474
+ openObjectSpan.end();
14475
+ objectSpans.delete(operationKey);
14476
+ }
14477
+ for (const [embedCallId, embedState] of embedSpans) {
14478
+ if (embedState.operationKey === operationKey) {
14479
+ if (error !== void 0) {
14480
+ logError(embedState.span, error);
14481
+ }
14482
+ embedState.span.end();
14483
+ embedSpans.delete(embedCallId);
14484
+ }
14485
+ }
14486
+ const openRerankSpan = rerankSpans.get(operationKey);
14487
+ if (openRerankSpan) {
14488
+ if (error !== void 0) {
14489
+ logError(openRerankSpan, error);
14490
+ }
14491
+ openRerankSpan.end();
14492
+ rerankSpans.delete(operationKey);
14493
+ }
14494
+ for (const [toolCallId, toolState] of toolSpans) {
14495
+ if (toolState.operationKey === operationKey) {
14496
+ if (error !== void 0) {
14497
+ logError(toolState.span, error);
14498
+ }
14499
+ toolState.span.end();
14500
+ toolSpans.delete(toolCallId);
14501
+ }
14502
+ }
14503
+ };
14504
+ const abortReasonFromEvent = (event) => {
14505
+ if (isObject(event)) {
14506
+ const abortEvent = event;
14507
+ if (abortEvent.error !== void 0) {
14508
+ return abortEvent.error;
14509
+ }
14510
+ if (abortEvent.reason !== void 0) {
14511
+ return abortEvent.reason;
14512
+ }
14513
+ }
14514
+ return new Error("AI SDK operation aborted");
14515
+ };
14516
+ const shouldSkipTelemetryChildren = (state) => state?.operationName === "WorkflowAgent.stream" && !state.ownsSpan;
14517
+ const onObjectStepEnd = (event) => {
14518
+ runSafely("onObjectStepEnd", () => {
14519
+ const operationKey = operationKeyFromEvent(event);
14520
+ const span = operationKey ? objectSpans.get(operationKey) : void 0;
14521
+ if (!operationKey || !span) {
14522
+ return;
14523
+ }
14524
+ const result = {
14525
+ ...event,
14526
+ text: event.objectText
14527
+ };
14528
+ span.log({
14529
+ ...shouldRecordOutputs(event) ? {
14530
+ output: processAISDKOutput(result, DEFAULT_DENY_OUTPUT_PATHS)
14531
+ } : {},
14532
+ metrics: extractTokenMetrics(result)
14533
+ });
14534
+ span.end();
14535
+ objectSpans.delete(operationKey);
14536
+ });
14537
+ };
14538
+ const onEmbedEnd = (event) => {
14539
+ runSafely("onEmbedEnd", () => {
14540
+ const state = embedSpans.get(event.embedCallId);
14541
+ if (!state) {
14542
+ return;
14543
+ }
14544
+ const result = {
14545
+ ...event,
14546
+ embeddings: event.embeddings
14547
+ };
14548
+ state.span.log({
14549
+ ...shouldRecordOutputs(event) ? {
14550
+ output: processAISDKEmbeddingOutput(
14551
+ result,
14552
+ DEFAULT_DENY_OUTPUT_PATHS
14553
+ )
14554
+ } : {},
14555
+ metrics: extractTokenMetrics(result)
14556
+ });
14557
+ state.span.end();
14558
+ embedSpans.delete(event.embedCallId);
14559
+ });
14560
+ };
14561
+ const onRerankEnd = (event) => {
14562
+ runSafely("onRerankEnd", () => {
14563
+ const operationKey = operationKeyFromEvent(event);
14564
+ const span = operationKey ? rerankSpans.get(operationKey) : void 0;
14565
+ if (!operationKey || !span) {
14566
+ return;
14567
+ }
14568
+ const result = {
14569
+ ranking: event.ranking?.map((entry) => ({
14570
+ originalIndex: entry.index,
14571
+ score: entry.relevanceScore
14572
+ }))
14573
+ };
14574
+ span.log({
14575
+ ...shouldRecordOutputs(event) ? {
14576
+ output: processAISDKRerankOutput(
14577
+ result,
14578
+ DEFAULT_DENY_OUTPUT_PATHS
14579
+ )
14580
+ } : {}
14581
+ });
14582
+ span.end();
14583
+ rerankSpans.delete(operationKey);
14584
+ });
14585
+ };
14586
+ const onEnd = (event) => {
14587
+ runSafely("onEnd", () => {
14588
+ const operationKey = operationKeyFromEvent(event, "finish");
14589
+ const state = operationKey ? operations.get(operationKey) : void 0;
14590
+ if (!state) {
14591
+ return;
14592
+ }
14593
+ if (!state.ownsSpan) {
14594
+ deleteOperation(state.operationKey);
14595
+ return;
14596
+ }
14597
+ const result = finishResult(event, state.operationName);
14598
+ const metrics = state.hadModelChild ? {} : extractTokenMetrics(result);
14599
+ const timeToFirstToken = state.operationName === "WorkflowAgent.stream" ? void 0 : extractTimeToFirstToken(result, state);
14600
+ if (timeToFirstToken !== void 0) {
14601
+ metrics.time_to_first_token = timeToFirstToken;
14602
+ }
14603
+ state.span.log({
14604
+ ...shouldRecordOutputs(event) ? {
14605
+ output: finishOutput(result, state.operationName)
14606
+ } : {},
14607
+ metrics
14608
+ });
14609
+ state.span.end();
14610
+ deleteOperation(state.operationKey);
14611
+ });
14612
+ };
13543
14613
  return {
13544
14614
  onStart(event) {
13545
14615
  runSafely("onStart", () => {
13546
14616
  const operationName = operationNameFromId(event.operationId);
13547
- const span = startSpan({
14617
+ const workflowAgent = operationName === "WorkflowAgent.stream";
14618
+ const wrapperSpan = workflowAgent ? currentWorkflowAgentWrapperSpan() : void 0;
14619
+ const ownsSpan = !wrapperSpan;
14620
+ const span = ownsSpan ? startSpan({
13548
14621
  name: operationName,
13549
14622
  spanAttributes: { type: "function" /* FUNCTION */ }
13550
- });
13551
- operations.set(event.callId, {
14623
+ }) : wrapperSpan;
14624
+ const operationKey = createOperationKey(event, operationName);
14625
+ registerOperation({
14626
+ callId: event.callId,
13552
14627
  hadModelChild: false,
14628
+ loggedInput: false,
13553
14629
  operationName,
14630
+ operationKey,
14631
+ ownsSpan,
13554
14632
  span,
13555
14633
  startTime: getCurrentUnixTimestamp()
13556
14634
  });
13557
- const metadata = metadataFromEvent(event);
14635
+ if (!ownsSpan) {
14636
+ return;
14637
+ }
14638
+ if (workflowAgent) {
14639
+ workflowOperationKeyStore.enterWith(operationKey);
14640
+ }
14641
+ let metadata = metadataFromEvent(event);
13558
14642
  const logPayload = { metadata };
14643
+ const workflowAgentCallInput = workflowAgent ? operationInput(event, operationName) : void 0;
14644
+ if (workflowAgentCallInput) {
14645
+ metadata = {
14646
+ ...metadata,
14647
+ ...extractWorkflowMetadataFromCallParams(workflowAgentCallInput)
14648
+ };
14649
+ logPayload.metadata = metadata;
14650
+ }
13559
14651
  if (shouldRecordInputs(event)) {
13560
- const { input, outputPromise } = processAISDKCallInput(
13561
- operationInput(event, operationName)
13562
- );
14652
+ const callInput = workflowAgentCallInput ?? operationInput(event, operationName);
14653
+ const { input, outputPromise } = workflowAgent ? processAISDKWorkflowAgentCallInput(callInput) : processAISDKCallInput(callInput);
13563
14654
  logPayload.input = input;
13564
- if (outputPromise && input && typeof input === "object") {
14655
+ const state = operations.get(operationKey);
14656
+ if (state) {
14657
+ state.loggedInput = hasPromptLikeInput(input);
14658
+ }
14659
+ if (outputPromise && !workflowAgent && input && typeof input === "object") {
13565
14660
  outputPromise.then((resolvedData) => {
13566
14661
  span.log({
13567
14662
  input: {
@@ -13578,41 +14673,67 @@ function braintrustAISDKTelemetry() {
13578
14673
  },
13579
14674
  onLanguageModelCallStart(event) {
13580
14675
  runSafely("onLanguageModelCallStart", () => {
13581
- const state = operations.get(event.callId);
13582
- const openSpans = modelSpans.get(event.callId);
13583
- if (openSpans) {
14676
+ const operationKey = operationKeyFromEvent(event);
14677
+ const state = operationKey ? operations.get(operationKey) : void 0;
14678
+ if (shouldSkipTelemetryChildren(state)) {
14679
+ return;
14680
+ }
14681
+ const operationName = state?.operationName ?? "generateText";
14682
+ const callInput = operationInput(event, operationName);
14683
+ const workflowAgent = operationName === "WorkflowAgent.stream";
14684
+ const processedInput = shouldRecordInputs(event) && workflowAgent ? processAISDKWorkflowAgentModelCallInput(callInput).input : shouldRecordInputs(event) ? processAISDKCallInput(callInput).input : void 0;
14685
+ if (workflowAgent && state?.ownsSpan && !state.loggedInput && hasPromptLikeInput(processedInput)) {
14686
+ state.span.log({
14687
+ input: processedInput,
14688
+ metadata: {
14689
+ ...metadataFromEvent(event),
14690
+ ...extractWorkflowMetadataFromCallParams(callInput)
14691
+ }
14692
+ });
14693
+ state.loggedInput = true;
14694
+ }
14695
+ const openSpans = operationKey ? modelSpans.get(operationKey) : void 0;
14696
+ if (operationKey && openSpans) {
13584
14697
  for (const span2 of openSpans) {
13585
14698
  span2.end();
13586
14699
  }
13587
- modelSpans.delete(event.callId);
14700
+ modelSpans.delete(operationKey);
13588
14701
  }
13589
14702
  const span = startChildSpan(
13590
- event.callId,
13591
- state?.operationName === "streamText" ? "doStream" : "doGenerate",
14703
+ operationKey ?? event.callId,
14704
+ operationName === "streamText" ? "doStream" : "doGenerate",
13592
14705
  "llm" /* LLM */,
13593
14706
  {
13594
14707
  ...shouldRecordInputs(event) ? {
13595
- input: processAISDKCallInput(
13596
- operationInput(
13597
- event,
13598
- state?.operationName ?? "generateText"
13599
- )
13600
- ).input
14708
+ input: processedInput
13601
14709
  } : {},
13602
- metadata: metadataFromEvent(event)
14710
+ metadata: workflowAgent ? {
14711
+ ...metadataFromEvent(event),
14712
+ ...extractWorkflowMetadataFromCallParams(callInput)
14713
+ } : metadataFromEvent(event)
13603
14714
  }
13604
14715
  );
13605
- const spans = modelSpans.get(event.callId) ?? [];
14716
+ const spanKey = operationKey ?? event.callId;
14717
+ const spans = modelSpans.get(spanKey) ?? [];
13606
14718
  spans.push(span);
13607
- modelSpans.set(event.callId, spans);
14719
+ modelSpans.set(spanKey, spans);
13608
14720
  });
13609
14721
  },
13610
14722
  onLanguageModelCallEnd(event) {
13611
14723
  runSafely("onLanguageModelCallEnd", () => {
13612
- const span = shiftModelSpan(modelSpans, event.callId);
14724
+ const operationKey = operationKeyFromEvent(event);
14725
+ const state = operationKey ? operations.get(operationKey) : void 0;
14726
+ if (shouldSkipTelemetryChildren(state)) {
14727
+ return;
14728
+ }
14729
+ const span = operationKey ? shiftModelSpan(modelSpans, operationKey) : void 0;
13613
14730
  if (!span) {
13614
14731
  return;
13615
14732
  }
14733
+ const timeToFirstOutputMs = safePerformance(event)?.timeToFirstOutputMs;
14734
+ if (state?.operationName === "streamText" && state.firstChunkTime === void 0 && typeof timeToFirstOutputMs === "number") {
14735
+ state.firstChunkTime = state.startTime + timeToFirstOutputMs / 1e3;
14736
+ }
13616
14737
  const result = {
13617
14738
  ...event,
13618
14739
  response: event.responseId ? { id: event.responseId } : void 0
@@ -13628,14 +14749,18 @@ function braintrustAISDKTelemetry() {
13628
14749
  },
13629
14750
  onObjectStepStart(event) {
13630
14751
  runSafely("onObjectStepStart", () => {
13631
- const state = operations.get(event.callId);
13632
- const openSpan = objectSpans.get(event.callId);
13633
- if (openSpan) {
14752
+ const operationKey = operationKeyFromEvent(event);
14753
+ const state = operationKey ? operations.get(operationKey) : void 0;
14754
+ if (shouldSkipTelemetryChildren(state)) {
14755
+ return;
14756
+ }
14757
+ const openSpan = operationKey ? objectSpans.get(operationKey) : void 0;
14758
+ if (operationKey && openSpan) {
13634
14759
  openSpan.end();
13635
- objectSpans.delete(event.callId);
14760
+ objectSpans.delete(operationKey);
13636
14761
  }
13637
14762
  const span = startChildSpan(
13638
- event.callId,
14763
+ operationKey ?? event.callId,
13639
14764
  state?.operationName === "streamObject" ? "doStream" : "doGenerate",
13640
14765
  "llm" /* LLM */,
13641
14766
  {
@@ -13647,40 +14772,25 @@ function braintrustAISDKTelemetry() {
13647
14772
  metadata: metadataFromEvent(event)
13648
14773
  }
13649
14774
  );
13650
- objectSpans.set(event.callId, span);
13651
- });
13652
- },
13653
- onObjectStepFinish(event) {
13654
- runSafely("onObjectStepFinish", () => {
13655
- const span = objectSpans.get(event.callId);
13656
- if (!span) {
13657
- return;
13658
- }
13659
- const result = {
13660
- ...event,
13661
- text: event.objectText
13662
- };
13663
- span.log({
13664
- ...shouldRecordOutputs(event) ? {
13665
- output: processAISDKOutput(result, DEFAULT_DENY_OUTPUT_PATHS)
13666
- } : {},
13667
- metrics: extractTokenMetrics(result)
13668
- });
13669
- span.end();
13670
- objectSpans.delete(event.callId);
14775
+ objectSpans.set(operationKey ?? event.callId, span);
13671
14776
  });
13672
14777
  },
14778
+ onObjectStepEnd,
13673
14779
  onEmbedStart(event) {
13674
14780
  runSafely("onEmbedStart", () => {
13675
- const state = operations.get(event.callId);
14781
+ const operationKey = operationKeyFromEvent(event);
14782
+ const state = operationKey ? operations.get(operationKey) : void 0;
14783
+ if (shouldSkipTelemetryChildren(state)) {
14784
+ return;
14785
+ }
13676
14786
  for (const [embedCallId, embedState] of embedSpans) {
13677
- if (embedState.callId === event.callId && (state?.operationName === "embed" || embedState.values === event.values)) {
14787
+ if (embedState.operationKey === operationKey && (state?.operationName === "embed" || embedState.values === event.values)) {
13678
14788
  embedState.span.end();
13679
14789
  embedSpans.delete(embedCallId);
13680
14790
  }
13681
14791
  }
13682
14792
  const span = startChildSpan(
13683
- event.callId,
14793
+ operationKey ?? event.callId,
13684
14794
  "doEmbed",
13685
14795
  "llm" /* LLM */,
13686
14796
  {
@@ -13693,44 +14803,27 @@ function braintrustAISDKTelemetry() {
13693
14803
  }
13694
14804
  );
13695
14805
  embedSpans.set(event.embedCallId, {
13696
- callId: event.callId,
14806
+ operationKey: operationKey ?? event.callId,
13697
14807
  span,
13698
14808
  values: event.values
13699
14809
  });
13700
14810
  });
13701
14811
  },
13702
- onEmbedFinish(event) {
13703
- runSafely("onEmbedFinish", () => {
13704
- const state = embedSpans.get(event.embedCallId);
13705
- if (!state) {
13706
- return;
13707
- }
13708
- const result = {
13709
- ...event,
13710
- embeddings: event.embeddings
13711
- };
13712
- state.span.log({
13713
- ...shouldRecordOutputs(event) ? {
13714
- output: processAISDKEmbeddingOutput(
13715
- result,
13716
- DEFAULT_DENY_OUTPUT_PATHS
13717
- )
13718
- } : {},
13719
- metrics: extractTokenMetrics(result)
13720
- });
13721
- state.span.end();
13722
- embedSpans.delete(event.embedCallId);
13723
- });
13724
- },
14812
+ onEmbedEnd,
13725
14813
  onRerankStart(event) {
13726
14814
  runSafely("onRerankStart", () => {
13727
- const openSpan = rerankSpans.get(event.callId);
13728
- if (openSpan) {
14815
+ const operationKey = operationKeyFromEvent(event);
14816
+ const state = operationKey ? operations.get(operationKey) : void 0;
14817
+ if (shouldSkipTelemetryChildren(state)) {
14818
+ return;
14819
+ }
14820
+ const openSpan = operationKey ? rerankSpans.get(operationKey) : void 0;
14821
+ if (operationKey && openSpan) {
13729
14822
  openSpan.end();
13730
- rerankSpans.delete(event.callId);
14823
+ rerankSpans.delete(operationKey);
13731
14824
  }
13732
14825
  const span = startChildSpan(
13733
- event.callId,
14826
+ operationKey ?? event.callId,
13734
14827
  "doRerank",
13735
14828
  "llm" /* LLM */,
13736
14829
  {
@@ -13744,41 +14837,23 @@ function braintrustAISDKTelemetry() {
13744
14837
  metadata: metadataFromEvent(event)
13745
14838
  }
13746
14839
  );
13747
- rerankSpans.set(event.callId, span);
13748
- });
13749
- },
13750
- onRerankFinish(event) {
13751
- runSafely("onRerankFinish", () => {
13752
- const span = rerankSpans.get(event.callId);
13753
- if (!span) {
13754
- return;
13755
- }
13756
- const result = {
13757
- ranking: event.ranking?.map((entry) => ({
13758
- originalIndex: entry.index,
13759
- score: entry.relevanceScore
13760
- }))
13761
- };
13762
- span.log({
13763
- ...shouldRecordOutputs(event) ? {
13764
- output: processAISDKRerankOutput(
13765
- result,
13766
- DEFAULT_DENY_OUTPUT_PATHS
13767
- )
13768
- } : {}
13769
- });
13770
- span.end();
13771
- rerankSpans.delete(event.callId);
14840
+ rerankSpans.set(operationKey ?? event.callId, span);
13772
14841
  });
13773
14842
  },
14843
+ onRerankEnd,
13774
14844
  onToolExecutionStart(event) {
13775
14845
  runSafely("onToolExecutionStart", () => {
14846
+ const operationKey = operationKeyFromEvent(event);
14847
+ const state = operationKey ? operations.get(operationKey) : void 0;
14848
+ if (shouldSkipTelemetryChildren(state)) {
14849
+ return;
14850
+ }
13776
14851
  const toolCallId = event.toolCall.toolCallId;
13777
- if (!toolCallId) {
14852
+ if (!operationKey || !toolCallId) {
13778
14853
  return;
13779
14854
  }
13780
14855
  const span = startChildSpan(
13781
- event.callId,
14856
+ operationKey,
13782
14857
  event.toolCall.toolName || "tool",
13783
14858
  "tool" /* TOOL */,
13784
14859
  {
@@ -13792,7 +14867,7 @@ function braintrustAISDKTelemetry() {
13792
14867
  }
13793
14868
  }
13794
14869
  );
13795
- toolSpans.set(toolCallId, { callId: event.callId, span });
14870
+ toolSpans.set(toolCallId, { operationKey, span });
13796
14871
  });
13797
14872
  },
13798
14873
  onToolExecutionEnd(event) {
@@ -13803,14 +14878,17 @@ function braintrustAISDKTelemetry() {
13803
14878
  return;
13804
14879
  }
13805
14880
  const toolOutput = event.toolOutput;
13806
- if (toolOutput?.type === "tool-error") {
14881
+ const workflowToolError = event.success === false && "error" in event ? event.error : void 0;
14882
+ if (toolOutput?.type === "tool-error" || workflowToolError !== void 0) {
14883
+ const error = toolOutput?.error ?? workflowToolError;
13807
14884
  state.span.log({
13808
- error: toolOutput.error instanceof Error ? toolOutput.error.message : String(toolOutput?.error),
14885
+ error: error instanceof Error ? error.message : String(error),
13809
14886
  metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
13810
14887
  });
13811
14888
  } else {
14889
+ const output = toolOutput && "output" in toolOutput ? toolOutput.output : event.output;
13812
14890
  state.span.log({
13813
- ...shouldRecordOutputs(event) ? { output: toolOutput?.output } : {},
14891
+ ...shouldRecordOutputs(event) ? { output } : {},
13814
14892
  metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
13815
14893
  });
13816
14894
  }
@@ -13824,83 +14902,46 @@ function braintrustAISDKTelemetry() {
13824
14902
  if (!callId) {
13825
14903
  return;
13826
14904
  }
13827
- const state = operations.get(callId);
14905
+ const operationKey = operationKeyForCallId(callId);
14906
+ const state = operationKey ? operations.get(operationKey) : void 0;
13828
14907
  if (!state || state.firstChunkTime !== void 0) {
13829
14908
  return;
13830
14909
  }
13831
14910
  state.firstChunkTime = getCurrentUnixTimestamp();
13832
14911
  });
13833
14912
  },
13834
- onFinish(event) {
13835
- runSafely("onFinish", () => {
13836
- const state = operations.get(event.callId);
13837
- if (!state) {
14913
+ onEnd,
14914
+ onAbort(event) {
14915
+ runSafely("onAbort", () => {
14916
+ const operationKey = operationKeyFromEvent(event, "finish");
14917
+ const state = operationKey ? operations.get(operationKey) : void 0;
14918
+ if (!operationKey || !state) {
13838
14919
  return;
13839
14920
  }
13840
- const result = finishResult(event, state.operationName);
13841
- const metrics = state.hadModelChild ? {} : extractTokenMetrics(result);
13842
- if (state.firstChunkTime !== void 0) {
13843
- metrics.time_to_first_token = state.firstChunkTime - state.startTime;
14921
+ const error = abortReasonFromEvent(event);
14922
+ closeOpenChildSpans(operationKey, error);
14923
+ if (state.ownsSpan) {
14924
+ logError(state.span, error);
14925
+ state.span.end();
13844
14926
  }
13845
- state.span.log({
13846
- ...shouldRecordOutputs(event) ? {
13847
- output: finishOutput(result, state.operationName)
13848
- } : {},
13849
- metrics
13850
- });
13851
- state.span.end();
13852
- operations.delete(event.callId);
14927
+ deleteOperation(operationKey);
13853
14928
  });
13854
14929
  },
13855
14930
  onError(event) {
13856
14931
  runSafely("onError", () => {
13857
14932
  const errorEvent = isObject(event) ? event : {};
13858
- const callId = typeof errorEvent.callId === "string" ? errorEvent.callId : void 0;
13859
- if (!callId) {
13860
- return;
13861
- }
13862
- const state = operations.get(callId);
13863
- if (!state) {
14933
+ const operationKey = operationKeyFromEvent(errorEvent, "finish");
14934
+ const state = operationKey ? operations.get(operationKey) : void 0;
14935
+ if (!operationKey || !state) {
13864
14936
  return;
13865
14937
  }
13866
14938
  const error = errorEvent.error ?? event;
13867
- const openModelSpans = modelSpans.get(callId);
13868
- if (openModelSpans) {
13869
- for (const span of openModelSpans) {
13870
- logError(span, error);
13871
- span.end();
13872
- }
13873
- modelSpans.delete(callId);
13874
- }
13875
- const openObjectSpan = objectSpans.get(callId);
13876
- if (openObjectSpan) {
13877
- logError(openObjectSpan, error);
13878
- openObjectSpan.end();
13879
- objectSpans.delete(callId);
13880
- }
13881
- for (const [embedCallId, embedState] of embedSpans) {
13882
- if (embedState.callId === callId) {
13883
- logError(embedState.span, error);
13884
- embedState.span.end();
13885
- embedSpans.delete(embedCallId);
13886
- }
13887
- }
13888
- const openRerankSpan = rerankSpans.get(callId);
13889
- if (openRerankSpan) {
13890
- logError(openRerankSpan, error);
13891
- openRerankSpan.end();
13892
- rerankSpans.delete(callId);
13893
- }
13894
- for (const [toolCallId, toolState] of toolSpans) {
13895
- if (toolState.callId === callId) {
13896
- logError(toolState.span, error);
13897
- toolState.span.end();
13898
- toolSpans.delete(toolCallId);
13899
- }
14939
+ closeOpenChildSpans(operationKey, error);
14940
+ if (state.ownsSpan) {
14941
+ logError(state.span, error);
14942
+ state.span.end();
13900
14943
  }
13901
- logError(state.span, error);
13902
- state.span.end();
13903
- operations.delete(callId);
14944
+ deleteOperation(operationKey);
13904
14945
  });
13905
14946
  },
13906
14947
  executeTool({ toolCallId, execute }) {
@@ -13915,7 +14956,16 @@ function shouldRecordInputs(event) {
13915
14956
  function shouldRecordOutputs(event) {
13916
14957
  return event.recordOutputs !== false;
13917
14958
  }
14959
+ function hasPromptLikeInput(input) {
14960
+ if (!isObject(input)) {
14961
+ return false;
14962
+ }
14963
+ return input.prompt !== void 0 || input.messages !== void 0;
14964
+ }
13918
14965
  function operationNameFromId(operationId) {
14966
+ if (operationId === "ai.workflowAgent.stream") {
14967
+ return "WorkflowAgent.stream";
14968
+ }
13919
14969
  return operationId?.startsWith("ai.") ? operationId.slice("ai.".length) : operationId || "ai-sdk";
13920
14970
  }
13921
14971
  function modelFromEvent(event) {
@@ -13961,6 +15011,7 @@ function operationInput(event, operationName) {
13961
15011
  }
13962
15012
  return {
13963
15013
  model: modelFromEvent(event),
15014
+ instructions: event.instructions,
13964
15015
  system: event.system,
13965
15016
  prompt: event.prompt,
13966
15017
  messages: event.messages,
@@ -14009,6 +15060,30 @@ function finishResult(event, operationName) {
14009
15060
  }
14010
15061
  return event;
14011
15062
  }
15063
+ function extractTimeToFirstToken(result, state) {
15064
+ if (state.firstChunkTime !== void 0) {
15065
+ return state.firstChunkTime - state.startTime;
15066
+ }
15067
+ const performanceCandidates = [
15068
+ safePerformance(result),
15069
+ safePerformance(result.finalStep),
15070
+ ...Array.isArray(result.steps) ? (result.steps ?? []).map(safePerformance) : []
15071
+ ];
15072
+ for (const performance2 of performanceCandidates) {
15073
+ const timeToFirstOutputMs = performance2?.timeToFirstOutputMs;
15074
+ if (typeof timeToFirstOutputMs === "number") {
15075
+ return timeToFirstOutputMs / 1e3;
15076
+ }
15077
+ }
15078
+ return void 0;
15079
+ }
15080
+ function safePerformance(value) {
15081
+ if (!isObject(value)) {
15082
+ return void 0;
15083
+ }
15084
+ const performance2 = value.performance;
15085
+ return isObject(performance2) ? performance2 : void 0;
15086
+ }
14012
15087
  function finishOutput(result, operationName) {
14013
15088
  if (operationName === "embed" || operationName === "embedMany") {
14014
15089
  return processAISDKEmbeddingOutput(
@@ -14085,6 +15160,10 @@ var aiSDKChannels = defineChannels("ai", {
14085
15160
  channelName: "ToolLoopAgent.stream",
14086
15161
  kind: "async"
14087
15162
  }),
15163
+ workflowAgentStream: channel({
15164
+ channelName: "WorkflowAgent.stream",
15165
+ kind: "async"
15166
+ }),
14088
15167
  v7CreateTelemetryDispatcher: channel({
14089
15168
  channelName: "createTelemetryDispatcher",
14090
15169
  kind: "sync-stream"
@@ -14095,14 +15174,19 @@ var aiSDKChannels = defineChannels("ai", {
14095
15174
  var DEFAULT_DENY_OUTPUT_PATHS = [
14096
15175
  // v3
14097
15176
  "roundtrips[].request.body",
15177
+ "roundtrips[].request.headers",
14098
15178
  "roundtrips[].response.headers",
14099
15179
  "rawResponse.headers",
14100
15180
  "responseMessages",
14101
15181
  // v5
14102
15182
  "request.body",
15183
+ "request.headers",
15184
+ "responses[].headers",
14103
15185
  "response.body",
14104
15186
  "response.headers",
14105
15187
  "steps[].request.body",
15188
+ "steps[].request.headers",
15189
+ "steps[].responses[].headers",
14106
15190
  "steps[].response.body",
14107
15191
  "steps[].response.headers"
14108
15192
  ];
@@ -14114,6 +15198,18 @@ var AUTO_PATCHED_V7_TELEMETRY_DISPATCHER = /* @__PURE__ */ Symbol.for(
14114
15198
  var RUNTIME_DENY_OUTPUT_PATHS = /* @__PURE__ */ Symbol.for(
14115
15199
  "braintrust.ai-sdk.deny-output-paths"
14116
15200
  );
15201
+ var aiSDKV7TelemetryOperationCounter = 0;
15202
+ var TRANSPORT_PAYLOAD_ROOT_PATHS = [
15203
+ "rawResponse",
15204
+ "request",
15205
+ "response",
15206
+ "responses[]",
15207
+ "roundtrips[].request",
15208
+ "roundtrips[].response",
15209
+ "steps[].request",
15210
+ "steps[].response",
15211
+ "steps[].responses[]"
15212
+ ];
14117
15213
  var AI_SDK_V7_TELEMETRY_CALLBACKS = [
14118
15214
  "onStart",
14119
15215
  "onStepStart",
@@ -14122,14 +15218,16 @@ var AI_SDK_V7_TELEMETRY_CALLBACKS = [
14122
15218
  "onToolExecutionStart",
14123
15219
  "onToolExecutionEnd",
14124
15220
  "onChunk",
15221
+ "onStepEnd",
14125
15222
  "onStepFinish",
14126
15223
  "onObjectStepStart",
14127
- "onObjectStepFinish",
15224
+ "onObjectStepEnd",
14128
15225
  "onEmbedStart",
14129
- "onEmbedFinish",
15226
+ "onEmbedEnd",
14130
15227
  "onRerankStart",
14131
- "onRerankFinish",
14132
- "onFinish",
15228
+ "onRerankEnd",
15229
+ "onEnd",
15230
+ "onAbort",
14133
15231
  "onError"
14134
15232
  ];
14135
15233
  var AISDKPlugin = class extends BasePlugin {
@@ -14287,7 +15385,9 @@ var AISDKPlugin = class extends BasePlugin {
14287
15385
  traceStreamingChannel(aiSDKChannels.agentGenerate, {
14288
15386
  name: "Agent.generate",
14289
15387
  type: "function" /* FUNCTION */,
14290
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
15388
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
15389
+ agentOwner: true
15390
+ }),
14291
15391
  extractOutput: (result, endEvent) => {
14292
15392
  finalizeAISDKChildTracing(endEvent);
14293
15393
  return processAISDKOutput(
@@ -14303,7 +15403,9 @@ var AISDKPlugin = class extends BasePlugin {
14303
15403
  traceStreamingChannel(aiSDKChannels.agentStream, {
14304
15404
  name: "Agent.stream",
14305
15405
  type: "function" /* FUNCTION */,
14306
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
15406
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
15407
+ agentOwner: true
15408
+ }),
14307
15409
  extractOutput: (result, endEvent) => processAISDKOutput(
14308
15410
  result,
14309
15411
  resolveDenyOutputPaths(endEvent, denyOutputPaths)
@@ -14323,7 +15425,9 @@ var AISDKPlugin = class extends BasePlugin {
14323
15425
  traceSyncStreamChannel(aiSDKChannels.agentStreamSync, {
14324
15426
  name: "Agent.stream",
14325
15427
  type: "function" /* FUNCTION */,
14326
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
15428
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
15429
+ agentOwner: true
15430
+ }),
14327
15431
  patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
14328
15432
  defaultDenyOutputPaths: denyOutputPaths,
14329
15433
  endEvent,
@@ -14337,7 +15441,9 @@ var AISDKPlugin = class extends BasePlugin {
14337
15441
  traceStreamingChannel(aiSDKChannels.toolLoopAgentGenerate, {
14338
15442
  name: "ToolLoopAgent.generate",
14339
15443
  type: "function" /* FUNCTION */,
14340
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
15444
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
15445
+ agentOwner: true
15446
+ }),
14341
15447
  extractOutput: (result, endEvent) => {
14342
15448
  finalizeAISDKChildTracing(endEvent);
14343
15449
  return processAISDKOutput(
@@ -14353,7 +15459,9 @@ var AISDKPlugin = class extends BasePlugin {
14353
15459
  traceStreamingChannel(aiSDKChannels.toolLoopAgentStream, {
14354
15460
  name: "ToolLoopAgent.stream",
14355
15461
  type: "function" /* FUNCTION */,
14356
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
15462
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
15463
+ agentOwner: true
15464
+ }),
14357
15465
  extractOutput: (result, endEvent) => processAISDKOutput(
14358
15466
  result,
14359
15467
  resolveDenyOutputPaths(endEvent, denyOutputPaths)
@@ -14369,6 +15477,42 @@ var AISDKPlugin = class extends BasePlugin {
14369
15477
  })
14370
15478
  })
14371
15479
  );
15480
+ this.unsubscribers.push(
15481
+ traceStreamingChannel(aiSDKChannels.workflowAgentStream, {
15482
+ name: "WorkflowAgent.stream",
15483
+ type: "function" /* FUNCTION */,
15484
+ extractInput: ([params], event, span) => prepareAISDKWorkflowAgentStreamInput(
15485
+ params,
15486
+ event,
15487
+ span,
15488
+ denyOutputPaths
15489
+ ),
15490
+ extractOutput: (result, endEvent) => {
15491
+ finalizeAISDKChildTracing(endEvent);
15492
+ return processAISDKOutput(
15493
+ result,
15494
+ resolveDenyOutputPaths(endEvent, denyOutputPaths)
15495
+ );
15496
+ },
15497
+ extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
15498
+ aggregateChunks: aggregateAISDKChunks,
15499
+ onComplete: ({ span }) => {
15500
+ unregisterWorkflowAgentWrapperSpan(span);
15501
+ },
15502
+ onError: ({ event, span }) => {
15503
+ finalizeAISDKChildTracing(event);
15504
+ unregisterWorkflowAgentWrapperSpan(span);
15505
+ },
15506
+ patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
15507
+ defaultDenyOutputPaths: denyOutputPaths,
15508
+ endEvent,
15509
+ onComplete: () => unregisterWorkflowAgentWrapperSpan(span),
15510
+ result,
15511
+ span,
15512
+ startTime
15513
+ })
15514
+ })
15515
+ );
14372
15516
  }
14373
15517
  };
14374
15518
  function subscribeToAISDKV7TelemetryDispatcher() {
@@ -14380,7 +15524,11 @@ function subscribeToAISDKV7TelemetryDispatcher() {
14380
15524
  if (telemetryOptions?.isEnabled === false) {
14381
15525
  return;
14382
15526
  }
14383
- patchAISDKV7TelemetryDispatcher(event.result, telemetry);
15527
+ patchAISDKV7TelemetryDispatcher(
15528
+ event.result,
15529
+ telemetry,
15530
+ telemetryOptions
15531
+ );
14384
15532
  }
14385
15533
  };
14386
15534
  channel2.subscribe(handlers);
@@ -14388,7 +15536,7 @@ function subscribeToAISDKV7TelemetryDispatcher() {
14388
15536
  channel2.unsubscribe(handlers);
14389
15537
  };
14390
15538
  }
14391
- function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
15539
+ function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry, telemetryOptions) {
14392
15540
  if (!isObject(dispatcher)) {
14393
15541
  return;
14394
15542
  }
@@ -14397,6 +15545,54 @@ function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
14397
15545
  return;
14398
15546
  }
14399
15547
  dispatcherRecord[AUTO_PATCHED_V7_TELEMETRY_DISPATCHER] = true;
15548
+ let operationKey;
15549
+ const telemetryEventFields = {};
15550
+ if (typeof telemetryOptions?.recordInputs === "boolean") {
15551
+ telemetryEventFields.recordInputs = telemetryOptions.recordInputs;
15552
+ }
15553
+ if (typeof telemetryOptions?.recordOutputs === "boolean") {
15554
+ telemetryEventFields.recordOutputs = telemetryOptions.recordOutputs;
15555
+ }
15556
+ if (typeof telemetryOptions?.functionId === "string") {
15557
+ telemetryEventFields.functionId = telemetryOptions.functionId;
15558
+ }
15559
+ const eventWithOperationKey = (event) => {
15560
+ if (!isObject(event)) {
15561
+ return event;
15562
+ }
15563
+ const eventRecord = event;
15564
+ const callId = typeof eventRecord.callId === "string" ? eventRecord.callId : "unknown";
15565
+ operationKey ??= `${callId}:${++aiSDKV7TelemetryOperationCounter}`;
15566
+ if (Object.keys(telemetryEventFields).length > 0) {
15567
+ const augmentedEvent = {
15568
+ ...telemetryEventFields,
15569
+ ...event
15570
+ };
15571
+ try {
15572
+ Object.defineProperty(augmentedEvent, BRAINTRUST_AI_SDK_V7_OPERATION_KEY, {
15573
+ configurable: true,
15574
+ enumerable: false,
15575
+ value: operationKey
15576
+ });
15577
+ } catch {
15578
+ augmentedEvent[BRAINTRUST_AI_SDK_V7_OPERATION_KEY] = operationKey;
15579
+ }
15580
+ return augmentedEvent;
15581
+ }
15582
+ try {
15583
+ Object.defineProperty(eventRecord, BRAINTRUST_AI_SDK_V7_OPERATION_KEY, {
15584
+ configurable: true,
15585
+ enumerable: false,
15586
+ value: operationKey
15587
+ });
15588
+ return event;
15589
+ } catch {
15590
+ return {
15591
+ ...event,
15592
+ [BRAINTRUST_AI_SDK_V7_OPERATION_KEY]: operationKey
15593
+ };
15594
+ }
15595
+ };
14400
15596
  for (const key of AI_SDK_V7_TELEMETRY_CALLBACKS) {
14401
15597
  const braintrustCallback = telemetry[key];
14402
15598
  if (typeof braintrustCallback !== "function") {
@@ -14405,11 +15601,17 @@ function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
14405
15601
  const existingCallback = dispatcherRecord[key];
14406
15602
  dispatcherRecord[key] = (event) => {
14407
15603
  const existingResult = typeof existingCallback === "function" ? existingCallback.call(dispatcher, event) : void 0;
14408
- const braintrustResult = braintrustCallback.call(telemetry, event);
14409
- const pending = [existingResult, braintrustResult].filter(isPromiseLike);
14410
- if (pending.length > 0) {
14411
- return Promise.allSettled(pending).then(() => void 0);
15604
+ try {
15605
+ const braintrustResult = braintrustCallback.call(
15606
+ telemetry,
15607
+ eventWithOperationKey(event)
15608
+ );
15609
+ if (isPromiseLike(braintrustResult)) {
15610
+ void Promise.resolve(braintrustResult).catch(() => void 0);
15611
+ }
15612
+ } catch {
14412
15613
  }
15614
+ return existingResult;
14413
15615
  };
14414
15616
  }
14415
15617
  const braintrustExecuteTool = telemetry.executeTool;
@@ -14419,6 +15621,7 @@ function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
14419
15621
  const existingExecuteTool = dispatcherRecord.executeTool;
14420
15622
  dispatcherRecord.executeTool = (args) => braintrustExecuteTool.call(telemetry, {
14421
15623
  ...args,
15624
+ ...operationKey ? { [BRAINTRUST_AI_SDK_V7_OPERATION_KEY]: operationKey } : {},
14422
15625
  execute: () => typeof existingExecuteTool === "function" ? existingExecuteTool.call(dispatcher, args) : args.execute()
14423
15626
  });
14424
15627
  }
@@ -14517,6 +15720,8 @@ var serializeOutputObject = (output, model) => {
14517
15720
  var processInputAttachmentsSync = (input) => {
14518
15721
  if (!input) return { input };
14519
15722
  const processed = { ...input };
15723
+ delete processed.headers;
15724
+ delete processed.experimental_output;
14520
15725
  if (input.messages && Array.isArray(input.messages)) {
14521
15726
  processed.messages = input.messages.map(processMessage);
14522
15727
  }
@@ -14550,10 +15755,10 @@ var processInputAttachmentsSync = (input) => {
14550
15755
  processed.output = serialized;
14551
15756
  }
14552
15757
  }
14553
- if ("prepareCall" in processed && typeof processed.prepareCall === "function") {
14554
- processed.prepareCall = "[Function]";
14555
- }
14556
- return { input: processed, outputPromise };
15758
+ return {
15759
+ input: sanitizeAISDKCallInputValue(processed),
15760
+ outputPromise
15761
+ };
14557
15762
  };
14558
15763
  var processMessage = (message) => {
14559
15764
  if (!message || typeof message !== "object") return message;
@@ -14717,7 +15922,21 @@ var convertDataToAttachment = (data, mimeType, filename) => {
14717
15922
  function processAISDKCallInput(params) {
14718
15923
  return processInputAttachmentsSync(params);
14719
15924
  }
14720
- function prepareAISDKCallInput(params, event, span, defaultDenyOutputPaths) {
15925
+ function processAISDKWorkflowAgentCallInput(params) {
15926
+ const processed = processAISDKCallInput(params);
15927
+ return {
15928
+ ...processed,
15929
+ input: extractWorkflowAgentInput(processed.input)
15930
+ };
15931
+ }
15932
+ function processAISDKWorkflowAgentModelCallInput(params) {
15933
+ const processed = processAISDKCallInput(params);
15934
+ return {
15935
+ ...processed,
15936
+ input: extractWorkflowAgentModelInput(processed.input)
15937
+ };
15938
+ }
15939
+ function prepareAISDKCallInput(params, event, span, defaultDenyOutputPaths, childTracingOptions = {}) {
14721
15940
  const { input, outputPromise } = processAISDKCallInput(params);
14722
15941
  if (outputPromise && input && typeof input === "object") {
14723
15942
  outputPromise.then((resolvedData) => {
@@ -14736,7 +15955,29 @@ function prepareAISDKCallInput(params, event, span, defaultDenyOutputPaths) {
14736
15955
  event.self,
14737
15956
  span,
14738
15957
  defaultDenyOutputPaths,
14739
- event.aiSDK
15958
+ event.aiSDK,
15959
+ childTracingOptions
15960
+ );
15961
+ event.modelWrapped = childTracing.modelWrapped;
15962
+ if (childTracing.cleanup) {
15963
+ event.__braintrust_ai_sdk_cleanup = childTracing.cleanup;
15964
+ }
15965
+ return {
15966
+ input,
15967
+ metadata
15968
+ };
15969
+ }
15970
+ function prepareAISDKWorkflowAgentStreamInput(params, event, span, defaultDenyOutputPaths) {
15971
+ registerWorkflowAgentWrapperSpan(span);
15972
+ const { input } = processAISDKWorkflowAgentCallInput(params);
15973
+ const metadata = extractWorkflowMetadataFromCallParams(params, event.self);
15974
+ const childTracing = prepareAISDKChildTracing(
15975
+ params,
15976
+ event.self,
15977
+ span,
15978
+ defaultDenyOutputPaths,
15979
+ event.aiSDK,
15980
+ { agentOwner: true, workflowAgent: true }
14740
15981
  );
14741
15982
  event.modelWrapped = childTracing.modelWrapped;
14742
15983
  if (childTracing.cleanup) {
@@ -14773,6 +16014,9 @@ function extractTopLevelAISDKMetrics(result, event, startTime) {
14773
16014
  function hasModelChildTracing(event) {
14774
16015
  return event?.modelWrapped === true || event?.__braintrust_ai_sdk_model_wrapped === true;
14775
16016
  }
16017
+ function serializeToolExecutionInput(args) {
16018
+ return args.length > 0 ? args[0] : args;
16019
+ }
14776
16020
  function createAISDKIntegrationMetadata() {
14777
16021
  return {
14778
16022
  braintrust: {
@@ -14784,6 +16028,13 @@ function createAISDKIntegrationMetadata() {
14784
16028
  function resolveModelFromSelf(self) {
14785
16029
  return self && typeof self === "object" && "model" in self && self.model ? self.model : self && typeof self === "object" && "settings" in self && self.settings?.model ? self.settings?.model : void 0;
14786
16030
  }
16031
+ function resolveToolsFromSelf(self) {
16032
+ if (!self || typeof self !== "object") {
16033
+ return void 0;
16034
+ }
16035
+ const selfRecord = self;
16036
+ return selfRecord.tools ?? selfRecord.settings?.tools;
16037
+ }
14787
16038
  function extractBaseMetadata(model, self) {
14788
16039
  const metadata = createAISDKIntegrationMetadata();
14789
16040
  const { model: modelId, provider } = serializeModelWithProvider(
@@ -14799,12 +16050,175 @@ function extractBaseMetadata(model, self) {
14799
16050
  }
14800
16051
  function extractMetadataFromCallParams(params, self) {
14801
16052
  const metadata = extractBaseMetadata(params.model, self);
14802
- const tools = serializeAISDKToolsForLogging(params.tools);
16053
+ const tools = serializeAISDKToolsForLogging(
16054
+ params.tools ?? resolveToolsFromSelf(self)
16055
+ );
14803
16056
  if (tools) {
14804
16057
  metadata.tools = tools;
14805
16058
  }
14806
16059
  return metadata;
14807
16060
  }
16061
+ function extractWorkflowMetadataFromCallParams(params, self) {
16062
+ const metadata = extractMetadataFromCallParams(params, self);
16063
+ const options = extractAISDKCallOptionsForMetadata(params);
16064
+ if (Object.keys(options).length > 0) {
16065
+ metadata.options = options;
16066
+ }
16067
+ return metadata;
16068
+ }
16069
+ function extractWorkflowAgentInput(params) {
16070
+ const input = {};
16071
+ if (params.instructions !== void 0) {
16072
+ input.instructions = params.instructions;
16073
+ }
16074
+ if (params.system !== void 0) {
16075
+ input.system = params.system;
16076
+ }
16077
+ if (Array.isArray(params.messages)) {
16078
+ return { ...input, messages: params.messages };
16079
+ }
16080
+ if (typeof params.prompt === "string") {
16081
+ return { ...input, prompt: params.prompt };
16082
+ }
16083
+ if (Array.isArray(params.prompt)) {
16084
+ return { ...input, prompt: params.prompt };
16085
+ }
16086
+ return input;
16087
+ }
16088
+ function extractWorkflowAgentModelInput(params) {
16089
+ const input = {};
16090
+ if (params.instructions !== void 0) {
16091
+ input.instructions = params.instructions;
16092
+ }
16093
+ if (params.system !== void 0) {
16094
+ input.system = params.system;
16095
+ }
16096
+ if (Array.isArray(params.messages)) {
16097
+ return { ...input, messages: params.messages };
16098
+ }
16099
+ if (typeof params.prompt === "string") {
16100
+ return { ...input, prompt: params.prompt };
16101
+ }
16102
+ if (Array.isArray(params.prompt)) {
16103
+ return { ...input, messages: params.prompt };
16104
+ }
16105
+ return input;
16106
+ }
16107
+ function sanitizeAISDKCallInputValue(value, depth = 0) {
16108
+ if (value === void 0 || typeof value === "function") {
16109
+ return void 0;
16110
+ }
16111
+ if (value === null || typeof value !== "object") {
16112
+ return value;
16113
+ }
16114
+ if (isPromiseLike(value)) {
16115
+ return "[Promise]";
16116
+ }
16117
+ if (typeof AbortSignal !== "undefined" && value instanceof AbortSignal) {
16118
+ return "[AbortSignal]";
16119
+ }
16120
+ if (depth >= 8) {
16121
+ return "[Object]";
16122
+ }
16123
+ if (Array.isArray(value)) {
16124
+ return value.map((item) => sanitizeAISDKCallInputValue(item, depth + 1)).filter((item) => item !== void 0);
16125
+ }
16126
+ if (!isObject(value)) {
16127
+ return value;
16128
+ }
16129
+ const prototype = Object.getPrototypeOf(value);
16130
+ if (prototype !== Object.prototype && prototype !== null) {
16131
+ return value;
16132
+ }
16133
+ const sanitized = {};
16134
+ for (const [key, nested] of Object.entries(value)) {
16135
+ if (key === "__proto__" || key === "constructor" || key === "prototype" || key.toLowerCase() === "headers") {
16136
+ continue;
16137
+ }
16138
+ const sanitizedNested = sanitizeAISDKCallInputValue(nested, depth + 1);
16139
+ if (sanitizedNested !== void 0) {
16140
+ sanitized[key] = sanitizedNested;
16141
+ }
16142
+ }
16143
+ return sanitized;
16144
+ }
16145
+ function extractAISDKCallOptionsForMetadata(params) {
16146
+ const options = {};
16147
+ const inputOrTopLevelKeys = /* @__PURE__ */ new Set([
16148
+ "model",
16149
+ "instructions",
16150
+ "messages",
16151
+ "prompt",
16152
+ "system",
16153
+ "tools",
16154
+ "headers",
16155
+ "abortSignal",
16156
+ "signal",
16157
+ "experimental_output"
16158
+ ]);
16159
+ for (const [key, value] of Object.entries(params)) {
16160
+ if (inputOrTopLevelKeys.has(key) || key === "__proto__" || key === "constructor" || key === "prototype" || /^on[A-Z]/.test(key) && typeof value === "function") {
16161
+ continue;
16162
+ }
16163
+ const sanitized = sanitizeAISDKMetadataValue(value);
16164
+ if (sanitized !== void 0) {
16165
+ options[key] = sanitized;
16166
+ }
16167
+ }
16168
+ return options;
16169
+ }
16170
+ function sanitizeAISDKMetadataValue(value, depth = 0) {
16171
+ if (value === void 0) {
16172
+ return void 0;
16173
+ }
16174
+ if (typeof value === "function") {
16175
+ return "[Function]";
16176
+ }
16177
+ if (value === null || typeof value !== "object") {
16178
+ return value;
16179
+ }
16180
+ if (isPromiseLike(value)) {
16181
+ return "[Promise]";
16182
+ }
16183
+ if (typeof AbortSignal !== "undefined" && value instanceof AbortSignal) {
16184
+ return "[AbortSignal]";
16185
+ }
16186
+ if (depth >= 8) {
16187
+ return "[Object]";
16188
+ }
16189
+ if (Array.isArray(value)) {
16190
+ return value.map((item) => sanitizeAISDKMetadataValue(item, depth + 1)).filter((item) => item !== void 0);
16191
+ }
16192
+ if (!isObject(value)) {
16193
+ return value;
16194
+ }
16195
+ const sanitized = {};
16196
+ for (const [key, nested] of Object.entries(value)) {
16197
+ if (key === "__proto__" || key === "constructor" || key === "prototype" || key.toLowerCase() === "headers") {
16198
+ continue;
16199
+ }
16200
+ const sanitizedNested = sanitizeAISDKMetadataValue(nested, depth + 1);
16201
+ if (sanitizedNested !== void 0) {
16202
+ sanitized[key] = sanitizedNested;
16203
+ }
16204
+ }
16205
+ return sanitized;
16206
+ }
16207
+ function buildAISDKModelStartEvent(callOptions, baseMetadata, options) {
16208
+ if (!options.workflowAgent) {
16209
+ return {
16210
+ input: processAISDKCallInput(callOptions).input,
16211
+ metadata: baseMetadata
16212
+ };
16213
+ }
16214
+ return {
16215
+ input: processAISDKWorkflowAgentModelCallInput(callOptions).input,
16216
+ metadata: {
16217
+ ...baseMetadata,
16218
+ ...extractWorkflowMetadataFromCallParams(callOptions)
16219
+ }
16220
+ };
16221
+ }
14808
16222
  function extractMetadataFromEmbedParams(params, self) {
14809
16223
  return extractBaseMetadata(params.model, self);
14810
16224
  }
@@ -14818,72 +16232,273 @@ function extractMetadataFromRerankParams(params, self) {
14818
16232
  }
14819
16233
  return metadata;
14820
16234
  }
14821
- function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiSDK) {
16235
+ function activeAISDKChildPatchEntry(entries) {
16236
+ const activeSpan = currentSpan();
16237
+ const activeSpanId = activeSpan.spanId;
16238
+ if (activeSpanId) {
16239
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
16240
+ const entry = entries[index];
16241
+ if (entry?.activeSpanIds.has(activeSpanId)) {
16242
+ return entry;
16243
+ }
16244
+ }
16245
+ }
16246
+ const activeParentSpanIds = activeSpan.spanParents ?? [];
16247
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
16248
+ const entry = entries[index];
16249
+ if (entry?.parentSpan.spanId && activeParentSpanIds.includes(entry.parentSpan.spanId)) {
16250
+ return entry;
16251
+ }
16252
+ }
16253
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
16254
+ const entry = entries[index];
16255
+ if (entry?.parentSpan.spanId === activeSpanId) {
16256
+ return entry;
16257
+ }
16258
+ }
16259
+ return entries[entries.length - 1];
16260
+ }
16261
+ function attachNestedAISDKChildPatchEntry(entries, nestedSpan, cleanup) {
16262
+ const activeSpanId = currentSpan().spanId;
16263
+ if (!activeSpanId || activeSpanId === nestedSpan.spanId) {
16264
+ return false;
16265
+ }
16266
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
16267
+ const entry = entries[index];
16268
+ if (entry?.parentSpan.spanId === activeSpanId || entry?.activeSpanIds.has(activeSpanId)) {
16269
+ entry.activeSpanIds.add(nestedSpan.spanId);
16270
+ cleanup.push(() => {
16271
+ entry.activeSpanIds.delete(nestedSpan.spanId);
16272
+ });
16273
+ return true;
16274
+ }
16275
+ }
16276
+ return false;
16277
+ }
16278
+ function shadowActiveAISDKChildPatchEntry(entries, entry, nestedSpan, cleanup) {
16279
+ const activeSpanId = currentSpan().spanId;
16280
+ if (!activeSpanId || activeSpanId === nestedSpan.spanId) {
16281
+ return;
16282
+ }
16283
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
16284
+ const existingEntry = entries[index];
16285
+ if (existingEntry?.parentSpan.spanId === activeSpanId || existingEntry?.activeSpanIds.has(activeSpanId)) {
16286
+ entry.activeSpanIds.add(activeSpanId);
16287
+ cleanup.push(() => {
16288
+ entry.activeSpanIds.delete(activeSpanId);
16289
+ });
16290
+ return;
16291
+ }
16292
+ }
16293
+ }
16294
+ function closeOpenAISDKModelPatchSpans(entry) {
16295
+ for (const span of entry.openSpans) {
16296
+ span.end();
16297
+ }
16298
+ entry.openSpans.clear();
16299
+ }
16300
+ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiSDK, childTracingOptions = {}) {
14822
16301
  const cleanup = [];
14823
- const patchedModels = /* @__PURE__ */ new WeakSet();
16302
+ const patchedModels = /* @__PURE__ */ new WeakMap();
14824
16303
  const patchedTools = /* @__PURE__ */ new WeakSet();
14825
16304
  let modelWrapped = false;
14826
16305
  const patchModel = (model) => {
14827
16306
  const resolvedModel = resolveAISDKModel(model, aiSDK);
14828
- if (!resolvedModel || typeof resolvedModel !== "object" || typeof resolvedModel.doGenerate !== "function" || patchedModels.has(resolvedModel) || resolvedModel[AUTO_PATCHED_MODEL]) {
16307
+ if (!resolvedModel || typeof resolvedModel !== "object" || typeof resolvedModel.doGenerate !== "function") {
14829
16308
  return resolvedModel;
14830
16309
  }
14831
- patchedModels.add(resolvedModel);
14832
- resolvedModel[AUTO_PATCHED_MODEL] = true;
16310
+ const existingWrappedModel = patchedModels.get(resolvedModel);
16311
+ if (existingWrappedModel) {
16312
+ modelWrapped = true;
16313
+ return existingWrappedModel;
16314
+ }
14833
16315
  modelWrapped = true;
16316
+ const modelRecord = resolvedModel;
16317
+ const entry = {
16318
+ activeSpanIds: /* @__PURE__ */ new Set([parentSpan.spanId]),
16319
+ baseMetadata: buildAISDKChildMetadata(resolvedModel),
16320
+ childTracingOptions,
16321
+ denyOutputPaths,
16322
+ openSpans: /* @__PURE__ */ new Set(),
16323
+ parentSpan
16324
+ };
16325
+ const cleanupModelEntry = (state2, patchedModel) => {
16326
+ closeOpenAISDKModelPatchSpans(entry);
16327
+ const index = state2.entries.indexOf(entry);
16328
+ if (index >= 0) {
16329
+ state2.entries.splice(index, 1);
16330
+ }
16331
+ if (state2.entries.length > 0) {
16332
+ return;
16333
+ }
16334
+ patchedModel.doGenerate = state2.originalDoGenerate;
16335
+ patchedModel.doStream = state2.originalDoStream;
16336
+ delete patchedModel[AUTO_PATCHED_MODEL];
16337
+ };
16338
+ const existingState = modelRecord[AUTO_PATCHED_MODEL];
16339
+ if (existingState) {
16340
+ patchedModels.set(resolvedModel, resolvedModel);
16341
+ if (childTracingOptions.agentOwner && attachNestedAISDKChildPatchEntry(
16342
+ existingState.entries,
16343
+ parentSpan,
16344
+ cleanup
16345
+ )) {
16346
+ return resolvedModel;
16347
+ }
16348
+ if (!childTracingOptions.agentOwner) {
16349
+ shadowActiveAISDKChildPatchEntry(
16350
+ existingState.entries,
16351
+ entry,
16352
+ parentSpan,
16353
+ cleanup
16354
+ );
16355
+ }
16356
+ existingState.entries.push(entry);
16357
+ cleanup.push(() => {
16358
+ cleanupModelEntry(existingState, modelRecord);
16359
+ });
16360
+ return resolvedModel;
16361
+ }
14834
16362
  const originalDoGenerate = resolvedModel.doGenerate;
14835
16363
  const originalDoStream = resolvedModel.doStream;
14836
- const baseMetadata = buildAISDKChildMetadata(resolvedModel);
14837
- resolvedModel.doGenerate = async function doGeneratePatched(options) {
14838
- return parentSpan.traced(
16364
+ const wrappedModel = Object.create(
16365
+ Object.getPrototypeOf(resolvedModel)
16366
+ );
16367
+ Object.defineProperties(
16368
+ wrappedModel,
16369
+ Object.getOwnPropertyDescriptors(resolvedModel)
16370
+ );
16371
+ const wrappedModelRecord = wrappedModel;
16372
+ const state = {
16373
+ entries: [entry],
16374
+ originalDoGenerate,
16375
+ originalDoStream
16376
+ };
16377
+ Object.defineProperty(wrappedModel, AUTO_PATCHED_MODEL, {
16378
+ configurable: true,
16379
+ value: state
16380
+ });
16381
+ wrappedModel.doGenerate = async function doGeneratePatched(callOptions) {
16382
+ const activeEntry = activeAISDKChildPatchEntry(state.entries);
16383
+ if (!activeEntry) {
16384
+ return Reflect.apply(originalDoGenerate, resolvedModel, [callOptions]);
16385
+ }
16386
+ closeOpenAISDKModelPatchSpans(activeEntry);
16387
+ return activeEntry.parentSpan.traced(
14839
16388
  async (span) => {
14840
- const result = await Reflect.apply(
14841
- originalDoGenerate,
14842
- resolvedModel,
14843
- [options]
14844
- );
14845
- span.log({
14846
- output: processAISDKOutput(result, denyOutputPaths),
14847
- metrics: extractTokenMetrics(result),
14848
- ...buildResolvedMetadataPayload(result)
14849
- });
14850
- return result;
16389
+ activeEntry.openSpans.add(span);
16390
+ try {
16391
+ const result = await Reflect.apply(
16392
+ originalDoGenerate,
16393
+ resolvedModel,
16394
+ [callOptions]
16395
+ );
16396
+ const output = processAISDKOutput(
16397
+ result,
16398
+ activeEntry.denyOutputPaths
16399
+ );
16400
+ const metrics = extractTokenMetrics(result);
16401
+ const metadataPayload = buildResolvedMetadataPayload(result);
16402
+ const missingUsageMetadata = buildMissingUsageMetadata(
16403
+ output,
16404
+ metrics,
16405
+ "ai_sdk_result_missing_usage"
16406
+ );
16407
+ span.log({
16408
+ output,
16409
+ metrics,
16410
+ ...mergeMetadataPayload(metadataPayload, missingUsageMetadata)
16411
+ });
16412
+ return result;
16413
+ } finally {
16414
+ activeEntry.openSpans.delete(span);
16415
+ }
14851
16416
  },
14852
16417
  {
14853
16418
  name: "doGenerate",
14854
16419
  spanAttributes: {
14855
16420
  type: "llm" /* LLM */
14856
16421
  },
14857
- event: {
14858
- input: processAISDKCallInput(options).input,
14859
- metadata: baseMetadata
14860
- }
16422
+ event: buildAISDKModelStartEvent(
16423
+ callOptions,
16424
+ activeEntry.baseMetadata,
16425
+ {
16426
+ workflowAgent: activeEntry.childTracingOptions.workflowAgent
16427
+ }
16428
+ )
14861
16429
  }
14862
16430
  );
14863
16431
  };
14864
16432
  if (originalDoStream) {
14865
- resolvedModel.doStream = async function doStreamPatched(options) {
14866
- const span = parentSpan.startSpan({
16433
+ wrappedModel.doStream = async function doStreamPatched(callOptions) {
16434
+ const activeEntry = activeAISDKChildPatchEntry(state.entries);
16435
+ if (!activeEntry) {
16436
+ return Reflect.apply(originalDoStream, resolvedModel, [callOptions]);
16437
+ }
16438
+ closeOpenAISDKModelPatchSpans(activeEntry);
16439
+ const span = activeEntry.parentSpan.startSpan({
14867
16440
  name: "doStream",
14868
16441
  spanAttributes: {
14869
16442
  type: "llm" /* LLM */
14870
16443
  },
14871
- event: {
14872
- input: processAISDKCallInput(options).input,
14873
- metadata: baseMetadata
14874
- }
16444
+ event: buildAISDKModelStartEvent(
16445
+ callOptions,
16446
+ activeEntry.baseMetadata,
16447
+ {
16448
+ workflowAgent: activeEntry.childTracingOptions.workflowAgent
16449
+ }
16450
+ )
14875
16451
  });
16452
+ activeEntry.openSpans.add(span);
14876
16453
  const streamStartTime = getCurrentUnixTimestamp();
14877
16454
  const result = await withCurrent(
14878
16455
  span,
14879
- () => Reflect.apply(originalDoStream, resolvedModel, [options])
16456
+ () => Reflect.apply(originalDoStream, resolvedModel, [callOptions])
14880
16457
  );
14881
16458
  let firstChunkTime;
14882
16459
  const output = {};
14883
16460
  let text = "";
14884
16461
  let reasoning = "";
14885
- const toolCalls = [];
16462
+ const toolCalls2 = [];
14886
16463
  let object = void 0;
16464
+ let streamSpanEnded = false;
16465
+ const logAndEndStreamSpan = (usageUnavailableReason) => {
16466
+ if (streamSpanEnded) {
16467
+ return;
16468
+ }
16469
+ output.text = text;
16470
+ output.reasoning = reasoning;
16471
+ output.toolCalls = toolCalls2;
16472
+ if (object !== void 0) {
16473
+ output.object = object;
16474
+ }
16475
+ const metrics = extractTokenMetrics(output);
16476
+ if (firstChunkTime !== void 0 && !activeEntry.childTracingOptions.workflowAgent) {
16477
+ metrics.time_to_first_token = Math.max(
16478
+ firstChunkTime - streamStartTime,
16479
+ 1e-6
16480
+ );
16481
+ }
16482
+ const metadataPayload = buildResolvedMetadataPayload(
16483
+ output
16484
+ );
16485
+ const missingUsageMetadata = usageUnavailableReason ? { usage_unavailable_reason: usageUnavailableReason } : buildMissingUsageMetadata(
16486
+ output,
16487
+ metrics,
16488
+ "ai_sdk_result_missing_usage"
16489
+ );
16490
+ span.log({
16491
+ output: processAISDKOutput(
16492
+ output,
16493
+ activeEntry.denyOutputPaths
16494
+ ),
16495
+ metrics,
16496
+ ...mergeMetadataPayload(metadataPayload, missingUsageMetadata)
16497
+ });
16498
+ activeEntry.openSpans.delete(span);
16499
+ span.end();
16500
+ streamSpanEnded = true;
16501
+ };
14887
16502
  const transformStream = new TransformStream({
14888
16503
  transform(chunk, controller) {
14889
16504
  if (firstChunkTime === void 0 && isAISDKContentStreamChunk(chunk)) {
@@ -14901,7 +16516,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
14901
16516
  }
14902
16517
  break;
14903
16518
  case "tool-call":
14904
- toolCalls.push(chunk);
16519
+ toolCalls2.push(chunk);
14905
16520
  break;
14906
16521
  case "object":
14907
16522
  object = chunk.object;
@@ -14921,33 +16536,15 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
14921
16536
  }
14922
16537
  break;
14923
16538
  case "finish":
14924
- output.text = text;
14925
- output.reasoning = reasoning;
14926
- output.toolCalls = toolCalls;
14927
16539
  output.finishReason = chunk.finishReason;
14928
16540
  output.usage = chunk.usage;
14929
- if (object !== void 0) {
14930
- output.object = object;
14931
- }
14932
- const metrics = extractTokenMetrics(output);
14933
- if (firstChunkTime !== void 0) {
14934
- metrics.time_to_first_token = Math.max(
14935
- firstChunkTime - streamStartTime,
14936
- 1e-6
14937
- );
14938
- }
14939
- span.log({
14940
- output: processAISDKOutput(
14941
- output,
14942
- denyOutputPaths
14943
- ),
14944
- metrics,
14945
- ...buildResolvedMetadataPayload(output)
14946
- });
14947
- span.end();
16541
+ logAndEndStreamSpan();
14948
16542
  break;
14949
16543
  }
14950
16544
  controller.enqueue(chunk);
16545
+ },
16546
+ flush() {
16547
+ logAndEndStreamSpan("ai_sdk_stream_finished_without_usage");
14951
16548
  }
14952
16549
  });
14953
16550
  return {
@@ -14957,32 +16554,79 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
14957
16554
  };
14958
16555
  }
14959
16556
  cleanup.push(() => {
14960
- resolvedModel.doGenerate = originalDoGenerate;
14961
- if (originalDoStream) {
14962
- resolvedModel.doStream = originalDoStream;
14963
- }
14964
- delete resolvedModel[AUTO_PATCHED_MODEL];
16557
+ cleanupModelEntry(state, wrappedModelRecord);
14965
16558
  });
14966
- return resolvedModel;
16559
+ patchedModels.set(resolvedModel, wrappedModel);
16560
+ patchedModels.set(wrappedModel, wrappedModel);
16561
+ return wrappedModel;
14967
16562
  };
14968
16563
  const patchTool = (tool, name) => {
14969
- if (tool == null || typeof tool !== "object" || !("execute" in tool) || typeof tool.execute !== "function" || patchedTools.has(tool) || tool[AUTO_PATCHED_TOOL]) {
16564
+ if (tool == null || typeof tool !== "object" || !("execute" in tool) || typeof tool.execute !== "function" || patchedTools.has(tool)) {
14970
16565
  return;
14971
16566
  }
14972
16567
  patchedTools.add(tool);
14973
- tool[AUTO_PATCHED_TOOL] = true;
14974
- const originalExecute = tool.execute;
16568
+ const toolRecord = tool;
16569
+ const entry = {
16570
+ activeSpanIds: /* @__PURE__ */ new Set([parentSpan.spanId]),
16571
+ childTracingOptions,
16572
+ name,
16573
+ parentSpan
16574
+ };
16575
+ const cleanupToolEntry = (state2) => {
16576
+ const index = state2.entries.indexOf(entry);
16577
+ if (index >= 0) {
16578
+ state2.entries.splice(index, 1);
16579
+ }
16580
+ if (state2.entries.length > 0) {
16581
+ return;
16582
+ }
16583
+ tool.execute = state2.originalExecute;
16584
+ delete toolRecord[AUTO_PATCHED_TOOL];
16585
+ };
16586
+ const existingState = toolRecord[AUTO_PATCHED_TOOL];
16587
+ if (existingState) {
16588
+ if (childTracingOptions.agentOwner && attachNestedAISDKChildPatchEntry(
16589
+ existingState.entries,
16590
+ parentSpan,
16591
+ cleanup
16592
+ )) {
16593
+ return;
16594
+ }
16595
+ if (!childTracingOptions.agentOwner) {
16596
+ shadowActiveAISDKChildPatchEntry(
16597
+ existingState.entries,
16598
+ entry,
16599
+ parentSpan,
16600
+ cleanup
16601
+ );
16602
+ }
16603
+ existingState.entries.push(entry);
16604
+ cleanup.push(() => {
16605
+ cleanupToolEntry(existingState);
16606
+ });
16607
+ return;
16608
+ }
16609
+ const originalExecute = toolRecord.execute;
16610
+ const state = {
16611
+ entries: [entry],
16612
+ originalExecute
16613
+ };
16614
+ toolRecord[AUTO_PATCHED_TOOL] = state;
14975
16615
  tool.execute = function executePatched(...args) {
16616
+ const activeEntry = activeAISDKChildPatchEntry(state.entries);
14976
16617
  const result = Reflect.apply(originalExecute, this, args);
16618
+ if (!activeEntry) {
16619
+ return result;
16620
+ }
14977
16621
  if (isAsyncGenerator(result)) {
14978
16622
  return (async function* () {
14979
- const span = parentSpan.startSpan({
14980
- name,
16623
+ const span = activeEntry.parentSpan.startSpan({
16624
+ name: activeEntry.name,
14981
16625
  spanAttributes: {
14982
16626
  type: "tool" /* TOOL */
14983
16627
  }
14984
16628
  });
14985
- span.log({ input: args.length === 1 ? args[0] : args });
16629
+ span.log({ input: serializeToolExecutionInput(args) });
14986
16630
  try {
14987
16631
  let lastValue;
14988
16632
  for await (const value of result) {
@@ -14998,15 +16642,15 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
14998
16642
  }
14999
16643
  })();
15000
16644
  }
15001
- return parentSpan.traced(
16645
+ return activeEntry.parentSpan.traced(
15002
16646
  async (span) => {
15003
- span.log({ input: args.length === 1 ? args[0] : args });
16647
+ span.log({ input: serializeToolExecutionInput(args) });
15004
16648
  const awaitedResult = await result;
15005
16649
  span.log({ output: awaitedResult });
15006
16650
  return awaitedResult;
15007
16651
  },
15008
16652
  {
15009
- name,
16653
+ name: activeEntry.name,
15010
16654
  spanAttributes: {
15011
16655
  type: "tool" /* TOOL */
15012
16656
  }
@@ -15014,8 +16658,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
15014
16658
  );
15015
16659
  };
15016
16660
  cleanup.push(() => {
15017
- tool.execute = originalExecute;
15018
- delete tool[AUTO_PATCHED_TOOL];
16661
+ cleanupToolEntry(state);
15019
16662
  });
15020
16663
  };
15021
16664
  const patchTools = (tools) => {
@@ -15034,25 +16677,42 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
15034
16677
  }
15035
16678
  };
15036
16679
  if (params && typeof params === "object") {
15037
- const patchedParamModel = patchModel(params.model);
15038
- if (typeof params.model === "string" && patchedParamModel && typeof patchedParamModel === "object") {
16680
+ const originalParamModel = params.model;
16681
+ const patchedParamModel = patchModel(originalParamModel);
16682
+ if (patchedParamModel && patchedParamModel !== originalParamModel) {
15039
16683
  params.model = patchedParamModel;
16684
+ cleanup.push(() => {
16685
+ params.model = originalParamModel;
16686
+ });
15040
16687
  }
15041
16688
  patchTools(params.tools);
15042
16689
  }
15043
16690
  if (self && typeof self === "object") {
15044
16691
  const selfRecord = self;
15045
16692
  if (selfRecord.model !== void 0) {
15046
- const patchedSelfModel = patchModel(selfRecord.model);
15047
- if (typeof selfRecord.model === "string" && patchedSelfModel && typeof patchedSelfModel === "object") {
16693
+ const originalSelfModel = selfRecord.model;
16694
+ const patchedSelfModel = patchModel(originalSelfModel);
16695
+ if (patchedSelfModel && patchedSelfModel !== originalSelfModel) {
15048
16696
  selfRecord.model = patchedSelfModel;
16697
+ cleanup.push(() => {
16698
+ selfRecord.model = originalSelfModel;
16699
+ });
15049
16700
  }
15050
16701
  }
16702
+ if (selfRecord.tools !== void 0) {
16703
+ patchTools(selfRecord.tools);
16704
+ }
15051
16705
  if (selfRecord.settings && typeof selfRecord.settings === "object") {
15052
16706
  if (selfRecord.settings.model !== void 0) {
15053
- const patchedSettingsModel = patchModel(selfRecord.settings.model);
15054
- if (typeof selfRecord.settings.model === "string" && patchedSettingsModel && typeof patchedSettingsModel === "object") {
16707
+ const originalSettingsModel = selfRecord.settings.model;
16708
+ const patchedSettingsModel = patchModel(originalSettingsModel);
16709
+ if (patchedSettingsModel && patchedSettingsModel !== originalSettingsModel) {
15055
16710
  selfRecord.settings.model = patchedSettingsModel;
16711
+ cleanup.push(() => {
16712
+ if (selfRecord.settings) {
16713
+ selfRecord.settings.model = originalSettingsModel;
16714
+ }
16715
+ });
15056
16716
  }
15057
16717
  }
15058
16718
  if (selfRecord.settings.tools !== void 0) {
@@ -15149,99 +16809,190 @@ function isAISDKContentAsyncIterableChunk(chunk) {
15149
16809
  return isObject(part) && typeof part.type !== "string";
15150
16810
  }
15151
16811
  function patchAISDKStreamingResult(args) {
15152
- const { defaultDenyOutputPaths, endEvent, result, span, startTime } = args;
16812
+ const {
16813
+ defaultDenyOutputPaths,
16814
+ endEvent,
16815
+ onComplete,
16816
+ result,
16817
+ span,
16818
+ startTime
16819
+ } = args;
15153
16820
  if (!result || typeof result !== "object") {
15154
16821
  return false;
15155
16822
  }
15156
16823
  const resultRecord = result;
15157
16824
  attachKnownResultPromiseHandlers(resultRecord);
16825
+ let finalized = false;
16826
+ const finalize = () => {
16827
+ if (finalized) {
16828
+ return;
16829
+ }
16830
+ finalized = true;
16831
+ finalizeAISDKChildTracing(endEvent);
16832
+ span.end();
16833
+ onComplete?.();
16834
+ };
16835
+ let outputLogged = false;
16836
+ const logStreamingOutput = async (firstChunkTime) => {
16837
+ if (outputLogged) {
16838
+ return;
16839
+ }
16840
+ outputLogged = true;
16841
+ try {
16842
+ const metrics = extractTopLevelAISDKMetrics(result, endEvent);
16843
+ if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
16844
+ metrics.time_to_first_token = firstChunkTime - startTime;
16845
+ }
16846
+ const output = await processAISDKStreamingOutput(
16847
+ result,
16848
+ resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
16849
+ );
16850
+ const metadata = buildResolvedMetadataPayload(result).metadata;
16851
+ span.log({
16852
+ output,
16853
+ ...metadata ? { metadata } : {},
16854
+ metrics
16855
+ });
16856
+ } catch (error) {
16857
+ span.log({ error: toLoggedError(error) });
16858
+ } finally {
16859
+ finalize();
16860
+ }
16861
+ };
16862
+ const createAsyncIterableHooks = () => {
16863
+ let firstChunkTime;
16864
+ return {
16865
+ onChunk: (chunk) => {
16866
+ if (firstChunkTime === void 0 && isAISDKContentAsyncIterableChunk(chunk)) {
16867
+ firstChunkTime = getCurrentUnixTimestamp();
16868
+ }
16869
+ },
16870
+ onComplete: async () => {
16871
+ await logStreamingOutput(firstChunkTime);
16872
+ },
16873
+ onError: (error) => {
16874
+ if (!outputLogged) {
16875
+ outputLogged = true;
16876
+ span.log({
16877
+ error: error.message
16878
+ });
16879
+ }
16880
+ finalize();
16881
+ },
16882
+ onCancel: finalize
16883
+ };
16884
+ };
16885
+ const patchAsyncIterable = (stream) => isReadableStreamLike(stream) ? createPatchedReadableStream(stream, createAsyncIterableHooks()) : createPatchedAsyncIterable(stream, createAsyncIterableHooks());
16886
+ const patchAsyncIterableField = (field) => {
16887
+ let descriptorOwner = resultRecord;
16888
+ let descriptor;
16889
+ while (descriptorOwner) {
16890
+ descriptor = Object.getOwnPropertyDescriptor(descriptorOwner, field);
16891
+ if (descriptor) {
16892
+ break;
16893
+ }
16894
+ descriptorOwner = Object.getPrototypeOf(descriptorOwner);
16895
+ }
16896
+ if (!descriptor || descriptorOwner === resultRecord && !descriptor.configurable) {
16897
+ return false;
16898
+ }
16899
+ if ("value" in descriptor) {
16900
+ if (!isAsyncIterable(descriptor.value)) {
16901
+ return false;
16902
+ }
16903
+ try {
16904
+ Object.defineProperty(resultRecord, field, {
16905
+ configurable: descriptorOwner === resultRecord ? descriptor.configurable : true,
16906
+ enumerable: descriptor.enumerable,
16907
+ value: patchAsyncIterable(descriptor.value),
16908
+ writable: descriptor.writable
16909
+ });
16910
+ return true;
16911
+ } catch {
16912
+ return false;
16913
+ }
16914
+ }
16915
+ if (typeof descriptor.get !== "function") {
16916
+ return false;
16917
+ }
16918
+ const originalGet = descriptor.get;
16919
+ const originalSet = descriptor.set;
16920
+ try {
16921
+ Object.defineProperty(resultRecord, field, {
16922
+ configurable: descriptorOwner === resultRecord ? descriptor.configurable : true,
16923
+ enumerable: descriptor.enumerable,
16924
+ get() {
16925
+ const stream = originalGet.call(this);
16926
+ return isAsyncIterable(stream) ? patchAsyncIterable(stream) : stream;
16927
+ },
16928
+ ...originalSet ? {
16929
+ set(value) {
16930
+ originalSet.call(this, value);
16931
+ }
16932
+ } : {}
16933
+ });
16934
+ return true;
16935
+ } catch {
16936
+ return false;
16937
+ }
16938
+ };
16939
+ let patched = false;
15158
16940
  if (isReadableStreamLike(resultRecord.baseStream)) {
15159
- let firstChunkTime2;
15160
- const wrappedBaseStream = resultRecord.baseStream.pipeThrough(
16941
+ let firstChunkTime;
16942
+ const transformedBaseStream = resultRecord.baseStream.pipeThrough(
15161
16943
  new TransformStream({
15162
16944
  transform(chunk, controller) {
15163
- if (firstChunkTime2 === void 0 && isAISDKContentStreamChunk(chunk)) {
15164
- firstChunkTime2 = getCurrentUnixTimestamp();
16945
+ if (firstChunkTime === void 0 && isAISDKContentStreamChunk(chunk)) {
16946
+ firstChunkTime = getCurrentUnixTimestamp();
15165
16947
  }
15166
16948
  controller.enqueue(chunk);
15167
16949
  },
15168
16950
  async flush() {
15169
- const metrics = extractTopLevelAISDKMetrics(result, endEvent);
15170
- if (metrics.time_to_first_token === void 0 && firstChunkTime2 !== void 0) {
15171
- metrics.time_to_first_token = firstChunkTime2 - startTime;
15172
- }
15173
- const output = await processAISDKStreamingOutput(
15174
- result,
15175
- resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
15176
- );
15177
- const metadata = buildResolvedMetadataPayload(result).metadata;
15178
- span.log({
15179
- output,
15180
- ...metadata ? { metadata } : {},
15181
- metrics
15182
- });
15183
- finalizeAISDKChildTracing(endEvent);
15184
- span.end();
16951
+ await logStreamingOutput(firstChunkTime);
15185
16952
  }
15186
16953
  })
15187
16954
  );
16955
+ const reader = transformedBaseStream.getReader();
16956
+ const wrappedBaseStream = new ReadableStream({
16957
+ async pull(controller) {
16958
+ try {
16959
+ const { done, value } = await reader.read();
16960
+ if (done) {
16961
+ controller.close();
16962
+ return;
16963
+ }
16964
+ controller.enqueue(value);
16965
+ } catch (error) {
16966
+ span.log({ error: toLoggedError(error) });
16967
+ finalize();
16968
+ controller.error(error);
16969
+ }
16970
+ },
16971
+ async cancel(reason) {
16972
+ try {
16973
+ finalize();
16974
+ } finally {
16975
+ await reader.cancel(reason);
16976
+ }
16977
+ }
16978
+ });
15188
16979
  Object.defineProperty(resultRecord, "baseStream", {
15189
16980
  configurable: true,
15190
16981
  enumerable: true,
15191
16982
  value: wrappedBaseStream,
15192
16983
  writable: true
15193
16984
  });
15194
- return true;
16985
+ patched = true;
15195
16986
  }
15196
- const streamField = findAsyncIterableField(resultRecord, [
16987
+ for (const field of [
15197
16988
  "partialObjectStream",
15198
16989
  "textStream",
15199
16990
  "fullStream",
15200
16991
  "stream"
15201
- ]);
15202
- if (!streamField) {
15203
- return false;
16992
+ ]) {
16993
+ patched = patchAsyncIterableField(field) || patched;
15204
16994
  }
15205
- let firstChunkTime;
15206
- const wrappedStream = createPatchedAsyncIterable(streamField.stream, {
15207
- onChunk: (chunk) => {
15208
- if (firstChunkTime === void 0 && isAISDKContentAsyncIterableChunk(chunk)) {
15209
- firstChunkTime = getCurrentUnixTimestamp();
15210
- }
15211
- },
15212
- onComplete: async () => {
15213
- const metrics = extractTopLevelAISDKMetrics(result, endEvent);
15214
- if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
15215
- metrics.time_to_first_token = firstChunkTime - startTime;
15216
- }
15217
- const output = await processAISDKStreamingOutput(
15218
- result,
15219
- resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
15220
- );
15221
- const metadata = buildResolvedMetadataPayload(result).metadata;
15222
- span.log({
15223
- output,
15224
- ...metadata ? { metadata } : {},
15225
- metrics
15226
- });
15227
- finalizeAISDKChildTracing(endEvent);
15228
- span.end();
15229
- },
15230
- onError: (error) => {
15231
- span.log({
15232
- error: error.message
15233
- });
15234
- finalizeAISDKChildTracing(endEvent);
15235
- span.end();
15236
- }
15237
- });
15238
- Object.defineProperty(resultRecord, streamField.field, {
15239
- configurable: true,
15240
- enumerable: true,
15241
- value: wrappedStream,
15242
- writable: true
15243
- });
15244
- return true;
16995
+ return patched;
15245
16996
  }
15246
16997
  function attachKnownResultPromiseHandlers(result) {
15247
16998
  const promiseLikeFields = [
@@ -15273,34 +17024,72 @@ function attachKnownResultPromiseHandlers(result) {
15273
17024
  }
15274
17025
  }
15275
17026
  function isReadableStreamLike(value) {
15276
- return value != null && typeof value === "object" && typeof value.pipeThrough === "function";
15277
- }
15278
- function findAsyncIterableField(result, candidateFields) {
15279
- for (const field of candidateFields) {
15280
- try {
15281
- const stream = result[field];
15282
- if (isAsyncIterable(stream)) {
15283
- return { field, stream };
17027
+ return value != null && typeof value === "object" && typeof value.getReader === "function" && typeof value.pipeThrough === "function";
17028
+ }
17029
+ function createPatchedReadableStream(stream, hooks) {
17030
+ let reader;
17031
+ let completed = false;
17032
+ return new ReadableStream({
17033
+ async pull(controller) {
17034
+ reader ??= stream.getReader();
17035
+ try {
17036
+ const { done, value } = await reader.read();
17037
+ if (done) {
17038
+ completed = true;
17039
+ await hooks.onComplete();
17040
+ controller.close();
17041
+ return;
17042
+ }
17043
+ hooks.onChunk(value);
17044
+ controller.enqueue(value);
17045
+ } catch (error) {
17046
+ completed = true;
17047
+ hooks.onError(
17048
+ error instanceof Error ? error : new Error(String(error))
17049
+ );
17050
+ controller.error(error);
17051
+ }
17052
+ },
17053
+ async cancel(reason) {
17054
+ if (!completed) {
17055
+ completed = true;
17056
+ try {
17057
+ await hooks.onCancel?.();
17058
+ } catch {
17059
+ }
17060
+ }
17061
+ if (reader) {
17062
+ await reader.cancel(reason);
17063
+ } else if (stream.cancel) {
17064
+ await stream.cancel(reason);
15284
17065
  }
15285
- } catch {
15286
17066
  }
15287
- }
15288
- return null;
17067
+ });
15289
17068
  }
15290
17069
  function createPatchedAsyncIterable(stream, hooks) {
15291
17070
  return {
15292
17071
  async *[Symbol.asyncIterator]() {
17072
+ let completed = false;
15293
17073
  try {
15294
17074
  for await (const chunk of stream) {
15295
17075
  hooks.onChunk(chunk);
15296
17076
  yield chunk;
15297
17077
  }
17078
+ completed = true;
15298
17079
  await hooks.onComplete();
15299
17080
  } catch (error) {
17081
+ completed = true;
15300
17082
  hooks.onError(
15301
17083
  error instanceof Error ? error : new Error(String(error))
15302
17084
  );
15303
17085
  throw error;
17086
+ } finally {
17087
+ if (!completed) {
17088
+ try {
17089
+ await hooks.onCancel?.();
17090
+ } catch {
17091
+ }
17092
+ }
15304
17093
  }
15305
17094
  }
15306
17095
  };
@@ -15375,6 +17164,40 @@ function buildResolvedMetadataPayload(result) {
15375
17164
  }
15376
17165
  return Object.keys(metadata).length > 0 ? { metadata } : {};
15377
17166
  }
17167
+ function mergeMetadataPayload(metadataPayload, extraMetadata) {
17168
+ if (!extraMetadata || Object.keys(extraMetadata).length === 0) {
17169
+ return metadataPayload;
17170
+ }
17171
+ return {
17172
+ metadata: {
17173
+ ...metadataPayload.metadata ?? {},
17174
+ ...extraMetadata
17175
+ }
17176
+ };
17177
+ }
17178
+ function buildMissingUsageMetadata(output, metrics, reason) {
17179
+ if (!hasLoggedOutput(output) || hasTokenUsageMetrics(metrics)) {
17180
+ return void 0;
17181
+ }
17182
+ return { usage_unavailable_reason: reason };
17183
+ }
17184
+ function hasLoggedOutput(output) {
17185
+ if (output === null || output === void 0) {
17186
+ return false;
17187
+ }
17188
+ if (Array.isArray(output)) {
17189
+ return output.length > 0;
17190
+ }
17191
+ if (typeof output === "object") {
17192
+ return Object.keys(output).length > 0;
17193
+ }
17194
+ return true;
17195
+ }
17196
+ function hasTokenUsageMetrics(metrics) {
17197
+ return Object.keys(metrics).some(
17198
+ (key) => key !== "estimated_cost" && key !== "time_to_first_token"
17199
+ );
17200
+ }
15378
17201
  function resolveAISDKModel(model, aiSDK) {
15379
17202
  if (typeof model !== "string") {
15380
17203
  return model;
@@ -15398,7 +17221,45 @@ function isAsyncGenerator(value) {
15398
17221
  function processAISDKOutput(output, denyOutputPaths) {
15399
17222
  if (!output) return output;
15400
17223
  const merged = extractSerializableOutputFields(output);
15401
- return normalizeAISDKLoggedOutput(omit(merged, denyOutputPaths));
17224
+ const deleteOutputPaths = denyOutputPaths.filter(
17225
+ (path) => path.toLowerCase().endsWith("headers")
17226
+ );
17227
+ const sanitized = omit(merged, denyOutputPaths, deleteOutputPaths);
17228
+ for (const path of TRANSPORT_PAYLOAD_ROOT_PATHS) {
17229
+ const stack = [{ obj: sanitized, keys: parsePath(path) }];
17230
+ while (stack.length > 0) {
17231
+ const entry = stack.pop();
17232
+ if (!entry || entry.keys.length === 0) {
17233
+ continue;
17234
+ }
17235
+ const firstKey = entry.keys[0];
17236
+ const remainingKeys = entry.keys.slice(1);
17237
+ if (firstKey === "[]") {
17238
+ if (Array.isArray(entry.obj)) {
17239
+ for (const item of entry.obj) {
17240
+ stack.push({
17241
+ obj: item,
17242
+ keys: remainingKeys
17243
+ });
17244
+ }
17245
+ }
17246
+ continue;
17247
+ }
17248
+ if (!entry.obj || typeof entry.obj !== "object" || !(firstKey in entry.obj)) {
17249
+ continue;
17250
+ }
17251
+ const record = entry.obj;
17252
+ if (remainingKeys.length === 0) {
17253
+ record[firstKey] = sanitizeAISDKMetadataValue(record[firstKey]);
17254
+ continue;
17255
+ }
17256
+ stack.push({
17257
+ obj: record[firstKey],
17258
+ keys: remainingKeys
17259
+ });
17260
+ }
17261
+ }
17262
+ return normalizeAISDKLoggedOutput(sanitized);
15402
17263
  }
15403
17264
  function processAISDKEmbeddingOutput(output, denyOutputPaths) {
15404
17265
  if (!output || typeof output !== "object") {
@@ -15489,6 +17350,8 @@ function extractTokenMetrics(result) {
15489
17350
  );
15490
17351
  if (totalTokens !== void 0) {
15491
17352
  metrics.tokens = totalTokens;
17353
+ } else if (promptTokens !== void 0 && completionTokens !== void 0) {
17354
+ metrics.tokens = promptTokens + completionTokens;
15492
17355
  }
15493
17356
  const promptCachedTokens = firstNumber2(
15494
17357
  usage.inputTokens?.cacheRead,
@@ -15600,9 +17463,9 @@ function aggregateAISDKChunks(chunks, _result, endEvent) {
15600
17463
  if (finishReason !== void 0) {
15601
17464
  output.finishReason = finishReason;
15602
17465
  }
15603
- const toolCalls = safeSerializableFieldRead(lastChunk, "toolCalls");
15604
- if (toolCalls !== void 0) {
15605
- output.toolCalls = toolCalls;
17466
+ const toolCalls2 = safeSerializableFieldRead(lastChunk, "toolCalls");
17467
+ if (toolCalls2 !== void 0) {
17468
+ output.toolCalls = toolCalls2;
15606
17469
  }
15607
17470
  }
15608
17471
  finalizeAISDKChildTracing(endEvent);
@@ -15612,7 +17475,9 @@ function extractGetterValues(obj) {
15612
17475
  const getterValues = {};
15613
17476
  const getterNames = [
15614
17477
  "content",
17478
+ "messages",
15615
17479
  "text",
17480
+ "output",
15616
17481
  "object",
15617
17482
  "value",
15618
17483
  "values",
@@ -15652,7 +17517,9 @@ function extractGetterValues(obj) {
15652
17517
  function extractSerializableOutputFields(output) {
15653
17518
  const serialized = {};
15654
17519
  const directFieldNames = [
17520
+ "messages",
15655
17521
  "steps",
17522
+ "output",
15656
17523
  "request",
15657
17524
  "responseMessages",
15658
17525
  "warnings",
@@ -15834,7 +17701,7 @@ function parsePath(path) {
15834
17701
  }
15835
17702
  return keys;
15836
17703
  }
15837
- function omitAtPath(obj, keys) {
17704
+ function omitAtPath(obj, keys, deleteLeaf = false) {
15838
17705
  if (keys.length === 0) return;
15839
17706
  const firstKey = keys[0];
15840
17707
  const remainingKeys = keys.slice(1);
@@ -15844,29 +17711,36 @@ function omitAtPath(obj, keys) {
15844
17711
  if (remainingKeys.length > 0) {
15845
17712
  omitAtPath(
15846
17713
  item,
15847
- remainingKeys
17714
+ remainingKeys,
17715
+ deleteLeaf
15848
17716
  );
15849
17717
  }
15850
17718
  });
15851
17719
  }
15852
17720
  } else if (remainingKeys.length === 0) {
15853
17721
  if (obj && typeof obj === "object" && firstKey in obj) {
15854
- obj[firstKey] = "<omitted>";
17722
+ if (deleteLeaf) {
17723
+ delete obj[firstKey];
17724
+ } else {
17725
+ obj[firstKey] = "<omitted>";
17726
+ }
15855
17727
  }
15856
17728
  } else {
15857
17729
  if (obj && typeof obj === "object" && firstKey in obj) {
15858
17730
  omitAtPath(
15859
17731
  obj[firstKey],
15860
- remainingKeys
17732
+ remainingKeys,
17733
+ deleteLeaf
15861
17734
  );
15862
17735
  }
15863
17736
  }
15864
17737
  }
15865
- function omit(obj, paths) {
17738
+ function omit(obj, paths, deletePaths = []) {
15866
17739
  const result = deepCopy(obj);
17740
+ const deletePathSet = new Set(deletePaths);
15867
17741
  for (const path of paths) {
15868
17742
  const keys = parsePath(path);
15869
- omitAtPath(result, keys);
17743
+ omitAtPath(result, keys, deletePathSet.has(path));
15870
17744
  }
15871
17745
  return result;
15872
17746
  }
@@ -20075,8 +21949,8 @@ function getChatToolCallDeltas(value) {
20075
21949
  if (!Array.isArray(value?.tool_calls)) {
20076
21950
  return void 0;
20077
21951
  }
20078
- const toolCalls = value.tool_calls.filter((toolCall) => isObject(toolCall));
20079
- return toolCalls.length > 0 ? toolCalls : void 0;
21952
+ const toolCalls2 = value.tool_calls.filter((toolCall) => isObject(toolCall));
21953
+ return toolCalls2.length > 0 ? toolCalls2 : void 0;
20080
21954
  }
20081
21955
  function mergeChatToolCallDeltas(toolCallsByIndex, toolCallDeltas) {
20082
21956
  for (const toolDelta of toolCallDeltas) {
@@ -21565,7 +23439,7 @@ function aggregateOpenRouterChatChunks(chunks) {
21565
23439
  let reasoningContent = "";
21566
23440
  let hasReasoningContent = false;
21567
23441
  let reasoningDetails;
21568
- let toolCalls;
23442
+ let toolCalls2;
21569
23443
  let finishReason;
21570
23444
  let metrics = {};
21571
23445
  for (const chunk of chunks) {
@@ -21618,9 +23492,9 @@ function aggregateOpenRouterChatChunks(chunks) {
21618
23492
  continue;
21619
23493
  }
21620
23494
  const toolIndex = toolDelta.index ?? 0;
21621
- const existingToolCall = toolCalls?.[toolIndex];
23495
+ const existingToolCall = toolCalls2?.[toolIndex];
21622
23496
  if (!existingToolCall || toolDelta.id && existingToolCall.id !== void 0 && existingToolCall.id !== toolDelta.id) {
21623
- const nextToolCalls = [...toolCalls || []];
23497
+ const nextToolCalls = [...toolCalls2 || []];
21624
23498
  nextToolCalls[toolIndex] = {
21625
23499
  index: toolIndex,
21626
23500
  id: toolDelta.id,
@@ -21630,7 +23504,7 @@ function aggregateOpenRouterChatChunks(chunks) {
21630
23504
  arguments: toolDelta.function.arguments || ""
21631
23505
  }
21632
23506
  };
21633
- toolCalls = nextToolCalls;
23507
+ toolCalls2 = nextToolCalls;
21634
23508
  continue;
21635
23509
  }
21636
23510
  const current = existingToolCall;
@@ -21656,7 +23530,7 @@ function aggregateOpenRouterChatChunks(chunks) {
21656
23530
  ...hasReasoning || hasReasoningContent ? { reasoning } : {},
21657
23531
  ...hasReasoningContent ? { reasoning_content: reasoningContent } : {},
21658
23532
  ...reasoningDetails ? { reasoning_details: reasoningDetails } : {},
21659
- ...toolCalls ? { tool_calls: toolCalls } : {}
23533
+ ...toolCalls2 ? { tool_calls: toolCalls2 } : {}
21660
23534
  },
21661
23535
  logprobs: null,
21662
23536
  finish_reason: finishReason
@@ -22501,8 +24375,8 @@ function appendMistralContent(accumulator, content) {
22501
24375
  delete accumulator.content;
22502
24376
  }
22503
24377
  function getDeltaToolCalls(delta) {
22504
- const toolCalls = Array.isArray(delta.toolCalls) && delta.toolCalls || Array.isArray(delta.tool_calls) && delta.tool_calls || [];
22505
- return toolCalls.filter((toolCall) => isObject(toolCall));
24378
+ const toolCalls2 = Array.isArray(delta.toolCalls) && delta.toolCalls || Array.isArray(delta.tool_calls) && delta.tool_calls || [];
24379
+ return toolCalls2.filter((toolCall) => isObject(toolCall));
22506
24380
  }
22507
24381
  function getToolCallIndex(toolCall) {
22508
24382
  return typeof toolCall.index === "number" && toolCall.index >= 0 ? toolCall.index : void 0;
@@ -22529,11 +24403,11 @@ function mergeToolCallDeltaPair(current, delta) {
22529
24403
  }
22530
24404
  };
22531
24405
  }
22532
- function mergeToolCallDeltas(toolCalls, deltas) {
24406
+ function mergeToolCallDeltas(toolCalls2, deltas) {
22533
24407
  if (deltas.length === 0) {
22534
- return toolCalls;
24408
+ return toolCalls2;
22535
24409
  }
22536
- const merged = toolCalls ? [...toolCalls] : [];
24410
+ const merged = toolCalls2 ? [...toolCalls2] : [];
22537
24411
  const indexToPosition = /* @__PURE__ */ new Map();
22538
24412
  const idToPosition = /* @__PURE__ */ new Map();
22539
24413
  for (const [position, toolCall] of merged.entries()) {
@@ -23604,12 +25478,12 @@ function extractCohereChatOutput(result) {
23604
25478
  if (typeof result.text !== "string") {
23605
25479
  return void 0;
23606
25480
  }
23607
- const toolCalls = Array.isArray(result.toolCalls) ? result.toolCalls : Array.isArray(result.tool_calls) ? result.tool_calls : void 0;
23608
- if (toolCalls && toolCalls.length > 0) {
25481
+ const toolCalls2 = Array.isArray(result.toolCalls) ? result.toolCalls : Array.isArray(result.tool_calls) ? result.tool_calls : void 0;
25482
+ if (toolCalls2 && toolCalls2.length > 0) {
23609
25483
  return {
23610
25484
  content: result.text,
23611
25485
  role: "assistant",
23612
- toolCalls
25486
+ toolCalls: toolCalls2
23613
25487
  };
23614
25488
  }
23615
25489
  return result.text;
@@ -23942,10 +25816,10 @@ function aggregateCohereChatStreamChunks(chunks) {
23942
25816
  continue;
23943
25817
  }
23944
25818
  if (eventType === "tool-call-start") {
23945
- const toolCalls = isObject(chunk.delta) && isObject(chunk.delta.message) ? toToolCallArray(
25819
+ const toolCalls2 = isObject(chunk.delta) && isObject(chunk.delta.message) ? toToolCallArray(
23946
25820
  Array.isArray(chunk.delta.message.toolCalls) ? chunk.delta.message.toolCalls : chunk.delta.message.toolCalls ?? chunk.delta.message.tool_calls
23947
25821
  ) : [];
23948
- for (const [index, toolCall] of toolCalls.entries()) {
25822
+ for (const [index, toolCall] of toolCalls2.entries()) {
23949
25823
  const normalizedIndex = getToolCallIndex2(
23950
25824
  toolCall,
23951
25825
  typeof chunk.index === "number" ? chunk.index : index
@@ -28020,14 +29894,14 @@ function normalizeAssistantMessage(message) {
28020
29894
  const thinking = message.content.flatMap(
28021
29895
  (part) => part.type === "thinking" && !part.redacted ? [part.thinking] : []
28022
29896
  ).join("");
28023
- const toolCalls = message.content.flatMap(
29897
+ const toolCalls2 = message.content.flatMap(
28024
29898
  (part) => part.type === "toolCall" ? [normalizeToolCall(part)] : []
28025
29899
  );
28026
29900
  return {
28027
29901
  role: "assistant",
28028
- content: text || (toolCalls.length > 0 ? null : ""),
29902
+ content: text || (toolCalls2.length > 0 ? null : ""),
28029
29903
  ...thinking ? { reasoning: thinking } : {},
28030
- ...toolCalls.length > 0 ? { tool_calls: toolCalls } : {}
29904
+ ...toolCalls2.length > 0 ? { tool_calls: toolCalls2 } : {}
28031
29905
  };
28032
29906
  }
28033
29907
  function normalizeToolResultMessage(message) {
@@ -29610,8 +31484,10 @@ var exports_exports = {};
29610
31484
  __export(exports_exports, {
29611
31485
  Attachment: () => Attachment,
29612
31486
  AttachmentReference: () => AttachmentReference,
31487
+ BAGGAGE_HEADER: () => BAGGAGE_HEADER,
29613
31488
  BRAINTRUST_CURRENT_SPAN_STORE: () => BRAINTRUST_CURRENT_SPAN_STORE,
29614
31489
  BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME: () => BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME,
31490
+ BRAINTRUST_PARENT_KEY: () => BRAINTRUST_PARENT_KEY,
29615
31491
  BaseAttachment: () => BaseAttachment,
29616
31492
  BaseExperiment: () => BaseExperiment,
29617
31493
  BraintrustLangChainCallbackHandler: () => BraintrustLangChainCallbackHandler,
@@ -29644,6 +31520,7 @@ __export(exports_exports, {
29644
31520
  NOOP_SPAN: () => NOOP_SPAN,
29645
31521
  NOOP_SPAN_PERMALINK: () => NOOP_SPAN_PERMALINK,
29646
31522
  NoopSpan: () => NoopSpan,
31523
+ OTELIDGenerator: () => OTELIDGenerator,
29647
31524
  ObjectFetcher: () => ObjectFetcher,
29648
31525
  Project: () => Project2,
29649
31526
  ProjectNameIdMap: () => ProjectNameIdMap,
@@ -29655,6 +31532,8 @@ __export(exports_exports, {
29655
31532
  ScorerBuilder: () => ScorerBuilder,
29656
31533
  SpanFetcher: () => SpanFetcher,
29657
31534
  SpanImpl: () => SpanImpl,
31535
+ TRACEPARENT_HEADER: () => TRACEPARENT_HEADER,
31536
+ TRACESTATE_HEADER: () => TRACESTATE_HEADER,
29658
31537
  TestBackgroundLogger: () => TestBackgroundLogger,
29659
31538
  ToolBuilder: () => ToolBuilder,
29660
31539
  UUIDGenerator: () => UUIDGenerator,
@@ -29664,6 +31543,7 @@ __export(exports_exports, {
29664
31543
  _internalIso: () => isomorph_default,
29665
31544
  _internalSetInitialState: () => _internalSetInitialState,
29666
31545
  addAzureBlobHeaders: () => addAzureBlobHeaders,
31546
+ agentAssertionScorer: () => agentAssertionScorer,
29667
31547
  braintrustAISDKTelemetry: () => braintrustAISDKTelemetry,
29668
31548
  braintrustFlueInstrumentation: () => braintrustFlueInstrumentation,
29669
31549
  braintrustFlueObserver: () => braintrustFlueObserver,
@@ -29681,6 +31561,7 @@ __export(exports_exports, {
29681
31561
  devNullWritableStream: () => devNullWritableStream,
29682
31562
  evaluatorDefinitionSchema: () => evaluatorDefinitionSchema,
29683
31563
  evaluatorDefinitionsSchema: () => evaluatorDefinitionsSchema,
31564
+ extractTraceContextFromHeaders: () => extractTraceContextFromHeaders,
29684
31565
  flush: () => flush,
29685
31566
  getContextManager: () => getContextManager,
29686
31567
  getIdGenerator: () => getIdGenerator,
@@ -29694,6 +31575,7 @@ __export(exports_exports, {
29694
31575
  initFunction: () => initFunction,
29695
31576
  initLogger: () => initLogger,
29696
31577
  initNodeTestSuite: () => initNodeTestSuite,
31578
+ injectTraceContext: () => injectTraceContext,
29697
31579
  invoke: () => invoke,
29698
31580
  isTemplateFormat: () => isTemplateFormat,
29699
31581
  loadParameters: () => loadParameters,
@@ -29732,7 +31614,7 @@ __export(exports_exports, {
29732
31614
  traced: () => traced,
29733
31615
  updateSpan: () => updateSpan,
29734
31616
  uploadLogs3OverflowPayload: () => uploadLogs3OverflowPayload,
29735
- utf8ByteLength: () => utf8ByteLength,
31617
+ utf8ByteLength: () => utf8ByteLength2,
29736
31618
  withCurrent: () => withCurrent,
29737
31619
  withDataset: () => withDataset,
29738
31620
  withExperiment: () => withExperiment,
@@ -30325,6 +32207,7 @@ function wrapAISDK(aiSDK, options = {}) {
30325
32207
  case "Agent":
30326
32208
  case "Experimental_Agent":
30327
32209
  case "ToolLoopAgent":
32210
+ case "WorkflowAgent":
30328
32211
  return original ? wrapAgentClass(original, options) : original;
30329
32212
  }
30330
32213
  return original;
@@ -30343,10 +32226,10 @@ var wrapAgentClass = (AgentClass, options = {}) => {
30343
32226
  return new Proxy(instance, {
30344
32227
  get(instanceTarget, prop, instanceReceiver) {
30345
32228
  const original = Reflect.get(instanceTarget, prop, instanceTarget);
30346
- if (prop === "generate") {
32229
+ if (prop === "generate" && typeof original === "function" && instanceTarget.constructor.name !== "WorkflowAgent") {
30347
32230
  return wrapAgentGenerate(original, instanceTarget, options);
30348
32231
  }
30349
- if (prop === "stream") {
32232
+ if (prop === "stream" && typeof original === "function") {
30350
32233
  return wrapAgentStream(original, instanceTarget, options);
30351
32234
  }
30352
32235
  if (typeof original === "function") {
@@ -30361,7 +32244,7 @@ var wrapAgentClass = (AgentClass, options = {}) => {
30361
32244
  var wrapAgentGenerate = (generate, instance, options = {}) => {
30362
32245
  const defaultName = `${instance.constructor.name}.generate`;
30363
32246
  return async (params) => makeGenerateTextWrapper(
30364
- aiSDKChannels.generateText,
32247
+ generateChannelForAgent(instance.constructor.name),
30365
32248
  defaultName,
30366
32249
  generate.bind(instance),
30367
32250
  {
@@ -30371,19 +32254,42 @@ var wrapAgentGenerate = (generate, instance, options = {}) => {
30371
32254
  options
30372
32255
  )({ ...instance.settings, ...params });
30373
32256
  };
32257
+ function generateChannelForAgent(agentName) {
32258
+ if (agentName === "ToolLoopAgent") {
32259
+ return aiSDKChannels.toolLoopAgentGenerate;
32260
+ }
32261
+ return aiSDKChannels.agentGenerate;
32262
+ }
30374
32263
  var wrapAgentStream = (stream, instance, options = {}) => {
30375
32264
  const defaultName = `${instance.constructor.name}.stream`;
30376
- return (params) => makeStreamWrapper(
30377
- aiSDKChannels.agentStream,
30378
- defaultName,
30379
- stream.bind(instance),
30380
- {
30381
- self: instance,
30382
- spanType: "function" /* FUNCTION */
30383
- },
30384
- options
30385
- )({ ...instance.settings, ...params });
32265
+ return (params) => {
32266
+ const workflowAgent = instance.constructor.name === "WorkflowAgent";
32267
+ if (workflowAgent && currentWorkflowAgentWrapperSpan()) {
32268
+ const { span_info: _spanInfo, ...cleanParams } = params;
32269
+ return stream.call(instance, { ...instance.settings, ...cleanParams });
32270
+ }
32271
+ const trace = () => makeStreamWrapper(
32272
+ streamChannelForAgent(instance.constructor.name),
32273
+ defaultName,
32274
+ stream.bind(instance),
32275
+ {
32276
+ self: instance,
32277
+ spanType: "function" /* FUNCTION */
32278
+ },
32279
+ options
32280
+ )({ ...instance.settings, ...params });
32281
+ return trace();
32282
+ };
30386
32283
  };
32284
+ function streamChannelForAgent(agentName) {
32285
+ if (agentName === "ToolLoopAgent") {
32286
+ return aiSDKChannels.toolLoopAgentStream;
32287
+ }
32288
+ if (agentName === "WorkflowAgent") {
32289
+ return aiSDKChannels.workflowAgentStream;
32290
+ }
32291
+ return aiSDKChannels.agentStream;
32292
+ }
30387
32293
  var makeGenerateTextWrapper = (channel2, name, generateText, contextOptions = {}, options = {}) => {
30388
32294
  const wrapper = async function(allParams) {
30389
32295
  const { span_info, ...params } = allParams;
@@ -30645,7 +32551,7 @@ var BraintrustLanguageModelWrapper = class {
30645
32551
  let time_to_first_token = void 0;
30646
32552
  let usage = void 0;
30647
32553
  let fullText = void 0;
30648
- const toolCalls = {};
32554
+ const toolCalls2 = {};
30649
32555
  let finishReason = void 0;
30650
32556
  return {
30651
32557
  ...ret,
@@ -30664,7 +32570,7 @@ var BraintrustLanguageModelWrapper = class {
30664
32570
  fullText += chunk.textDelta;
30665
32571
  break;
30666
32572
  case "tool-call":
30667
- toolCalls[chunk.toolCallId] = {
32573
+ toolCalls2[chunk.toolCallId] = {
30668
32574
  toolCallType: chunk.toolCallType,
30669
32575
  toolCallId: chunk.toolCallId,
30670
32576
  toolName: chunk.toolName,
@@ -30672,15 +32578,15 @@ var BraintrustLanguageModelWrapper = class {
30672
32578
  };
30673
32579
  break;
30674
32580
  case "tool-call-delta":
30675
- if (toolCalls[chunk.toolCallId] === void 0) {
30676
- toolCalls[chunk.toolCallId] = {
32581
+ if (toolCalls2[chunk.toolCallId] === void 0) {
32582
+ toolCalls2[chunk.toolCallId] = {
30677
32583
  toolCallType: chunk.toolCallType,
30678
32584
  toolCallId: chunk.toolCallId,
30679
32585
  toolName: chunk.toolName,
30680
32586
  args: ""
30681
32587
  };
30682
32588
  }
30683
- toolCalls[chunk.toolCallId].args += chunk.argsTextDelta;
32589
+ toolCalls2[chunk.toolCallId].args += chunk.argsTextDelta;
30684
32590
  break;
30685
32591
  case "finish":
30686
32592
  usage = chunk.usage;
@@ -30693,7 +32599,7 @@ var BraintrustLanguageModelWrapper = class {
30693
32599
  span.log({
30694
32600
  output: postProcessOutput(
30695
32601
  fullText,
30696
- Object.keys(toolCalls).length > 0 ? Object.values(toolCalls) : void 0,
32602
+ Object.keys(toolCalls2).length > 0 ? Object.values(toolCalls2) : void 0,
30697
32603
  finishReason
30698
32604
  ),
30699
32605
  metrics: {
@@ -30794,15 +32700,15 @@ function postProcessPrompt(prompt) {
30794
32700
  }
30795
32701
  });
30796
32702
  }
30797
- function postProcessOutput(text, toolCalls, finishReason) {
32703
+ function postProcessOutput(text, toolCalls2, finishReason) {
30798
32704
  return [
30799
32705
  {
30800
32706
  index: 0,
30801
32707
  message: {
30802
32708
  role: "assistant",
30803
32709
  content: text ?? "",
30804
- ...toolCalls && toolCalls.length > 0 ? {
30805
- tool_calls: toolCalls.map((toolCall) => ({
32710
+ ...toolCalls2 && toolCalls2.length > 0 ? {
32711
+ tool_calls: toolCalls2.map((toolCall) => ({
30806
32712
  id: toolCall.toolCallId,
30807
32713
  function: {
30808
32714
  name: toolCall.toolName,
@@ -30901,29 +32807,29 @@ function normalizeFinishReason(reason) {
30901
32807
  if (typeof reason !== "string") return void 0;
30902
32808
  return reason.replace(/-/g, "_");
30903
32809
  }
30904
- function buildAssistantOutputWithToolCalls(result, toolCalls) {
32810
+ function buildAssistantOutputWithToolCalls(result, toolCalls2) {
30905
32811
  return [
30906
32812
  {
30907
32813
  index: 0,
30908
32814
  logprobs: null,
30909
- finish_reason: normalizeFinishReason(result?.finishReason) ?? (toolCalls.length ? "tool_calls" : void 0),
32815
+ finish_reason: normalizeFinishReason(result?.finishReason) ?? (toolCalls2.length ? "tool_calls" : void 0),
30910
32816
  message: {
30911
32817
  role: "assistant",
30912
- tool_calls: toolCalls.length > 0 ? toolCalls : void 0
32818
+ tool_calls: toolCalls2.length > 0 ? toolCalls2 : void 0
30913
32819
  }
30914
32820
  }
30915
32821
  ];
30916
32822
  }
30917
32823
  function extractToolCallsFromSteps(steps) {
30918
- const toolCalls = [];
30919
- if (!Array.isArray(steps)) return toolCalls;
32824
+ const toolCalls2 = [];
32825
+ if (!Array.isArray(steps)) return toolCalls2;
30920
32826
  let idx = 0;
30921
32827
  for (const step of steps) {
30922
32828
  const blocks = step?.content;
30923
32829
  if (!Array.isArray(blocks)) continue;
30924
32830
  for (const block of blocks) {
30925
32831
  if (block && typeof block === "object" && block.type === "tool-call") {
30926
- toolCalls.push({
32832
+ toolCalls2.push({
30927
32833
  id: block.toolCallId,
30928
32834
  type: "function",
30929
32835
  index: idx++,
@@ -30935,7 +32841,7 @@ function extractToolCallsFromSteps(steps) {
30935
32841
  }
30936
32842
  }
30937
32843
  }
30938
- return toolCalls;
32844
+ return toolCalls2;
30939
32845
  }
30940
32846
  function extractToolCallsFromBlocks(blocks) {
30941
32847
  if (!Array.isArray(blocks)) return [];
@@ -31001,12 +32907,12 @@ function BraintrustMiddleware(config = {}) {
31001
32907
  metadata.model = modelId;
31002
32908
  }
31003
32909
  }
31004
- let toolCalls = extractToolCallsFromSteps(result?.steps);
31005
- if (!toolCalls || toolCalls.length === 0) {
31006
- toolCalls = extractToolCallsFromBlocks(result?.content);
32910
+ let toolCalls2 = extractToolCallsFromSteps(result?.steps);
32911
+ if (!toolCalls2 || toolCalls2.length === 0) {
32912
+ toolCalls2 = extractToolCallsFromBlocks(result?.content);
31007
32913
  }
31008
32914
  span.log({
31009
- output: toolCalls.length > 0 ? buildAssistantOutputWithToolCalls(result, toolCalls) : result?.content,
32915
+ output: toolCalls2.length > 0 ? buildAssistantOutputWithToolCalls(result, toolCalls2) : result?.content,
31010
32916
  metadata,
31011
32917
  metrics: normalizeUsageMetrics(
31012
32918
  result.usage,
@@ -31095,13 +33001,13 @@ function BraintrustMiddleware(config = {}) {
31095
33001
  metadata.model = model;
31096
33002
  }
31097
33003
  if (toolBlocks.length > 0) {
31098
- const toolCalls = extractToolCallsFromSteps([
33004
+ const toolCalls2 = extractToolCallsFromSteps([
31099
33005
  { content: toolBlocks }
31100
33006
  ]);
31101
- if (toolCalls.length > 0) {
33007
+ if (toolCalls2.length > 0) {
31102
33008
  output = buildAssistantOutputWithToolCalls(
31103
33009
  resultForDetection,
31104
- toolCalls
33010
+ toolCalls2
31105
33011
  );
31106
33012
  }
31107
33013
  }
@@ -31736,9 +33642,9 @@ function isModuleNamespace3(obj) {
31736
33642
  const descriptor = Object.getOwnPropertyDescriptor(obj, keys[0]);
31737
33643
  return descriptor ? !descriptor.configurable && !descriptor.writable : false;
31738
33644
  }
31739
- function wrapCursorAgentClass(Agent) {
33645
+ function wrapCursorAgentClass(Agent2) {
31740
33646
  const cache = /* @__PURE__ */ new Map();
31741
- return new Proxy(Agent, {
33647
+ return new Proxy(Agent2, {
31742
33648
  get(target, prop, receiver) {
31743
33649
  if (cache.has(prop)) {
31744
33650
  return cache.get(prop);
@@ -35286,15 +37192,21 @@ var waterfall$1 = awaitify(waterfall);
35286
37192
 
35287
37193
  // src/trace.ts
35288
37194
  var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
35289
- constructor(objectType, _objectId, rootSpanId, _state, spanTypeFilter, includeScorers = false) {
37195
+ constructor(objectType, _objectId, rootSpanId, _state, spanTypeFilter, includeScorers = false, brainstoreRealtime = true) {
35290
37196
  const filterExpr = _SpanFetcher.buildFilter(
35291
37197
  rootSpanId,
35292
37198
  spanTypeFilter,
35293
37199
  includeScorers
35294
37200
  );
35295
- super(objectType, void 0, void 0, {
35296
- filter: filterExpr
35297
- });
37201
+ super(
37202
+ objectType,
37203
+ void 0,
37204
+ void 0,
37205
+ {
37206
+ filter: filterExpr
37207
+ },
37208
+ brainstoreRealtime
37209
+ );
35298
37210
  this._objectId = _objectId;
35299
37211
  this.rootSpanId = rootSpanId;
35300
37212
  this._state = _state;
@@ -35348,7 +37260,7 @@ var CachedSpanFetcher = class {
35348
37260
  spanCache = /* @__PURE__ */ new Map();
35349
37261
  allFetched = false;
35350
37262
  fetchFn;
35351
- constructor(objectTypeOrFetchFn, objectId, rootSpanId, getState) {
37263
+ constructor(objectTypeOrFetchFn, objectId, rootSpanId, getState, brainstoreRealtime = true) {
35352
37264
  if (typeof objectTypeOrFetchFn === "function") {
35353
37265
  this.fetchFn = (spanType) => objectTypeOrFetchFn(spanType);
35354
37266
  } else {
@@ -35361,7 +37273,8 @@ var CachedSpanFetcher = class {
35361
37273
  rootSpanId,
35362
37274
  state,
35363
37275
  spanType,
35364
- includeScorers
37276
+ includeScorers,
37277
+ brainstoreRealtime
35365
37278
  );
35366
37279
  const rows = await fetcher.fetchedData();
35367
37280
  return rows.map((row) => ({
@@ -36191,7 +38104,7 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
36191
38104
  }
36192
38105
  };
36193
38106
  const parentStr = state.currentParent.getStore();
36194
- const parentComponents = parentStr ? SpanComponentsV3.fromStr(parentStr) : null;
38107
+ const parentComponents = typeof parentStr === "string" ? SpanComponentsV4.fromStr(parentStr) : null;
36195
38108
  const trace = state ? new LocalTrace({
36196
38109
  objectType: parentComponents ? spanObjectTypeV3ToTypedString(
36197
38110
  parentComponents.data.object_type
@@ -36717,6 +38630,350 @@ var defaultReporter = {
36717
38630
  }
36718
38631
  };
36719
38632
 
38633
+ // src/agent-assertions.ts
38634
+ function agentAssertionScorer(callback, options = {}) {
38635
+ return async (args) => {
38636
+ const { trace: _trace, ...callbackArgs } = args;
38637
+ const callbackMetadata = callbackArgs.metadata ?? {};
38638
+ const assertions = await callback({
38639
+ ...callbackArgs,
38640
+ metadata: callbackMetadata,
38641
+ assert: agentAssertionHelpers
38642
+ });
38643
+ const resources = {};
38644
+ if (assertions.some((assertion) => assertion.requiresTrace)) {
38645
+ resources.spans = await args.trace?.getSpans({ spanType: ["tool"] });
38646
+ }
38647
+ const results = await Promise.all(
38648
+ assertions.map(async (assertion) => {
38649
+ const result = await assertion.evaluate(resources);
38650
+ return {
38651
+ name: assertion.name,
38652
+ passed: result.passed,
38653
+ failure: result.failure
38654
+ };
38655
+ })
38656
+ );
38657
+ const passed = results.filter((result) => result.passed).length;
38658
+ const total = results.length;
38659
+ const failed = results.filter((result) => !result.passed).map(
38660
+ (result) => `${result.name}: ${result.failure ?? "assertion did not pass"}`
38661
+ );
38662
+ return {
38663
+ name: options.name ?? "assertions",
38664
+ score: total === 0 ? 1 : passed / total,
38665
+ metadata: {
38666
+ assertions: results.map(({ name, passed: passed2 }) => ({ name, passed: passed2 })),
38667
+ failed
38668
+ }
38669
+ };
38670
+ };
38671
+ }
38672
+ var agentAssertionHelpers = {
38673
+ equals: (actual, expected, name = "equals") => ({
38674
+ name,
38675
+ evaluate: () => {
38676
+ const passed = deepEqual(actual, expected);
38677
+ return {
38678
+ passed,
38679
+ failure: passed ? void 0 : `expected ${formatValue(actual)} to equal ${formatValue(expected)}`
38680
+ };
38681
+ }
38682
+ }),
38683
+ notEquals: (actual, expected, name = "not equals") => ({
38684
+ name,
38685
+ evaluate: () => {
38686
+ const passed = !deepEqual(actual, expected);
38687
+ return {
38688
+ passed,
38689
+ failure: passed ? void 0 : `expected ${formatValue(actual)} not to equal ${formatValue(expected)}`
38690
+ };
38691
+ }
38692
+ }),
38693
+ contains: (value, expected, name = "contains") => ({
38694
+ name,
38695
+ evaluate: () => {
38696
+ const searchedValue = typeof value === "string" ? value : formatValue(value);
38697
+ const passed = expected instanceof RegExp ? testRegex(expected, value) : searchedValue.includes(expected);
38698
+ return {
38699
+ passed,
38700
+ failure: passed ? void 0 : `expected ${formatValue(value)} to contain ${formatValue(expected)}`
38701
+ };
38702
+ }
38703
+ }),
38704
+ matches: (value, schema, name = "matches schema") => ({
38705
+ name,
38706
+ evaluate: async () => {
38707
+ const result = await validateSchema(schema, value);
38708
+ return {
38709
+ passed: result.passed,
38710
+ failure: result.passed ? void 0 : `expected value to match schema: ${result.message}`
38711
+ };
38712
+ }
38713
+ }),
38714
+ calledTool: (toolName, options = {}, name = `called tool ${toolName}`) => ({
38715
+ name,
38716
+ requiresTrace: true,
38717
+ evaluate: ({ spans }) => {
38718
+ const calls = matchingToolCalls(spans ?? [], toolName, options);
38719
+ const passed = options.times === void 0 ? calls.length > 0 : calls.length === options.times;
38720
+ return {
38721
+ passed,
38722
+ failure: passed ? void 0 : options.times === void 0 ? `expected tool "${toolName}" to be called; found ${calls.length} matching call${calls.length === 1 ? "" : "s"}` : `expected tool "${toolName}" to be called ${options.times} time${options.times === 1 ? "" : "s"}; found ${calls.length} matching call${calls.length === 1 ? "" : "s"}`
38723
+ };
38724
+ }
38725
+ }),
38726
+ notCalledTool: (toolName, name = `did not call tool ${toolName}`) => ({
38727
+ name,
38728
+ requiresTrace: true,
38729
+ evaluate: ({ spans }) => {
38730
+ const calls = toolCalls(spans ?? []).filter(
38731
+ (span) => getToolName(span) === toolName
38732
+ );
38733
+ const passed = calls.length === 0;
38734
+ return {
38735
+ passed,
38736
+ failure: passed ? void 0 : `expected tool "${toolName}" not to be called; found ${calls.length} call${calls.length === 1 ? "" : "s"}`
38737
+ };
38738
+ }
38739
+ }),
38740
+ toolOrder: (toolNames, name = "tool order") => ({
38741
+ name,
38742
+ requiresTrace: true,
38743
+ evaluate: ({ spans }) => {
38744
+ const observed = toolCalls(spans ?? []).map(getToolName).filter((toolName) => toolName !== void 0);
38745
+ let fromIndex = 0;
38746
+ const passed = toolNames.every((toolName) => {
38747
+ const index = observed.indexOf(toolName, fromIndex);
38748
+ if (index === -1) return false;
38749
+ fromIndex = index + 1;
38750
+ return true;
38751
+ });
38752
+ return {
38753
+ passed,
38754
+ failure: passed ? void 0 : `expected tool order ${toolNames.join(" -> ")}; observed ${observed.join(" -> ") || "no tools"}`
38755
+ };
38756
+ }
38757
+ }),
38758
+ usedNoTools: (name = "used no tools") => ({
38759
+ name,
38760
+ requiresTrace: true,
38761
+ evaluate: ({ spans }) => {
38762
+ const calls = toolCalls(spans ?? []);
38763
+ const passed = calls.length === 0;
38764
+ return {
38765
+ passed,
38766
+ failure: passed ? void 0 : `expected no tool calls; found ${calls.length}`
38767
+ };
38768
+ }
38769
+ }),
38770
+ maxToolCalls: (max, name = `at most ${max} tool calls`) => ({
38771
+ name,
38772
+ requiresTrace: true,
38773
+ evaluate: ({ spans }) => {
38774
+ const calls = toolCalls(spans ?? []);
38775
+ const passed = calls.length <= max;
38776
+ return {
38777
+ passed,
38778
+ failure: passed ? void 0 : `expected at most ${max} tool call${max === 1 ? "" : "s"}; found ${calls.length}`
38779
+ };
38780
+ }
38781
+ })
38782
+ };
38783
+ async function validateSchema(schema, value) {
38784
+ try {
38785
+ if ("safeParse" in schema) {
38786
+ const result2 = schema.safeParse(value);
38787
+ return result2.success ? { passed: true, message: "" } : { passed: false, message: formatSchemaError(result2.error) };
38788
+ }
38789
+ if ("parse" in schema) {
38790
+ schema.parse(value);
38791
+ return { passed: true, message: "" };
38792
+ }
38793
+ const result = await schema["~standard"].validate(value);
38794
+ if (typeof result === "object" && result !== null && "issues" in result && Array.isArray(result.issues) && result.issues.length > 0) {
38795
+ return { passed: false, message: formatValue(result.issues) };
38796
+ }
38797
+ return { passed: true, message: "" };
38798
+ } catch (e) {
38799
+ return { passed: false, message: formatSchemaError(e) };
38800
+ }
38801
+ }
38802
+ function toolCalls(spans) {
38803
+ return spans.filter((span) => span.span_attributes?.type === "tool");
38804
+ }
38805
+ function matchingToolCalls(spans, toolName, options) {
38806
+ return toolCalls(spans).filter((span) => {
38807
+ if (getToolName(span) !== toolName) return false;
38808
+ if (Object.prototype.hasOwnProperty.call(options, "input") && !matchesValue(span.input, options.input)) {
38809
+ return false;
38810
+ }
38811
+ if (Object.prototype.hasOwnProperty.call(options, "output") && !matchesValue(span.output, options.output)) {
38812
+ return false;
38813
+ }
38814
+ if (options.isError !== void 0 && Boolean(span.error) !== options.isError) {
38815
+ return false;
38816
+ }
38817
+ return true;
38818
+ });
38819
+ }
38820
+ function getToolName(span) {
38821
+ const spanName = [span.span_attributes?.name, span.name].map(normalizeToolName).find((value) => value !== void 0);
38822
+ if (spanName?.includes("/")) {
38823
+ return spanName;
38824
+ }
38825
+ const metadataName = [
38826
+ span.metadata?.tool_name,
38827
+ span.metadata?.["gen_ai.tool.name"]
38828
+ ].map(normalizeToolName).find((value) => value !== void 0);
38829
+ const mcpServer = [
38830
+ span.metadata?.["mcp.server"],
38831
+ span.metadata?.["openai_codex.mcp.server"]
38832
+ ].find((value) => typeof value === "string" && value !== "");
38833
+ if (metadataName && mcpServer) {
38834
+ return `${mcpServer}/${metadataName}`;
38835
+ }
38836
+ return metadataName ?? spanName;
38837
+ }
38838
+ function normalizeToolName(value) {
38839
+ if (typeof value !== "string" || value === "") {
38840
+ return void 0;
38841
+ }
38842
+ return value.startsWith("tool:") ? value.slice("tool:".length).trim() : value;
38843
+ }
38844
+ function matchesValue(actual, matcher) {
38845
+ if (matcher instanceof RegExp) {
38846
+ return testRegex(matcher, actual);
38847
+ }
38848
+ if (typeof matcher === "function") {
38849
+ return matcher(actual);
38850
+ }
38851
+ if (Array.isArray(matcher)) {
38852
+ return Array.isArray(actual) && actual.length === matcher.length && matcher.every((value, index) => matchesValue(actual[index], value));
38853
+ }
38854
+ if (isPlainObject(matcher) && isPlainObject(actual)) {
38855
+ return Object.entries(matcher).every(
38856
+ ([key, value]) => Object.prototype.hasOwnProperty.call(actual, key) && matchesValue(actual[key], value)
38857
+ );
38858
+ }
38859
+ return deepEqual(actual, matcher);
38860
+ }
38861
+ function testRegex(matcher, value) {
38862
+ matcher.lastIndex = 0;
38863
+ return matcher.test(typeof value === "string" ? value : formatValue(value));
38864
+ }
38865
+ function deepEqual(left, right) {
38866
+ if (Object.is(left, right)) return true;
38867
+ if (Array.isArray(left) && Array.isArray(right)) {
38868
+ return left.length === right.length && left.every((item, index) => deepEqual(item, right[index]));
38869
+ }
38870
+ if (isPlainObject(left) && isPlainObject(right)) {
38871
+ const leftKeys = Object.keys(left);
38872
+ const rightKeys = Object.keys(right);
38873
+ return leftKeys.length === rightKeys.length && leftKeys.every(
38874
+ (key) => Object.prototype.hasOwnProperty.call(right, key) && deepEqual(left[key], right[key])
38875
+ );
38876
+ }
38877
+ return false;
38878
+ }
38879
+ function isPlainObject(value) {
38880
+ return typeof value === "object" && value !== null && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype;
38881
+ }
38882
+ function formatSchemaError(error) {
38883
+ if (error instanceof Error) {
38884
+ return error.message;
38885
+ }
38886
+ return formatValue(error);
38887
+ }
38888
+ function formatValue(value) {
38889
+ if (value instanceof RegExp) {
38890
+ return value.toString();
38891
+ }
38892
+ if (typeof value === "string") {
38893
+ return JSON.stringify(value);
38894
+ }
38895
+ try {
38896
+ const serialized = JSON.stringify(value);
38897
+ if (serialized !== void 0 && !hasUndefinedJsonValue(value)) {
38898
+ return serialized;
38899
+ }
38900
+ return formatValueWithUndefined(value, /* @__PURE__ */ new Set());
38901
+ } catch {
38902
+ return String(value);
38903
+ }
38904
+ }
38905
+ function hasUndefinedJsonValue(value, seen = /* @__PURE__ */ new Set()) {
38906
+ if (value === void 0) {
38907
+ return true;
38908
+ }
38909
+ if (typeof value !== "object" || value === null) {
38910
+ return false;
38911
+ }
38912
+ if (seen.has(value)) {
38913
+ return false;
38914
+ }
38915
+ seen.add(value);
38916
+ if (Array.isArray(value)) {
38917
+ return Array.from({ length: value.length }).some(
38918
+ (_, index) => hasUndefinedJsonValue(value[index], seen)
38919
+ );
38920
+ }
38921
+ return Object.keys(value).some(
38922
+ (key) => hasUndefinedJsonValue(value[key], seen)
38923
+ );
38924
+ }
38925
+ function formatValueWithUndefined(value, seen) {
38926
+ if (value === void 0) {
38927
+ return "undefined";
38928
+ }
38929
+ if (value === null) {
38930
+ return "null";
38931
+ }
38932
+ if (typeof value === "string") {
38933
+ return JSON.stringify(value);
38934
+ }
38935
+ if (typeof value === "number" || typeof value === "boolean") {
38936
+ return JSON.stringify(value);
38937
+ }
38938
+ if (typeof value === "bigint" || typeof value === "function") {
38939
+ return String(value);
38940
+ }
38941
+ if (typeof value === "symbol") {
38942
+ return String(value);
38943
+ }
38944
+ if (value instanceof RegExp) {
38945
+ return value.toString();
38946
+ }
38947
+ if (typeof value !== "object") {
38948
+ return String(value);
38949
+ }
38950
+ if (seen.has(value)) {
38951
+ return '"[Circular]"';
38952
+ }
38953
+ seen.add(value);
38954
+ if (typeof value.toJSON === "function") {
38955
+ const jsonValue = value.toJSON();
38956
+ seen.delete(value);
38957
+ return formatValueWithUndefined(jsonValue, seen);
38958
+ }
38959
+ if (Array.isArray(value)) {
38960
+ const formatted2 = Array.from(
38961
+ { length: value.length },
38962
+ (_, index) => formatValueWithUndefined(value[index], seen)
38963
+ );
38964
+ seen.delete(value);
38965
+ return `[${formatted2.join(",")}]`;
38966
+ }
38967
+ const formatted = Object.keys(value).map(
38968
+ (key) => `${JSON.stringify(key)}:${formatValueWithUndefined(
38969
+ value[key],
38970
+ seen
38971
+ )}`
38972
+ );
38973
+ seen.delete(value);
38974
+ return `{${formatted.join(",")}}`;
38975
+ }
38976
+
36720
38977
  // src/dataset-pipeline.ts
36721
38978
  function DatasetPipeline(definition) {
36722
38979
  if (!globalThis.__braintrust_dataset_pipelines) {