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
@@ -32,8 +32,10 @@ var edge_light_exports = {};
32
32
  __export(edge_light_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(edge_light_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(edge_light_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(edge_light_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(edge_light_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(edge_light_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(edge_light_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,
@@ -470,8 +478,291 @@ var UUIDGenerator = class extends IDGenerator {
470
478
  return true;
471
479
  }
472
480
  };
481
+ function generateHexId(bytes) {
482
+ let result = "";
483
+ for (let i = 0; i < bytes; i++) {
484
+ result += Math.floor(Math.random() * 256).toString(16).padStart(2, "0");
485
+ }
486
+ return result;
487
+ }
488
+ var OTELIDGenerator = class extends IDGenerator {
489
+ getSpanId() {
490
+ return generateHexId(8);
491
+ }
492
+ getTraceId() {
493
+ return generateHexId(16);
494
+ }
495
+ shareRootSpanId() {
496
+ return false;
497
+ }
498
+ };
499
+ function parseEnvBool(name) {
500
+ const raw = isomorph_default.getEnv(name);
501
+ if (raw === void 0 || raw === null) {
502
+ return false;
503
+ }
504
+ const normalized = raw.trim().toLowerCase();
505
+ return normalized === "true" || normalized === "1" || normalized === "yes" || normalized === "y" || normalized === "on";
506
+ }
507
+ var _warnedLegacyUuidConflict = false;
508
+ function resolveUseLegacyUuidIds() {
509
+ const legacy = parseEnvBool("BRAINTRUST_LEGACY_IDS");
510
+ if (parseEnvBool("BRAINTRUST_OTEL_COMPAT")) {
511
+ if (legacy && !_warnedLegacyUuidConflict) {
512
+ _warnedLegacyUuidConflict = true;
513
+ debugLogger.warn(
514
+ "BRAINTRUST_LEGACY_IDS is ignored because BRAINTRUST_OTEL_COMPAT requires OpenTelemetry-compatible hex span IDs. Using hex IDs."
515
+ );
516
+ }
517
+ return false;
518
+ }
519
+ return legacy;
520
+ }
473
521
  function getIdGenerator() {
474
- return globalThis.BRAINTRUST_ID_GENERATOR !== void 0 ? new globalThis.BRAINTRUST_ID_GENERATOR() : new UUIDGenerator();
522
+ if (globalThis.BRAINTRUST_ID_GENERATOR !== void 0) {
523
+ return new globalThis.BRAINTRUST_ID_GENERATOR();
524
+ }
525
+ return resolveUseLegacyUuidIds() ? new UUIDGenerator() : new OTELIDGenerator();
526
+ }
527
+
528
+ // src/propagation.ts
529
+ var TRACEPARENT_HEADER = "traceparent";
530
+ var TRACESTATE_HEADER = "tracestate";
531
+ var BAGGAGE_HEADER = "baggage";
532
+ var BRAINTRUST_PARENT_KEY = "braintrust.parent";
533
+ var DEFAULT_TRACE_FLAGS = "01";
534
+ var TRACEPARENT_RE = /^00-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$/;
535
+ var ZERO_TRACE_ID = "0".repeat(32);
536
+ var ZERO_SPAN_ID = "0".repeat(16);
537
+ var MAX_BAGGAGE_LENGTH = 8192;
538
+ var MAX_BAGGAGE_MEMBERS = 64;
539
+ var _utf8Encoder = new TextEncoder();
540
+ function utf8ByteLength(value) {
541
+ return _utf8Encoder.encode(value).length;
542
+ }
543
+ function capBaggageToMemberBoundary(value) {
544
+ const totalBytes = utf8ByteLength(value);
545
+ const withinBytes = totalBytes <= MAX_BAGGAGE_LENGTH;
546
+ let commaCount = 0;
547
+ for (let i = 0; i < value.length; i++) {
548
+ if (value.charCodeAt(i) === 44) {
549
+ commaCount++;
550
+ }
551
+ }
552
+ const withinMembers = commaCount < MAX_BAGGAGE_MEMBERS;
553
+ if (withinBytes && withinMembers) {
554
+ return value;
555
+ }
556
+ const kept = [];
557
+ let length = 0;
558
+ for (const rawMember of value.split(",")) {
559
+ if (kept.length >= MAX_BAGGAGE_MEMBERS) {
560
+ break;
561
+ }
562
+ const cost = utf8ByteLength(rawMember) + (kept.length ? 1 : 0);
563
+ if (length + cost > MAX_BAGGAGE_LENGTH) {
564
+ break;
565
+ }
566
+ kept.push(rawMember);
567
+ length += cost;
568
+ }
569
+ if (!kept.length) {
570
+ return "";
571
+ }
572
+ return kept.join(",");
573
+ }
574
+ function isTraceContextHeaderTupleArray(value) {
575
+ return Array.isArray(value) && value.every(
576
+ (item) => Array.isArray(item) && typeof item[0] === "string" && typeof item[1] === "string"
577
+ );
578
+ }
579
+ function isListHeader(name) {
580
+ const lowered = name.toLowerCase();
581
+ return lowered === BAGGAGE_HEADER || lowered === TRACESTATE_HEADER;
582
+ }
583
+ function headerValueToString(value, name) {
584
+ if (value === void 0 || value === null) {
585
+ return void 0;
586
+ }
587
+ if (Array.isArray(value)) {
588
+ const stringValues = value.filter((item) => {
589
+ return typeof item === "string";
590
+ });
591
+ if (!stringValues.length) {
592
+ return void 0;
593
+ }
594
+ return isListHeader(name) ? stringValues.join(",") : stringValues[0];
595
+ }
596
+ return typeof value === "string" ? value : String(value);
597
+ }
598
+ function getHeader(headers, name) {
599
+ if (!headers) {
600
+ return void 0;
601
+ }
602
+ if (isTraceContextHeaderTupleArray(headers)) {
603
+ const lowered2 = name.toLowerCase();
604
+ const matches = headers.filter(([key]) => key.toLowerCase() === lowered2).map(([, value]) => value);
605
+ if (!matches.length) {
606
+ return void 0;
607
+ }
608
+ return headerValueToString(matches, name);
609
+ }
610
+ const getter = headers.get;
611
+ if (typeof getter === "function") {
612
+ try {
613
+ const value = headerValueToString(getter.call(headers, name), name);
614
+ if (value !== void 0) {
615
+ return value;
616
+ }
617
+ } catch {
618
+ }
619
+ }
620
+ const nodeGetter = headers.getHeader;
621
+ if (typeof nodeGetter === "function") {
622
+ try {
623
+ const value = headerValueToString(nodeGetter.call(headers, name), name);
624
+ if (value !== void 0) {
625
+ return value;
626
+ }
627
+ } catch {
628
+ }
629
+ }
630
+ const headerBag = headers;
631
+ const exact = headerValueToString(headerBag[name], name);
632
+ if (exact !== void 0) {
633
+ return exact;
634
+ }
635
+ const lowered = name.toLowerCase();
636
+ for (const key of Object.keys(headers)) {
637
+ if (key !== name && key.toLowerCase() === lowered) {
638
+ const value = headerValueToString(headerBag[key], name);
639
+ if (value !== void 0) {
640
+ return value;
641
+ }
642
+ }
643
+ }
644
+ return void 0;
645
+ }
646
+ function isHex(value, length) {
647
+ if (typeof value !== "string" || value.length !== length) {
648
+ return false;
649
+ }
650
+ for (let i = 0; i < value.length; i++) {
651
+ const c = value[i];
652
+ const isDigit = c >= "0" && c <= "9";
653
+ const isLowerHex = c >= "a" && c <= "f";
654
+ if (!isDigit && !isLowerHex) {
655
+ return false;
656
+ }
657
+ }
658
+ return true;
659
+ }
660
+ function parseTraceparent(value) {
661
+ if (!value || typeof value !== "string") {
662
+ return void 0;
663
+ }
664
+ const match = TRACEPARENT_RE.exec(value.trim());
665
+ if (!match) {
666
+ return void 0;
667
+ }
668
+ const traceId = match[1];
669
+ const spanId = match[2];
670
+ const traceFlags = match[3];
671
+ if (traceId === ZERO_TRACE_ID || spanId === ZERO_SPAN_ID) {
672
+ return void 0;
673
+ }
674
+ return { traceId, spanId, traceFlags };
675
+ }
676
+ function formatTraceparent(traceId, spanId, traceFlags = DEFAULT_TRACE_FLAGS) {
677
+ if (!isHex(traceId, 32) || traceId === ZERO_TRACE_ID) {
678
+ return void 0;
679
+ }
680
+ if (!isHex(spanId, 16) || spanId === ZERO_SPAN_ID) {
681
+ return void 0;
682
+ }
683
+ const flags = isHex(traceFlags, 2) ? traceFlags : DEFAULT_TRACE_FLAGS;
684
+ return `00-${traceId}-${spanId}-${flags}`;
685
+ }
686
+ function percentEncode(value) {
687
+ return encodeURIComponent(value);
688
+ }
689
+ function percentDecode(value) {
690
+ if (!value.includes("%")) {
691
+ return value;
692
+ }
693
+ try {
694
+ return decodeURIComponent(value);
695
+ } catch {
696
+ return value;
697
+ }
698
+ }
699
+ function parseBaggage(value) {
700
+ const result = {};
701
+ if (!value || typeof value !== "string") {
702
+ return result;
703
+ }
704
+ const bounded = capBaggageToMemberBoundary(value);
705
+ for (let member of bounded.split(",")) {
706
+ member = member.trim();
707
+ if (!member || !member.includes("=")) {
708
+ continue;
709
+ }
710
+ member = member.split(";", 1)[0];
711
+ const eq = member.indexOf("=");
712
+ const key = percentDecode(member.slice(0, eq).trim());
713
+ const val = member.slice(eq + 1).trim();
714
+ if (!key) {
715
+ continue;
716
+ }
717
+ result[key] = percentDecode(val);
718
+ }
719
+ return result;
720
+ }
721
+ function mergeBaggage(existing, braintrustParent) {
722
+ let btMember = void 0;
723
+ if (braintrustParent) {
724
+ const encodedKey = percentEncode(BRAINTRUST_PARENT_KEY);
725
+ const encodedVal = percentEncode(String(braintrustParent));
726
+ btMember = `${encodedKey}=${encodedVal}`;
727
+ if (utf8ByteLength(btMember) > MAX_BAGGAGE_LENGTH) {
728
+ btMember = void 0;
729
+ }
730
+ }
731
+ let byteBudget = MAX_BAGGAGE_LENGTH;
732
+ let memberBudget = MAX_BAGGAGE_MEMBERS;
733
+ if (btMember !== void 0) {
734
+ byteBudget -= utf8ByteLength(btMember) + 1;
735
+ memberBudget -= 1;
736
+ }
737
+ const relayed = [];
738
+ let length = 0;
739
+ if (existing && typeof existing === "string") {
740
+ for (const rawMember of existing.split(",")) {
741
+ const member = rawMember.trim();
742
+ if (!member || !member.includes("=")) {
743
+ continue;
744
+ }
745
+ const keyPart = member.split(";", 1)[0].split("=", 1)[0];
746
+ const key = percentDecode(keyPart.trim());
747
+ if (key === BRAINTRUST_PARENT_KEY) {
748
+ continue;
749
+ }
750
+ if (relayed.length >= memberBudget) {
751
+ break;
752
+ }
753
+ const cost = utf8ByteLength(member) + (relayed.length ? 1 : 0);
754
+ if (length + cost > byteBudget) {
755
+ break;
756
+ }
757
+ relayed.push(member);
758
+ length += cost;
759
+ }
760
+ }
761
+ const members = btMember !== void 0 ? [...relayed, btMember] : relayed;
762
+ if (!members.length) {
763
+ return void 0;
764
+ }
765
+ return members.join(",");
475
766
  }
476
767
 
477
768
  // util/db_fields.ts
@@ -1079,7 +1370,7 @@ var SpanComponentsV3 = class _SpanComponentsV3 {
1079
1370
  case 3 /* PLAYGROUND_LOGS */:
1080
1371
  return { prompt_session_id: this.data.object_id, log_id: "x" };
1081
1372
  default:
1082
- const _ = this.data.object_type;
1373
+ this.data.object_type;
1083
1374
  throw new Error("Impossible");
1084
1375
  }
1085
1376
  }
@@ -1608,7 +1899,7 @@ var SpanComponentsV4 = class _SpanComponentsV4 {
1608
1899
  case 3 /* PLAYGROUND_LOGS */:
1609
1900
  return { prompt_session_id: this.data.object_id, log_id: "x" };
1610
1901
  default:
1611
- const _ = this.data.object_type;
1902
+ this.data.object_type;
1612
1903
  throw new Error(`Invalid object_type ${this.data.object_type}`);
1613
1904
  }
1614
1905
  }
@@ -1787,7 +2078,8 @@ var AclObjectType = import_v36.z.union([
1787
2078
  "role",
1788
2079
  "org_member",
1789
2080
  "project_log",
1790
- "org_project"
2081
+ "org_project",
2082
+ "org_audit_logs"
1791
2083
  ]),
1792
2084
  import_v36.z.null()
1793
2085
  ]);
@@ -1813,6 +2105,17 @@ var Acl = import_v36.z.object({
1813
2105
  _object_org_id: import_v36.z.string().uuid(),
1814
2106
  created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional()
1815
2107
  });
2108
+ var Agent = import_v36.z.object({
2109
+ id: import_v36.z.string().uuid(),
2110
+ project_id: import_v36.z.string().uuid(),
2111
+ user_id: import_v36.z.string().uuid(),
2112
+ created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2113
+ name: import_v36.z.string(),
2114
+ slug: import_v36.z.string(),
2115
+ kind: import_v36.z.string(),
2116
+ description: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2117
+ metadata: import_v36.z.union([import_v36.z.object({}).partial().passthrough(), import_v36.z.null()]).optional()
2118
+ });
1816
2119
  var AISecret = import_v36.z.object({
1817
2120
  id: import_v36.z.string().uuid(),
1818
2121
  created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
@@ -1959,6 +2262,7 @@ var AttachmentStatus = import_v36.z.object({
1959
2262
  upload_status: UploadStatus,
1960
2263
  error_message: import_v36.z.string().optional()
1961
2264
  });
2265
+ var AutomationStatus = import_v36.z.enum(["active", "paused"]);
1962
2266
  var FunctionTypeEnum = import_v36.z.enum([
1963
2267
  "llm",
1964
2268
  "scorer",
@@ -2004,7 +2308,9 @@ var TopicMapData = import_v36.z.object({
2004
2308
  topic_names: import_v36.z.record(import_v36.z.string()).optional(),
2005
2309
  generation_settings: TopicMapGenerationSettings.optional(),
2006
2310
  disable_reconciliation: import_v36.z.boolean().optional(),
2007
- distance_threshold: import_v36.z.number().optional()
2311
+ distance_threshold: import_v36.z.number().optional(),
2312
+ btql_filter: import_v36.z.string().optional(),
2313
+ automation_btql_filter: import_v36.z.string().optional()
2008
2314
  });
2009
2315
  var BatchedFacetData = import_v36.z.object({
2010
2316
  type: import_v36.z.literal("batched_facet"),
@@ -2287,7 +2593,7 @@ var DatasetEvent = import_v36.z.object({
2287
2593
  origin: ObjectReferenceNullish.optional(),
2288
2594
  comments: import_v36.z.union([import_v36.z.array(import_v36.z.unknown()), import_v36.z.null()]).optional(),
2289
2595
  audit_data: import_v36.z.union([import_v36.z.array(import_v36.z.unknown()), import_v36.z.null()]).optional(),
2290
- facets: import_v36.z.union([import_v36.z.object({}).partial().passthrough(), import_v36.z.null()]).optional(),
2596
+ 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(),
2291
2597
  classifications: import_v36.z.union([
2292
2598
  import_v36.z.record(
2293
2599
  import_v36.z.array(
@@ -2439,7 +2745,7 @@ var ExperimentEvent = import_v36.z.object({
2439
2745
  origin: ObjectReferenceNullish.optional(),
2440
2746
  comments: import_v36.z.union([import_v36.z.array(import_v36.z.unknown()), import_v36.z.null()]).optional(),
2441
2747
  audit_data: import_v36.z.union([import_v36.z.array(import_v36.z.unknown()), import_v36.z.null()]).optional(),
2442
- facets: import_v36.z.union([import_v36.z.object({}).partial().passthrough(), import_v36.z.null()]).optional(),
2748
+ 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(),
2443
2749
  classifications: import_v36.z.union([
2444
2750
  import_v36.z.record(
2445
2751
  import_v36.z.array(
@@ -2577,7 +2883,8 @@ var PromptParserNullish = import_v36.z.union([
2577
2883
  use_cot: import_v36.z.boolean(),
2578
2884
  choice_scores: import_v36.z.record(import_v36.z.number().gte(0).lte(1)).optional(),
2579
2885
  choice: import_v36.z.array(import_v36.z.string()).optional(),
2580
- allow_no_match: import_v36.z.boolean().optional()
2886
+ allow_no_match: import_v36.z.boolean().optional(),
2887
+ allow_skip: import_v36.z.boolean().optional()
2581
2888
  }),
2582
2889
  import_v36.z.null()
2583
2890
  ]);
@@ -2907,6 +3214,9 @@ var Group = import_v36.z.object({
2907
3214
  var GroupScope = import_v36.z.object({
2908
3215
  type: import_v36.z.literal("group"),
2909
3216
  group_by: import_v36.z.string(),
3217
+ interval_seconds: import_v36.z.number().gte(1).optional(),
3218
+ max_traces: import_v36.z.number().int().gte(1).lte(64).optional(),
3219
+ placement: import_v36.z.enum(["first", "each"]),
2910
3220
  idle_seconds: import_v36.z.number().optional()
2911
3221
  });
2912
3222
  var IfExists = import_v36.z.enum(["error", "ignore", "replace"]);
@@ -3055,6 +3365,10 @@ var RetentionObjectType = import_v36.z.enum([
3055
3365
  "experiment",
3056
3366
  "dataset"
3057
3367
  ]);
3368
+ var TopicAutomationFacetModel = import_v36.z.union([
3369
+ import_v36.z.enum(["brain-facet-latest", "brain-facet-1", "brain-facet-2"]),
3370
+ import_v36.z.null()
3371
+ ]);
3058
3372
  var TopicMapFunctionAutomation = import_v36.z.object({
3059
3373
  function: SavedFunctionId.and(import_v36.z.unknown()),
3060
3374
  btql_filter: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional()
@@ -3067,7 +3381,9 @@ var TopicAutomationDataScope = import_v36.z.union([
3067
3381
  ]);
3068
3382
  var TopicAutomationConfig = import_v36.z.object({
3069
3383
  event_type: import_v36.z.literal("topic"),
3384
+ status: AutomationStatus.optional(),
3070
3385
  sampling_rate: import_v36.z.number().gte(0).lte(1),
3386
+ facet_model: TopicAutomationFacetModel.optional(),
3071
3387
  facet_functions: import_v36.z.array(SavedFunctionId),
3072
3388
  topic_map_functions: import_v36.z.array(TopicMapFunctionAutomation),
3073
3389
  scope: import_v36.z.union([SpanScope, TraceScope, GroupScope, import_v36.z.null()]).optional(),
@@ -3081,6 +3397,19 @@ var TopicAutomationConfig = import_v36.z.object({
3081
3397
  import_v36.z.null()
3082
3398
  ]).optional()
3083
3399
  });
3400
+ var TopicDigestAutomationConfig = import_v36.z.object({
3401
+ event_type: import_v36.z.literal("topic_digest"),
3402
+ status: AutomationStatus.optional(),
3403
+ window_seconds: import_v36.z.number().int().gte(3600).lte(2592e3).optional().default(86400),
3404
+ scheduled_time_minutes_utc: import_v36.z.number().int().gte(0).lte(1439),
3405
+ action: import_v36.z.object({
3406
+ type: import_v36.z.literal("slack"),
3407
+ workspace_id: import_v36.z.string(),
3408
+ channel: import_v36.z.string(),
3409
+ message_template: import_v36.z.string().optional()
3410
+ }),
3411
+ topic_map_function_ids: import_v36.z.array(import_v36.z.string()).max(10).optional()
3412
+ });
3084
3413
  var ProjectAutomation = import_v36.z.object({
3085
3414
  id: import_v36.z.string().uuid(),
3086
3415
  project_id: import_v36.z.string().uuid(),
@@ -3105,6 +3434,7 @@ var ProjectAutomation = import_v36.z.object({
3105
3434
  }),
3106
3435
  import_v36.z.object({
3107
3436
  event_type: import_v36.z.literal("btql_export"),
3437
+ status: AutomationStatus.optional(),
3108
3438
  export_definition: import_v36.z.union([
3109
3439
  import_v36.z.object({ type: import_v36.z.literal("log_traces") }),
3110
3440
  import_v36.z.object({ type: import_v36.z.literal("log_spans") }),
@@ -3127,6 +3457,21 @@ var ProjectAutomation = import_v36.z.object({
3127
3457
  ]),
3128
3458
  batch_size: import_v36.z.union([import_v36.z.number(), import_v36.z.null()]).optional()
3129
3459
  }),
3460
+ import_v36.z.object({
3461
+ event_type: import_v36.z.literal("async_query"),
3462
+ status: AutomationStatus.optional(),
3463
+ created_by_user_id: import_v36.z.string().uuid(),
3464
+ object_type: import_v36.z.enum([
3465
+ "project_logs",
3466
+ "experiment",
3467
+ "dataset",
3468
+ "playground_logs"
3469
+ ]),
3470
+ object_id: import_v36.z.string(),
3471
+ query: import_v36.z.string(),
3472
+ format: import_v36.z.literal("jsonl"),
3473
+ batch_size: import_v36.z.union([import_v36.z.number(), import_v36.z.null()]).optional()
3474
+ }),
3130
3475
  import_v36.z.object({
3131
3476
  event_type: import_v36.z.literal("retention"),
3132
3477
  object_type: RetentionObjectType,
@@ -3145,7 +3490,8 @@ var ProjectAutomation = import_v36.z.object({
3145
3490
  })
3146
3491
  ])
3147
3492
  }),
3148
- TopicAutomationConfig
3493
+ TopicAutomationConfig,
3494
+ TopicDigestAutomationConfig
3149
3495
  ])
3150
3496
  });
3151
3497
  var ProjectLogsEvent = import_v36.z.object({
@@ -3184,7 +3530,7 @@ var ProjectLogsEvent = import_v36.z.object({
3184
3530
  comments: import_v36.z.union([import_v36.z.array(import_v36.z.unknown()), import_v36.z.null()]).optional(),
3185
3531
  audit_data: import_v36.z.union([import_v36.z.array(import_v36.z.unknown()), import_v36.z.null()]).optional(),
3186
3532
  _async_scoring_state: import_v36.z.unknown().optional(),
3187
- facets: import_v36.z.union([import_v36.z.object({}).partial().passthrough(), import_v36.z.null()]).optional(),
3533
+ 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(),
3188
3534
  classifications: import_v36.z.union([
3189
3535
  import_v36.z.record(
3190
3536
  import_v36.z.array(
@@ -3233,11 +3579,34 @@ var ProjectScoreCategories = import_v36.z.union([
3233
3579
  import_v36.z.array(import_v36.z.string()),
3234
3580
  import_v36.z.null()
3235
3581
  ]);
3582
+ var ProjectScoreCondition = import_v36.z.union([
3583
+ import_v36.z.object({
3584
+ when: import_v36.z.object({
3585
+ clauses: import_v36.z.union([import_v36.z.array(import_v36.z.string()), import_v36.z.null()]),
3586
+ subspan_clauses: import_v36.z.union([import_v36.z.array(import_v36.z.string()), import_v36.z.null()]),
3587
+ trace_clauses: import_v36.z.union([import_v36.z.array(import_v36.z.string()), import_v36.z.null()])
3588
+ }).partial(),
3589
+ behavior: import_v36.z.literal("hidden").optional().default("hidden")
3590
+ }),
3591
+ import_v36.z.null()
3592
+ ]);
3236
3593
  var ProjectScoreConfig = import_v36.z.union([
3237
3594
  import_v36.z.object({
3238
3595
  multi_select: import_v36.z.union([import_v36.z.boolean(), import_v36.z.null()]),
3239
3596
  destination: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
3240
- online: OnlineScoreConfig
3597
+ visibility: import_v36.z.union([
3598
+ import_v36.z.object({
3599
+ users: import_v36.z.union([import_v36.z.array(import_v36.z.string()), import_v36.z.null()]),
3600
+ groups: import_v36.z.union([import_v36.z.array(import_v36.z.string()), import_v36.z.null()])
3601
+ }).partial(),
3602
+ import_v36.z.null()
3603
+ ]),
3604
+ online: OnlineScoreConfig,
3605
+ condition: ProjectScoreCondition,
3606
+ object_types: import_v36.z.union([
3607
+ import_v36.z.array(import_v36.z.enum(["project_logs", "dataset", "experiment"])),
3608
+ import_v36.z.null()
3609
+ ])
3241
3610
  }).partial(),
3242
3611
  import_v36.z.null()
3243
3612
  ]);
@@ -3422,8 +3791,7 @@ var User = import_v36.z.object({
3422
3791
  family_name: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3423
3792
  email: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3424
3793
  avatar_url: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3425
- created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3426
- last_active_at: import_v36.z.union([import_v36.z.number(), import_v36.z.null()]).optional()
3794
+ created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional()
3427
3795
  });
3428
3796
  var ViewDataSearch = import_v36.z.union([
3429
3797
  import_v36.z.object({
@@ -4710,7 +5078,10 @@ var BraintrustContextManager = class extends ContextManager {
4710
5078
  }
4711
5079
  };
4712
5080
  function getSpanComponentsClass() {
4713
- return globalThis.BRAINTRUST_SPAN_COMPONENT ? globalThis.BRAINTRUST_SPAN_COMPONENT : SpanComponentsV3;
5081
+ if (globalThis.BRAINTRUST_SPAN_COMPONENT) {
5082
+ return globalThis.BRAINTRUST_SPAN_COMPONENT;
5083
+ }
5084
+ return resolveUseLegacyUuidIds() ? SpanComponentsV3 : SpanComponentsV4;
4714
5085
  }
4715
5086
  function getContextManager() {
4716
5087
  return globalThis.BRAINTRUST_CONTEXT_MANAGER ? new globalThis.BRAINTRUST_CONTEXT_MANAGER() : new BraintrustContextManager();
@@ -4746,6 +5117,9 @@ var NoopSpan = class {
4746
5117
  async export() {
4747
5118
  return "";
4748
5119
  }
5120
+ inject(carrier) {
5121
+ return carrier ?? {};
5122
+ }
4749
5123
  async permalink() {
4750
5124
  return NOOP_SPAN_PERMALINK;
4751
5125
  }
@@ -4796,6 +5170,10 @@ var loginSchema = import_v38.z.strictObject({
4796
5170
  debugLogLevelDisabled: import_v38.z.boolean().optional()
4797
5171
  });
4798
5172
  var stateNonce = 0;
5173
+ var V1_PROXY_SUFFIX = "/v1/proxy";
5174
+ function normalizeProxyConnUrl(proxyUrl) {
5175
+ return proxyUrl.endsWith(V1_PROXY_SUFFIX) ? proxyUrl.slice(0, proxyUrl.length - V1_PROXY_SUFFIX.length) : proxyUrl;
5176
+ }
4799
5177
  var BraintrustState = class _BraintrustState {
4800
5178
  constructor(loginParams) {
4801
5179
  this.loginParams = loginParams;
@@ -5066,7 +5444,10 @@ var BraintrustState = class _BraintrustState {
5066
5444
  if (!this.proxyUrl) {
5067
5445
  throw new Error("Must initialize proxyUrl before requesting proxyConn");
5068
5446
  }
5069
- this._proxyConn = new HTTPConnection(this.proxyUrl, this.fetch);
5447
+ this._proxyConn = new HTTPConnection(
5448
+ normalizeProxyConnUrl(this.proxyUrl),
5449
+ this.fetch
5450
+ );
5070
5451
  }
5071
5452
  return this._proxyConn;
5072
5453
  }
@@ -5824,7 +6205,7 @@ function updateSpan({
5824
6205
  ...event
5825
6206
  }) {
5826
6207
  const resolvedState = state ?? _globalState;
5827
- const components = getSpanComponentsClass().fromStr(exported);
6208
+ const components = SpanComponentsV4.fromStr(exported);
5828
6209
  if (!components.data.row_id) {
5829
6210
  throw new Error("Exported span must have a row id");
5830
6211
  }
@@ -5924,7 +6305,7 @@ async function permalink(slug, opts) {
5924
6305
  return state.appUrl;
5925
6306
  };
5926
6307
  try {
5927
- const components = getSpanComponentsClass().fromStr(slug);
6308
+ const components = SpanComponentsV4.fromStr(slug);
5928
6309
  const object_type = spanObjectTypeV3ToString(components.data.object_type);
5929
6310
  const [orgName, appUrl, object_id] = await Promise.all([
5930
6311
  getOrgName(),
@@ -5948,35 +6329,47 @@ function startSpanParentArgs(args) {
5948
6329
  let argParentObjectId = void 0;
5949
6330
  let argParentSpanIds = void 0;
5950
6331
  let argPropagatedEvent = void 0;
5951
- if (args.parent) {
6332
+ let argPropagatedState = void 0;
6333
+ const { parentSlug, propagatedState: parentPropagatedState } = normalizeParent(args.parent, args.state);
6334
+ if (parentSlug) {
5952
6335
  if (args.parentSpanIds) {
5953
6336
  throw new Error("Cannot specify both parent and parentSpanIds");
5954
6337
  }
5955
- const parentComponents = getSpanComponentsClass().fromStr(args.parent);
6338
+ const parentComponents = SpanComponentsV4.fromStr(parentSlug);
5956
6339
  if (args.parentObjectType !== parentComponents.data.object_type) {
5957
6340
  throw new Error(
5958
6341
  `Mismatch between expected span parent object type ${args.parentObjectType} and provided type ${parentComponents.data.object_type}`
5959
6342
  );
5960
6343
  }
5961
6344
  argParentObjectId = args.parentObjectId;
5962
- if (parentComponents.data.row_id) {
6345
+ if (parentComponents.data.row_id && parentSpanIdsUsable(
6346
+ parentComponents.data.span_id,
6347
+ parentComponents.data.root_span_id
6348
+ )) {
5963
6349
  argParentSpanIds = {
5964
6350
  spanId: parentComponents.data.span_id,
5965
6351
  rootSpanId: parentComponents.data.root_span_id
5966
6352
  };
5967
6353
  }
5968
6354
  argPropagatedEvent = args.propagatedEvent ?? (parentComponents.data.propagated_event ?? void 0);
6355
+ const propagatedState = args.propagatedState ?? parentPropagatedState;
6356
+ if (propagatedState) {
6357
+ const { braintrustParent: _ignoredBraintrustParent, ...w3cState } = propagatedState;
6358
+ argPropagatedState = w3cState;
6359
+ }
5969
6360
  } else {
5970
6361
  argParentObjectId = args.parentObjectId;
5971
6362
  argParentSpanIds = args.parentSpanIds;
5972
6363
  argPropagatedEvent = args.propagatedEvent;
6364
+ argPropagatedState = args.propagatedState;
5973
6365
  }
5974
6366
  return {
5975
6367
  parentObjectType: args.parentObjectType,
5976
6368
  parentObjectId: argParentObjectId,
5977
6369
  parentComputeObjectMetadataArgs: args.parentComputeObjectMetadataArgs,
5978
6370
  parentSpanIds: argParentSpanIds,
5979
- propagatedEvent: argPropagatedEvent
6371
+ propagatedEvent: argPropagatedEvent,
6372
+ propagatedState: argPropagatedState
5980
6373
  };
5981
6374
  }
5982
6375
  var Logger = class {
@@ -6177,6 +6570,22 @@ var Logger = class {
6177
6570
  _getLinkBaseUrl() {
6178
6571
  return _getLinkBaseUrl(this.state, this._linkArgs);
6179
6572
  }
6573
+ /**
6574
+ * Return this logger's Braintrust parent string (`project_id:<id>` or
6575
+ * `project_name:<name>`) for the `braintrust.parent` baggage entry, or
6576
+ * undefined when it cannot be determined synchronously.
6577
+ */
6578
+ _getOtelParent() {
6579
+ const id = this.computeMetadataArgs?.project_id || this.lazyId.getSync().value;
6580
+ if (id) {
6581
+ return `project_id:${id}`;
6582
+ }
6583
+ const name = this.computeMetadataArgs?.project_name;
6584
+ if (name) {
6585
+ return `project_name:${name}`;
6586
+ }
6587
+ return void 0;
6588
+ }
6180
6589
  };
6181
6590
  function castLogger(logger, asyncFlush) {
6182
6591
  if (logger === void 0) return void 0;
@@ -6271,12 +6680,12 @@ function stringifyWithOverflowMeta(item) {
6271
6680
  object_ids: pickLogs3OverflowObjectIds(record),
6272
6681
  is_delete: record[OBJECT_DELETE_FIELD] === true,
6273
6682
  input_row: {
6274
- byte_size: utf8ByteLength(str)
6683
+ byte_size: utf8ByteLength2(str)
6275
6684
  }
6276
6685
  }
6277
6686
  };
6278
6687
  }
6279
- function utf8ByteLength(value) {
6688
+ function utf8ByteLength2(value) {
6280
6689
  if (typeof TextEncoder !== "undefined") {
6281
6690
  return new TextEncoder().encode(value).length;
6282
6691
  }
@@ -6664,7 +7073,7 @@ var HTTPBackgroundLogger = class _HTTPBackgroundLogger {
6664
7073
  }) {
6665
7074
  const conn = await this.apiConn.get();
6666
7075
  const dataStr = constructLogs3Data(items);
6667
- const payloadBytes = utf8ByteLength(dataStr);
7076
+ const payloadBytes = utf8ByteLength2(dataStr);
6668
7077
  const useOverflow = canUseOverflow && payloadBytes > maxRequestSize;
6669
7078
  if (this.allPublishPayloadsDir) {
6670
7079
  await _HTTPBackgroundLogger.writePayloadToDir({
@@ -7285,6 +7694,8 @@ function initDataset(projectOrOptions, optionalOptions) {
7285
7694
  const normalizedVersion = selection.version;
7286
7695
  const normalizedEnvironment = selection.environment;
7287
7696
  const normalizedSnapshotName = selection.snapshotName;
7697
+ const cliInternalBtql = globalThis.__bt_eval_internal_btql;
7698
+ const internalBtql = cliInternalBtql === void 0 ? _internal_btql : _internal_btql === void 0 ? cliInternalBtql : isObject(_internal_btql) ? { ...cliInternalBtql, ..._internal_btql } : _internal_btql;
7288
7699
  const state = stateArg ?? _globalState;
7289
7700
  const lazyMetadata = new LazyValue(
7290
7701
  async () => {
@@ -7336,7 +7747,7 @@ function initDataset(projectOrOptions, optionalOptions) {
7336
7747
  lazyMetadata,
7337
7748
  typeof resolvedVersion === "string" ? resolvedVersion : void 0,
7338
7749
  legacy,
7339
- _internal_btql,
7750
+ internalBtql,
7340
7751
  resolvedVersion instanceof LazyValue || normalizedEnvironment !== void 0 || normalizedSnapshotName !== void 0 ? {
7341
7752
  ...resolvedVersion instanceof LazyValue ? {
7342
7753
  lazyPinnedVersion: resolvedVersion
@@ -7800,23 +8211,285 @@ function currentSpan(options) {
7800
8211
  const state = options?.state ?? _globalState;
7801
8212
  return state.contextManager.getCurrentSpan() ?? NOOP_SPAN;
7802
8213
  }
7803
- function getSpanParentObject(options) {
8214
+ function getSpanParentObjectAndPropagatedState(options) {
7804
8215
  const state = options?.state ?? _globalState;
7805
8216
  const parentSpan = currentSpan({ state });
7806
8217
  if (!Object.is(parentSpan, NOOP_SPAN)) {
7807
- return parentSpan;
8218
+ return { parentObject: parentSpan, propagatedState: void 0 };
8219
+ }
8220
+ const parent = options?.parent ?? state.currentParent.getStore();
8221
+ const { parentSlug, propagatedState } = normalizeParent(parent, state);
8222
+ if (parentSlug) {
8223
+ return {
8224
+ parentObject: SpanComponentsV4.fromStr(parentSlug),
8225
+ propagatedState
8226
+ };
7808
8227
  }
7809
- const parentStr = options?.parent ?? state.currentParent.getStore();
7810
- if (parentStr) return getSpanComponentsClass().fromStr(parentStr);
7811
8228
  const experiment = currentExperiment();
7812
8229
  if (experiment) {
7813
- return experiment;
8230
+ return { parentObject: experiment, propagatedState: void 0 };
7814
8231
  }
7815
8232
  const logger = currentLogger(options);
7816
8233
  if (logger) {
7817
- return logger;
8234
+ return { parentObject: logger, propagatedState: void 0 };
8235
+ }
8236
+ return { parentObject: NOOP_SPAN, propagatedState: void 0 };
8237
+ }
8238
+ function getSpanParentObject(options) {
8239
+ return getSpanParentObjectAndPropagatedState(options).parentObject;
8240
+ }
8241
+ function currentBraintrustParent(state) {
8242
+ const resolvedState = state ?? _globalState;
8243
+ const experiment = currentExperiment({ state: resolvedState });
8244
+ if (experiment) {
8245
+ try {
8246
+ return experiment._getOtelParent() ?? void 0;
8247
+ } catch {
8248
+ return void 0;
8249
+ }
8250
+ }
8251
+ const logger = currentLogger({ state: resolvedState });
8252
+ if (logger) {
8253
+ try {
8254
+ return logger._getOtelParent() ?? void 0;
8255
+ } catch {
8256
+ return void 0;
8257
+ }
8258
+ }
8259
+ return void 0;
8260
+ }
8261
+ function braintrustParentToComponents(braintrustParent) {
8262
+ if (!braintrustParent) {
8263
+ return void 0;
8264
+ }
8265
+ if (braintrustParent.startsWith("project_id:")) {
8266
+ const objectId = braintrustParent.slice("project_id:".length);
8267
+ return objectId ? {
8268
+ objectType: 2 /* PROJECT_LOGS */,
8269
+ objectId,
8270
+ computeArgs: void 0
8271
+ } : void 0;
8272
+ }
8273
+ if (braintrustParent.startsWith("project_name:")) {
8274
+ const name = braintrustParent.slice("project_name:".length);
8275
+ return name ? {
8276
+ objectType: 2 /* PROJECT_LOGS */,
8277
+ objectId: void 0,
8278
+ computeArgs: { project_name: name }
8279
+ } : void 0;
8280
+ }
8281
+ if (braintrustParent.startsWith("experiment_id:")) {
8282
+ const objectId = braintrustParent.slice("experiment_id:".length);
8283
+ return objectId ? {
8284
+ objectType: 1 /* EXPERIMENT */,
8285
+ objectId,
8286
+ computeArgs: void 0
8287
+ } : void 0;
8288
+ }
8289
+ return void 0;
8290
+ }
8291
+ function isMutableHeaderTupleArray(carrier) {
8292
+ return Array.isArray(carrier) && carrier.every((item) => Array.isArray(item) && typeof item[0] === "string");
8293
+ }
8294
+ function setHeader(carrier, name, value) {
8295
+ if (isMutableHeaderTupleArray(carrier)) {
8296
+ const lowered2 = name.toLowerCase();
8297
+ for (let i = carrier.length - 1; i >= 0; i--) {
8298
+ if (carrier[i][0].toLowerCase() === lowered2) {
8299
+ carrier.splice(i, 1);
8300
+ }
8301
+ }
8302
+ carrier.push([name, value]);
8303
+ return;
8304
+ }
8305
+ const setter = carrier.set;
8306
+ if (typeof setter === "function") {
8307
+ const deleter = carrier.delete;
8308
+ if (typeof deleter === "function") {
8309
+ try {
8310
+ deleter.call(carrier, name);
8311
+ } catch {
8312
+ }
8313
+ }
8314
+ setter.call(carrier, name, value);
8315
+ return;
8316
+ }
8317
+ const nodeSetter = carrier.setHeader;
8318
+ if (typeof nodeSetter === "function") {
8319
+ const remover = carrier.removeHeader;
8320
+ if (typeof remover === "function") {
8321
+ try {
8322
+ remover.call(carrier, name);
8323
+ } catch {
8324
+ }
8325
+ }
8326
+ nodeSetter.call(carrier, name, value);
8327
+ return;
8328
+ }
8329
+ const headerSetter = carrier.header;
8330
+ if (typeof headerSetter === "function") {
8331
+ const deleter = carrier.delete;
8332
+ if (typeof deleter === "function") {
8333
+ try {
8334
+ deleter.call(carrier, name);
8335
+ } catch {
8336
+ }
8337
+ }
8338
+ const remover = carrier.removeHeader;
8339
+ if (typeof remover === "function") {
8340
+ try {
8341
+ remover.call(carrier, name);
8342
+ } catch {
8343
+ }
8344
+ }
8345
+ headerSetter.call(carrier, name, value);
8346
+ return;
8347
+ }
8348
+ const headerBag = carrier;
8349
+ const lowered = name.toLowerCase();
8350
+ for (const key of Object.keys(headerBag)) {
8351
+ if (key !== name && key.toLowerCase() === lowered) {
8352
+ delete headerBag[key];
8353
+ }
8354
+ }
8355
+ headerBag[name] = value;
8356
+ }
8357
+ function deleteHeader(carrier, name) {
8358
+ const lowered = name.toLowerCase();
8359
+ if (isMutableHeaderTupleArray(carrier)) {
8360
+ for (let i = carrier.length - 1; i >= 0; i--) {
8361
+ if (carrier[i][0].toLowerCase() === lowered) {
8362
+ carrier.splice(i, 1);
8363
+ }
8364
+ }
8365
+ return;
8366
+ }
8367
+ const deleter = carrier.delete;
8368
+ if (typeof deleter === "function") {
8369
+ try {
8370
+ deleter.call(carrier, name);
8371
+ return;
8372
+ } catch {
8373
+ }
8374
+ }
8375
+ const remover = carrier.removeHeader;
8376
+ if (typeof remover === "function") {
8377
+ try {
8378
+ remover.call(carrier, name);
8379
+ return;
8380
+ } catch {
8381
+ }
7818
8382
  }
7819
- return NOOP_SPAN;
8383
+ const headerBag = carrier;
8384
+ for (const key of Object.keys(headerBag)) {
8385
+ if (key.toLowerCase() === lowered) {
8386
+ delete headerBag[key];
8387
+ }
8388
+ }
8389
+ }
8390
+ function _injectIntoCarrier(carrier, args) {
8391
+ const traceFlags = args.propagatedState?.traceFlags;
8392
+ const traceparent = traceFlags ? formatTraceparent(args.traceId, args.spanId, traceFlags) : formatTraceparent(args.traceId, args.spanId);
8393
+ if (traceparent === void 0) {
8394
+ return;
8395
+ }
8396
+ setHeader(carrier, TRACEPARENT_HEADER, traceparent);
8397
+ const tracestate = args.propagatedState?.tracestate;
8398
+ if (tracestate) {
8399
+ setHeader(carrier, TRACESTATE_HEADER, tracestate);
8400
+ }
8401
+ const existing = getHeader(carrier, BAGGAGE_HEADER);
8402
+ const baggageValue = mergeBaggage(existing, args.braintrustParent);
8403
+ if (baggageValue !== void 0) {
8404
+ setHeader(carrier, BAGGAGE_HEADER, baggageValue);
8405
+ } else if (existing !== void 0) {
8406
+ deleteHeader(carrier, BAGGAGE_HEADER);
8407
+ }
8408
+ }
8409
+ function injectTraceContext(carrier, options) {
8410
+ const resolvedCarrier = carrier ?? {};
8411
+ const span = options?.span ?? currentSpan({ state: options?.state });
8412
+ try {
8413
+ return span.inject(resolvedCarrier);
8414
+ } catch (e) {
8415
+ debugLogger.warn(`Error injecting trace context: ${e}`);
8416
+ return resolvedCarrier;
8417
+ }
8418
+ }
8419
+ function extractTraceContextFromHeaders(headers) {
8420
+ if (!headers) {
8421
+ return void 0;
8422
+ }
8423
+ const traceparent = getHeader(headers, TRACEPARENT_HEADER);
8424
+ if (!traceparent || parseTraceparent(traceparent) === void 0) {
8425
+ return void 0;
8426
+ }
8427
+ const context = { [TRACEPARENT_HEADER]: traceparent };
8428
+ const baggageValue = getHeader(headers, BAGGAGE_HEADER);
8429
+ if (baggageValue) {
8430
+ context[BAGGAGE_HEADER] = baggageValue;
8431
+ }
8432
+ const tracestate = getHeader(headers, TRACESTATE_HEADER);
8433
+ if (tracestate) {
8434
+ context[TRACESTATE_HEADER] = tracestate;
8435
+ }
8436
+ return context;
8437
+ }
8438
+ function resolveW3cParent(context, state) {
8439
+ const traceparent = getHeader(context, TRACEPARENT_HEADER);
8440
+ const parsed = traceparent ? parseTraceparent(traceparent) : void 0;
8441
+ if (parsed === void 0) {
8442
+ return { parentSlug: void 0, propagatedState: void 0 };
8443
+ }
8444
+ const { traceId, spanId, traceFlags } = parsed;
8445
+ let braintrustParent = void 0;
8446
+ const baggageValue = getHeader(context, BAGGAGE_HEADER);
8447
+ if (baggageValue) {
8448
+ braintrustParent = parseBaggage(baggageValue)[BRAINTRUST_PARENT_KEY];
8449
+ }
8450
+ if (!braintrustParent) {
8451
+ braintrustParent = currentBraintrustParent(state);
8452
+ }
8453
+ if (!braintrustParent) {
8454
+ debugLogger.warn(
8455
+ "Received traceparent without a braintrust.parent and no active logger/experiment; cannot route the trace. Starting a fresh local span instead."
8456
+ );
8457
+ return { parentSlug: void 0, propagatedState: void 0 };
8458
+ }
8459
+ const parsedParent = braintrustParentToComponents(braintrustParent);
8460
+ if (parsedParent === void 0) {
8461
+ debugLogger.warn(
8462
+ `Invalid braintrust.parent: ${JSON.stringify(braintrustParent)}`
8463
+ );
8464
+ return { parentSlug: void 0, propagatedState: void 0 };
8465
+ }
8466
+ const { objectType, objectId, computeArgs } = parsedParent;
8467
+ const tracestate = getHeader(context, TRACESTATE_HEADER);
8468
+ const slug = new SpanComponentsV4({
8469
+ object_type: objectType,
8470
+ ...computeArgs ? { compute_object_metadata_args: computeArgs } : { object_id: objectId },
8471
+ row_id: "bt-propagation",
8472
+ // non-empty to enable span_id/root_span_id
8473
+ span_id: spanId,
8474
+ root_span_id: traceId
8475
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
8476
+ }).toStr();
8477
+ return {
8478
+ parentSlug: slug,
8479
+ propagatedState: { tracestate, traceFlags, braintrustParent }
8480
+ };
8481
+ }
8482
+ function normalizeParent(parent, state) {
8483
+ if (parent && typeof parent === "object") {
8484
+ return resolveW3cParent(parent, state);
8485
+ }
8486
+ return {
8487
+ parentSlug: parent ?? void 0,
8488
+ propagatedState: void 0
8489
+ };
8490
+ }
8491
+ function parentSpanIdsUsable(spanId, rootSpanId) {
8492
+ return Boolean(spanId) && Boolean(rootSpanId);
7820
8493
  }
7821
8494
  function logError(span, error) {
7822
8495
  let errorMessage = "<error>";
@@ -8024,19 +8697,23 @@ function setFetch(fetch2) {
8024
8697
  }
8025
8698
  function startSpanAndIsLogger(args) {
8026
8699
  const state = args?.state ?? _globalState;
8027
- const parentObject = getSpanParentObject({
8700
+ const { parentObject, propagatedState } = getSpanParentObjectAndPropagatedState({
8028
8701
  asyncFlush: args?.asyncFlush,
8029
8702
  parent: args?.parent,
8030
8703
  state
8031
8704
  });
8032
8705
  if (parentObject instanceof SpanComponentsV3 || parentObject instanceof SpanComponentsV4) {
8033
- const parentSpanIds = parentObject.data.row_id ? {
8706
+ const parentSpanIds = parentObject.data.row_id && parentSpanIdsUsable(
8707
+ parentObject.data.span_id,
8708
+ parentObject.data.root_span_id
8709
+ ) ? {
8034
8710
  spanId: parentObject.data.span_id,
8035
8711
  rootSpanId: parentObject.data.root_span_id
8036
8712
  } : void 0;
8713
+ const { parent: _ignoredParent, ...spanArgs } = args ?? {};
8037
8714
  const span = new SpanImpl({
8038
8715
  state,
8039
- ...args,
8716
+ ...spanArgs,
8040
8717
  parentObjectType: parentObject.data.object_type,
8041
8718
  parentObjectId: new LazyValue(
8042
8719
  spanComponentsToObjectIdLambda(state, parentObject)
@@ -8044,7 +8721,8 @@ function startSpanAndIsLogger(args) {
8044
8721
  parentComputeObjectMetadataArgs: parentObject.data.compute_object_metadata_args ?? void 0,
8045
8722
  parentSpanIds,
8046
8723
  propagatedEvent: args?.propagatedEvent ?? // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
8047
- (parentObject.data.propagated_event ?? void 0)
8724
+ (parentObject.data.propagated_event ?? void 0),
8725
+ propagatedState
8048
8726
  });
8049
8727
  return {
8050
8728
  span,
@@ -8333,11 +9011,12 @@ function validateAndSanitizeExperimentLogFullArgs(event, hasDataset) {
8333
9011
  var DEFAULT_FETCH_BATCH_SIZE = 1e3;
8334
9012
  var MAX_BTQL_ITERATIONS = 1e4;
8335
9013
  var ObjectFetcher = class {
8336
- constructor(objectType, pinnedVersion, mutateRecord, _internal_btql) {
9014
+ constructor(objectType, pinnedVersion, mutateRecord, _internal_btql, _internalBrainstoreRealtime = true) {
8337
9015
  this.objectType = objectType;
8338
9016
  this.pinnedVersion = pinnedVersion;
8339
9017
  this.mutateRecord = mutateRecord;
8340
9018
  this._internal_btql = _internal_btql;
9019
+ this._internalBrainstoreRealtime = _internalBrainstoreRealtime;
8341
9020
  }
8342
9021
  _fetchedData = void 0;
8343
9022
  get id() {
@@ -8396,7 +9075,7 @@ var ObjectFetcher = class {
8396
9075
  ...internalBtqlWithoutReservedQueryKeys
8397
9076
  },
8398
9077
  use_columnstore: false,
8399
- brainstore_realtime: true,
9078
+ brainstore_realtime: this._internalBrainstoreRealtime,
8400
9079
  query_source: `js_sdk_object_fetcher_${this.objectType}`,
8401
9080
  ...this.pinnedVersion !== void 0 ? {
8402
9081
  version: this.pinnedVersion
@@ -8745,6 +9424,15 @@ View complete results in Braintrust or run experiment.summarize() again.`
8745
9424
  object_id: await this.id
8746
9425
  }).toStr();
8747
9426
  }
9427
+ /**
9428
+ * Return this experiment's Braintrust parent string (`experiment_id:<id>`) for
9429
+ * the `braintrust.parent` baggage entry, or undefined when it cannot be
9430
+ * determined synchronously.
9431
+ */
9432
+ _getOtelParent() {
9433
+ const id = this.lazyId.getSync().value;
9434
+ return id ? `experiment_id:${id}` : void 0;
9435
+ }
8748
9436
  /**
8749
9437
  * Flush any pending rows to the server.
8750
9438
  */
@@ -8787,7 +9475,8 @@ var ReadonlyExperiment = class extends ObjectFetcher {
8787
9475
  async *asDataset(options) {
8788
9476
  const records = this.fetch(options);
8789
9477
  for await (const record of records) {
8790
- if (record.root_span_id !== record.span_id) {
9478
+ const isRoot = record.is_root ?? record.root_span_id === record.span_id;
9479
+ if (!isRoot) {
8791
9480
  continue;
8792
9481
  }
8793
9482
  const { output, expected: expectedRecord, metadata } = record;
@@ -8849,9 +9538,16 @@ var SpanImpl = class _SpanImpl {
8849
9538
  _spanId;
8850
9539
  _rootSpanId;
8851
9540
  _spanParents;
9541
+ // Inbound W3C trace-context state (tracestate + raw traceparent flags) to
9542
+ // forward on outbound propagation. Captured at the span that received it (via
9543
+ // extractTraceContextFromHeaders) and inherited by all subspans, so that any
9544
+ // inject() within the trace re-emits the upstream state unchanged, per the W3C
9545
+ // Trace Context spec. Not interpreted.
9546
+ _propagatedState;
8852
9547
  kind = "span";
8853
9548
  constructor(args) {
8854
9549
  this._state = args.state;
9550
+ this._propagatedState = args.propagatedState;
8855
9551
  const spanAttributes = args.spanAttributes ?? {};
8856
9552
  const rawEvent = args.event ?? {};
8857
9553
  const type = args.type ?? (args.parentSpanIds ? void 0 : args.defaultRootType);
@@ -8967,7 +9663,7 @@ var SpanImpl = class _SpanImpl {
8967
9663
  tags: partialRecord.tags,
8968
9664
  span_id: this._spanId,
8969
9665
  span_parents: this._spanParents,
8970
- is_root: this._spanId === this._rootSpanId,
9666
+ is_root: !this._spanParents || this._spanParents.length === 0,
8971
9667
  span_attributes: partialRecord.span_attributes
8972
9668
  };
8973
9669
  this._state.spanCache.queueWrite(
@@ -9029,7 +9725,8 @@ var SpanImpl = class _SpanImpl {
9029
9725
  parentObjectId: this.parentObjectId,
9030
9726
  parentComputeObjectMetadataArgs: this.parentComputeObjectMetadataArgs,
9031
9727
  parentSpanIds,
9032
- propagatedEvent: args?.propagatedEvent ?? this.propagatedEvent
9728
+ propagatedEvent: args?.propagatedEvent ?? this.propagatedEvent,
9729
+ propagatedState: this._propagatedState
9033
9730
  })
9034
9731
  });
9035
9732
  }
@@ -9048,7 +9745,8 @@ var SpanImpl = class _SpanImpl {
9048
9745
  parentObjectId: this.parentObjectId,
9049
9746
  parentComputeObjectMetadataArgs: this.parentComputeObjectMetadataArgs,
9050
9747
  parentSpanIds,
9051
- propagatedEvent: args?.propagatedEvent ?? this.propagatedEvent
9748
+ propagatedEvent: args?.propagatedEvent ?? this.propagatedEvent,
9749
+ propagatedState: this._propagatedState
9052
9750
  }),
9053
9751
  spanId
9054
9752
  });
@@ -9076,6 +9774,42 @@ var SpanImpl = class _SpanImpl {
9076
9774
  propagated_event: this.propagatedEvent
9077
9775
  }).toStr();
9078
9776
  }
9777
+ /**
9778
+ * Return this span's Braintrust parent string (`project_id:<id>`,
9779
+ * `project_name:<name>`, or `experiment_id:<id>`) for the `braintrust.parent`
9780
+ * baggage entry, or undefined when it cannot be determined synchronously.
9781
+ */
9782
+ _getOtelParent() {
9783
+ if (this.parentObjectType === 2 /* PROJECT_LOGS */) {
9784
+ const id = this.parentComputeObjectMetadataArgs?.project_id || this.parentObjectId.getSync().value;
9785
+ const name = this.parentComputeObjectMetadataArgs?.project_name;
9786
+ if (id) {
9787
+ return `project_id:${id}`;
9788
+ } else if (name) {
9789
+ return `project_name:${name}`;
9790
+ }
9791
+ } else if (this.parentObjectType === 1 /* EXPERIMENT */) {
9792
+ const id = this.parentComputeObjectMetadataArgs?.experiment_id || this.parentObjectId.getSync().value;
9793
+ if (id) {
9794
+ return `experiment_id:${id}`;
9795
+ }
9796
+ }
9797
+ return void 0;
9798
+ }
9799
+ inject(carrier) {
9800
+ const resolvedCarrier = carrier ?? {};
9801
+ try {
9802
+ _injectIntoCarrier(resolvedCarrier, {
9803
+ traceId: this._rootSpanId,
9804
+ spanId: this._spanId,
9805
+ braintrustParent: this._getOtelParent() ?? this._propagatedState?.braintrustParent,
9806
+ propagatedState: this._propagatedState
9807
+ });
9808
+ } catch (e) {
9809
+ debugLogger.warn(`Error injecting trace context: ${e}`);
9810
+ }
9811
+ return resolvedCarrier;
9812
+ }
9079
9813
  async permalink() {
9080
9814
  return await permalink(await this.export(), {
9081
9815
  state: this._state
@@ -9211,6 +9945,7 @@ var Dataset2 = class extends ObjectFetcher {
9211
9945
  _internal_btql
9212
9946
  );
9213
9947
  this.state = state;
9948
+ void this.__braintrust_dataset_marker;
9214
9949
  this.lazyMetadata = lazyMetadata;
9215
9950
  this.lazyPinnedVersion = pinState?.lazyPinnedVersion;
9216
9951
  this.pinnedEnvironment = pinState?.pinnedEnvironment;
@@ -9728,6 +10463,7 @@ var Prompt2 = class _Prompt {
9728
10463
  this.metadata = metadata;
9729
10464
  this.defaults = defaults;
9730
10465
  this.noTrace = noTrace;
10466
+ void this.__braintrust_prompt_marker;
9731
10467
  }
9732
10468
  parsedPromptData;
9733
10469
  hasParsedPromptData = false;
@@ -9964,6 +10700,7 @@ var Prompt2 = class _Prompt {
9964
10700
  var RemoteEvalParameters = class {
9965
10701
  constructor(metadata) {
9966
10702
  this.metadata = metadata;
10703
+ void this.__braintrust_parameters_marker;
9967
10704
  }
9968
10705
  __braintrust_parameters_marker = true;
9969
10706
  get id() {
@@ -10100,6 +10837,7 @@ var _exportsForTestingOnly = {
10100
10837
  isAsyncGeneratorFunction,
10101
10838
  resetIdGenStateForTests,
10102
10839
  validateTags,
10840
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
10103
10841
  isomorph: isomorph_default
10104
10842
  // Expose isomorph for build type detection
10105
10843
  };
@@ -11051,6 +11789,22 @@ function runStreamingCompletionHook(args) {
11051
11789
  );
11052
11790
  }
11053
11791
  }
11792
+ function runStreamingErrorHook(args) {
11793
+ if (!args.config.onError) {
11794
+ return;
11795
+ }
11796
+ try {
11797
+ args.config.onError({
11798
+ channelName: args.channelName,
11799
+ error: args.error,
11800
+ event: args.event,
11801
+ span: args.span,
11802
+ startTime: args.startTime
11803
+ });
11804
+ } catch (error) {
11805
+ debugLogger.error(`Error in onError hook for ${args.channelName}:`, error);
11806
+ }
11807
+ }
11054
11808
  function traceAsyncChannel(channel2, config) {
11055
11809
  const tracingChannel2 = channel2.tracingChannel();
11056
11810
  const states = /* @__PURE__ */ new WeakMap();
@@ -11212,6 +11966,14 @@ function traceStreamingChannel(channel2, config) {
11212
11966
  }
11213
11967
  },
11214
11968
  onError: (error) => {
11969
+ runStreamingErrorHook({
11970
+ channelName,
11971
+ config,
11972
+ error,
11973
+ event: asyncEndEvent,
11974
+ span,
11975
+ startTime
11976
+ });
11215
11977
  span.log({
11216
11978
  error: error.message
11217
11979
  });
@@ -11269,6 +12031,17 @@ function traceStreamingChannel(channel2, config) {
11269
12031
  }
11270
12032
  },
11271
12033
  error: (event) => {
12034
+ const spanData = states.get(event);
12035
+ if (spanData) {
12036
+ runStreamingErrorHook({
12037
+ channelName,
12038
+ config,
12039
+ error: event.error,
12040
+ event,
12041
+ span: spanData.span,
12042
+ startTime: spanData.startTime
12043
+ });
12044
+ }
11272
12045
  logErrorAndEnd(states, event);
11273
12046
  }
11274
12047
  };
@@ -13631,14 +14404,45 @@ function serializeAISDKToolsForLogging(tools) {
13631
14404
  return serialized;
13632
14405
  }
13633
14406
 
14407
+ // src/vendor-sdk-types/ai-sdk-v7-telemetry.ts
14408
+ var BRAINTRUST_AI_SDK_V7_OPERATION_KEY = /* @__PURE__ */ Symbol.for(
14409
+ "braintrust.ai-sdk.v7.telemetry-operation-key"
14410
+ );
14411
+
14412
+ // src/wrappers/ai-sdk/workflow-agent-context.ts
14413
+ var workflowAgentWrapperSpans = /* @__PURE__ */ new Map();
14414
+ function registerWorkflowAgentWrapperSpan(span) {
14415
+ if (span.spanId) {
14416
+ workflowAgentWrapperSpans.set(span.spanId, span);
14417
+ }
14418
+ }
14419
+ function unregisterWorkflowAgentWrapperSpan(span) {
14420
+ if (span.spanId) {
14421
+ workflowAgentWrapperSpans.delete(span.spanId);
14422
+ }
14423
+ }
14424
+ function currentWorkflowAgentWrapperSpan() {
14425
+ const parentSpanIds = _internalGetGlobalState().contextManager.getParentSpanIds()?.spanParents ?? [];
14426
+ for (const parentSpanId of parentSpanIds) {
14427
+ const span = workflowAgentWrapperSpans.get(parentSpanId);
14428
+ if (span) {
14429
+ return span;
14430
+ }
14431
+ }
14432
+ return void 0;
14433
+ }
14434
+
13634
14435
  // src/wrappers/ai-sdk/telemetry.ts
13635
14436
  function braintrustAISDKTelemetry() {
13636
14437
  const operations = /* @__PURE__ */ new Map();
14438
+ const operationKeysByCallId = /* @__PURE__ */ new Map();
14439
+ const workflowOperationKeyStore = isomorph_default.newAsyncLocalStorage();
13637
14440
  const modelSpans = /* @__PURE__ */ new Map();
13638
14441
  const objectSpans = /* @__PURE__ */ new Map();
13639
14442
  const embedSpans = /* @__PURE__ */ new Map();
13640
14443
  const rerankSpans = /* @__PURE__ */ new Map();
13641
14444
  const toolSpans = /* @__PURE__ */ new Map();
14445
+ let workflowAgentOperationCounter = 0;
13642
14446
  const runSafely = (name, callback) => {
13643
14447
  try {
13644
14448
  callback();
@@ -13646,42 +14450,333 @@ function braintrustAISDKTelemetry() {
13646
14450
  console.error(`Error in Braintrust AI SDK telemetry ${name}:`, error);
13647
14451
  }
13648
14452
  };
13649
- const startChildSpan = (callId, name, type, event) => {
13650
- const parent = operations.get(callId)?.span;
14453
+ const startChildSpan = (operationKey, name, type, event) => {
14454
+ const parent = operations.get(operationKey)?.span;
13651
14455
  const spanArgs = {
13652
14456
  name,
13653
14457
  spanAttributes: { type },
13654
14458
  ...event ? { event } : {}
13655
14459
  };
13656
14460
  const span = parent ? parent.startSpan(spanArgs) : startSpan(spanArgs);
13657
- const state = operations.get(callId);
14461
+ const state = operations.get(operationKey);
13658
14462
  if (state && type === "llm" /* LLM */) {
13659
14463
  state.hadModelChild = true;
13660
14464
  }
13661
14465
  return span;
13662
14466
  };
14467
+ const registerOperation = (state) => {
14468
+ operations.set(state.operationKey, state);
14469
+ const keys = operationKeysByCallId.get(state.callId) ?? [];
14470
+ keys.push(state.operationKey);
14471
+ operationKeysByCallId.set(state.callId, keys);
14472
+ };
14473
+ const deleteOperation = (operationKey) => {
14474
+ const state = operations.get(operationKey);
14475
+ if (!state) {
14476
+ return;
14477
+ }
14478
+ operations.delete(operationKey);
14479
+ if (workflowOperationKeyStore.getStore() === operationKey) {
14480
+ workflowOperationKeyStore.enterWith(void 0);
14481
+ }
14482
+ const keys = operationKeysByCallId.get(state.callId);
14483
+ if (!keys) {
14484
+ return;
14485
+ }
14486
+ const index = keys.indexOf(operationKey);
14487
+ if (index >= 0) {
14488
+ keys.splice(index, 1);
14489
+ }
14490
+ if (keys.length === 0) {
14491
+ operationKeysByCallId.delete(state.callId);
14492
+ }
14493
+ };
14494
+ const explicitOperationKey = (event) => {
14495
+ if (!isObject(event)) {
14496
+ return void 0;
14497
+ }
14498
+ const key = event[BRAINTRUST_AI_SDK_V7_OPERATION_KEY];
14499
+ return typeof key === "string" ? key : void 0;
14500
+ };
14501
+ const createOperationKey = (event, operationName) => {
14502
+ const explicit = explicitOperationKey(event);
14503
+ if (explicit) {
14504
+ return explicit;
14505
+ }
14506
+ if (operationName === "WorkflowAgent.stream") {
14507
+ workflowAgentOperationCounter += 1;
14508
+ return `${event.callId}:${workflowAgentOperationCounter}`;
14509
+ }
14510
+ return event.callId;
14511
+ };
14512
+ const operationKeyForCallId = (callId, mode = "active") => {
14513
+ const keys = operationKeysByCallId.get(callId);
14514
+ if (!keys || keys.length === 0) {
14515
+ return operations.has(callId) ? callId : void 0;
14516
+ }
14517
+ if (keys.length === 1) {
14518
+ return keys[0];
14519
+ }
14520
+ const wrapperSpan = currentWorkflowAgentWrapperSpan();
14521
+ if (wrapperSpan?.spanId) {
14522
+ const key = keys.find(
14523
+ (candidate) => operations.get(candidate)?.span.spanId === wrapperSpan.spanId
14524
+ );
14525
+ if (key) {
14526
+ return key;
14527
+ }
14528
+ }
14529
+ const workflowOperationKey = workflowOperationKeyStore.getStore();
14530
+ if (workflowOperationKey && keys.includes(workflowOperationKey)) {
14531
+ return workflowOperationKey;
14532
+ }
14533
+ if (callId === "workflow-agent") {
14534
+ return void 0;
14535
+ }
14536
+ return mode === "finish" ? keys[0] : keys[keys.length - 1];
14537
+ };
14538
+ const operationKeyFromEvent = (event, mode = "active") => {
14539
+ const explicit = explicitOperationKey(event);
14540
+ if (explicit && operations.has(explicit)) {
14541
+ return explicit;
14542
+ }
14543
+ if (isObject(event)) {
14544
+ const callId = event.callId;
14545
+ if (typeof callId === "string") {
14546
+ const operationKey = operationKeyForCallId(callId, mode);
14547
+ if (operationKey) {
14548
+ return operationKey;
14549
+ }
14550
+ const workflowOperationKey2 = workflowOperationKeyStore.getStore();
14551
+ if (workflowOperationKey2 && operations.has(workflowOperationKey2)) {
14552
+ return workflowOperationKey2;
14553
+ }
14554
+ return callId === "workflow-agent" ? void 0 : callId;
14555
+ }
14556
+ }
14557
+ const workflowOperationKey = workflowOperationKeyStore.getStore();
14558
+ if (workflowOperationKey && operations.has(workflowOperationKey)) {
14559
+ return workflowOperationKey;
14560
+ }
14561
+ const wrapperSpan = currentWorkflowAgentWrapperSpan();
14562
+ if (wrapperSpan?.spanId) {
14563
+ for (const [operationKey, state] of operations) {
14564
+ if (state.operationName === "WorkflowAgent.stream" && state.span.spanId === wrapperSpan.spanId) {
14565
+ return operationKey;
14566
+ }
14567
+ }
14568
+ }
14569
+ const workflowAgentKeys = operationKeysByCallId.get("workflow-agent");
14570
+ if (workflowAgentKeys?.length === 1) {
14571
+ return workflowAgentKeys[0];
14572
+ }
14573
+ if (operations.size === 1) {
14574
+ return operations.keys().next().value;
14575
+ }
14576
+ return void 0;
14577
+ };
14578
+ const closeOpenChildSpans = (operationKey, error) => {
14579
+ const openModelSpans = modelSpans.get(operationKey);
14580
+ if (openModelSpans) {
14581
+ for (const span of openModelSpans) {
14582
+ if (error !== void 0) {
14583
+ logError(span, error);
14584
+ }
14585
+ span.end();
14586
+ }
14587
+ modelSpans.delete(operationKey);
14588
+ }
14589
+ const openObjectSpan = objectSpans.get(operationKey);
14590
+ if (openObjectSpan) {
14591
+ if (error !== void 0) {
14592
+ logError(openObjectSpan, error);
14593
+ }
14594
+ openObjectSpan.end();
14595
+ objectSpans.delete(operationKey);
14596
+ }
14597
+ for (const [embedCallId, embedState] of embedSpans) {
14598
+ if (embedState.operationKey === operationKey) {
14599
+ if (error !== void 0) {
14600
+ logError(embedState.span, error);
14601
+ }
14602
+ embedState.span.end();
14603
+ embedSpans.delete(embedCallId);
14604
+ }
14605
+ }
14606
+ const openRerankSpan = rerankSpans.get(operationKey);
14607
+ if (openRerankSpan) {
14608
+ if (error !== void 0) {
14609
+ logError(openRerankSpan, error);
14610
+ }
14611
+ openRerankSpan.end();
14612
+ rerankSpans.delete(operationKey);
14613
+ }
14614
+ for (const [toolCallId, toolState] of toolSpans) {
14615
+ if (toolState.operationKey === operationKey) {
14616
+ if (error !== void 0) {
14617
+ logError(toolState.span, error);
14618
+ }
14619
+ toolState.span.end();
14620
+ toolSpans.delete(toolCallId);
14621
+ }
14622
+ }
14623
+ };
14624
+ const abortReasonFromEvent = (event) => {
14625
+ if (isObject(event)) {
14626
+ const abortEvent = event;
14627
+ if (abortEvent.error !== void 0) {
14628
+ return abortEvent.error;
14629
+ }
14630
+ if (abortEvent.reason !== void 0) {
14631
+ return abortEvent.reason;
14632
+ }
14633
+ }
14634
+ return new Error("AI SDK operation aborted");
14635
+ };
14636
+ const shouldSkipTelemetryChildren = (state) => state?.operationName === "WorkflowAgent.stream" && !state.ownsSpan;
14637
+ const onObjectStepEnd = (event) => {
14638
+ runSafely("onObjectStepEnd", () => {
14639
+ const operationKey = operationKeyFromEvent(event);
14640
+ const span = operationKey ? objectSpans.get(operationKey) : void 0;
14641
+ if (!operationKey || !span) {
14642
+ return;
14643
+ }
14644
+ const result = {
14645
+ ...event,
14646
+ text: event.objectText
14647
+ };
14648
+ span.log({
14649
+ ...shouldRecordOutputs(event) ? {
14650
+ output: processAISDKOutput(result, DEFAULT_DENY_OUTPUT_PATHS)
14651
+ } : {},
14652
+ metrics: extractTokenMetrics(result)
14653
+ });
14654
+ span.end();
14655
+ objectSpans.delete(operationKey);
14656
+ });
14657
+ };
14658
+ const onEmbedEnd = (event) => {
14659
+ runSafely("onEmbedEnd", () => {
14660
+ const state = embedSpans.get(event.embedCallId);
14661
+ if (!state) {
14662
+ return;
14663
+ }
14664
+ const result = {
14665
+ ...event,
14666
+ embeddings: event.embeddings
14667
+ };
14668
+ state.span.log({
14669
+ ...shouldRecordOutputs(event) ? {
14670
+ output: processAISDKEmbeddingOutput(
14671
+ result,
14672
+ DEFAULT_DENY_OUTPUT_PATHS
14673
+ )
14674
+ } : {},
14675
+ metrics: extractTokenMetrics(result)
14676
+ });
14677
+ state.span.end();
14678
+ embedSpans.delete(event.embedCallId);
14679
+ });
14680
+ };
14681
+ const onRerankEnd = (event) => {
14682
+ runSafely("onRerankEnd", () => {
14683
+ const operationKey = operationKeyFromEvent(event);
14684
+ const span = operationKey ? rerankSpans.get(operationKey) : void 0;
14685
+ if (!operationKey || !span) {
14686
+ return;
14687
+ }
14688
+ const result = {
14689
+ ranking: event.ranking?.map((entry) => ({
14690
+ originalIndex: entry.index,
14691
+ score: entry.relevanceScore
14692
+ }))
14693
+ };
14694
+ span.log({
14695
+ ...shouldRecordOutputs(event) ? {
14696
+ output: processAISDKRerankOutput(
14697
+ result,
14698
+ DEFAULT_DENY_OUTPUT_PATHS
14699
+ )
14700
+ } : {}
14701
+ });
14702
+ span.end();
14703
+ rerankSpans.delete(operationKey);
14704
+ });
14705
+ };
14706
+ const onEnd = (event) => {
14707
+ runSafely("onEnd", () => {
14708
+ const operationKey = operationKeyFromEvent(event, "finish");
14709
+ const state = operationKey ? operations.get(operationKey) : void 0;
14710
+ if (!state) {
14711
+ return;
14712
+ }
14713
+ if (!state.ownsSpan) {
14714
+ deleteOperation(state.operationKey);
14715
+ return;
14716
+ }
14717
+ const result = finishResult(event, state.operationName);
14718
+ const metrics = state.hadModelChild ? {} : extractTokenMetrics(result);
14719
+ const timeToFirstToken = state.operationName === "WorkflowAgent.stream" ? void 0 : extractTimeToFirstToken(result, state);
14720
+ if (timeToFirstToken !== void 0) {
14721
+ metrics.time_to_first_token = timeToFirstToken;
14722
+ }
14723
+ state.span.log({
14724
+ ...shouldRecordOutputs(event) ? {
14725
+ output: finishOutput(result, state.operationName)
14726
+ } : {},
14727
+ metrics
14728
+ });
14729
+ state.span.end();
14730
+ deleteOperation(state.operationKey);
14731
+ });
14732
+ };
13663
14733
  return {
13664
14734
  onStart(event) {
13665
14735
  runSafely("onStart", () => {
13666
14736
  const operationName = operationNameFromId(event.operationId);
13667
- const span = startSpan({
14737
+ const workflowAgent = operationName === "WorkflowAgent.stream";
14738
+ const wrapperSpan = workflowAgent ? currentWorkflowAgentWrapperSpan() : void 0;
14739
+ const ownsSpan = !wrapperSpan;
14740
+ const span = ownsSpan ? startSpan({
13668
14741
  name: operationName,
13669
14742
  spanAttributes: { type: "function" /* FUNCTION */ }
13670
- });
13671
- operations.set(event.callId, {
14743
+ }) : wrapperSpan;
14744
+ const operationKey = createOperationKey(event, operationName);
14745
+ registerOperation({
14746
+ callId: event.callId,
13672
14747
  hadModelChild: false,
14748
+ loggedInput: false,
13673
14749
  operationName,
14750
+ operationKey,
14751
+ ownsSpan,
13674
14752
  span,
13675
14753
  startTime: getCurrentUnixTimestamp()
13676
14754
  });
13677
- const metadata = metadataFromEvent(event);
14755
+ if (!ownsSpan) {
14756
+ return;
14757
+ }
14758
+ if (workflowAgent) {
14759
+ workflowOperationKeyStore.enterWith(operationKey);
14760
+ }
14761
+ let metadata = metadataFromEvent(event);
13678
14762
  const logPayload = { metadata };
14763
+ const workflowAgentCallInput = workflowAgent ? operationInput(event, operationName) : void 0;
14764
+ if (workflowAgentCallInput) {
14765
+ metadata = {
14766
+ ...metadata,
14767
+ ...extractWorkflowMetadataFromCallParams(workflowAgentCallInput)
14768
+ };
14769
+ logPayload.metadata = metadata;
14770
+ }
13679
14771
  if (shouldRecordInputs(event)) {
13680
- const { input, outputPromise } = processAISDKCallInput(
13681
- operationInput(event, operationName)
13682
- );
14772
+ const callInput = workflowAgentCallInput ?? operationInput(event, operationName);
14773
+ const { input, outputPromise } = workflowAgent ? processAISDKWorkflowAgentCallInput(callInput) : processAISDKCallInput(callInput);
13683
14774
  logPayload.input = input;
13684
- if (outputPromise && input && typeof input === "object") {
14775
+ const state = operations.get(operationKey);
14776
+ if (state) {
14777
+ state.loggedInput = hasPromptLikeInput(input);
14778
+ }
14779
+ if (outputPromise && !workflowAgent && input && typeof input === "object") {
13685
14780
  outputPromise.then((resolvedData) => {
13686
14781
  span.log({
13687
14782
  input: {
@@ -13698,41 +14793,67 @@ function braintrustAISDKTelemetry() {
13698
14793
  },
13699
14794
  onLanguageModelCallStart(event) {
13700
14795
  runSafely("onLanguageModelCallStart", () => {
13701
- const state = operations.get(event.callId);
13702
- const openSpans = modelSpans.get(event.callId);
13703
- if (openSpans) {
14796
+ const operationKey = operationKeyFromEvent(event);
14797
+ const state = operationKey ? operations.get(operationKey) : void 0;
14798
+ if (shouldSkipTelemetryChildren(state)) {
14799
+ return;
14800
+ }
14801
+ const operationName = state?.operationName ?? "generateText";
14802
+ const callInput = operationInput(event, operationName);
14803
+ const workflowAgent = operationName === "WorkflowAgent.stream";
14804
+ const processedInput = shouldRecordInputs(event) && workflowAgent ? processAISDKWorkflowAgentModelCallInput(callInput).input : shouldRecordInputs(event) ? processAISDKCallInput(callInput).input : void 0;
14805
+ if (workflowAgent && state?.ownsSpan && !state.loggedInput && hasPromptLikeInput(processedInput)) {
14806
+ state.span.log({
14807
+ input: processedInput,
14808
+ metadata: {
14809
+ ...metadataFromEvent(event),
14810
+ ...extractWorkflowMetadataFromCallParams(callInput)
14811
+ }
14812
+ });
14813
+ state.loggedInput = true;
14814
+ }
14815
+ const openSpans = operationKey ? modelSpans.get(operationKey) : void 0;
14816
+ if (operationKey && openSpans) {
13704
14817
  for (const span2 of openSpans) {
13705
14818
  span2.end();
13706
14819
  }
13707
- modelSpans.delete(event.callId);
14820
+ modelSpans.delete(operationKey);
13708
14821
  }
13709
14822
  const span = startChildSpan(
13710
- event.callId,
13711
- state?.operationName === "streamText" ? "doStream" : "doGenerate",
14823
+ operationKey ?? event.callId,
14824
+ operationName === "streamText" ? "doStream" : "doGenerate",
13712
14825
  "llm" /* LLM */,
13713
14826
  {
13714
14827
  ...shouldRecordInputs(event) ? {
13715
- input: processAISDKCallInput(
13716
- operationInput(
13717
- event,
13718
- state?.operationName ?? "generateText"
13719
- )
13720
- ).input
14828
+ input: processedInput
13721
14829
  } : {},
13722
- metadata: metadataFromEvent(event)
14830
+ metadata: workflowAgent ? {
14831
+ ...metadataFromEvent(event),
14832
+ ...extractWorkflowMetadataFromCallParams(callInput)
14833
+ } : metadataFromEvent(event)
13723
14834
  }
13724
14835
  );
13725
- const spans = modelSpans.get(event.callId) ?? [];
14836
+ const spanKey = operationKey ?? event.callId;
14837
+ const spans = modelSpans.get(spanKey) ?? [];
13726
14838
  spans.push(span);
13727
- modelSpans.set(event.callId, spans);
14839
+ modelSpans.set(spanKey, spans);
13728
14840
  });
13729
14841
  },
13730
14842
  onLanguageModelCallEnd(event) {
13731
14843
  runSafely("onLanguageModelCallEnd", () => {
13732
- const span = shiftModelSpan(modelSpans, event.callId);
14844
+ const operationKey = operationKeyFromEvent(event);
14845
+ const state = operationKey ? operations.get(operationKey) : void 0;
14846
+ if (shouldSkipTelemetryChildren(state)) {
14847
+ return;
14848
+ }
14849
+ const span = operationKey ? shiftModelSpan(modelSpans, operationKey) : void 0;
13733
14850
  if (!span) {
13734
14851
  return;
13735
14852
  }
14853
+ const timeToFirstOutputMs = safePerformance(event)?.timeToFirstOutputMs;
14854
+ if (state?.operationName === "streamText" && state.firstChunkTime === void 0 && typeof timeToFirstOutputMs === "number") {
14855
+ state.firstChunkTime = state.startTime + timeToFirstOutputMs / 1e3;
14856
+ }
13736
14857
  const result = {
13737
14858
  ...event,
13738
14859
  response: event.responseId ? { id: event.responseId } : void 0
@@ -13748,14 +14869,18 @@ function braintrustAISDKTelemetry() {
13748
14869
  },
13749
14870
  onObjectStepStart(event) {
13750
14871
  runSafely("onObjectStepStart", () => {
13751
- const state = operations.get(event.callId);
13752
- const openSpan = objectSpans.get(event.callId);
13753
- if (openSpan) {
14872
+ const operationKey = operationKeyFromEvent(event);
14873
+ const state = operationKey ? operations.get(operationKey) : void 0;
14874
+ if (shouldSkipTelemetryChildren(state)) {
14875
+ return;
14876
+ }
14877
+ const openSpan = operationKey ? objectSpans.get(operationKey) : void 0;
14878
+ if (operationKey && openSpan) {
13754
14879
  openSpan.end();
13755
- objectSpans.delete(event.callId);
14880
+ objectSpans.delete(operationKey);
13756
14881
  }
13757
14882
  const span = startChildSpan(
13758
- event.callId,
14883
+ operationKey ?? event.callId,
13759
14884
  state?.operationName === "streamObject" ? "doStream" : "doGenerate",
13760
14885
  "llm" /* LLM */,
13761
14886
  {
@@ -13767,40 +14892,25 @@ function braintrustAISDKTelemetry() {
13767
14892
  metadata: metadataFromEvent(event)
13768
14893
  }
13769
14894
  );
13770
- objectSpans.set(event.callId, span);
13771
- });
13772
- },
13773
- onObjectStepFinish(event) {
13774
- runSafely("onObjectStepFinish", () => {
13775
- const span = objectSpans.get(event.callId);
13776
- if (!span) {
13777
- return;
13778
- }
13779
- const result = {
13780
- ...event,
13781
- text: event.objectText
13782
- };
13783
- span.log({
13784
- ...shouldRecordOutputs(event) ? {
13785
- output: processAISDKOutput(result, DEFAULT_DENY_OUTPUT_PATHS)
13786
- } : {},
13787
- metrics: extractTokenMetrics(result)
13788
- });
13789
- span.end();
13790
- objectSpans.delete(event.callId);
14895
+ objectSpans.set(operationKey ?? event.callId, span);
13791
14896
  });
13792
14897
  },
14898
+ onObjectStepEnd,
13793
14899
  onEmbedStart(event) {
13794
14900
  runSafely("onEmbedStart", () => {
13795
- const state = operations.get(event.callId);
14901
+ const operationKey = operationKeyFromEvent(event);
14902
+ const state = operationKey ? operations.get(operationKey) : void 0;
14903
+ if (shouldSkipTelemetryChildren(state)) {
14904
+ return;
14905
+ }
13796
14906
  for (const [embedCallId, embedState] of embedSpans) {
13797
- if (embedState.callId === event.callId && (state?.operationName === "embed" || embedState.values === event.values)) {
14907
+ if (embedState.operationKey === operationKey && (state?.operationName === "embed" || embedState.values === event.values)) {
13798
14908
  embedState.span.end();
13799
14909
  embedSpans.delete(embedCallId);
13800
14910
  }
13801
14911
  }
13802
14912
  const span = startChildSpan(
13803
- event.callId,
14913
+ operationKey ?? event.callId,
13804
14914
  "doEmbed",
13805
14915
  "llm" /* LLM */,
13806
14916
  {
@@ -13813,44 +14923,27 @@ function braintrustAISDKTelemetry() {
13813
14923
  }
13814
14924
  );
13815
14925
  embedSpans.set(event.embedCallId, {
13816
- callId: event.callId,
14926
+ operationKey: operationKey ?? event.callId,
13817
14927
  span,
13818
14928
  values: event.values
13819
14929
  });
13820
14930
  });
13821
14931
  },
13822
- onEmbedFinish(event) {
13823
- runSafely("onEmbedFinish", () => {
13824
- const state = embedSpans.get(event.embedCallId);
13825
- if (!state) {
13826
- return;
13827
- }
13828
- const result = {
13829
- ...event,
13830
- embeddings: event.embeddings
13831
- };
13832
- state.span.log({
13833
- ...shouldRecordOutputs(event) ? {
13834
- output: processAISDKEmbeddingOutput(
13835
- result,
13836
- DEFAULT_DENY_OUTPUT_PATHS
13837
- )
13838
- } : {},
13839
- metrics: extractTokenMetrics(result)
13840
- });
13841
- state.span.end();
13842
- embedSpans.delete(event.embedCallId);
13843
- });
13844
- },
14932
+ onEmbedEnd,
13845
14933
  onRerankStart(event) {
13846
14934
  runSafely("onRerankStart", () => {
13847
- const openSpan = rerankSpans.get(event.callId);
13848
- if (openSpan) {
14935
+ const operationKey = operationKeyFromEvent(event);
14936
+ const state = operationKey ? operations.get(operationKey) : void 0;
14937
+ if (shouldSkipTelemetryChildren(state)) {
14938
+ return;
14939
+ }
14940
+ const openSpan = operationKey ? rerankSpans.get(operationKey) : void 0;
14941
+ if (operationKey && openSpan) {
13849
14942
  openSpan.end();
13850
- rerankSpans.delete(event.callId);
14943
+ rerankSpans.delete(operationKey);
13851
14944
  }
13852
14945
  const span = startChildSpan(
13853
- event.callId,
14946
+ operationKey ?? event.callId,
13854
14947
  "doRerank",
13855
14948
  "llm" /* LLM */,
13856
14949
  {
@@ -13864,41 +14957,23 @@ function braintrustAISDKTelemetry() {
13864
14957
  metadata: metadataFromEvent(event)
13865
14958
  }
13866
14959
  );
13867
- rerankSpans.set(event.callId, span);
13868
- });
13869
- },
13870
- onRerankFinish(event) {
13871
- runSafely("onRerankFinish", () => {
13872
- const span = rerankSpans.get(event.callId);
13873
- if (!span) {
13874
- return;
13875
- }
13876
- const result = {
13877
- ranking: event.ranking?.map((entry) => ({
13878
- originalIndex: entry.index,
13879
- score: entry.relevanceScore
13880
- }))
13881
- };
13882
- span.log({
13883
- ...shouldRecordOutputs(event) ? {
13884
- output: processAISDKRerankOutput(
13885
- result,
13886
- DEFAULT_DENY_OUTPUT_PATHS
13887
- )
13888
- } : {}
13889
- });
13890
- span.end();
13891
- rerankSpans.delete(event.callId);
14960
+ rerankSpans.set(operationKey ?? event.callId, span);
13892
14961
  });
13893
14962
  },
14963
+ onRerankEnd,
13894
14964
  onToolExecutionStart(event) {
13895
14965
  runSafely("onToolExecutionStart", () => {
14966
+ const operationKey = operationKeyFromEvent(event);
14967
+ const state = operationKey ? operations.get(operationKey) : void 0;
14968
+ if (shouldSkipTelemetryChildren(state)) {
14969
+ return;
14970
+ }
13896
14971
  const toolCallId = event.toolCall.toolCallId;
13897
- if (!toolCallId) {
14972
+ if (!operationKey || !toolCallId) {
13898
14973
  return;
13899
14974
  }
13900
14975
  const span = startChildSpan(
13901
- event.callId,
14976
+ operationKey,
13902
14977
  event.toolCall.toolName || "tool",
13903
14978
  "tool" /* TOOL */,
13904
14979
  {
@@ -13912,7 +14987,7 @@ function braintrustAISDKTelemetry() {
13912
14987
  }
13913
14988
  }
13914
14989
  );
13915
- toolSpans.set(toolCallId, { callId: event.callId, span });
14990
+ toolSpans.set(toolCallId, { operationKey, span });
13916
14991
  });
13917
14992
  },
13918
14993
  onToolExecutionEnd(event) {
@@ -13923,14 +14998,17 @@ function braintrustAISDKTelemetry() {
13923
14998
  return;
13924
14999
  }
13925
15000
  const toolOutput = event.toolOutput;
13926
- if (toolOutput?.type === "tool-error") {
15001
+ const workflowToolError = event.success === false && "error" in event ? event.error : void 0;
15002
+ if (toolOutput?.type === "tool-error" || workflowToolError !== void 0) {
15003
+ const error = toolOutput?.error ?? workflowToolError;
13927
15004
  state.span.log({
13928
- error: toolOutput.error instanceof Error ? toolOutput.error.message : String(toolOutput?.error),
15005
+ error: error instanceof Error ? error.message : String(error),
13929
15006
  metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
13930
15007
  });
13931
15008
  } else {
15009
+ const output = toolOutput && "output" in toolOutput ? toolOutput.output : event.output;
13932
15010
  state.span.log({
13933
- ...shouldRecordOutputs(event) ? { output: toolOutput?.output } : {},
15011
+ ...shouldRecordOutputs(event) ? { output } : {},
13934
15012
  metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
13935
15013
  });
13936
15014
  }
@@ -13944,83 +15022,46 @@ function braintrustAISDKTelemetry() {
13944
15022
  if (!callId) {
13945
15023
  return;
13946
15024
  }
13947
- const state = operations.get(callId);
15025
+ const operationKey = operationKeyForCallId(callId);
15026
+ const state = operationKey ? operations.get(operationKey) : void 0;
13948
15027
  if (!state || state.firstChunkTime !== void 0) {
13949
15028
  return;
13950
15029
  }
13951
15030
  state.firstChunkTime = getCurrentUnixTimestamp();
13952
15031
  });
13953
15032
  },
13954
- onFinish(event) {
13955
- runSafely("onFinish", () => {
13956
- const state = operations.get(event.callId);
13957
- if (!state) {
15033
+ onEnd,
15034
+ onAbort(event) {
15035
+ runSafely("onAbort", () => {
15036
+ const operationKey = operationKeyFromEvent(event, "finish");
15037
+ const state = operationKey ? operations.get(operationKey) : void 0;
15038
+ if (!operationKey || !state) {
13958
15039
  return;
13959
15040
  }
13960
- const result = finishResult(event, state.operationName);
13961
- const metrics = state.hadModelChild ? {} : extractTokenMetrics(result);
13962
- if (state.firstChunkTime !== void 0) {
13963
- metrics.time_to_first_token = state.firstChunkTime - state.startTime;
15041
+ const error = abortReasonFromEvent(event);
15042
+ closeOpenChildSpans(operationKey, error);
15043
+ if (state.ownsSpan) {
15044
+ logError(state.span, error);
15045
+ state.span.end();
13964
15046
  }
13965
- state.span.log({
13966
- ...shouldRecordOutputs(event) ? {
13967
- output: finishOutput(result, state.operationName)
13968
- } : {},
13969
- metrics
13970
- });
13971
- state.span.end();
13972
- operations.delete(event.callId);
15047
+ deleteOperation(operationKey);
13973
15048
  });
13974
15049
  },
13975
15050
  onError(event) {
13976
15051
  runSafely("onError", () => {
13977
15052
  const errorEvent = isObject(event) ? event : {};
13978
- const callId = typeof errorEvent.callId === "string" ? errorEvent.callId : void 0;
13979
- if (!callId) {
13980
- return;
13981
- }
13982
- const state = operations.get(callId);
13983
- if (!state) {
15053
+ const operationKey = operationKeyFromEvent(errorEvent, "finish");
15054
+ const state = operationKey ? operations.get(operationKey) : void 0;
15055
+ if (!operationKey || !state) {
13984
15056
  return;
13985
15057
  }
13986
15058
  const error = errorEvent.error ?? event;
13987
- const openModelSpans = modelSpans.get(callId);
13988
- if (openModelSpans) {
13989
- for (const span of openModelSpans) {
13990
- logError(span, error);
13991
- span.end();
13992
- }
13993
- modelSpans.delete(callId);
13994
- }
13995
- const openObjectSpan = objectSpans.get(callId);
13996
- if (openObjectSpan) {
13997
- logError(openObjectSpan, error);
13998
- openObjectSpan.end();
13999
- objectSpans.delete(callId);
14000
- }
14001
- for (const [embedCallId, embedState] of embedSpans) {
14002
- if (embedState.callId === callId) {
14003
- logError(embedState.span, error);
14004
- embedState.span.end();
14005
- embedSpans.delete(embedCallId);
14006
- }
14007
- }
14008
- const openRerankSpan = rerankSpans.get(callId);
14009
- if (openRerankSpan) {
14010
- logError(openRerankSpan, error);
14011
- openRerankSpan.end();
14012
- rerankSpans.delete(callId);
14013
- }
14014
- for (const [toolCallId, toolState] of toolSpans) {
14015
- if (toolState.callId === callId) {
14016
- logError(toolState.span, error);
14017
- toolState.span.end();
14018
- toolSpans.delete(toolCallId);
14019
- }
15059
+ closeOpenChildSpans(operationKey, error);
15060
+ if (state.ownsSpan) {
15061
+ logError(state.span, error);
15062
+ state.span.end();
14020
15063
  }
14021
- logError(state.span, error);
14022
- state.span.end();
14023
- operations.delete(callId);
15064
+ deleteOperation(operationKey);
14024
15065
  });
14025
15066
  },
14026
15067
  executeTool({ toolCallId, execute }) {
@@ -14035,7 +15076,16 @@ function shouldRecordInputs(event) {
14035
15076
  function shouldRecordOutputs(event) {
14036
15077
  return event.recordOutputs !== false;
14037
15078
  }
15079
+ function hasPromptLikeInput(input) {
15080
+ if (!isObject(input)) {
15081
+ return false;
15082
+ }
15083
+ return input.prompt !== void 0 || input.messages !== void 0;
15084
+ }
14038
15085
  function operationNameFromId(operationId) {
15086
+ if (operationId === "ai.workflowAgent.stream") {
15087
+ return "WorkflowAgent.stream";
15088
+ }
14039
15089
  return operationId?.startsWith("ai.") ? operationId.slice("ai.".length) : operationId || "ai-sdk";
14040
15090
  }
14041
15091
  function modelFromEvent(event) {
@@ -14081,6 +15131,7 @@ function operationInput(event, operationName) {
14081
15131
  }
14082
15132
  return {
14083
15133
  model: modelFromEvent(event),
15134
+ instructions: event.instructions,
14084
15135
  system: event.system,
14085
15136
  prompt: event.prompt,
14086
15137
  messages: event.messages,
@@ -14129,6 +15180,30 @@ function finishResult(event, operationName) {
14129
15180
  }
14130
15181
  return event;
14131
15182
  }
15183
+ function extractTimeToFirstToken(result, state) {
15184
+ if (state.firstChunkTime !== void 0) {
15185
+ return state.firstChunkTime - state.startTime;
15186
+ }
15187
+ const performanceCandidates = [
15188
+ safePerformance(result),
15189
+ safePerformance(result.finalStep),
15190
+ ...Array.isArray(result.steps) ? (result.steps ?? []).map(safePerformance) : []
15191
+ ];
15192
+ for (const performance2 of performanceCandidates) {
15193
+ const timeToFirstOutputMs = performance2?.timeToFirstOutputMs;
15194
+ if (typeof timeToFirstOutputMs === "number") {
15195
+ return timeToFirstOutputMs / 1e3;
15196
+ }
15197
+ }
15198
+ return void 0;
15199
+ }
15200
+ function safePerformance(value) {
15201
+ if (!isObject(value)) {
15202
+ return void 0;
15203
+ }
15204
+ const performance2 = value.performance;
15205
+ return isObject(performance2) ? performance2 : void 0;
15206
+ }
14132
15207
  function finishOutput(result, operationName) {
14133
15208
  if (operationName === "embed" || operationName === "embedMany") {
14134
15209
  return processAISDKEmbeddingOutput(
@@ -14205,6 +15280,10 @@ var aiSDKChannels = defineChannels("ai", {
14205
15280
  channelName: "ToolLoopAgent.stream",
14206
15281
  kind: "async"
14207
15282
  }),
15283
+ workflowAgentStream: channel({
15284
+ channelName: "WorkflowAgent.stream",
15285
+ kind: "async"
15286
+ }),
14208
15287
  v7CreateTelemetryDispatcher: channel({
14209
15288
  channelName: "createTelemetryDispatcher",
14210
15289
  kind: "sync-stream"
@@ -14215,14 +15294,19 @@ var aiSDKChannels = defineChannels("ai", {
14215
15294
  var DEFAULT_DENY_OUTPUT_PATHS = [
14216
15295
  // v3
14217
15296
  "roundtrips[].request.body",
15297
+ "roundtrips[].request.headers",
14218
15298
  "roundtrips[].response.headers",
14219
15299
  "rawResponse.headers",
14220
15300
  "responseMessages",
14221
15301
  // v5
14222
15302
  "request.body",
15303
+ "request.headers",
15304
+ "responses[].headers",
14223
15305
  "response.body",
14224
15306
  "response.headers",
14225
15307
  "steps[].request.body",
15308
+ "steps[].request.headers",
15309
+ "steps[].responses[].headers",
14226
15310
  "steps[].response.body",
14227
15311
  "steps[].response.headers"
14228
15312
  ];
@@ -14234,6 +15318,18 @@ var AUTO_PATCHED_V7_TELEMETRY_DISPATCHER = /* @__PURE__ */ Symbol.for(
14234
15318
  var RUNTIME_DENY_OUTPUT_PATHS = /* @__PURE__ */ Symbol.for(
14235
15319
  "braintrust.ai-sdk.deny-output-paths"
14236
15320
  );
15321
+ var aiSDKV7TelemetryOperationCounter = 0;
15322
+ var TRANSPORT_PAYLOAD_ROOT_PATHS = [
15323
+ "rawResponse",
15324
+ "request",
15325
+ "response",
15326
+ "responses[]",
15327
+ "roundtrips[].request",
15328
+ "roundtrips[].response",
15329
+ "steps[].request",
15330
+ "steps[].response",
15331
+ "steps[].responses[]"
15332
+ ];
14237
15333
  var AI_SDK_V7_TELEMETRY_CALLBACKS = [
14238
15334
  "onStart",
14239
15335
  "onStepStart",
@@ -14242,14 +15338,16 @@ var AI_SDK_V7_TELEMETRY_CALLBACKS = [
14242
15338
  "onToolExecutionStart",
14243
15339
  "onToolExecutionEnd",
14244
15340
  "onChunk",
15341
+ "onStepEnd",
14245
15342
  "onStepFinish",
14246
15343
  "onObjectStepStart",
14247
- "onObjectStepFinish",
15344
+ "onObjectStepEnd",
14248
15345
  "onEmbedStart",
14249
- "onEmbedFinish",
15346
+ "onEmbedEnd",
14250
15347
  "onRerankStart",
14251
- "onRerankFinish",
14252
- "onFinish",
15348
+ "onRerankEnd",
15349
+ "onEnd",
15350
+ "onAbort",
14253
15351
  "onError"
14254
15352
  ];
14255
15353
  var AISDKPlugin = class extends BasePlugin {
@@ -14407,7 +15505,9 @@ var AISDKPlugin = class extends BasePlugin {
14407
15505
  traceStreamingChannel(aiSDKChannels.agentGenerate, {
14408
15506
  name: "Agent.generate",
14409
15507
  type: "function" /* FUNCTION */,
14410
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
15508
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
15509
+ agentOwner: true
15510
+ }),
14411
15511
  extractOutput: (result, endEvent) => {
14412
15512
  finalizeAISDKChildTracing(endEvent);
14413
15513
  return processAISDKOutput(
@@ -14423,7 +15523,9 @@ var AISDKPlugin = class extends BasePlugin {
14423
15523
  traceStreamingChannel(aiSDKChannels.agentStream, {
14424
15524
  name: "Agent.stream",
14425
15525
  type: "function" /* FUNCTION */,
14426
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
15526
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
15527
+ agentOwner: true
15528
+ }),
14427
15529
  extractOutput: (result, endEvent) => processAISDKOutput(
14428
15530
  result,
14429
15531
  resolveDenyOutputPaths(endEvent, denyOutputPaths)
@@ -14443,7 +15545,9 @@ var AISDKPlugin = class extends BasePlugin {
14443
15545
  traceSyncStreamChannel(aiSDKChannels.agentStreamSync, {
14444
15546
  name: "Agent.stream",
14445
15547
  type: "function" /* FUNCTION */,
14446
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
15548
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
15549
+ agentOwner: true
15550
+ }),
14447
15551
  patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
14448
15552
  defaultDenyOutputPaths: denyOutputPaths,
14449
15553
  endEvent,
@@ -14457,7 +15561,9 @@ var AISDKPlugin = class extends BasePlugin {
14457
15561
  traceStreamingChannel(aiSDKChannels.toolLoopAgentGenerate, {
14458
15562
  name: "ToolLoopAgent.generate",
14459
15563
  type: "function" /* FUNCTION */,
14460
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
15564
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
15565
+ agentOwner: true
15566
+ }),
14461
15567
  extractOutput: (result, endEvent) => {
14462
15568
  finalizeAISDKChildTracing(endEvent);
14463
15569
  return processAISDKOutput(
@@ -14473,7 +15579,9 @@ var AISDKPlugin = class extends BasePlugin {
14473
15579
  traceStreamingChannel(aiSDKChannels.toolLoopAgentStream, {
14474
15580
  name: "ToolLoopAgent.stream",
14475
15581
  type: "function" /* FUNCTION */,
14476
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
15582
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
15583
+ agentOwner: true
15584
+ }),
14477
15585
  extractOutput: (result, endEvent) => processAISDKOutput(
14478
15586
  result,
14479
15587
  resolveDenyOutputPaths(endEvent, denyOutputPaths)
@@ -14489,6 +15597,42 @@ var AISDKPlugin = class extends BasePlugin {
14489
15597
  })
14490
15598
  })
14491
15599
  );
15600
+ this.unsubscribers.push(
15601
+ traceStreamingChannel(aiSDKChannels.workflowAgentStream, {
15602
+ name: "WorkflowAgent.stream",
15603
+ type: "function" /* FUNCTION */,
15604
+ extractInput: ([params], event, span) => prepareAISDKWorkflowAgentStreamInput(
15605
+ params,
15606
+ event,
15607
+ span,
15608
+ denyOutputPaths
15609
+ ),
15610
+ extractOutput: (result, endEvent) => {
15611
+ finalizeAISDKChildTracing(endEvent);
15612
+ return processAISDKOutput(
15613
+ result,
15614
+ resolveDenyOutputPaths(endEvent, denyOutputPaths)
15615
+ );
15616
+ },
15617
+ extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
15618
+ aggregateChunks: aggregateAISDKChunks,
15619
+ onComplete: ({ span }) => {
15620
+ unregisterWorkflowAgentWrapperSpan(span);
15621
+ },
15622
+ onError: ({ event, span }) => {
15623
+ finalizeAISDKChildTracing(event);
15624
+ unregisterWorkflowAgentWrapperSpan(span);
15625
+ },
15626
+ patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
15627
+ defaultDenyOutputPaths: denyOutputPaths,
15628
+ endEvent,
15629
+ onComplete: () => unregisterWorkflowAgentWrapperSpan(span),
15630
+ result,
15631
+ span,
15632
+ startTime
15633
+ })
15634
+ })
15635
+ );
14492
15636
  }
14493
15637
  };
14494
15638
  function subscribeToAISDKV7TelemetryDispatcher() {
@@ -14500,7 +15644,11 @@ function subscribeToAISDKV7TelemetryDispatcher() {
14500
15644
  if (telemetryOptions?.isEnabled === false) {
14501
15645
  return;
14502
15646
  }
14503
- patchAISDKV7TelemetryDispatcher(event.result, telemetry);
15647
+ patchAISDKV7TelemetryDispatcher(
15648
+ event.result,
15649
+ telemetry,
15650
+ telemetryOptions
15651
+ );
14504
15652
  }
14505
15653
  };
14506
15654
  channel2.subscribe(handlers);
@@ -14508,7 +15656,7 @@ function subscribeToAISDKV7TelemetryDispatcher() {
14508
15656
  channel2.unsubscribe(handlers);
14509
15657
  };
14510
15658
  }
14511
- function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
15659
+ function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry, telemetryOptions) {
14512
15660
  if (!isObject(dispatcher)) {
14513
15661
  return;
14514
15662
  }
@@ -14517,6 +15665,54 @@ function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
14517
15665
  return;
14518
15666
  }
14519
15667
  dispatcherRecord[AUTO_PATCHED_V7_TELEMETRY_DISPATCHER] = true;
15668
+ let operationKey;
15669
+ const telemetryEventFields = {};
15670
+ if (typeof telemetryOptions?.recordInputs === "boolean") {
15671
+ telemetryEventFields.recordInputs = telemetryOptions.recordInputs;
15672
+ }
15673
+ if (typeof telemetryOptions?.recordOutputs === "boolean") {
15674
+ telemetryEventFields.recordOutputs = telemetryOptions.recordOutputs;
15675
+ }
15676
+ if (typeof telemetryOptions?.functionId === "string") {
15677
+ telemetryEventFields.functionId = telemetryOptions.functionId;
15678
+ }
15679
+ const eventWithOperationKey = (event) => {
15680
+ if (!isObject(event)) {
15681
+ return event;
15682
+ }
15683
+ const eventRecord = event;
15684
+ const callId = typeof eventRecord.callId === "string" ? eventRecord.callId : "unknown";
15685
+ operationKey ??= `${callId}:${++aiSDKV7TelemetryOperationCounter}`;
15686
+ if (Object.keys(telemetryEventFields).length > 0) {
15687
+ const augmentedEvent = {
15688
+ ...telemetryEventFields,
15689
+ ...event
15690
+ };
15691
+ try {
15692
+ Object.defineProperty(augmentedEvent, BRAINTRUST_AI_SDK_V7_OPERATION_KEY, {
15693
+ configurable: true,
15694
+ enumerable: false,
15695
+ value: operationKey
15696
+ });
15697
+ } catch {
15698
+ augmentedEvent[BRAINTRUST_AI_SDK_V7_OPERATION_KEY] = operationKey;
15699
+ }
15700
+ return augmentedEvent;
15701
+ }
15702
+ try {
15703
+ Object.defineProperty(eventRecord, BRAINTRUST_AI_SDK_V7_OPERATION_KEY, {
15704
+ configurable: true,
15705
+ enumerable: false,
15706
+ value: operationKey
15707
+ });
15708
+ return event;
15709
+ } catch {
15710
+ return {
15711
+ ...event,
15712
+ [BRAINTRUST_AI_SDK_V7_OPERATION_KEY]: operationKey
15713
+ };
15714
+ }
15715
+ };
14520
15716
  for (const key of AI_SDK_V7_TELEMETRY_CALLBACKS) {
14521
15717
  const braintrustCallback = telemetry[key];
14522
15718
  if (typeof braintrustCallback !== "function") {
@@ -14525,11 +15721,17 @@ function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
14525
15721
  const existingCallback = dispatcherRecord[key];
14526
15722
  dispatcherRecord[key] = (event) => {
14527
15723
  const existingResult = typeof existingCallback === "function" ? existingCallback.call(dispatcher, event) : void 0;
14528
- const braintrustResult = braintrustCallback.call(telemetry, event);
14529
- const pending = [existingResult, braintrustResult].filter(isPromiseLike);
14530
- if (pending.length > 0) {
14531
- return Promise.allSettled(pending).then(() => void 0);
15724
+ try {
15725
+ const braintrustResult = braintrustCallback.call(
15726
+ telemetry,
15727
+ eventWithOperationKey(event)
15728
+ );
15729
+ if (isPromiseLike(braintrustResult)) {
15730
+ void Promise.resolve(braintrustResult).catch(() => void 0);
15731
+ }
15732
+ } catch {
14532
15733
  }
15734
+ return existingResult;
14533
15735
  };
14534
15736
  }
14535
15737
  const braintrustExecuteTool = telemetry.executeTool;
@@ -14539,6 +15741,7 @@ function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
14539
15741
  const existingExecuteTool = dispatcherRecord.executeTool;
14540
15742
  dispatcherRecord.executeTool = (args) => braintrustExecuteTool.call(telemetry, {
14541
15743
  ...args,
15744
+ ...operationKey ? { [BRAINTRUST_AI_SDK_V7_OPERATION_KEY]: operationKey } : {},
14542
15745
  execute: () => typeof existingExecuteTool === "function" ? existingExecuteTool.call(dispatcher, args) : args.execute()
14543
15746
  });
14544
15747
  }
@@ -14637,6 +15840,8 @@ var serializeOutputObject = (output, model) => {
14637
15840
  var processInputAttachmentsSync = (input) => {
14638
15841
  if (!input) return { input };
14639
15842
  const processed = { ...input };
15843
+ delete processed.headers;
15844
+ delete processed.experimental_output;
14640
15845
  if (input.messages && Array.isArray(input.messages)) {
14641
15846
  processed.messages = input.messages.map(processMessage);
14642
15847
  }
@@ -14670,10 +15875,10 @@ var processInputAttachmentsSync = (input) => {
14670
15875
  processed.output = serialized;
14671
15876
  }
14672
15877
  }
14673
- if ("prepareCall" in processed && typeof processed.prepareCall === "function") {
14674
- processed.prepareCall = "[Function]";
14675
- }
14676
- return { input: processed, outputPromise };
15878
+ return {
15879
+ input: sanitizeAISDKCallInputValue(processed),
15880
+ outputPromise
15881
+ };
14677
15882
  };
14678
15883
  var processMessage = (message) => {
14679
15884
  if (!message || typeof message !== "object") return message;
@@ -14837,7 +16042,21 @@ var convertDataToAttachment = (data, mimeType, filename) => {
14837
16042
  function processAISDKCallInput(params) {
14838
16043
  return processInputAttachmentsSync(params);
14839
16044
  }
14840
- function prepareAISDKCallInput(params, event, span, defaultDenyOutputPaths) {
16045
+ function processAISDKWorkflowAgentCallInput(params) {
16046
+ const processed = processAISDKCallInput(params);
16047
+ return {
16048
+ ...processed,
16049
+ input: extractWorkflowAgentInput(processed.input)
16050
+ };
16051
+ }
16052
+ function processAISDKWorkflowAgentModelCallInput(params) {
16053
+ const processed = processAISDKCallInput(params);
16054
+ return {
16055
+ ...processed,
16056
+ input: extractWorkflowAgentModelInput(processed.input)
16057
+ };
16058
+ }
16059
+ function prepareAISDKCallInput(params, event, span, defaultDenyOutputPaths, childTracingOptions = {}) {
14841
16060
  const { input, outputPromise } = processAISDKCallInput(params);
14842
16061
  if (outputPromise && input && typeof input === "object") {
14843
16062
  outputPromise.then((resolvedData) => {
@@ -14856,7 +16075,29 @@ function prepareAISDKCallInput(params, event, span, defaultDenyOutputPaths) {
14856
16075
  event.self,
14857
16076
  span,
14858
16077
  defaultDenyOutputPaths,
14859
- event.aiSDK
16078
+ event.aiSDK,
16079
+ childTracingOptions
16080
+ );
16081
+ event.modelWrapped = childTracing.modelWrapped;
16082
+ if (childTracing.cleanup) {
16083
+ event.__braintrust_ai_sdk_cleanup = childTracing.cleanup;
16084
+ }
16085
+ return {
16086
+ input,
16087
+ metadata
16088
+ };
16089
+ }
16090
+ function prepareAISDKWorkflowAgentStreamInput(params, event, span, defaultDenyOutputPaths) {
16091
+ registerWorkflowAgentWrapperSpan(span);
16092
+ const { input } = processAISDKWorkflowAgentCallInput(params);
16093
+ const metadata = extractWorkflowMetadataFromCallParams(params, event.self);
16094
+ const childTracing = prepareAISDKChildTracing(
16095
+ params,
16096
+ event.self,
16097
+ span,
16098
+ defaultDenyOutputPaths,
16099
+ event.aiSDK,
16100
+ { agentOwner: true, workflowAgent: true }
14860
16101
  );
14861
16102
  event.modelWrapped = childTracing.modelWrapped;
14862
16103
  if (childTracing.cleanup) {
@@ -14893,6 +16134,9 @@ function extractTopLevelAISDKMetrics(result, event, startTime) {
14893
16134
  function hasModelChildTracing(event) {
14894
16135
  return event?.modelWrapped === true || event?.__braintrust_ai_sdk_model_wrapped === true;
14895
16136
  }
16137
+ function serializeToolExecutionInput(args) {
16138
+ return args.length > 0 ? args[0] : args;
16139
+ }
14896
16140
  function createAISDKIntegrationMetadata() {
14897
16141
  return {
14898
16142
  braintrust: {
@@ -14904,6 +16148,13 @@ function createAISDKIntegrationMetadata() {
14904
16148
  function resolveModelFromSelf(self) {
14905
16149
  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;
14906
16150
  }
16151
+ function resolveToolsFromSelf(self) {
16152
+ if (!self || typeof self !== "object") {
16153
+ return void 0;
16154
+ }
16155
+ const selfRecord = self;
16156
+ return selfRecord.tools ?? selfRecord.settings?.tools;
16157
+ }
14907
16158
  function extractBaseMetadata(model, self) {
14908
16159
  const metadata = createAISDKIntegrationMetadata();
14909
16160
  const { model: modelId, provider } = serializeModelWithProvider(
@@ -14919,12 +16170,175 @@ function extractBaseMetadata(model, self) {
14919
16170
  }
14920
16171
  function extractMetadataFromCallParams(params, self) {
14921
16172
  const metadata = extractBaseMetadata(params.model, self);
14922
- const tools = serializeAISDKToolsForLogging(params.tools);
16173
+ const tools = serializeAISDKToolsForLogging(
16174
+ params.tools ?? resolveToolsFromSelf(self)
16175
+ );
14923
16176
  if (tools) {
14924
16177
  metadata.tools = tools;
14925
16178
  }
14926
16179
  return metadata;
14927
16180
  }
16181
+ function extractWorkflowMetadataFromCallParams(params, self) {
16182
+ const metadata = extractMetadataFromCallParams(params, self);
16183
+ const options = extractAISDKCallOptionsForMetadata(params);
16184
+ if (Object.keys(options).length > 0) {
16185
+ metadata.options = options;
16186
+ }
16187
+ return metadata;
16188
+ }
16189
+ function extractWorkflowAgentInput(params) {
16190
+ const input = {};
16191
+ if (params.instructions !== void 0) {
16192
+ input.instructions = params.instructions;
16193
+ }
16194
+ if (params.system !== void 0) {
16195
+ input.system = params.system;
16196
+ }
16197
+ if (Array.isArray(params.messages)) {
16198
+ return { ...input, messages: params.messages };
16199
+ }
16200
+ if (typeof params.prompt === "string") {
16201
+ return { ...input, prompt: params.prompt };
16202
+ }
16203
+ if (Array.isArray(params.prompt)) {
16204
+ return { ...input, prompt: params.prompt };
16205
+ }
16206
+ return input;
16207
+ }
16208
+ function extractWorkflowAgentModelInput(params) {
16209
+ const input = {};
16210
+ if (params.instructions !== void 0) {
16211
+ input.instructions = params.instructions;
16212
+ }
16213
+ if (params.system !== void 0) {
16214
+ input.system = params.system;
16215
+ }
16216
+ if (Array.isArray(params.messages)) {
16217
+ return { ...input, messages: params.messages };
16218
+ }
16219
+ if (typeof params.prompt === "string") {
16220
+ return { ...input, prompt: params.prompt };
16221
+ }
16222
+ if (Array.isArray(params.prompt)) {
16223
+ return { ...input, messages: params.prompt };
16224
+ }
16225
+ return input;
16226
+ }
16227
+ function sanitizeAISDKCallInputValue(value, depth = 0) {
16228
+ if (value === void 0 || typeof value === "function") {
16229
+ return void 0;
16230
+ }
16231
+ if (value === null || typeof value !== "object") {
16232
+ return value;
16233
+ }
16234
+ if (isPromiseLike(value)) {
16235
+ return "[Promise]";
16236
+ }
16237
+ if (typeof AbortSignal !== "undefined" && value instanceof AbortSignal) {
16238
+ return "[AbortSignal]";
16239
+ }
16240
+ if (depth >= 8) {
16241
+ return "[Object]";
16242
+ }
16243
+ if (Array.isArray(value)) {
16244
+ return value.map((item) => sanitizeAISDKCallInputValue(item, depth + 1)).filter((item) => item !== void 0);
16245
+ }
16246
+ if (!isObject(value)) {
16247
+ return value;
16248
+ }
16249
+ const prototype = Object.getPrototypeOf(value);
16250
+ if (prototype !== Object.prototype && prototype !== null) {
16251
+ return value;
16252
+ }
16253
+ const sanitized = {};
16254
+ for (const [key, nested] of Object.entries(value)) {
16255
+ if (key === "__proto__" || key === "constructor" || key === "prototype" || key.toLowerCase() === "headers") {
16256
+ continue;
16257
+ }
16258
+ const sanitizedNested = sanitizeAISDKCallInputValue(nested, depth + 1);
16259
+ if (sanitizedNested !== void 0) {
16260
+ sanitized[key] = sanitizedNested;
16261
+ }
16262
+ }
16263
+ return sanitized;
16264
+ }
16265
+ function extractAISDKCallOptionsForMetadata(params) {
16266
+ const options = {};
16267
+ const inputOrTopLevelKeys = /* @__PURE__ */ new Set([
16268
+ "model",
16269
+ "instructions",
16270
+ "messages",
16271
+ "prompt",
16272
+ "system",
16273
+ "tools",
16274
+ "headers",
16275
+ "abortSignal",
16276
+ "signal",
16277
+ "experimental_output"
16278
+ ]);
16279
+ for (const [key, value] of Object.entries(params)) {
16280
+ if (inputOrTopLevelKeys.has(key) || key === "__proto__" || key === "constructor" || key === "prototype" || /^on[A-Z]/.test(key) && typeof value === "function") {
16281
+ continue;
16282
+ }
16283
+ const sanitized = sanitizeAISDKMetadataValue(value);
16284
+ if (sanitized !== void 0) {
16285
+ options[key] = sanitized;
16286
+ }
16287
+ }
16288
+ return options;
16289
+ }
16290
+ function sanitizeAISDKMetadataValue(value, depth = 0) {
16291
+ if (value === void 0) {
16292
+ return void 0;
16293
+ }
16294
+ if (typeof value === "function") {
16295
+ return "[Function]";
16296
+ }
16297
+ if (value === null || typeof value !== "object") {
16298
+ return value;
16299
+ }
16300
+ if (isPromiseLike(value)) {
16301
+ return "[Promise]";
16302
+ }
16303
+ if (typeof AbortSignal !== "undefined" && value instanceof AbortSignal) {
16304
+ return "[AbortSignal]";
16305
+ }
16306
+ if (depth >= 8) {
16307
+ return "[Object]";
16308
+ }
16309
+ if (Array.isArray(value)) {
16310
+ return value.map((item) => sanitizeAISDKMetadataValue(item, depth + 1)).filter((item) => item !== void 0);
16311
+ }
16312
+ if (!isObject(value)) {
16313
+ return value;
16314
+ }
16315
+ const sanitized = {};
16316
+ for (const [key, nested] of Object.entries(value)) {
16317
+ if (key === "__proto__" || key === "constructor" || key === "prototype" || key.toLowerCase() === "headers") {
16318
+ continue;
16319
+ }
16320
+ const sanitizedNested = sanitizeAISDKMetadataValue(nested, depth + 1);
16321
+ if (sanitizedNested !== void 0) {
16322
+ sanitized[key] = sanitizedNested;
16323
+ }
16324
+ }
16325
+ return sanitized;
16326
+ }
16327
+ function buildAISDKModelStartEvent(callOptions, baseMetadata, options) {
16328
+ if (!options.workflowAgent) {
16329
+ return {
16330
+ input: processAISDKCallInput(callOptions).input,
16331
+ metadata: baseMetadata
16332
+ };
16333
+ }
16334
+ return {
16335
+ input: processAISDKWorkflowAgentModelCallInput(callOptions).input,
16336
+ metadata: {
16337
+ ...baseMetadata,
16338
+ ...extractWorkflowMetadataFromCallParams(callOptions)
16339
+ }
16340
+ };
16341
+ }
14928
16342
  function extractMetadataFromEmbedParams(params, self) {
14929
16343
  return extractBaseMetadata(params.model, self);
14930
16344
  }
@@ -14938,72 +16352,273 @@ function extractMetadataFromRerankParams(params, self) {
14938
16352
  }
14939
16353
  return metadata;
14940
16354
  }
14941
- function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiSDK) {
16355
+ function activeAISDKChildPatchEntry(entries) {
16356
+ const activeSpan = currentSpan();
16357
+ const activeSpanId = activeSpan.spanId;
16358
+ if (activeSpanId) {
16359
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
16360
+ const entry = entries[index];
16361
+ if (entry?.activeSpanIds.has(activeSpanId)) {
16362
+ return entry;
16363
+ }
16364
+ }
16365
+ }
16366
+ const activeParentSpanIds = activeSpan.spanParents ?? [];
16367
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
16368
+ const entry = entries[index];
16369
+ if (entry?.parentSpan.spanId && activeParentSpanIds.includes(entry.parentSpan.spanId)) {
16370
+ return entry;
16371
+ }
16372
+ }
16373
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
16374
+ const entry = entries[index];
16375
+ if (entry?.parentSpan.spanId === activeSpanId) {
16376
+ return entry;
16377
+ }
16378
+ }
16379
+ return entries[entries.length - 1];
16380
+ }
16381
+ function attachNestedAISDKChildPatchEntry(entries, nestedSpan, cleanup) {
16382
+ const activeSpanId = currentSpan().spanId;
16383
+ if (!activeSpanId || activeSpanId === nestedSpan.spanId) {
16384
+ return false;
16385
+ }
16386
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
16387
+ const entry = entries[index];
16388
+ if (entry?.parentSpan.spanId === activeSpanId || entry?.activeSpanIds.has(activeSpanId)) {
16389
+ entry.activeSpanIds.add(nestedSpan.spanId);
16390
+ cleanup.push(() => {
16391
+ entry.activeSpanIds.delete(nestedSpan.spanId);
16392
+ });
16393
+ return true;
16394
+ }
16395
+ }
16396
+ return false;
16397
+ }
16398
+ function shadowActiveAISDKChildPatchEntry(entries, entry, nestedSpan, cleanup) {
16399
+ const activeSpanId = currentSpan().spanId;
16400
+ if (!activeSpanId || activeSpanId === nestedSpan.spanId) {
16401
+ return;
16402
+ }
16403
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
16404
+ const existingEntry = entries[index];
16405
+ if (existingEntry?.parentSpan.spanId === activeSpanId || existingEntry?.activeSpanIds.has(activeSpanId)) {
16406
+ entry.activeSpanIds.add(activeSpanId);
16407
+ cleanup.push(() => {
16408
+ entry.activeSpanIds.delete(activeSpanId);
16409
+ });
16410
+ return;
16411
+ }
16412
+ }
16413
+ }
16414
+ function closeOpenAISDKModelPatchSpans(entry) {
16415
+ for (const span of entry.openSpans) {
16416
+ span.end();
16417
+ }
16418
+ entry.openSpans.clear();
16419
+ }
16420
+ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiSDK, childTracingOptions = {}) {
14942
16421
  const cleanup = [];
14943
- const patchedModels = /* @__PURE__ */ new WeakSet();
16422
+ const patchedModels = /* @__PURE__ */ new WeakMap();
14944
16423
  const patchedTools = /* @__PURE__ */ new WeakSet();
14945
16424
  let modelWrapped = false;
14946
16425
  const patchModel = (model) => {
14947
16426
  const resolvedModel = resolveAISDKModel(model, aiSDK);
14948
- if (!resolvedModel || typeof resolvedModel !== "object" || typeof resolvedModel.doGenerate !== "function" || patchedModels.has(resolvedModel) || resolvedModel[AUTO_PATCHED_MODEL]) {
16427
+ if (!resolvedModel || typeof resolvedModel !== "object" || typeof resolvedModel.doGenerate !== "function") {
14949
16428
  return resolvedModel;
14950
16429
  }
14951
- patchedModels.add(resolvedModel);
14952
- resolvedModel[AUTO_PATCHED_MODEL] = true;
16430
+ const existingWrappedModel = patchedModels.get(resolvedModel);
16431
+ if (existingWrappedModel) {
16432
+ modelWrapped = true;
16433
+ return existingWrappedModel;
16434
+ }
14953
16435
  modelWrapped = true;
16436
+ const modelRecord = resolvedModel;
16437
+ const entry = {
16438
+ activeSpanIds: /* @__PURE__ */ new Set([parentSpan.spanId]),
16439
+ baseMetadata: buildAISDKChildMetadata(resolvedModel),
16440
+ childTracingOptions,
16441
+ denyOutputPaths,
16442
+ openSpans: /* @__PURE__ */ new Set(),
16443
+ parentSpan
16444
+ };
16445
+ const cleanupModelEntry = (state2, patchedModel) => {
16446
+ closeOpenAISDKModelPatchSpans(entry);
16447
+ const index = state2.entries.indexOf(entry);
16448
+ if (index >= 0) {
16449
+ state2.entries.splice(index, 1);
16450
+ }
16451
+ if (state2.entries.length > 0) {
16452
+ return;
16453
+ }
16454
+ patchedModel.doGenerate = state2.originalDoGenerate;
16455
+ patchedModel.doStream = state2.originalDoStream;
16456
+ delete patchedModel[AUTO_PATCHED_MODEL];
16457
+ };
16458
+ const existingState = modelRecord[AUTO_PATCHED_MODEL];
16459
+ if (existingState) {
16460
+ patchedModels.set(resolvedModel, resolvedModel);
16461
+ if (childTracingOptions.agentOwner && attachNestedAISDKChildPatchEntry(
16462
+ existingState.entries,
16463
+ parentSpan,
16464
+ cleanup
16465
+ )) {
16466
+ return resolvedModel;
16467
+ }
16468
+ if (!childTracingOptions.agentOwner) {
16469
+ shadowActiveAISDKChildPatchEntry(
16470
+ existingState.entries,
16471
+ entry,
16472
+ parentSpan,
16473
+ cleanup
16474
+ );
16475
+ }
16476
+ existingState.entries.push(entry);
16477
+ cleanup.push(() => {
16478
+ cleanupModelEntry(existingState, modelRecord);
16479
+ });
16480
+ return resolvedModel;
16481
+ }
14954
16482
  const originalDoGenerate = resolvedModel.doGenerate;
14955
16483
  const originalDoStream = resolvedModel.doStream;
14956
- const baseMetadata = buildAISDKChildMetadata(resolvedModel);
14957
- resolvedModel.doGenerate = async function doGeneratePatched(options) {
14958
- return parentSpan.traced(
16484
+ const wrappedModel = Object.create(
16485
+ Object.getPrototypeOf(resolvedModel)
16486
+ );
16487
+ Object.defineProperties(
16488
+ wrappedModel,
16489
+ Object.getOwnPropertyDescriptors(resolvedModel)
16490
+ );
16491
+ const wrappedModelRecord = wrappedModel;
16492
+ const state = {
16493
+ entries: [entry],
16494
+ originalDoGenerate,
16495
+ originalDoStream
16496
+ };
16497
+ Object.defineProperty(wrappedModel, AUTO_PATCHED_MODEL, {
16498
+ configurable: true,
16499
+ value: state
16500
+ });
16501
+ wrappedModel.doGenerate = async function doGeneratePatched(callOptions) {
16502
+ const activeEntry = activeAISDKChildPatchEntry(state.entries);
16503
+ if (!activeEntry) {
16504
+ return Reflect.apply(originalDoGenerate, resolvedModel, [callOptions]);
16505
+ }
16506
+ closeOpenAISDKModelPatchSpans(activeEntry);
16507
+ return activeEntry.parentSpan.traced(
14959
16508
  async (span) => {
14960
- const result = await Reflect.apply(
14961
- originalDoGenerate,
14962
- resolvedModel,
14963
- [options]
14964
- );
14965
- span.log({
14966
- output: processAISDKOutput(result, denyOutputPaths),
14967
- metrics: extractTokenMetrics(result),
14968
- ...buildResolvedMetadataPayload(result)
14969
- });
14970
- return result;
16509
+ activeEntry.openSpans.add(span);
16510
+ try {
16511
+ const result = await Reflect.apply(
16512
+ originalDoGenerate,
16513
+ resolvedModel,
16514
+ [callOptions]
16515
+ );
16516
+ const output = processAISDKOutput(
16517
+ result,
16518
+ activeEntry.denyOutputPaths
16519
+ );
16520
+ const metrics = extractTokenMetrics(result);
16521
+ const metadataPayload = buildResolvedMetadataPayload(result);
16522
+ const missingUsageMetadata = buildMissingUsageMetadata(
16523
+ output,
16524
+ metrics,
16525
+ "ai_sdk_result_missing_usage"
16526
+ );
16527
+ span.log({
16528
+ output,
16529
+ metrics,
16530
+ ...mergeMetadataPayload(metadataPayload, missingUsageMetadata)
16531
+ });
16532
+ return result;
16533
+ } finally {
16534
+ activeEntry.openSpans.delete(span);
16535
+ }
14971
16536
  },
14972
16537
  {
14973
16538
  name: "doGenerate",
14974
16539
  spanAttributes: {
14975
16540
  type: "llm" /* LLM */
14976
16541
  },
14977
- event: {
14978
- input: processAISDKCallInput(options).input,
14979
- metadata: baseMetadata
14980
- }
16542
+ event: buildAISDKModelStartEvent(
16543
+ callOptions,
16544
+ activeEntry.baseMetadata,
16545
+ {
16546
+ workflowAgent: activeEntry.childTracingOptions.workflowAgent
16547
+ }
16548
+ )
14981
16549
  }
14982
16550
  );
14983
16551
  };
14984
16552
  if (originalDoStream) {
14985
- resolvedModel.doStream = async function doStreamPatched(options) {
14986
- const span = parentSpan.startSpan({
16553
+ wrappedModel.doStream = async function doStreamPatched(callOptions) {
16554
+ const activeEntry = activeAISDKChildPatchEntry(state.entries);
16555
+ if (!activeEntry) {
16556
+ return Reflect.apply(originalDoStream, resolvedModel, [callOptions]);
16557
+ }
16558
+ closeOpenAISDKModelPatchSpans(activeEntry);
16559
+ const span = activeEntry.parentSpan.startSpan({
14987
16560
  name: "doStream",
14988
16561
  spanAttributes: {
14989
16562
  type: "llm" /* LLM */
14990
16563
  },
14991
- event: {
14992
- input: processAISDKCallInput(options).input,
14993
- metadata: baseMetadata
14994
- }
16564
+ event: buildAISDKModelStartEvent(
16565
+ callOptions,
16566
+ activeEntry.baseMetadata,
16567
+ {
16568
+ workflowAgent: activeEntry.childTracingOptions.workflowAgent
16569
+ }
16570
+ )
14995
16571
  });
16572
+ activeEntry.openSpans.add(span);
14996
16573
  const streamStartTime = getCurrentUnixTimestamp();
14997
16574
  const result = await withCurrent(
14998
16575
  span,
14999
- () => Reflect.apply(originalDoStream, resolvedModel, [options])
16576
+ () => Reflect.apply(originalDoStream, resolvedModel, [callOptions])
15000
16577
  );
15001
16578
  let firstChunkTime;
15002
16579
  const output = {};
15003
16580
  let text = "";
15004
16581
  let reasoning = "";
15005
- const toolCalls = [];
16582
+ const toolCalls2 = [];
15006
16583
  let object = void 0;
16584
+ let streamSpanEnded = false;
16585
+ const logAndEndStreamSpan = (usageUnavailableReason) => {
16586
+ if (streamSpanEnded) {
16587
+ return;
16588
+ }
16589
+ output.text = text;
16590
+ output.reasoning = reasoning;
16591
+ output.toolCalls = toolCalls2;
16592
+ if (object !== void 0) {
16593
+ output.object = object;
16594
+ }
16595
+ const metrics = extractTokenMetrics(output);
16596
+ if (firstChunkTime !== void 0 && !activeEntry.childTracingOptions.workflowAgent) {
16597
+ metrics.time_to_first_token = Math.max(
16598
+ firstChunkTime - streamStartTime,
16599
+ 1e-6
16600
+ );
16601
+ }
16602
+ const metadataPayload = buildResolvedMetadataPayload(
16603
+ output
16604
+ );
16605
+ const missingUsageMetadata = usageUnavailableReason ? { usage_unavailable_reason: usageUnavailableReason } : buildMissingUsageMetadata(
16606
+ output,
16607
+ metrics,
16608
+ "ai_sdk_result_missing_usage"
16609
+ );
16610
+ span.log({
16611
+ output: processAISDKOutput(
16612
+ output,
16613
+ activeEntry.denyOutputPaths
16614
+ ),
16615
+ metrics,
16616
+ ...mergeMetadataPayload(metadataPayload, missingUsageMetadata)
16617
+ });
16618
+ activeEntry.openSpans.delete(span);
16619
+ span.end();
16620
+ streamSpanEnded = true;
16621
+ };
15007
16622
  const transformStream = new TransformStream({
15008
16623
  transform(chunk, controller) {
15009
16624
  if (firstChunkTime === void 0 && isAISDKContentStreamChunk(chunk)) {
@@ -15021,7 +16636,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
15021
16636
  }
15022
16637
  break;
15023
16638
  case "tool-call":
15024
- toolCalls.push(chunk);
16639
+ toolCalls2.push(chunk);
15025
16640
  break;
15026
16641
  case "object":
15027
16642
  object = chunk.object;
@@ -15041,33 +16656,15 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
15041
16656
  }
15042
16657
  break;
15043
16658
  case "finish":
15044
- output.text = text;
15045
- output.reasoning = reasoning;
15046
- output.toolCalls = toolCalls;
15047
16659
  output.finishReason = chunk.finishReason;
15048
16660
  output.usage = chunk.usage;
15049
- if (object !== void 0) {
15050
- output.object = object;
15051
- }
15052
- const metrics = extractTokenMetrics(output);
15053
- if (firstChunkTime !== void 0) {
15054
- metrics.time_to_first_token = Math.max(
15055
- firstChunkTime - streamStartTime,
15056
- 1e-6
15057
- );
15058
- }
15059
- span.log({
15060
- output: processAISDKOutput(
15061
- output,
15062
- denyOutputPaths
15063
- ),
15064
- metrics,
15065
- ...buildResolvedMetadataPayload(output)
15066
- });
15067
- span.end();
16661
+ logAndEndStreamSpan();
15068
16662
  break;
15069
16663
  }
15070
16664
  controller.enqueue(chunk);
16665
+ },
16666
+ flush() {
16667
+ logAndEndStreamSpan("ai_sdk_stream_finished_without_usage");
15071
16668
  }
15072
16669
  });
15073
16670
  return {
@@ -15077,32 +16674,79 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
15077
16674
  };
15078
16675
  }
15079
16676
  cleanup.push(() => {
15080
- resolvedModel.doGenerate = originalDoGenerate;
15081
- if (originalDoStream) {
15082
- resolvedModel.doStream = originalDoStream;
15083
- }
15084
- delete resolvedModel[AUTO_PATCHED_MODEL];
16677
+ cleanupModelEntry(state, wrappedModelRecord);
15085
16678
  });
15086
- return resolvedModel;
16679
+ patchedModels.set(resolvedModel, wrappedModel);
16680
+ patchedModels.set(wrappedModel, wrappedModel);
16681
+ return wrappedModel;
15087
16682
  };
15088
16683
  const patchTool = (tool, name) => {
15089
- if (tool == null || typeof tool !== "object" || !("execute" in tool) || typeof tool.execute !== "function" || patchedTools.has(tool) || tool[AUTO_PATCHED_TOOL]) {
16684
+ if (tool == null || typeof tool !== "object" || !("execute" in tool) || typeof tool.execute !== "function" || patchedTools.has(tool)) {
15090
16685
  return;
15091
16686
  }
15092
16687
  patchedTools.add(tool);
15093
- tool[AUTO_PATCHED_TOOL] = true;
15094
- const originalExecute = tool.execute;
16688
+ const toolRecord = tool;
16689
+ const entry = {
16690
+ activeSpanIds: /* @__PURE__ */ new Set([parentSpan.spanId]),
16691
+ childTracingOptions,
16692
+ name,
16693
+ parentSpan
16694
+ };
16695
+ const cleanupToolEntry = (state2) => {
16696
+ const index = state2.entries.indexOf(entry);
16697
+ if (index >= 0) {
16698
+ state2.entries.splice(index, 1);
16699
+ }
16700
+ if (state2.entries.length > 0) {
16701
+ return;
16702
+ }
16703
+ tool.execute = state2.originalExecute;
16704
+ delete toolRecord[AUTO_PATCHED_TOOL];
16705
+ };
16706
+ const existingState = toolRecord[AUTO_PATCHED_TOOL];
16707
+ if (existingState) {
16708
+ if (childTracingOptions.agentOwner && attachNestedAISDKChildPatchEntry(
16709
+ existingState.entries,
16710
+ parentSpan,
16711
+ cleanup
16712
+ )) {
16713
+ return;
16714
+ }
16715
+ if (!childTracingOptions.agentOwner) {
16716
+ shadowActiveAISDKChildPatchEntry(
16717
+ existingState.entries,
16718
+ entry,
16719
+ parentSpan,
16720
+ cleanup
16721
+ );
16722
+ }
16723
+ existingState.entries.push(entry);
16724
+ cleanup.push(() => {
16725
+ cleanupToolEntry(existingState);
16726
+ });
16727
+ return;
16728
+ }
16729
+ const originalExecute = toolRecord.execute;
16730
+ const state = {
16731
+ entries: [entry],
16732
+ originalExecute
16733
+ };
16734
+ toolRecord[AUTO_PATCHED_TOOL] = state;
15095
16735
  tool.execute = function executePatched(...args) {
16736
+ const activeEntry = activeAISDKChildPatchEntry(state.entries);
15096
16737
  const result = Reflect.apply(originalExecute, this, args);
16738
+ if (!activeEntry) {
16739
+ return result;
16740
+ }
15097
16741
  if (isAsyncGenerator(result)) {
15098
16742
  return (async function* () {
15099
- const span = parentSpan.startSpan({
15100
- name,
16743
+ const span = activeEntry.parentSpan.startSpan({
16744
+ name: activeEntry.name,
15101
16745
  spanAttributes: {
15102
16746
  type: "tool" /* TOOL */
15103
16747
  }
15104
16748
  });
15105
- span.log({ input: args.length === 1 ? args[0] : args });
16749
+ span.log({ input: serializeToolExecutionInput(args) });
15106
16750
  try {
15107
16751
  let lastValue;
15108
16752
  for await (const value of result) {
@@ -15118,15 +16762,15 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
15118
16762
  }
15119
16763
  })();
15120
16764
  }
15121
- return parentSpan.traced(
16765
+ return activeEntry.parentSpan.traced(
15122
16766
  async (span) => {
15123
- span.log({ input: args.length === 1 ? args[0] : args });
16767
+ span.log({ input: serializeToolExecutionInput(args) });
15124
16768
  const awaitedResult = await result;
15125
16769
  span.log({ output: awaitedResult });
15126
16770
  return awaitedResult;
15127
16771
  },
15128
16772
  {
15129
- name,
16773
+ name: activeEntry.name,
15130
16774
  spanAttributes: {
15131
16775
  type: "tool" /* TOOL */
15132
16776
  }
@@ -15134,8 +16778,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
15134
16778
  );
15135
16779
  };
15136
16780
  cleanup.push(() => {
15137
- tool.execute = originalExecute;
15138
- delete tool[AUTO_PATCHED_TOOL];
16781
+ cleanupToolEntry(state);
15139
16782
  });
15140
16783
  };
15141
16784
  const patchTools = (tools) => {
@@ -15154,25 +16797,42 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
15154
16797
  }
15155
16798
  };
15156
16799
  if (params && typeof params === "object") {
15157
- const patchedParamModel = patchModel(params.model);
15158
- if (typeof params.model === "string" && patchedParamModel && typeof patchedParamModel === "object") {
16800
+ const originalParamModel = params.model;
16801
+ const patchedParamModel = patchModel(originalParamModel);
16802
+ if (patchedParamModel && patchedParamModel !== originalParamModel) {
15159
16803
  params.model = patchedParamModel;
16804
+ cleanup.push(() => {
16805
+ params.model = originalParamModel;
16806
+ });
15160
16807
  }
15161
16808
  patchTools(params.tools);
15162
16809
  }
15163
16810
  if (self && typeof self === "object") {
15164
16811
  const selfRecord = self;
15165
16812
  if (selfRecord.model !== void 0) {
15166
- const patchedSelfModel = patchModel(selfRecord.model);
15167
- if (typeof selfRecord.model === "string" && patchedSelfModel && typeof patchedSelfModel === "object") {
16813
+ const originalSelfModel = selfRecord.model;
16814
+ const patchedSelfModel = patchModel(originalSelfModel);
16815
+ if (patchedSelfModel && patchedSelfModel !== originalSelfModel) {
15168
16816
  selfRecord.model = patchedSelfModel;
16817
+ cleanup.push(() => {
16818
+ selfRecord.model = originalSelfModel;
16819
+ });
15169
16820
  }
15170
16821
  }
16822
+ if (selfRecord.tools !== void 0) {
16823
+ patchTools(selfRecord.tools);
16824
+ }
15171
16825
  if (selfRecord.settings && typeof selfRecord.settings === "object") {
15172
16826
  if (selfRecord.settings.model !== void 0) {
15173
- const patchedSettingsModel = patchModel(selfRecord.settings.model);
15174
- if (typeof selfRecord.settings.model === "string" && patchedSettingsModel && typeof patchedSettingsModel === "object") {
16827
+ const originalSettingsModel = selfRecord.settings.model;
16828
+ const patchedSettingsModel = patchModel(originalSettingsModel);
16829
+ if (patchedSettingsModel && patchedSettingsModel !== originalSettingsModel) {
15175
16830
  selfRecord.settings.model = patchedSettingsModel;
16831
+ cleanup.push(() => {
16832
+ if (selfRecord.settings) {
16833
+ selfRecord.settings.model = originalSettingsModel;
16834
+ }
16835
+ });
15176
16836
  }
15177
16837
  }
15178
16838
  if (selfRecord.settings.tools !== void 0) {
@@ -15269,99 +16929,190 @@ function isAISDKContentAsyncIterableChunk(chunk) {
15269
16929
  return isObject(part) && typeof part.type !== "string";
15270
16930
  }
15271
16931
  function patchAISDKStreamingResult(args) {
15272
- const { defaultDenyOutputPaths, endEvent, result, span, startTime } = args;
16932
+ const {
16933
+ defaultDenyOutputPaths,
16934
+ endEvent,
16935
+ onComplete,
16936
+ result,
16937
+ span,
16938
+ startTime
16939
+ } = args;
15273
16940
  if (!result || typeof result !== "object") {
15274
16941
  return false;
15275
16942
  }
15276
16943
  const resultRecord = result;
15277
16944
  attachKnownResultPromiseHandlers(resultRecord);
16945
+ let finalized = false;
16946
+ const finalize = () => {
16947
+ if (finalized) {
16948
+ return;
16949
+ }
16950
+ finalized = true;
16951
+ finalizeAISDKChildTracing(endEvent);
16952
+ span.end();
16953
+ onComplete?.();
16954
+ };
16955
+ let outputLogged = false;
16956
+ const logStreamingOutput = async (firstChunkTime) => {
16957
+ if (outputLogged) {
16958
+ return;
16959
+ }
16960
+ outputLogged = true;
16961
+ try {
16962
+ const metrics = extractTopLevelAISDKMetrics(result, endEvent);
16963
+ if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
16964
+ metrics.time_to_first_token = firstChunkTime - startTime;
16965
+ }
16966
+ const output = await processAISDKStreamingOutput(
16967
+ result,
16968
+ resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
16969
+ );
16970
+ const metadata = buildResolvedMetadataPayload(result).metadata;
16971
+ span.log({
16972
+ output,
16973
+ ...metadata ? { metadata } : {},
16974
+ metrics
16975
+ });
16976
+ } catch (error) {
16977
+ span.log({ error: toLoggedError(error) });
16978
+ } finally {
16979
+ finalize();
16980
+ }
16981
+ };
16982
+ const createAsyncIterableHooks = () => {
16983
+ let firstChunkTime;
16984
+ return {
16985
+ onChunk: (chunk) => {
16986
+ if (firstChunkTime === void 0 && isAISDKContentAsyncIterableChunk(chunk)) {
16987
+ firstChunkTime = getCurrentUnixTimestamp();
16988
+ }
16989
+ },
16990
+ onComplete: async () => {
16991
+ await logStreamingOutput(firstChunkTime);
16992
+ },
16993
+ onError: (error) => {
16994
+ if (!outputLogged) {
16995
+ outputLogged = true;
16996
+ span.log({
16997
+ error: error.message
16998
+ });
16999
+ }
17000
+ finalize();
17001
+ },
17002
+ onCancel: finalize
17003
+ };
17004
+ };
17005
+ const patchAsyncIterable = (stream) => isReadableStreamLike(stream) ? createPatchedReadableStream(stream, createAsyncIterableHooks()) : createPatchedAsyncIterable(stream, createAsyncIterableHooks());
17006
+ const patchAsyncIterableField = (field) => {
17007
+ let descriptorOwner = resultRecord;
17008
+ let descriptor;
17009
+ while (descriptorOwner) {
17010
+ descriptor = Object.getOwnPropertyDescriptor(descriptorOwner, field);
17011
+ if (descriptor) {
17012
+ break;
17013
+ }
17014
+ descriptorOwner = Object.getPrototypeOf(descriptorOwner);
17015
+ }
17016
+ if (!descriptor || descriptorOwner === resultRecord && !descriptor.configurable) {
17017
+ return false;
17018
+ }
17019
+ if ("value" in descriptor) {
17020
+ if (!isAsyncIterable(descriptor.value)) {
17021
+ return false;
17022
+ }
17023
+ try {
17024
+ Object.defineProperty(resultRecord, field, {
17025
+ configurable: descriptorOwner === resultRecord ? descriptor.configurable : true,
17026
+ enumerable: descriptor.enumerable,
17027
+ value: patchAsyncIterable(descriptor.value),
17028
+ writable: descriptor.writable
17029
+ });
17030
+ return true;
17031
+ } catch {
17032
+ return false;
17033
+ }
17034
+ }
17035
+ if (typeof descriptor.get !== "function") {
17036
+ return false;
17037
+ }
17038
+ const originalGet = descriptor.get;
17039
+ const originalSet = descriptor.set;
17040
+ try {
17041
+ Object.defineProperty(resultRecord, field, {
17042
+ configurable: descriptorOwner === resultRecord ? descriptor.configurable : true,
17043
+ enumerable: descriptor.enumerable,
17044
+ get() {
17045
+ const stream = originalGet.call(this);
17046
+ return isAsyncIterable(stream) ? patchAsyncIterable(stream) : stream;
17047
+ },
17048
+ ...originalSet ? {
17049
+ set(value) {
17050
+ originalSet.call(this, value);
17051
+ }
17052
+ } : {}
17053
+ });
17054
+ return true;
17055
+ } catch {
17056
+ return false;
17057
+ }
17058
+ };
17059
+ let patched = false;
15278
17060
  if (isReadableStreamLike(resultRecord.baseStream)) {
15279
- let firstChunkTime2;
15280
- const wrappedBaseStream = resultRecord.baseStream.pipeThrough(
17061
+ let firstChunkTime;
17062
+ const transformedBaseStream = resultRecord.baseStream.pipeThrough(
15281
17063
  new TransformStream({
15282
17064
  transform(chunk, controller) {
15283
- if (firstChunkTime2 === void 0 && isAISDKContentStreamChunk(chunk)) {
15284
- firstChunkTime2 = getCurrentUnixTimestamp();
17065
+ if (firstChunkTime === void 0 && isAISDKContentStreamChunk(chunk)) {
17066
+ firstChunkTime = getCurrentUnixTimestamp();
15285
17067
  }
15286
17068
  controller.enqueue(chunk);
15287
17069
  },
15288
17070
  async flush() {
15289
- const metrics = extractTopLevelAISDKMetrics(result, endEvent);
15290
- if (metrics.time_to_first_token === void 0 && firstChunkTime2 !== void 0) {
15291
- metrics.time_to_first_token = firstChunkTime2 - startTime;
15292
- }
15293
- const output = await processAISDKStreamingOutput(
15294
- result,
15295
- resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
15296
- );
15297
- const metadata = buildResolvedMetadataPayload(result).metadata;
15298
- span.log({
15299
- output,
15300
- ...metadata ? { metadata } : {},
15301
- metrics
15302
- });
15303
- finalizeAISDKChildTracing(endEvent);
15304
- span.end();
17071
+ await logStreamingOutput(firstChunkTime);
15305
17072
  }
15306
17073
  })
15307
17074
  );
17075
+ const reader = transformedBaseStream.getReader();
17076
+ const wrappedBaseStream = new ReadableStream({
17077
+ async pull(controller) {
17078
+ try {
17079
+ const { done, value } = await reader.read();
17080
+ if (done) {
17081
+ controller.close();
17082
+ return;
17083
+ }
17084
+ controller.enqueue(value);
17085
+ } catch (error) {
17086
+ span.log({ error: toLoggedError(error) });
17087
+ finalize();
17088
+ controller.error(error);
17089
+ }
17090
+ },
17091
+ async cancel(reason) {
17092
+ try {
17093
+ finalize();
17094
+ } finally {
17095
+ await reader.cancel(reason);
17096
+ }
17097
+ }
17098
+ });
15308
17099
  Object.defineProperty(resultRecord, "baseStream", {
15309
17100
  configurable: true,
15310
17101
  enumerable: true,
15311
17102
  value: wrappedBaseStream,
15312
17103
  writable: true
15313
17104
  });
15314
- return true;
17105
+ patched = true;
15315
17106
  }
15316
- const streamField = findAsyncIterableField(resultRecord, [
17107
+ for (const field of [
15317
17108
  "partialObjectStream",
15318
17109
  "textStream",
15319
17110
  "fullStream",
15320
17111
  "stream"
15321
- ]);
15322
- if (!streamField) {
15323
- return false;
17112
+ ]) {
17113
+ patched = patchAsyncIterableField(field) || patched;
15324
17114
  }
15325
- let firstChunkTime;
15326
- const wrappedStream = createPatchedAsyncIterable(streamField.stream, {
15327
- onChunk: (chunk) => {
15328
- if (firstChunkTime === void 0 && isAISDKContentAsyncIterableChunk(chunk)) {
15329
- firstChunkTime = getCurrentUnixTimestamp();
15330
- }
15331
- },
15332
- onComplete: async () => {
15333
- const metrics = extractTopLevelAISDKMetrics(result, endEvent);
15334
- if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
15335
- metrics.time_to_first_token = firstChunkTime - startTime;
15336
- }
15337
- const output = await processAISDKStreamingOutput(
15338
- result,
15339
- resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
15340
- );
15341
- const metadata = buildResolvedMetadataPayload(result).metadata;
15342
- span.log({
15343
- output,
15344
- ...metadata ? { metadata } : {},
15345
- metrics
15346
- });
15347
- finalizeAISDKChildTracing(endEvent);
15348
- span.end();
15349
- },
15350
- onError: (error) => {
15351
- span.log({
15352
- error: error.message
15353
- });
15354
- finalizeAISDKChildTracing(endEvent);
15355
- span.end();
15356
- }
15357
- });
15358
- Object.defineProperty(resultRecord, streamField.field, {
15359
- configurable: true,
15360
- enumerable: true,
15361
- value: wrappedStream,
15362
- writable: true
15363
- });
15364
- return true;
17115
+ return patched;
15365
17116
  }
15366
17117
  function attachKnownResultPromiseHandlers(result) {
15367
17118
  const promiseLikeFields = [
@@ -15393,34 +17144,72 @@ function attachKnownResultPromiseHandlers(result) {
15393
17144
  }
15394
17145
  }
15395
17146
  function isReadableStreamLike(value) {
15396
- return value != null && typeof value === "object" && typeof value.pipeThrough === "function";
15397
- }
15398
- function findAsyncIterableField(result, candidateFields) {
15399
- for (const field of candidateFields) {
15400
- try {
15401
- const stream = result[field];
15402
- if (isAsyncIterable(stream)) {
15403
- return { field, stream };
17147
+ return value != null && typeof value === "object" && typeof value.getReader === "function" && typeof value.pipeThrough === "function";
17148
+ }
17149
+ function createPatchedReadableStream(stream, hooks) {
17150
+ let reader;
17151
+ let completed = false;
17152
+ return new ReadableStream({
17153
+ async pull(controller) {
17154
+ reader ??= stream.getReader();
17155
+ try {
17156
+ const { done, value } = await reader.read();
17157
+ if (done) {
17158
+ completed = true;
17159
+ await hooks.onComplete();
17160
+ controller.close();
17161
+ return;
17162
+ }
17163
+ hooks.onChunk(value);
17164
+ controller.enqueue(value);
17165
+ } catch (error) {
17166
+ completed = true;
17167
+ hooks.onError(
17168
+ error instanceof Error ? error : new Error(String(error))
17169
+ );
17170
+ controller.error(error);
17171
+ }
17172
+ },
17173
+ async cancel(reason) {
17174
+ if (!completed) {
17175
+ completed = true;
17176
+ try {
17177
+ await hooks.onCancel?.();
17178
+ } catch {
17179
+ }
17180
+ }
17181
+ if (reader) {
17182
+ await reader.cancel(reason);
17183
+ } else if (stream.cancel) {
17184
+ await stream.cancel(reason);
15404
17185
  }
15405
- } catch {
15406
17186
  }
15407
- }
15408
- return null;
17187
+ });
15409
17188
  }
15410
17189
  function createPatchedAsyncIterable(stream, hooks) {
15411
17190
  return {
15412
17191
  async *[Symbol.asyncIterator]() {
17192
+ let completed = false;
15413
17193
  try {
15414
17194
  for await (const chunk of stream) {
15415
17195
  hooks.onChunk(chunk);
15416
17196
  yield chunk;
15417
17197
  }
17198
+ completed = true;
15418
17199
  await hooks.onComplete();
15419
17200
  } catch (error) {
17201
+ completed = true;
15420
17202
  hooks.onError(
15421
17203
  error instanceof Error ? error : new Error(String(error))
15422
17204
  );
15423
17205
  throw error;
17206
+ } finally {
17207
+ if (!completed) {
17208
+ try {
17209
+ await hooks.onCancel?.();
17210
+ } catch {
17211
+ }
17212
+ }
15424
17213
  }
15425
17214
  }
15426
17215
  };
@@ -15495,6 +17284,40 @@ function buildResolvedMetadataPayload(result) {
15495
17284
  }
15496
17285
  return Object.keys(metadata).length > 0 ? { metadata } : {};
15497
17286
  }
17287
+ function mergeMetadataPayload(metadataPayload, extraMetadata) {
17288
+ if (!extraMetadata || Object.keys(extraMetadata).length === 0) {
17289
+ return metadataPayload;
17290
+ }
17291
+ return {
17292
+ metadata: {
17293
+ ...metadataPayload.metadata ?? {},
17294
+ ...extraMetadata
17295
+ }
17296
+ };
17297
+ }
17298
+ function buildMissingUsageMetadata(output, metrics, reason) {
17299
+ if (!hasLoggedOutput(output) || hasTokenUsageMetrics(metrics)) {
17300
+ return void 0;
17301
+ }
17302
+ return { usage_unavailable_reason: reason };
17303
+ }
17304
+ function hasLoggedOutput(output) {
17305
+ if (output === null || output === void 0) {
17306
+ return false;
17307
+ }
17308
+ if (Array.isArray(output)) {
17309
+ return output.length > 0;
17310
+ }
17311
+ if (typeof output === "object") {
17312
+ return Object.keys(output).length > 0;
17313
+ }
17314
+ return true;
17315
+ }
17316
+ function hasTokenUsageMetrics(metrics) {
17317
+ return Object.keys(metrics).some(
17318
+ (key) => key !== "estimated_cost" && key !== "time_to_first_token"
17319
+ );
17320
+ }
15498
17321
  function resolveAISDKModel(model, aiSDK) {
15499
17322
  if (typeof model !== "string") {
15500
17323
  return model;
@@ -15518,7 +17341,45 @@ function isAsyncGenerator(value) {
15518
17341
  function processAISDKOutput(output, denyOutputPaths) {
15519
17342
  if (!output) return output;
15520
17343
  const merged = extractSerializableOutputFields(output);
15521
- return normalizeAISDKLoggedOutput(omit(merged, denyOutputPaths));
17344
+ const deleteOutputPaths = denyOutputPaths.filter(
17345
+ (path) => path.toLowerCase().endsWith("headers")
17346
+ );
17347
+ const sanitized = omit(merged, denyOutputPaths, deleteOutputPaths);
17348
+ for (const path of TRANSPORT_PAYLOAD_ROOT_PATHS) {
17349
+ const stack = [{ obj: sanitized, keys: parsePath(path) }];
17350
+ while (stack.length > 0) {
17351
+ const entry = stack.pop();
17352
+ if (!entry || entry.keys.length === 0) {
17353
+ continue;
17354
+ }
17355
+ const firstKey = entry.keys[0];
17356
+ const remainingKeys = entry.keys.slice(1);
17357
+ if (firstKey === "[]") {
17358
+ if (Array.isArray(entry.obj)) {
17359
+ for (const item of entry.obj) {
17360
+ stack.push({
17361
+ obj: item,
17362
+ keys: remainingKeys
17363
+ });
17364
+ }
17365
+ }
17366
+ continue;
17367
+ }
17368
+ if (!entry.obj || typeof entry.obj !== "object" || !(firstKey in entry.obj)) {
17369
+ continue;
17370
+ }
17371
+ const record = entry.obj;
17372
+ if (remainingKeys.length === 0) {
17373
+ record[firstKey] = sanitizeAISDKMetadataValue(record[firstKey]);
17374
+ continue;
17375
+ }
17376
+ stack.push({
17377
+ obj: record[firstKey],
17378
+ keys: remainingKeys
17379
+ });
17380
+ }
17381
+ }
17382
+ return normalizeAISDKLoggedOutput(sanitized);
15522
17383
  }
15523
17384
  function processAISDKEmbeddingOutput(output, denyOutputPaths) {
15524
17385
  if (!output || typeof output !== "object") {
@@ -15609,6 +17470,8 @@ function extractTokenMetrics(result) {
15609
17470
  );
15610
17471
  if (totalTokens !== void 0) {
15611
17472
  metrics.tokens = totalTokens;
17473
+ } else if (promptTokens !== void 0 && completionTokens !== void 0) {
17474
+ metrics.tokens = promptTokens + completionTokens;
15612
17475
  }
15613
17476
  const promptCachedTokens = firstNumber2(
15614
17477
  usage.inputTokens?.cacheRead,
@@ -15720,9 +17583,9 @@ function aggregateAISDKChunks(chunks, _result, endEvent) {
15720
17583
  if (finishReason !== void 0) {
15721
17584
  output.finishReason = finishReason;
15722
17585
  }
15723
- const toolCalls = safeSerializableFieldRead(lastChunk, "toolCalls");
15724
- if (toolCalls !== void 0) {
15725
- output.toolCalls = toolCalls;
17586
+ const toolCalls2 = safeSerializableFieldRead(lastChunk, "toolCalls");
17587
+ if (toolCalls2 !== void 0) {
17588
+ output.toolCalls = toolCalls2;
15726
17589
  }
15727
17590
  }
15728
17591
  finalizeAISDKChildTracing(endEvent);
@@ -15732,7 +17595,9 @@ function extractGetterValues(obj) {
15732
17595
  const getterValues = {};
15733
17596
  const getterNames = [
15734
17597
  "content",
17598
+ "messages",
15735
17599
  "text",
17600
+ "output",
15736
17601
  "object",
15737
17602
  "value",
15738
17603
  "values",
@@ -15772,7 +17637,9 @@ function extractGetterValues(obj) {
15772
17637
  function extractSerializableOutputFields(output) {
15773
17638
  const serialized = {};
15774
17639
  const directFieldNames = [
17640
+ "messages",
15775
17641
  "steps",
17642
+ "output",
15776
17643
  "request",
15777
17644
  "responseMessages",
15778
17645
  "warnings",
@@ -15954,7 +17821,7 @@ function parsePath(path) {
15954
17821
  }
15955
17822
  return keys;
15956
17823
  }
15957
- function omitAtPath(obj, keys) {
17824
+ function omitAtPath(obj, keys, deleteLeaf = false) {
15958
17825
  if (keys.length === 0) return;
15959
17826
  const firstKey = keys[0];
15960
17827
  const remainingKeys = keys.slice(1);
@@ -15964,29 +17831,36 @@ function omitAtPath(obj, keys) {
15964
17831
  if (remainingKeys.length > 0) {
15965
17832
  omitAtPath(
15966
17833
  item,
15967
- remainingKeys
17834
+ remainingKeys,
17835
+ deleteLeaf
15968
17836
  );
15969
17837
  }
15970
17838
  });
15971
17839
  }
15972
17840
  } else if (remainingKeys.length === 0) {
15973
17841
  if (obj && typeof obj === "object" && firstKey in obj) {
15974
- obj[firstKey] = "<omitted>";
17842
+ if (deleteLeaf) {
17843
+ delete obj[firstKey];
17844
+ } else {
17845
+ obj[firstKey] = "<omitted>";
17846
+ }
15975
17847
  }
15976
17848
  } else {
15977
17849
  if (obj && typeof obj === "object" && firstKey in obj) {
15978
17850
  omitAtPath(
15979
17851
  obj[firstKey],
15980
- remainingKeys
17852
+ remainingKeys,
17853
+ deleteLeaf
15981
17854
  );
15982
17855
  }
15983
17856
  }
15984
17857
  }
15985
- function omit(obj, paths) {
17858
+ function omit(obj, paths, deletePaths = []) {
15986
17859
  const result = deepCopy(obj);
17860
+ const deletePathSet = new Set(deletePaths);
15987
17861
  for (const path of paths) {
15988
17862
  const keys = parsePath(path);
15989
- omitAtPath(result, keys);
17863
+ omitAtPath(result, keys, deletePathSet.has(path));
15990
17864
  }
15991
17865
  return result;
15992
17866
  }
@@ -20195,8 +22069,8 @@ function getChatToolCallDeltas(value) {
20195
22069
  if (!Array.isArray(value?.tool_calls)) {
20196
22070
  return void 0;
20197
22071
  }
20198
- const toolCalls = value.tool_calls.filter((toolCall) => isObject(toolCall));
20199
- return toolCalls.length > 0 ? toolCalls : void 0;
22072
+ const toolCalls2 = value.tool_calls.filter((toolCall) => isObject(toolCall));
22073
+ return toolCalls2.length > 0 ? toolCalls2 : void 0;
20200
22074
  }
20201
22075
  function mergeChatToolCallDeltas(toolCallsByIndex, toolCallDeltas) {
20202
22076
  for (const toolDelta of toolCallDeltas) {
@@ -21685,7 +23559,7 @@ function aggregateOpenRouterChatChunks(chunks) {
21685
23559
  let reasoningContent = "";
21686
23560
  let hasReasoningContent = false;
21687
23561
  let reasoningDetails;
21688
- let toolCalls;
23562
+ let toolCalls2;
21689
23563
  let finishReason;
21690
23564
  let metrics = {};
21691
23565
  for (const chunk of chunks) {
@@ -21738,9 +23612,9 @@ function aggregateOpenRouterChatChunks(chunks) {
21738
23612
  continue;
21739
23613
  }
21740
23614
  const toolIndex = toolDelta.index ?? 0;
21741
- const existingToolCall = toolCalls?.[toolIndex];
23615
+ const existingToolCall = toolCalls2?.[toolIndex];
21742
23616
  if (!existingToolCall || toolDelta.id && existingToolCall.id !== void 0 && existingToolCall.id !== toolDelta.id) {
21743
- const nextToolCalls = [...toolCalls || []];
23617
+ const nextToolCalls = [...toolCalls2 || []];
21744
23618
  nextToolCalls[toolIndex] = {
21745
23619
  index: toolIndex,
21746
23620
  id: toolDelta.id,
@@ -21750,7 +23624,7 @@ function aggregateOpenRouterChatChunks(chunks) {
21750
23624
  arguments: toolDelta.function.arguments || ""
21751
23625
  }
21752
23626
  };
21753
- toolCalls = nextToolCalls;
23627
+ toolCalls2 = nextToolCalls;
21754
23628
  continue;
21755
23629
  }
21756
23630
  const current = existingToolCall;
@@ -21776,7 +23650,7 @@ function aggregateOpenRouterChatChunks(chunks) {
21776
23650
  ...hasReasoning || hasReasoningContent ? { reasoning } : {},
21777
23651
  ...hasReasoningContent ? { reasoning_content: reasoningContent } : {},
21778
23652
  ...reasoningDetails ? { reasoning_details: reasoningDetails } : {},
21779
- ...toolCalls ? { tool_calls: toolCalls } : {}
23653
+ ...toolCalls2 ? { tool_calls: toolCalls2 } : {}
21780
23654
  },
21781
23655
  logprobs: null,
21782
23656
  finish_reason: finishReason
@@ -22621,8 +24495,8 @@ function appendMistralContent(accumulator, content) {
22621
24495
  delete accumulator.content;
22622
24496
  }
22623
24497
  function getDeltaToolCalls(delta) {
22624
- const toolCalls = Array.isArray(delta.toolCalls) && delta.toolCalls || Array.isArray(delta.tool_calls) && delta.tool_calls || [];
22625
- return toolCalls.filter((toolCall) => isObject(toolCall));
24498
+ const toolCalls2 = Array.isArray(delta.toolCalls) && delta.toolCalls || Array.isArray(delta.tool_calls) && delta.tool_calls || [];
24499
+ return toolCalls2.filter((toolCall) => isObject(toolCall));
22626
24500
  }
22627
24501
  function getToolCallIndex(toolCall) {
22628
24502
  return typeof toolCall.index === "number" && toolCall.index >= 0 ? toolCall.index : void 0;
@@ -22649,11 +24523,11 @@ function mergeToolCallDeltaPair(current, delta) {
22649
24523
  }
22650
24524
  };
22651
24525
  }
22652
- function mergeToolCallDeltas(toolCalls, deltas) {
24526
+ function mergeToolCallDeltas(toolCalls2, deltas) {
22653
24527
  if (deltas.length === 0) {
22654
- return toolCalls;
24528
+ return toolCalls2;
22655
24529
  }
22656
- const merged = toolCalls ? [...toolCalls] : [];
24530
+ const merged = toolCalls2 ? [...toolCalls2] : [];
22657
24531
  const indexToPosition = /* @__PURE__ */ new Map();
22658
24532
  const idToPosition = /* @__PURE__ */ new Map();
22659
24533
  for (const [position, toolCall] of merged.entries()) {
@@ -23724,12 +25598,12 @@ function extractCohereChatOutput(result) {
23724
25598
  if (typeof result.text !== "string") {
23725
25599
  return void 0;
23726
25600
  }
23727
- const toolCalls = Array.isArray(result.toolCalls) ? result.toolCalls : Array.isArray(result.tool_calls) ? result.tool_calls : void 0;
23728
- if (toolCalls && toolCalls.length > 0) {
25601
+ const toolCalls2 = Array.isArray(result.toolCalls) ? result.toolCalls : Array.isArray(result.tool_calls) ? result.tool_calls : void 0;
25602
+ if (toolCalls2 && toolCalls2.length > 0) {
23729
25603
  return {
23730
25604
  content: result.text,
23731
25605
  role: "assistant",
23732
- toolCalls
25606
+ toolCalls: toolCalls2
23733
25607
  };
23734
25608
  }
23735
25609
  return result.text;
@@ -24062,10 +25936,10 @@ function aggregateCohereChatStreamChunks(chunks) {
24062
25936
  continue;
24063
25937
  }
24064
25938
  if (eventType === "tool-call-start") {
24065
- const toolCalls = isObject(chunk.delta) && isObject(chunk.delta.message) ? toToolCallArray(
25939
+ const toolCalls2 = isObject(chunk.delta) && isObject(chunk.delta.message) ? toToolCallArray(
24066
25940
  Array.isArray(chunk.delta.message.toolCalls) ? chunk.delta.message.toolCalls : chunk.delta.message.toolCalls ?? chunk.delta.message.tool_calls
24067
25941
  ) : [];
24068
- for (const [index, toolCall] of toolCalls.entries()) {
25942
+ for (const [index, toolCall] of toolCalls2.entries()) {
24069
25943
  const normalizedIndex = getToolCallIndex2(
24070
25944
  toolCall,
24071
25945
  typeof chunk.index === "number" ? chunk.index : index
@@ -28140,14 +30014,14 @@ function normalizeAssistantMessage(message) {
28140
30014
  const thinking = message.content.flatMap(
28141
30015
  (part) => part.type === "thinking" && !part.redacted ? [part.thinking] : []
28142
30016
  ).join("");
28143
- const toolCalls = message.content.flatMap(
30017
+ const toolCalls2 = message.content.flatMap(
28144
30018
  (part) => part.type === "toolCall" ? [normalizeToolCall(part)] : []
28145
30019
  );
28146
30020
  return {
28147
30021
  role: "assistant",
28148
- content: text || (toolCalls.length > 0 ? null : ""),
30022
+ content: text || (toolCalls2.length > 0 ? null : ""),
28149
30023
  ...thinking ? { reasoning: thinking } : {},
28150
- ...toolCalls.length > 0 ? { tool_calls: toolCalls } : {}
30024
+ ...toolCalls2.length > 0 ? { tool_calls: toolCalls2 } : {}
28151
30025
  };
28152
30026
  }
28153
30027
  function normalizeToolResultMessage(message) {
@@ -29645,8 +31519,10 @@ var exports_exports = {};
29645
31519
  __export(exports_exports, {
29646
31520
  Attachment: () => Attachment,
29647
31521
  AttachmentReference: () => AttachmentReference,
31522
+ BAGGAGE_HEADER: () => BAGGAGE_HEADER,
29648
31523
  BRAINTRUST_CURRENT_SPAN_STORE: () => BRAINTRUST_CURRENT_SPAN_STORE,
29649
31524
  BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME: () => BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME,
31525
+ BRAINTRUST_PARENT_KEY: () => BRAINTRUST_PARENT_KEY,
29650
31526
  BaseAttachment: () => BaseAttachment,
29651
31527
  BaseExperiment: () => BaseExperiment,
29652
31528
  BraintrustLangChainCallbackHandler: () => BraintrustLangChainCallbackHandler,
@@ -29679,6 +31555,7 @@ __export(exports_exports, {
29679
31555
  NOOP_SPAN: () => NOOP_SPAN,
29680
31556
  NOOP_SPAN_PERMALINK: () => NOOP_SPAN_PERMALINK,
29681
31557
  NoopSpan: () => NoopSpan,
31558
+ OTELIDGenerator: () => OTELIDGenerator,
29682
31559
  ObjectFetcher: () => ObjectFetcher,
29683
31560
  Project: () => Project2,
29684
31561
  ProjectNameIdMap: () => ProjectNameIdMap,
@@ -29690,6 +31567,8 @@ __export(exports_exports, {
29690
31567
  ScorerBuilder: () => ScorerBuilder,
29691
31568
  SpanFetcher: () => SpanFetcher,
29692
31569
  SpanImpl: () => SpanImpl,
31570
+ TRACEPARENT_HEADER: () => TRACEPARENT_HEADER,
31571
+ TRACESTATE_HEADER: () => TRACESTATE_HEADER,
29693
31572
  TestBackgroundLogger: () => TestBackgroundLogger,
29694
31573
  ToolBuilder: () => ToolBuilder,
29695
31574
  UUIDGenerator: () => UUIDGenerator,
@@ -29699,6 +31578,7 @@ __export(exports_exports, {
29699
31578
  _internalIso: () => isomorph_default,
29700
31579
  _internalSetInitialState: () => _internalSetInitialState,
29701
31580
  addAzureBlobHeaders: () => addAzureBlobHeaders,
31581
+ agentAssertionScorer: () => agentAssertionScorer,
29702
31582
  braintrustAISDKTelemetry: () => braintrustAISDKTelemetry,
29703
31583
  braintrustFlueInstrumentation: () => braintrustFlueInstrumentation,
29704
31584
  braintrustFlueObserver: () => braintrustFlueObserver,
@@ -29716,6 +31596,7 @@ __export(exports_exports, {
29716
31596
  devNullWritableStream: () => devNullWritableStream,
29717
31597
  evaluatorDefinitionSchema: () => evaluatorDefinitionSchema,
29718
31598
  evaluatorDefinitionsSchema: () => evaluatorDefinitionsSchema,
31599
+ extractTraceContextFromHeaders: () => extractTraceContextFromHeaders,
29719
31600
  flush: () => flush,
29720
31601
  getContextManager: () => getContextManager,
29721
31602
  getIdGenerator: () => getIdGenerator,
@@ -29729,6 +31610,7 @@ __export(exports_exports, {
29729
31610
  initFunction: () => initFunction,
29730
31611
  initLogger: () => initLogger,
29731
31612
  initNodeTestSuite: () => initNodeTestSuite,
31613
+ injectTraceContext: () => injectTraceContext,
29732
31614
  invoke: () => invoke,
29733
31615
  isTemplateFormat: () => isTemplateFormat,
29734
31616
  loadParameters: () => loadParameters,
@@ -29767,7 +31649,7 @@ __export(exports_exports, {
29767
31649
  traced: () => traced,
29768
31650
  updateSpan: () => updateSpan,
29769
31651
  uploadLogs3OverflowPayload: () => uploadLogs3OverflowPayload,
29770
- utf8ByteLength: () => utf8ByteLength,
31652
+ utf8ByteLength: () => utf8ByteLength2,
29771
31653
  withCurrent: () => withCurrent,
29772
31654
  withDataset: () => withDataset,
29773
31655
  withExperiment: () => withExperiment,
@@ -30360,6 +32242,7 @@ function wrapAISDK(aiSDK, options = {}) {
30360
32242
  case "Agent":
30361
32243
  case "Experimental_Agent":
30362
32244
  case "ToolLoopAgent":
32245
+ case "WorkflowAgent":
30363
32246
  return original ? wrapAgentClass(original, options) : original;
30364
32247
  }
30365
32248
  return original;
@@ -30378,10 +32261,10 @@ var wrapAgentClass = (AgentClass, options = {}) => {
30378
32261
  return new Proxy(instance, {
30379
32262
  get(instanceTarget, prop, instanceReceiver) {
30380
32263
  const original = Reflect.get(instanceTarget, prop, instanceTarget);
30381
- if (prop === "generate") {
32264
+ if (prop === "generate" && typeof original === "function" && instanceTarget.constructor.name !== "WorkflowAgent") {
30382
32265
  return wrapAgentGenerate(original, instanceTarget, options);
30383
32266
  }
30384
- if (prop === "stream") {
32267
+ if (prop === "stream" && typeof original === "function") {
30385
32268
  return wrapAgentStream(original, instanceTarget, options);
30386
32269
  }
30387
32270
  if (typeof original === "function") {
@@ -30396,7 +32279,7 @@ var wrapAgentClass = (AgentClass, options = {}) => {
30396
32279
  var wrapAgentGenerate = (generate, instance, options = {}) => {
30397
32280
  const defaultName = `${instance.constructor.name}.generate`;
30398
32281
  return async (params) => makeGenerateTextWrapper(
30399
- aiSDKChannels.generateText,
32282
+ generateChannelForAgent(instance.constructor.name),
30400
32283
  defaultName,
30401
32284
  generate.bind(instance),
30402
32285
  {
@@ -30406,19 +32289,42 @@ var wrapAgentGenerate = (generate, instance, options = {}) => {
30406
32289
  options
30407
32290
  )({ ...instance.settings, ...params });
30408
32291
  };
32292
+ function generateChannelForAgent(agentName) {
32293
+ if (agentName === "ToolLoopAgent") {
32294
+ return aiSDKChannels.toolLoopAgentGenerate;
32295
+ }
32296
+ return aiSDKChannels.agentGenerate;
32297
+ }
30409
32298
  var wrapAgentStream = (stream, instance, options = {}) => {
30410
32299
  const defaultName = `${instance.constructor.name}.stream`;
30411
- return (params) => makeStreamWrapper(
30412
- aiSDKChannels.agentStream,
30413
- defaultName,
30414
- stream.bind(instance),
30415
- {
30416
- self: instance,
30417
- spanType: "function" /* FUNCTION */
30418
- },
30419
- options
30420
- )({ ...instance.settings, ...params });
32300
+ return (params) => {
32301
+ const workflowAgent = instance.constructor.name === "WorkflowAgent";
32302
+ if (workflowAgent && currentWorkflowAgentWrapperSpan()) {
32303
+ const { span_info: _spanInfo, ...cleanParams } = params;
32304
+ return stream.call(instance, { ...instance.settings, ...cleanParams });
32305
+ }
32306
+ const trace = () => makeStreamWrapper(
32307
+ streamChannelForAgent(instance.constructor.name),
32308
+ defaultName,
32309
+ stream.bind(instance),
32310
+ {
32311
+ self: instance,
32312
+ spanType: "function" /* FUNCTION */
32313
+ },
32314
+ options
32315
+ )({ ...instance.settings, ...params });
32316
+ return trace();
32317
+ };
30421
32318
  };
32319
+ function streamChannelForAgent(agentName) {
32320
+ if (agentName === "ToolLoopAgent") {
32321
+ return aiSDKChannels.toolLoopAgentStream;
32322
+ }
32323
+ if (agentName === "WorkflowAgent") {
32324
+ return aiSDKChannels.workflowAgentStream;
32325
+ }
32326
+ return aiSDKChannels.agentStream;
32327
+ }
30422
32328
  var makeGenerateTextWrapper = (channel2, name, generateText, contextOptions = {}, options = {}) => {
30423
32329
  const wrapper = async function(allParams) {
30424
32330
  const { span_info, ...params } = allParams;
@@ -30680,7 +32586,7 @@ var BraintrustLanguageModelWrapper = class {
30680
32586
  let time_to_first_token = void 0;
30681
32587
  let usage = void 0;
30682
32588
  let fullText = void 0;
30683
- const toolCalls = {};
32589
+ const toolCalls2 = {};
30684
32590
  let finishReason = void 0;
30685
32591
  return {
30686
32592
  ...ret,
@@ -30699,7 +32605,7 @@ var BraintrustLanguageModelWrapper = class {
30699
32605
  fullText += chunk.textDelta;
30700
32606
  break;
30701
32607
  case "tool-call":
30702
- toolCalls[chunk.toolCallId] = {
32608
+ toolCalls2[chunk.toolCallId] = {
30703
32609
  toolCallType: chunk.toolCallType,
30704
32610
  toolCallId: chunk.toolCallId,
30705
32611
  toolName: chunk.toolName,
@@ -30707,15 +32613,15 @@ var BraintrustLanguageModelWrapper = class {
30707
32613
  };
30708
32614
  break;
30709
32615
  case "tool-call-delta":
30710
- if (toolCalls[chunk.toolCallId] === void 0) {
30711
- toolCalls[chunk.toolCallId] = {
32616
+ if (toolCalls2[chunk.toolCallId] === void 0) {
32617
+ toolCalls2[chunk.toolCallId] = {
30712
32618
  toolCallType: chunk.toolCallType,
30713
32619
  toolCallId: chunk.toolCallId,
30714
32620
  toolName: chunk.toolName,
30715
32621
  args: ""
30716
32622
  };
30717
32623
  }
30718
- toolCalls[chunk.toolCallId].args += chunk.argsTextDelta;
32624
+ toolCalls2[chunk.toolCallId].args += chunk.argsTextDelta;
30719
32625
  break;
30720
32626
  case "finish":
30721
32627
  usage = chunk.usage;
@@ -30728,7 +32634,7 @@ var BraintrustLanguageModelWrapper = class {
30728
32634
  span.log({
30729
32635
  output: postProcessOutput(
30730
32636
  fullText,
30731
- Object.keys(toolCalls).length > 0 ? Object.values(toolCalls) : void 0,
32637
+ Object.keys(toolCalls2).length > 0 ? Object.values(toolCalls2) : void 0,
30732
32638
  finishReason
30733
32639
  ),
30734
32640
  metrics: {
@@ -30829,15 +32735,15 @@ function postProcessPrompt(prompt) {
30829
32735
  }
30830
32736
  });
30831
32737
  }
30832
- function postProcessOutput(text, toolCalls, finishReason) {
32738
+ function postProcessOutput(text, toolCalls2, finishReason) {
30833
32739
  return [
30834
32740
  {
30835
32741
  index: 0,
30836
32742
  message: {
30837
32743
  role: "assistant",
30838
32744
  content: text ?? "",
30839
- ...toolCalls && toolCalls.length > 0 ? {
30840
- tool_calls: toolCalls.map((toolCall) => ({
32745
+ ...toolCalls2 && toolCalls2.length > 0 ? {
32746
+ tool_calls: toolCalls2.map((toolCall) => ({
30841
32747
  id: toolCall.toolCallId,
30842
32748
  function: {
30843
32749
  name: toolCall.toolName,
@@ -30936,29 +32842,29 @@ function normalizeFinishReason(reason) {
30936
32842
  if (typeof reason !== "string") return void 0;
30937
32843
  return reason.replace(/-/g, "_");
30938
32844
  }
30939
- function buildAssistantOutputWithToolCalls(result, toolCalls) {
32845
+ function buildAssistantOutputWithToolCalls(result, toolCalls2) {
30940
32846
  return [
30941
32847
  {
30942
32848
  index: 0,
30943
32849
  logprobs: null,
30944
- finish_reason: normalizeFinishReason(result?.finishReason) ?? (toolCalls.length ? "tool_calls" : void 0),
32850
+ finish_reason: normalizeFinishReason(result?.finishReason) ?? (toolCalls2.length ? "tool_calls" : void 0),
30945
32851
  message: {
30946
32852
  role: "assistant",
30947
- tool_calls: toolCalls.length > 0 ? toolCalls : void 0
32853
+ tool_calls: toolCalls2.length > 0 ? toolCalls2 : void 0
30948
32854
  }
30949
32855
  }
30950
32856
  ];
30951
32857
  }
30952
32858
  function extractToolCallsFromSteps(steps) {
30953
- const toolCalls = [];
30954
- if (!Array.isArray(steps)) return toolCalls;
32859
+ const toolCalls2 = [];
32860
+ if (!Array.isArray(steps)) return toolCalls2;
30955
32861
  let idx = 0;
30956
32862
  for (const step of steps) {
30957
32863
  const blocks = step?.content;
30958
32864
  if (!Array.isArray(blocks)) continue;
30959
32865
  for (const block of blocks) {
30960
32866
  if (block && typeof block === "object" && block.type === "tool-call") {
30961
- toolCalls.push({
32867
+ toolCalls2.push({
30962
32868
  id: block.toolCallId,
30963
32869
  type: "function",
30964
32870
  index: idx++,
@@ -30970,7 +32876,7 @@ function extractToolCallsFromSteps(steps) {
30970
32876
  }
30971
32877
  }
30972
32878
  }
30973
- return toolCalls;
32879
+ return toolCalls2;
30974
32880
  }
30975
32881
  function extractToolCallsFromBlocks(blocks) {
30976
32882
  if (!Array.isArray(blocks)) return [];
@@ -31036,12 +32942,12 @@ function BraintrustMiddleware(config = {}) {
31036
32942
  metadata.model = modelId;
31037
32943
  }
31038
32944
  }
31039
- let toolCalls = extractToolCallsFromSteps(result?.steps);
31040
- if (!toolCalls || toolCalls.length === 0) {
31041
- toolCalls = extractToolCallsFromBlocks(result?.content);
32945
+ let toolCalls2 = extractToolCallsFromSteps(result?.steps);
32946
+ if (!toolCalls2 || toolCalls2.length === 0) {
32947
+ toolCalls2 = extractToolCallsFromBlocks(result?.content);
31042
32948
  }
31043
32949
  span.log({
31044
- output: toolCalls.length > 0 ? buildAssistantOutputWithToolCalls(result, toolCalls) : result?.content,
32950
+ output: toolCalls2.length > 0 ? buildAssistantOutputWithToolCalls(result, toolCalls2) : result?.content,
31045
32951
  metadata,
31046
32952
  metrics: normalizeUsageMetrics(
31047
32953
  result.usage,
@@ -31130,13 +33036,13 @@ function BraintrustMiddleware(config = {}) {
31130
33036
  metadata.model = model;
31131
33037
  }
31132
33038
  if (toolBlocks.length > 0) {
31133
- const toolCalls = extractToolCallsFromSteps([
33039
+ const toolCalls2 = extractToolCallsFromSteps([
31134
33040
  { content: toolBlocks }
31135
33041
  ]);
31136
- if (toolCalls.length > 0) {
33042
+ if (toolCalls2.length > 0) {
31137
33043
  output = buildAssistantOutputWithToolCalls(
31138
33044
  resultForDetection,
31139
- toolCalls
33045
+ toolCalls2
31140
33046
  );
31141
33047
  }
31142
33048
  }
@@ -31771,9 +33677,9 @@ function isModuleNamespace3(obj) {
31771
33677
  const descriptor = Object.getOwnPropertyDescriptor(obj, keys[0]);
31772
33678
  return descriptor ? !descriptor.configurable && !descriptor.writable : false;
31773
33679
  }
31774
- function wrapCursorAgentClass(Agent) {
33680
+ function wrapCursorAgentClass(Agent2) {
31775
33681
  const cache = /* @__PURE__ */ new Map();
31776
- return new Proxy(Agent, {
33682
+ return new Proxy(Agent2, {
31777
33683
  get(target, prop, receiver) {
31778
33684
  if (cache.has(prop)) {
31779
33685
  return cache.get(prop);
@@ -35321,15 +37227,21 @@ var waterfall$1 = awaitify(waterfall);
35321
37227
 
35322
37228
  // src/trace.ts
35323
37229
  var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
35324
- constructor(objectType, _objectId, rootSpanId, _state, spanTypeFilter, includeScorers = false) {
37230
+ constructor(objectType, _objectId, rootSpanId, _state, spanTypeFilter, includeScorers = false, brainstoreRealtime = true) {
35325
37231
  const filterExpr = _SpanFetcher.buildFilter(
35326
37232
  rootSpanId,
35327
37233
  spanTypeFilter,
35328
37234
  includeScorers
35329
37235
  );
35330
- super(objectType, void 0, void 0, {
35331
- filter: filterExpr
35332
- });
37236
+ super(
37237
+ objectType,
37238
+ void 0,
37239
+ void 0,
37240
+ {
37241
+ filter: filterExpr
37242
+ },
37243
+ brainstoreRealtime
37244
+ );
35333
37245
  this._objectId = _objectId;
35334
37246
  this.rootSpanId = rootSpanId;
35335
37247
  this._state = _state;
@@ -35383,7 +37295,7 @@ var CachedSpanFetcher = class {
35383
37295
  spanCache = /* @__PURE__ */ new Map();
35384
37296
  allFetched = false;
35385
37297
  fetchFn;
35386
- constructor(objectTypeOrFetchFn, objectId, rootSpanId, getState) {
37298
+ constructor(objectTypeOrFetchFn, objectId, rootSpanId, getState, brainstoreRealtime = true) {
35387
37299
  if (typeof objectTypeOrFetchFn === "function") {
35388
37300
  this.fetchFn = (spanType) => objectTypeOrFetchFn(spanType);
35389
37301
  } else {
@@ -35396,7 +37308,8 @@ var CachedSpanFetcher = class {
35396
37308
  rootSpanId,
35397
37309
  state,
35398
37310
  spanType,
35399
- includeScorers
37311
+ includeScorers,
37312
+ brainstoreRealtime
35400
37313
  );
35401
37314
  const rows = await fetcher.fetchedData();
35402
37315
  return rows.map((row) => ({
@@ -36226,7 +38139,7 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
36226
38139
  }
36227
38140
  };
36228
38141
  const parentStr = state.currentParent.getStore();
36229
- const parentComponents = parentStr ? SpanComponentsV3.fromStr(parentStr) : null;
38142
+ const parentComponents = typeof parentStr === "string" ? SpanComponentsV4.fromStr(parentStr) : null;
36230
38143
  const trace = state ? new LocalTrace({
36231
38144
  objectType: parentComponents ? spanObjectTypeV3ToTypedString(
36232
38145
  parentComponents.data.object_type
@@ -36752,6 +38665,350 @@ var defaultReporter = {
36752
38665
  }
36753
38666
  };
36754
38667
 
38668
+ // src/agent-assertions.ts
38669
+ function agentAssertionScorer(callback, options = {}) {
38670
+ return async (args) => {
38671
+ const { trace: _trace, ...callbackArgs } = args;
38672
+ const callbackMetadata = callbackArgs.metadata ?? {};
38673
+ const assertions = await callback({
38674
+ ...callbackArgs,
38675
+ metadata: callbackMetadata,
38676
+ assert: agentAssertionHelpers
38677
+ });
38678
+ const resources = {};
38679
+ if (assertions.some((assertion) => assertion.requiresTrace)) {
38680
+ resources.spans = await args.trace?.getSpans({ spanType: ["tool"] });
38681
+ }
38682
+ const results = await Promise.all(
38683
+ assertions.map(async (assertion) => {
38684
+ const result = await assertion.evaluate(resources);
38685
+ return {
38686
+ name: assertion.name,
38687
+ passed: result.passed,
38688
+ failure: result.failure
38689
+ };
38690
+ })
38691
+ );
38692
+ const passed = results.filter((result) => result.passed).length;
38693
+ const total = results.length;
38694
+ const failed = results.filter((result) => !result.passed).map(
38695
+ (result) => `${result.name}: ${result.failure ?? "assertion did not pass"}`
38696
+ );
38697
+ return {
38698
+ name: options.name ?? "assertions",
38699
+ score: total === 0 ? 1 : passed / total,
38700
+ metadata: {
38701
+ assertions: results.map(({ name, passed: passed2 }) => ({ name, passed: passed2 })),
38702
+ failed
38703
+ }
38704
+ };
38705
+ };
38706
+ }
38707
+ var agentAssertionHelpers = {
38708
+ equals: (actual, expected, name = "equals") => ({
38709
+ name,
38710
+ evaluate: () => {
38711
+ const passed = deepEqual(actual, expected);
38712
+ return {
38713
+ passed,
38714
+ failure: passed ? void 0 : `expected ${formatValue(actual)} to equal ${formatValue(expected)}`
38715
+ };
38716
+ }
38717
+ }),
38718
+ notEquals: (actual, expected, name = "not equals") => ({
38719
+ name,
38720
+ evaluate: () => {
38721
+ const passed = !deepEqual(actual, expected);
38722
+ return {
38723
+ passed,
38724
+ failure: passed ? void 0 : `expected ${formatValue(actual)} not to equal ${formatValue(expected)}`
38725
+ };
38726
+ }
38727
+ }),
38728
+ contains: (value, expected, name = "contains") => ({
38729
+ name,
38730
+ evaluate: () => {
38731
+ const searchedValue = typeof value === "string" ? value : formatValue(value);
38732
+ const passed = expected instanceof RegExp ? testRegex(expected, value) : searchedValue.includes(expected);
38733
+ return {
38734
+ passed,
38735
+ failure: passed ? void 0 : `expected ${formatValue(value)} to contain ${formatValue(expected)}`
38736
+ };
38737
+ }
38738
+ }),
38739
+ matches: (value, schema, name = "matches schema") => ({
38740
+ name,
38741
+ evaluate: async () => {
38742
+ const result = await validateSchema(schema, value);
38743
+ return {
38744
+ passed: result.passed,
38745
+ failure: result.passed ? void 0 : `expected value to match schema: ${result.message}`
38746
+ };
38747
+ }
38748
+ }),
38749
+ calledTool: (toolName, options = {}, name = `called tool ${toolName}`) => ({
38750
+ name,
38751
+ requiresTrace: true,
38752
+ evaluate: ({ spans }) => {
38753
+ const calls = matchingToolCalls(spans ?? [], toolName, options);
38754
+ const passed = options.times === void 0 ? calls.length > 0 : calls.length === options.times;
38755
+ return {
38756
+ passed,
38757
+ 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"}`
38758
+ };
38759
+ }
38760
+ }),
38761
+ notCalledTool: (toolName, name = `did not call tool ${toolName}`) => ({
38762
+ name,
38763
+ requiresTrace: true,
38764
+ evaluate: ({ spans }) => {
38765
+ const calls = toolCalls(spans ?? []).filter(
38766
+ (span) => getToolName(span) === toolName
38767
+ );
38768
+ const passed = calls.length === 0;
38769
+ return {
38770
+ passed,
38771
+ failure: passed ? void 0 : `expected tool "${toolName}" not to be called; found ${calls.length} call${calls.length === 1 ? "" : "s"}`
38772
+ };
38773
+ }
38774
+ }),
38775
+ toolOrder: (toolNames, name = "tool order") => ({
38776
+ name,
38777
+ requiresTrace: true,
38778
+ evaluate: ({ spans }) => {
38779
+ const observed = toolCalls(spans ?? []).map(getToolName).filter((toolName) => toolName !== void 0);
38780
+ let fromIndex = 0;
38781
+ const passed = toolNames.every((toolName) => {
38782
+ const index = observed.indexOf(toolName, fromIndex);
38783
+ if (index === -1) return false;
38784
+ fromIndex = index + 1;
38785
+ return true;
38786
+ });
38787
+ return {
38788
+ passed,
38789
+ failure: passed ? void 0 : `expected tool order ${toolNames.join(" -> ")}; observed ${observed.join(" -> ") || "no tools"}`
38790
+ };
38791
+ }
38792
+ }),
38793
+ usedNoTools: (name = "used no tools") => ({
38794
+ name,
38795
+ requiresTrace: true,
38796
+ evaluate: ({ spans }) => {
38797
+ const calls = toolCalls(spans ?? []);
38798
+ const passed = calls.length === 0;
38799
+ return {
38800
+ passed,
38801
+ failure: passed ? void 0 : `expected no tool calls; found ${calls.length}`
38802
+ };
38803
+ }
38804
+ }),
38805
+ maxToolCalls: (max, name = `at most ${max} tool calls`) => ({
38806
+ name,
38807
+ requiresTrace: true,
38808
+ evaluate: ({ spans }) => {
38809
+ const calls = toolCalls(spans ?? []);
38810
+ const passed = calls.length <= max;
38811
+ return {
38812
+ passed,
38813
+ failure: passed ? void 0 : `expected at most ${max} tool call${max === 1 ? "" : "s"}; found ${calls.length}`
38814
+ };
38815
+ }
38816
+ })
38817
+ };
38818
+ async function validateSchema(schema, value) {
38819
+ try {
38820
+ if ("safeParse" in schema) {
38821
+ const result2 = schema.safeParse(value);
38822
+ return result2.success ? { passed: true, message: "" } : { passed: false, message: formatSchemaError(result2.error) };
38823
+ }
38824
+ if ("parse" in schema) {
38825
+ schema.parse(value);
38826
+ return { passed: true, message: "" };
38827
+ }
38828
+ const result = await schema["~standard"].validate(value);
38829
+ if (typeof result === "object" && result !== null && "issues" in result && Array.isArray(result.issues) && result.issues.length > 0) {
38830
+ return { passed: false, message: formatValue(result.issues) };
38831
+ }
38832
+ return { passed: true, message: "" };
38833
+ } catch (e) {
38834
+ return { passed: false, message: formatSchemaError(e) };
38835
+ }
38836
+ }
38837
+ function toolCalls(spans) {
38838
+ return spans.filter((span) => span.span_attributes?.type === "tool");
38839
+ }
38840
+ function matchingToolCalls(spans, toolName, options) {
38841
+ return toolCalls(spans).filter((span) => {
38842
+ if (getToolName(span) !== toolName) return false;
38843
+ if (Object.prototype.hasOwnProperty.call(options, "input") && !matchesValue(span.input, options.input)) {
38844
+ return false;
38845
+ }
38846
+ if (Object.prototype.hasOwnProperty.call(options, "output") && !matchesValue(span.output, options.output)) {
38847
+ return false;
38848
+ }
38849
+ if (options.isError !== void 0 && Boolean(span.error) !== options.isError) {
38850
+ return false;
38851
+ }
38852
+ return true;
38853
+ });
38854
+ }
38855
+ function getToolName(span) {
38856
+ const spanName = [span.span_attributes?.name, span.name].map(normalizeToolName).find((value) => value !== void 0);
38857
+ if (spanName?.includes("/")) {
38858
+ return spanName;
38859
+ }
38860
+ const metadataName = [
38861
+ span.metadata?.tool_name,
38862
+ span.metadata?.["gen_ai.tool.name"]
38863
+ ].map(normalizeToolName).find((value) => value !== void 0);
38864
+ const mcpServer = [
38865
+ span.metadata?.["mcp.server"],
38866
+ span.metadata?.["openai_codex.mcp.server"]
38867
+ ].find((value) => typeof value === "string" && value !== "");
38868
+ if (metadataName && mcpServer) {
38869
+ return `${mcpServer}/${metadataName}`;
38870
+ }
38871
+ return metadataName ?? spanName;
38872
+ }
38873
+ function normalizeToolName(value) {
38874
+ if (typeof value !== "string" || value === "") {
38875
+ return void 0;
38876
+ }
38877
+ return value.startsWith("tool:") ? value.slice("tool:".length).trim() : value;
38878
+ }
38879
+ function matchesValue(actual, matcher) {
38880
+ if (matcher instanceof RegExp) {
38881
+ return testRegex(matcher, actual);
38882
+ }
38883
+ if (typeof matcher === "function") {
38884
+ return matcher(actual);
38885
+ }
38886
+ if (Array.isArray(matcher)) {
38887
+ return Array.isArray(actual) && actual.length === matcher.length && matcher.every((value, index) => matchesValue(actual[index], value));
38888
+ }
38889
+ if (isPlainObject(matcher) && isPlainObject(actual)) {
38890
+ return Object.entries(matcher).every(
38891
+ ([key, value]) => Object.prototype.hasOwnProperty.call(actual, key) && matchesValue(actual[key], value)
38892
+ );
38893
+ }
38894
+ return deepEqual(actual, matcher);
38895
+ }
38896
+ function testRegex(matcher, value) {
38897
+ matcher.lastIndex = 0;
38898
+ return matcher.test(typeof value === "string" ? value : formatValue(value));
38899
+ }
38900
+ function deepEqual(left, right) {
38901
+ if (Object.is(left, right)) return true;
38902
+ if (Array.isArray(left) && Array.isArray(right)) {
38903
+ return left.length === right.length && left.every((item, index) => deepEqual(item, right[index]));
38904
+ }
38905
+ if (isPlainObject(left) && isPlainObject(right)) {
38906
+ const leftKeys = Object.keys(left);
38907
+ const rightKeys = Object.keys(right);
38908
+ return leftKeys.length === rightKeys.length && leftKeys.every(
38909
+ (key) => Object.prototype.hasOwnProperty.call(right, key) && deepEqual(left[key], right[key])
38910
+ );
38911
+ }
38912
+ return false;
38913
+ }
38914
+ function isPlainObject(value) {
38915
+ return typeof value === "object" && value !== null && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype;
38916
+ }
38917
+ function formatSchemaError(error) {
38918
+ if (error instanceof Error) {
38919
+ return error.message;
38920
+ }
38921
+ return formatValue(error);
38922
+ }
38923
+ function formatValue(value) {
38924
+ if (value instanceof RegExp) {
38925
+ return value.toString();
38926
+ }
38927
+ if (typeof value === "string") {
38928
+ return JSON.stringify(value);
38929
+ }
38930
+ try {
38931
+ const serialized = JSON.stringify(value);
38932
+ if (serialized !== void 0 && !hasUndefinedJsonValue(value)) {
38933
+ return serialized;
38934
+ }
38935
+ return formatValueWithUndefined(value, /* @__PURE__ */ new Set());
38936
+ } catch {
38937
+ return String(value);
38938
+ }
38939
+ }
38940
+ function hasUndefinedJsonValue(value, seen = /* @__PURE__ */ new Set()) {
38941
+ if (value === void 0) {
38942
+ return true;
38943
+ }
38944
+ if (typeof value !== "object" || value === null) {
38945
+ return false;
38946
+ }
38947
+ if (seen.has(value)) {
38948
+ return false;
38949
+ }
38950
+ seen.add(value);
38951
+ if (Array.isArray(value)) {
38952
+ return Array.from({ length: value.length }).some(
38953
+ (_, index) => hasUndefinedJsonValue(value[index], seen)
38954
+ );
38955
+ }
38956
+ return Object.keys(value).some(
38957
+ (key) => hasUndefinedJsonValue(value[key], seen)
38958
+ );
38959
+ }
38960
+ function formatValueWithUndefined(value, seen) {
38961
+ if (value === void 0) {
38962
+ return "undefined";
38963
+ }
38964
+ if (value === null) {
38965
+ return "null";
38966
+ }
38967
+ if (typeof value === "string") {
38968
+ return JSON.stringify(value);
38969
+ }
38970
+ if (typeof value === "number" || typeof value === "boolean") {
38971
+ return JSON.stringify(value);
38972
+ }
38973
+ if (typeof value === "bigint" || typeof value === "function") {
38974
+ return String(value);
38975
+ }
38976
+ if (typeof value === "symbol") {
38977
+ return String(value);
38978
+ }
38979
+ if (value instanceof RegExp) {
38980
+ return value.toString();
38981
+ }
38982
+ if (typeof value !== "object") {
38983
+ return String(value);
38984
+ }
38985
+ if (seen.has(value)) {
38986
+ return '"[Circular]"';
38987
+ }
38988
+ seen.add(value);
38989
+ if (typeof value.toJSON === "function") {
38990
+ const jsonValue = value.toJSON();
38991
+ seen.delete(value);
38992
+ return formatValueWithUndefined(jsonValue, seen);
38993
+ }
38994
+ if (Array.isArray(value)) {
38995
+ const formatted2 = Array.from(
38996
+ { length: value.length },
38997
+ (_, index) => formatValueWithUndefined(value[index], seen)
38998
+ );
38999
+ seen.delete(value);
39000
+ return `[${formatted2.join(",")}]`;
39001
+ }
39002
+ const formatted = Object.keys(value).map(
39003
+ (key) => `${JSON.stringify(key)}:${formatValueWithUndefined(
39004
+ value[key],
39005
+ seen
39006
+ )}`
39007
+ );
39008
+ seen.delete(value);
39009
+ return `{${formatted.join(",")}}`;
39010
+ }
39011
+
36755
39012
  // src/dataset-pipeline.ts
36756
39013
  function DatasetPipeline(definition) {
36757
39014
  if (!globalThis.__braintrust_dataset_pipelines) {