braintrust 3.19.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 +2833 -987
  6. package/dev/dist/index.mjs +2294 -448
  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 +1369 -848
  49. package/dist/browser.d.ts +1369 -848
  50. package/dist/browser.js +2735 -473
  51. package/dist/browser.mjs +2735 -473
  52. package/dist/{chunk-LPC4W2WX.js → chunk-BFGIH2ZJ.js} +4 -0
  53. package/dist/{chunk-37RLJF2U.js → chunk-FY7DAKA5.js} +3149 -1273
  54. package/dist/{chunk-Y7W7WP6H.mjs → chunk-KMGUTPB7.mjs} +4 -0
  55. package/dist/{chunk-VEQ2PCMC.mjs → chunk-O2P765XK.mjs} +2399 -523
  56. package/dist/cli.js +2267 -412
  57. package/dist/edge-light.d.mts +1 -1
  58. package/dist/edge-light.d.ts +1 -1
  59. package/dist/edge-light.js +2735 -473
  60. package/dist/edge-light.mjs +2735 -473
  61. package/dist/index.d.mts +1848 -1327
  62. package/dist/index.d.ts +1848 -1327
  63. package/dist/index.js +754 -352
  64. package/dist/index.mjs +448 -46
  65. package/dist/instrumentation/index.d.mts +119 -21
  66. package/dist/instrumentation/index.d.ts +119 -21
  67. package/dist/instrumentation/index.js +2345 -512
  68. package/dist/instrumentation/index.mjs +2344 -512
  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 +2735 -473
  74. package/dist/workerd.mjs +2735 -473
  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,7 +91,9 @@ __export(edge_light_exports, {
86
91
  _internalIso: () => isomorph_default,
87
92
  _internalSetInitialState: () => _internalSetInitialState,
88
93
  addAzureBlobHeaders: () => addAzureBlobHeaders,
94
+ agentAssertionScorer: () => agentAssertionScorer,
89
95
  braintrustAISDKTelemetry: () => braintrustAISDKTelemetry,
96
+ braintrustFlueInstrumentation: () => braintrustFlueInstrumentation,
90
97
  braintrustFlueObserver: () => braintrustFlueObserver,
91
98
  braintrustStreamChunkSchema: () => braintrustStreamChunkSchema,
92
99
  buildLocalSummary: () => buildLocalSummary,
@@ -103,6 +110,7 @@ __export(edge_light_exports, {
103
110
  devNullWritableStream: () => devNullWritableStream,
104
111
  evaluatorDefinitionSchema: () => evaluatorDefinitionSchema,
105
112
  evaluatorDefinitionsSchema: () => evaluatorDefinitionsSchema,
113
+ extractTraceContextFromHeaders: () => extractTraceContextFromHeaders,
106
114
  flush: () => flush,
107
115
  getContextManager: () => getContextManager,
108
116
  getIdGenerator: () => getIdGenerator,
@@ -116,6 +124,7 @@ __export(edge_light_exports, {
116
124
  initFunction: () => initFunction,
117
125
  initLogger: () => initLogger,
118
126
  initNodeTestSuite: () => initNodeTestSuite,
127
+ injectTraceContext: () => injectTraceContext,
119
128
  invoke: () => invoke,
120
129
  isTemplateFormat: () => isTemplateFormat,
121
130
  loadParameters: () => loadParameters,
@@ -154,7 +163,7 @@ __export(edge_light_exports, {
154
163
  traced: () => traced,
155
164
  updateSpan: () => updateSpan,
156
165
  uploadLogs3OverflowPayload: () => uploadLogs3OverflowPayload,
157
- utf8ByteLength: () => utf8ByteLength,
166
+ utf8ByteLength: () => utf8ByteLength2,
158
167
  withCurrent: () => withCurrent,
159
168
  withDataset: () => withDataset,
160
169
  withExperiment: () => withExperiment,
@@ -469,8 +478,291 @@ var UUIDGenerator = class extends IDGenerator {
469
478
  return true;
470
479
  }
471
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
+ }
472
521
  function getIdGenerator() {
473
- 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(",");
474
766
  }
475
767
 
476
768
  // util/db_fields.ts
@@ -1078,7 +1370,7 @@ var SpanComponentsV3 = class _SpanComponentsV3 {
1078
1370
  case 3 /* PLAYGROUND_LOGS */:
1079
1371
  return { prompt_session_id: this.data.object_id, log_id: "x" };
1080
1372
  default:
1081
- const _ = this.data.object_type;
1373
+ this.data.object_type;
1082
1374
  throw new Error("Impossible");
1083
1375
  }
1084
1376
  }
@@ -1607,7 +1899,7 @@ var SpanComponentsV4 = class _SpanComponentsV4 {
1607
1899
  case 3 /* PLAYGROUND_LOGS */:
1608
1900
  return { prompt_session_id: this.data.object_id, log_id: "x" };
1609
1901
  default:
1610
- const _ = this.data.object_type;
1902
+ this.data.object_type;
1611
1903
  throw new Error(`Invalid object_type ${this.data.object_type}`);
1612
1904
  }
1613
1905
  }
@@ -1786,7 +2078,8 @@ var AclObjectType = import_v36.z.union([
1786
2078
  "role",
1787
2079
  "org_member",
1788
2080
  "project_log",
1789
- "org_project"
2081
+ "org_project",
2082
+ "org_audit_logs"
1790
2083
  ]),
1791
2084
  import_v36.z.null()
1792
2085
  ]);
@@ -1812,6 +2105,17 @@ var Acl = import_v36.z.object({
1812
2105
  _object_org_id: import_v36.z.string().uuid(),
1813
2106
  created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional()
1814
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
+ });
1815
2119
  var AISecret = import_v36.z.object({
1816
2120
  id: import_v36.z.string().uuid(),
1817
2121
  created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
@@ -1958,6 +2262,7 @@ var AttachmentStatus = import_v36.z.object({
1958
2262
  upload_status: UploadStatus,
1959
2263
  error_message: import_v36.z.string().optional()
1960
2264
  });
2265
+ var AutomationStatus = import_v36.z.enum(["active", "paused"]);
1961
2266
  var FunctionTypeEnum = import_v36.z.enum([
1962
2267
  "llm",
1963
2268
  "scorer",
@@ -2003,7 +2308,9 @@ var TopicMapData = import_v36.z.object({
2003
2308
  topic_names: import_v36.z.record(import_v36.z.string()).optional(),
2004
2309
  generation_settings: TopicMapGenerationSettings.optional(),
2005
2310
  disable_reconciliation: import_v36.z.boolean().optional(),
2006
- 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()
2007
2314
  });
2008
2315
  var BatchedFacetData = import_v36.z.object({
2009
2316
  type: import_v36.z.literal("batched_facet"),
@@ -2286,7 +2593,7 @@ var DatasetEvent = import_v36.z.object({
2286
2593
  origin: ObjectReferenceNullish.optional(),
2287
2594
  comments: import_v36.z.union([import_v36.z.array(import_v36.z.unknown()), import_v36.z.null()]).optional(),
2288
2595
  audit_data: import_v36.z.union([import_v36.z.array(import_v36.z.unknown()), import_v36.z.null()]).optional(),
2289
- 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(),
2290
2597
  classifications: import_v36.z.union([
2291
2598
  import_v36.z.record(
2292
2599
  import_v36.z.array(
@@ -2438,7 +2745,7 @@ var ExperimentEvent = import_v36.z.object({
2438
2745
  origin: ObjectReferenceNullish.optional(),
2439
2746
  comments: import_v36.z.union([import_v36.z.array(import_v36.z.unknown()), import_v36.z.null()]).optional(),
2440
2747
  audit_data: import_v36.z.union([import_v36.z.array(import_v36.z.unknown()), import_v36.z.null()]).optional(),
2441
- 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(),
2442
2749
  classifications: import_v36.z.union([
2443
2750
  import_v36.z.record(
2444
2751
  import_v36.z.array(
@@ -2576,7 +2883,8 @@ var PromptParserNullish = import_v36.z.union([
2576
2883
  use_cot: import_v36.z.boolean(),
2577
2884
  choice_scores: import_v36.z.record(import_v36.z.number().gte(0).lte(1)).optional(),
2578
2885
  choice: import_v36.z.array(import_v36.z.string()).optional(),
2579
- 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()
2580
2888
  }),
2581
2889
  import_v36.z.null()
2582
2890
  ]);
@@ -2906,6 +3214,9 @@ var Group = import_v36.z.object({
2906
3214
  var GroupScope = import_v36.z.object({
2907
3215
  type: import_v36.z.literal("group"),
2908
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"]),
2909
3220
  idle_seconds: import_v36.z.number().optional()
2910
3221
  });
2911
3222
  var IfExists = import_v36.z.enum(["error", "ignore", "replace"]);
@@ -3054,6 +3365,10 @@ var RetentionObjectType = import_v36.z.enum([
3054
3365
  "experiment",
3055
3366
  "dataset"
3056
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
+ ]);
3057
3372
  var TopicMapFunctionAutomation = import_v36.z.object({
3058
3373
  function: SavedFunctionId.and(import_v36.z.unknown()),
3059
3374
  btql_filter: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional()
@@ -3066,7 +3381,9 @@ var TopicAutomationDataScope = import_v36.z.union([
3066
3381
  ]);
3067
3382
  var TopicAutomationConfig = import_v36.z.object({
3068
3383
  event_type: import_v36.z.literal("topic"),
3384
+ status: AutomationStatus.optional(),
3069
3385
  sampling_rate: import_v36.z.number().gte(0).lte(1),
3386
+ facet_model: TopicAutomationFacetModel.optional(),
3070
3387
  facet_functions: import_v36.z.array(SavedFunctionId),
3071
3388
  topic_map_functions: import_v36.z.array(TopicMapFunctionAutomation),
3072
3389
  scope: import_v36.z.union([SpanScope, TraceScope, GroupScope, import_v36.z.null()]).optional(),
@@ -3080,6 +3397,19 @@ var TopicAutomationConfig = import_v36.z.object({
3080
3397
  import_v36.z.null()
3081
3398
  ]).optional()
3082
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
+ });
3083
3413
  var ProjectAutomation = import_v36.z.object({
3084
3414
  id: import_v36.z.string().uuid(),
3085
3415
  project_id: import_v36.z.string().uuid(),
@@ -3104,6 +3434,7 @@ var ProjectAutomation = import_v36.z.object({
3104
3434
  }),
3105
3435
  import_v36.z.object({
3106
3436
  event_type: import_v36.z.literal("btql_export"),
3437
+ status: AutomationStatus.optional(),
3107
3438
  export_definition: import_v36.z.union([
3108
3439
  import_v36.z.object({ type: import_v36.z.literal("log_traces") }),
3109
3440
  import_v36.z.object({ type: import_v36.z.literal("log_spans") }),
@@ -3126,6 +3457,21 @@ var ProjectAutomation = import_v36.z.object({
3126
3457
  ]),
3127
3458
  batch_size: import_v36.z.union([import_v36.z.number(), import_v36.z.null()]).optional()
3128
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
+ }),
3129
3475
  import_v36.z.object({
3130
3476
  event_type: import_v36.z.literal("retention"),
3131
3477
  object_type: RetentionObjectType,
@@ -3144,7 +3490,8 @@ var ProjectAutomation = import_v36.z.object({
3144
3490
  })
3145
3491
  ])
3146
3492
  }),
3147
- TopicAutomationConfig
3493
+ TopicAutomationConfig,
3494
+ TopicDigestAutomationConfig
3148
3495
  ])
3149
3496
  });
3150
3497
  var ProjectLogsEvent = import_v36.z.object({
@@ -3183,7 +3530,7 @@ var ProjectLogsEvent = import_v36.z.object({
3183
3530
  comments: import_v36.z.union([import_v36.z.array(import_v36.z.unknown()), import_v36.z.null()]).optional(),
3184
3531
  audit_data: import_v36.z.union([import_v36.z.array(import_v36.z.unknown()), import_v36.z.null()]).optional(),
3185
3532
  _async_scoring_state: import_v36.z.unknown().optional(),
3186
- 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(),
3187
3534
  classifications: import_v36.z.union([
3188
3535
  import_v36.z.record(
3189
3536
  import_v36.z.array(
@@ -3232,11 +3579,34 @@ var ProjectScoreCategories = import_v36.z.union([
3232
3579
  import_v36.z.array(import_v36.z.string()),
3233
3580
  import_v36.z.null()
3234
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
+ ]);
3235
3593
  var ProjectScoreConfig = import_v36.z.union([
3236
3594
  import_v36.z.object({
3237
3595
  multi_select: import_v36.z.union([import_v36.z.boolean(), import_v36.z.null()]),
3238
3596
  destination: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
3239
- 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
+ ])
3240
3610
  }).partial(),
3241
3611
  import_v36.z.null()
3242
3612
  ]);
@@ -3421,8 +3791,7 @@ var User = import_v36.z.object({
3421
3791
  family_name: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3422
3792
  email: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3423
3793
  avatar_url: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3424
- created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3425
- 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()
3426
3795
  });
3427
3796
  var ViewDataSearch = import_v36.z.union([
3428
3797
  import_v36.z.object({
@@ -4709,7 +5078,10 @@ var BraintrustContextManager = class extends ContextManager {
4709
5078
  }
4710
5079
  };
4711
5080
  function getSpanComponentsClass() {
4712
- 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;
4713
5085
  }
4714
5086
  function getContextManager() {
4715
5087
  return globalThis.BRAINTRUST_CONTEXT_MANAGER ? new globalThis.BRAINTRUST_CONTEXT_MANAGER() : new BraintrustContextManager();
@@ -4745,6 +5117,9 @@ var NoopSpan = class {
4745
5117
  async export() {
4746
5118
  return "";
4747
5119
  }
5120
+ inject(carrier) {
5121
+ return carrier ?? {};
5122
+ }
4748
5123
  async permalink() {
4749
5124
  return NOOP_SPAN_PERMALINK;
4750
5125
  }
@@ -4795,6 +5170,10 @@ var loginSchema = import_v38.z.strictObject({
4795
5170
  debugLogLevelDisabled: import_v38.z.boolean().optional()
4796
5171
  });
4797
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
+ }
4798
5177
  var BraintrustState = class _BraintrustState {
4799
5178
  constructor(loginParams) {
4800
5179
  this.loginParams = loginParams;
@@ -5065,7 +5444,10 @@ var BraintrustState = class _BraintrustState {
5065
5444
  if (!this.proxyUrl) {
5066
5445
  throw new Error("Must initialize proxyUrl before requesting proxyConn");
5067
5446
  }
5068
- this._proxyConn = new HTTPConnection(this.proxyUrl, this.fetch);
5447
+ this._proxyConn = new HTTPConnection(
5448
+ normalizeProxyConnUrl(this.proxyUrl),
5449
+ this.fetch
5450
+ );
5069
5451
  }
5070
5452
  return this._proxyConn;
5071
5453
  }
@@ -5823,7 +6205,7 @@ function updateSpan({
5823
6205
  ...event
5824
6206
  }) {
5825
6207
  const resolvedState = state ?? _globalState;
5826
- const components = getSpanComponentsClass().fromStr(exported);
6208
+ const components = SpanComponentsV4.fromStr(exported);
5827
6209
  if (!components.data.row_id) {
5828
6210
  throw new Error("Exported span must have a row id");
5829
6211
  }
@@ -5923,7 +6305,7 @@ async function permalink(slug, opts) {
5923
6305
  return state.appUrl;
5924
6306
  };
5925
6307
  try {
5926
- const components = getSpanComponentsClass().fromStr(slug);
6308
+ const components = SpanComponentsV4.fromStr(slug);
5927
6309
  const object_type = spanObjectTypeV3ToString(components.data.object_type);
5928
6310
  const [orgName, appUrl, object_id] = await Promise.all([
5929
6311
  getOrgName(),
@@ -5947,35 +6329,47 @@ function startSpanParentArgs(args) {
5947
6329
  let argParentObjectId = void 0;
5948
6330
  let argParentSpanIds = void 0;
5949
6331
  let argPropagatedEvent = void 0;
5950
- if (args.parent) {
6332
+ let argPropagatedState = void 0;
6333
+ const { parentSlug, propagatedState: parentPropagatedState } = normalizeParent(args.parent, args.state);
6334
+ if (parentSlug) {
5951
6335
  if (args.parentSpanIds) {
5952
6336
  throw new Error("Cannot specify both parent and parentSpanIds");
5953
6337
  }
5954
- const parentComponents = getSpanComponentsClass().fromStr(args.parent);
6338
+ const parentComponents = SpanComponentsV4.fromStr(parentSlug);
5955
6339
  if (args.parentObjectType !== parentComponents.data.object_type) {
5956
6340
  throw new Error(
5957
6341
  `Mismatch between expected span parent object type ${args.parentObjectType} and provided type ${parentComponents.data.object_type}`
5958
6342
  );
5959
6343
  }
5960
6344
  argParentObjectId = args.parentObjectId;
5961
- if (parentComponents.data.row_id) {
6345
+ if (parentComponents.data.row_id && parentSpanIdsUsable(
6346
+ parentComponents.data.span_id,
6347
+ parentComponents.data.root_span_id
6348
+ )) {
5962
6349
  argParentSpanIds = {
5963
6350
  spanId: parentComponents.data.span_id,
5964
6351
  rootSpanId: parentComponents.data.root_span_id
5965
6352
  };
5966
6353
  }
5967
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
+ }
5968
6360
  } else {
5969
6361
  argParentObjectId = args.parentObjectId;
5970
6362
  argParentSpanIds = args.parentSpanIds;
5971
6363
  argPropagatedEvent = args.propagatedEvent;
6364
+ argPropagatedState = args.propagatedState;
5972
6365
  }
5973
6366
  return {
5974
6367
  parentObjectType: args.parentObjectType,
5975
6368
  parentObjectId: argParentObjectId,
5976
6369
  parentComputeObjectMetadataArgs: args.parentComputeObjectMetadataArgs,
5977
6370
  parentSpanIds: argParentSpanIds,
5978
- propagatedEvent: argPropagatedEvent
6371
+ propagatedEvent: argPropagatedEvent,
6372
+ propagatedState: argPropagatedState
5979
6373
  };
5980
6374
  }
5981
6375
  var Logger = class {
@@ -6176,6 +6570,22 @@ var Logger = class {
6176
6570
  _getLinkBaseUrl() {
6177
6571
  return _getLinkBaseUrl(this.state, this._linkArgs);
6178
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
+ }
6179
6589
  };
6180
6590
  function castLogger(logger, asyncFlush) {
6181
6591
  if (logger === void 0) return void 0;
@@ -6270,12 +6680,12 @@ function stringifyWithOverflowMeta(item) {
6270
6680
  object_ids: pickLogs3OverflowObjectIds(record),
6271
6681
  is_delete: record[OBJECT_DELETE_FIELD] === true,
6272
6682
  input_row: {
6273
- byte_size: utf8ByteLength(str)
6683
+ byte_size: utf8ByteLength2(str)
6274
6684
  }
6275
6685
  }
6276
6686
  };
6277
6687
  }
6278
- function utf8ByteLength(value) {
6688
+ function utf8ByteLength2(value) {
6279
6689
  if (typeof TextEncoder !== "undefined") {
6280
6690
  return new TextEncoder().encode(value).length;
6281
6691
  }
@@ -6663,7 +7073,7 @@ var HTTPBackgroundLogger = class _HTTPBackgroundLogger {
6663
7073
  }) {
6664
7074
  const conn = await this.apiConn.get();
6665
7075
  const dataStr = constructLogs3Data(items);
6666
- const payloadBytes = utf8ByteLength(dataStr);
7076
+ const payloadBytes = utf8ByteLength2(dataStr);
6667
7077
  const useOverflow = canUseOverflow && payloadBytes > maxRequestSize;
6668
7078
  if (this.allPublishPayloadsDir) {
6669
7079
  await _HTTPBackgroundLogger.writePayloadToDir({
@@ -7284,6 +7694,8 @@ function initDataset(projectOrOptions, optionalOptions) {
7284
7694
  const normalizedVersion = selection.version;
7285
7695
  const normalizedEnvironment = selection.environment;
7286
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;
7287
7699
  const state = stateArg ?? _globalState;
7288
7700
  const lazyMetadata = new LazyValue(
7289
7701
  async () => {
@@ -7335,7 +7747,7 @@ function initDataset(projectOrOptions, optionalOptions) {
7335
7747
  lazyMetadata,
7336
7748
  typeof resolvedVersion === "string" ? resolvedVersion : void 0,
7337
7749
  legacy,
7338
- _internal_btql,
7750
+ internalBtql,
7339
7751
  resolvedVersion instanceof LazyValue || normalizedEnvironment !== void 0 || normalizedSnapshotName !== void 0 ? {
7340
7752
  ...resolvedVersion instanceof LazyValue ? {
7341
7753
  lazyPinnedVersion: resolvedVersion
@@ -7799,23 +8211,285 @@ function currentSpan(options) {
7799
8211
  const state = options?.state ?? _globalState;
7800
8212
  return state.contextManager.getCurrentSpan() ?? NOOP_SPAN;
7801
8213
  }
7802
- function getSpanParentObject(options) {
8214
+ function getSpanParentObjectAndPropagatedState(options) {
7803
8215
  const state = options?.state ?? _globalState;
7804
8216
  const parentSpan = currentSpan({ state });
7805
8217
  if (!Object.is(parentSpan, NOOP_SPAN)) {
7806
- 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
+ };
7807
8227
  }
7808
- const parentStr = options?.parent ?? state.currentParent.getStore();
7809
- if (parentStr) return getSpanComponentsClass().fromStr(parentStr);
7810
8228
  const experiment = currentExperiment();
7811
8229
  if (experiment) {
7812
- return experiment;
8230
+ return { parentObject: experiment, propagatedState: void 0 };
7813
8231
  }
7814
8232
  const logger = currentLogger(options);
7815
8233
  if (logger) {
7816
- 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
+ }
7817
8382
  }
7818
- 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);
7819
8493
  }
7820
8494
  function logError(span, error) {
7821
8495
  let errorMessage = "<error>";
@@ -8023,19 +8697,23 @@ function setFetch(fetch2) {
8023
8697
  }
8024
8698
  function startSpanAndIsLogger(args) {
8025
8699
  const state = args?.state ?? _globalState;
8026
- const parentObject = getSpanParentObject({
8700
+ const { parentObject, propagatedState } = getSpanParentObjectAndPropagatedState({
8027
8701
  asyncFlush: args?.asyncFlush,
8028
8702
  parent: args?.parent,
8029
8703
  state
8030
8704
  });
8031
8705
  if (parentObject instanceof SpanComponentsV3 || parentObject instanceof SpanComponentsV4) {
8032
- 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
+ ) ? {
8033
8710
  spanId: parentObject.data.span_id,
8034
8711
  rootSpanId: parentObject.data.root_span_id
8035
8712
  } : void 0;
8713
+ const { parent: _ignoredParent, ...spanArgs } = args ?? {};
8036
8714
  const span = new SpanImpl({
8037
8715
  state,
8038
- ...args,
8716
+ ...spanArgs,
8039
8717
  parentObjectType: parentObject.data.object_type,
8040
8718
  parentObjectId: new LazyValue(
8041
8719
  spanComponentsToObjectIdLambda(state, parentObject)
@@ -8043,7 +8721,8 @@ function startSpanAndIsLogger(args) {
8043
8721
  parentComputeObjectMetadataArgs: parentObject.data.compute_object_metadata_args ?? void 0,
8044
8722
  parentSpanIds,
8045
8723
  propagatedEvent: args?.propagatedEvent ?? // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
8046
- (parentObject.data.propagated_event ?? void 0)
8724
+ (parentObject.data.propagated_event ?? void 0),
8725
+ propagatedState
8047
8726
  });
8048
8727
  return {
8049
8728
  span,
@@ -8332,11 +9011,12 @@ function validateAndSanitizeExperimentLogFullArgs(event, hasDataset) {
8332
9011
  var DEFAULT_FETCH_BATCH_SIZE = 1e3;
8333
9012
  var MAX_BTQL_ITERATIONS = 1e4;
8334
9013
  var ObjectFetcher = class {
8335
- constructor(objectType, pinnedVersion, mutateRecord, _internal_btql) {
9014
+ constructor(objectType, pinnedVersion, mutateRecord, _internal_btql, _internalBrainstoreRealtime = true) {
8336
9015
  this.objectType = objectType;
8337
9016
  this.pinnedVersion = pinnedVersion;
8338
9017
  this.mutateRecord = mutateRecord;
8339
9018
  this._internal_btql = _internal_btql;
9019
+ this._internalBrainstoreRealtime = _internalBrainstoreRealtime;
8340
9020
  }
8341
9021
  _fetchedData = void 0;
8342
9022
  get id() {
@@ -8395,7 +9075,7 @@ var ObjectFetcher = class {
8395
9075
  ...internalBtqlWithoutReservedQueryKeys
8396
9076
  },
8397
9077
  use_columnstore: false,
8398
- brainstore_realtime: true,
9078
+ brainstore_realtime: this._internalBrainstoreRealtime,
8399
9079
  query_source: `js_sdk_object_fetcher_${this.objectType}`,
8400
9080
  ...this.pinnedVersion !== void 0 ? {
8401
9081
  version: this.pinnedVersion
@@ -8744,6 +9424,15 @@ View complete results in Braintrust or run experiment.summarize() again.`
8744
9424
  object_id: await this.id
8745
9425
  }).toStr();
8746
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
+ }
8747
9436
  /**
8748
9437
  * Flush any pending rows to the server.
8749
9438
  */
@@ -8786,7 +9475,8 @@ var ReadonlyExperiment = class extends ObjectFetcher {
8786
9475
  async *asDataset(options) {
8787
9476
  const records = this.fetch(options);
8788
9477
  for await (const record of records) {
8789
- if (record.root_span_id !== record.span_id) {
9478
+ const isRoot = record.is_root ?? record.root_span_id === record.span_id;
9479
+ if (!isRoot) {
8790
9480
  continue;
8791
9481
  }
8792
9482
  const { output, expected: expectedRecord, metadata } = record;
@@ -8848,9 +9538,16 @@ var SpanImpl = class _SpanImpl {
8848
9538
  _spanId;
8849
9539
  _rootSpanId;
8850
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;
8851
9547
  kind = "span";
8852
9548
  constructor(args) {
8853
9549
  this._state = args.state;
9550
+ this._propagatedState = args.propagatedState;
8854
9551
  const spanAttributes = args.spanAttributes ?? {};
8855
9552
  const rawEvent = args.event ?? {};
8856
9553
  const type = args.type ?? (args.parentSpanIds ? void 0 : args.defaultRootType);
@@ -8966,7 +9663,7 @@ var SpanImpl = class _SpanImpl {
8966
9663
  tags: partialRecord.tags,
8967
9664
  span_id: this._spanId,
8968
9665
  span_parents: this._spanParents,
8969
- is_root: this._spanId === this._rootSpanId,
9666
+ is_root: !this._spanParents || this._spanParents.length === 0,
8970
9667
  span_attributes: partialRecord.span_attributes
8971
9668
  };
8972
9669
  this._state.spanCache.queueWrite(
@@ -9028,7 +9725,8 @@ var SpanImpl = class _SpanImpl {
9028
9725
  parentObjectId: this.parentObjectId,
9029
9726
  parentComputeObjectMetadataArgs: this.parentComputeObjectMetadataArgs,
9030
9727
  parentSpanIds,
9031
- propagatedEvent: args?.propagatedEvent ?? this.propagatedEvent
9728
+ propagatedEvent: args?.propagatedEvent ?? this.propagatedEvent,
9729
+ propagatedState: this._propagatedState
9032
9730
  })
9033
9731
  });
9034
9732
  }
@@ -9047,7 +9745,8 @@ var SpanImpl = class _SpanImpl {
9047
9745
  parentObjectId: this.parentObjectId,
9048
9746
  parentComputeObjectMetadataArgs: this.parentComputeObjectMetadataArgs,
9049
9747
  parentSpanIds,
9050
- propagatedEvent: args?.propagatedEvent ?? this.propagatedEvent
9748
+ propagatedEvent: args?.propagatedEvent ?? this.propagatedEvent,
9749
+ propagatedState: this._propagatedState
9051
9750
  }),
9052
9751
  spanId
9053
9752
  });
@@ -9075,6 +9774,42 @@ var SpanImpl = class _SpanImpl {
9075
9774
  propagated_event: this.propagatedEvent
9076
9775
  }).toStr();
9077
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
+ }
9078
9813
  async permalink() {
9079
9814
  return await permalink(await this.export(), {
9080
9815
  state: this._state
@@ -9210,6 +9945,7 @@ var Dataset2 = class extends ObjectFetcher {
9210
9945
  _internal_btql
9211
9946
  );
9212
9947
  this.state = state;
9948
+ void this.__braintrust_dataset_marker;
9213
9949
  this.lazyMetadata = lazyMetadata;
9214
9950
  this.lazyPinnedVersion = pinState?.lazyPinnedVersion;
9215
9951
  this.pinnedEnvironment = pinState?.pinnedEnvironment;
@@ -9727,6 +10463,7 @@ var Prompt2 = class _Prompt {
9727
10463
  this.metadata = metadata;
9728
10464
  this.defaults = defaults;
9729
10465
  this.noTrace = noTrace;
10466
+ void this.__braintrust_prompt_marker;
9730
10467
  }
9731
10468
  parsedPromptData;
9732
10469
  hasParsedPromptData = false;
@@ -9963,6 +10700,7 @@ var Prompt2 = class _Prompt {
9963
10700
  var RemoteEvalParameters = class {
9964
10701
  constructor(metadata) {
9965
10702
  this.metadata = metadata;
10703
+ void this.__braintrust_parameters_marker;
9966
10704
  }
9967
10705
  __braintrust_parameters_marker = true;
9968
10706
  get id() {
@@ -10099,6 +10837,7 @@ var _exportsForTestingOnly = {
10099
10837
  isAsyncGeneratorFunction,
10100
10838
  resetIdGenStateForTests,
10101
10839
  validateTags,
10840
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
10102
10841
  isomorph: isomorph_default
10103
10842
  // Expose isomorph for build type detection
10104
10843
  };
@@ -11050,6 +11789,22 @@ function runStreamingCompletionHook(args) {
11050
11789
  );
11051
11790
  }
11052
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
+ }
11053
11808
  function traceAsyncChannel(channel2, config) {
11054
11809
  const tracingChannel2 = channel2.tracingChannel();
11055
11810
  const states = /* @__PURE__ */ new WeakMap();
@@ -11211,6 +11966,14 @@ function traceStreamingChannel(channel2, config) {
11211
11966
  }
11212
11967
  },
11213
11968
  onError: (error) => {
11969
+ runStreamingErrorHook({
11970
+ channelName,
11971
+ config,
11972
+ error,
11973
+ event: asyncEndEvent,
11974
+ span,
11975
+ startTime
11976
+ });
11214
11977
  span.log({
11215
11978
  error: error.message
11216
11979
  });
@@ -11268,6 +12031,17 @@ function traceStreamingChannel(channel2, config) {
11268
12031
  }
11269
12032
  },
11270
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
+ }
11271
12045
  logErrorAndEnd(states, event);
11272
12046
  }
11273
12047
  };
@@ -13630,14 +14404,45 @@ function serializeAISDKToolsForLogging(tools) {
13630
14404
  return serialized;
13631
14405
  }
13632
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
+
13633
14435
  // src/wrappers/ai-sdk/telemetry.ts
13634
14436
  function braintrustAISDKTelemetry() {
13635
14437
  const operations = /* @__PURE__ */ new Map();
14438
+ const operationKeysByCallId = /* @__PURE__ */ new Map();
14439
+ const workflowOperationKeyStore = isomorph_default.newAsyncLocalStorage();
13636
14440
  const modelSpans = /* @__PURE__ */ new Map();
13637
14441
  const objectSpans = /* @__PURE__ */ new Map();
13638
14442
  const embedSpans = /* @__PURE__ */ new Map();
13639
14443
  const rerankSpans = /* @__PURE__ */ new Map();
13640
14444
  const toolSpans = /* @__PURE__ */ new Map();
14445
+ let workflowAgentOperationCounter = 0;
13641
14446
  const runSafely = (name, callback) => {
13642
14447
  try {
13643
14448
  callback();
@@ -13645,42 +14450,333 @@ function braintrustAISDKTelemetry() {
13645
14450
  console.error(`Error in Braintrust AI SDK telemetry ${name}:`, error);
13646
14451
  }
13647
14452
  };
13648
- const startChildSpan = (callId, name, type, event) => {
13649
- const parent = operations.get(callId)?.span;
14453
+ const startChildSpan = (operationKey, name, type, event) => {
14454
+ const parent = operations.get(operationKey)?.span;
13650
14455
  const spanArgs = {
13651
14456
  name,
13652
14457
  spanAttributes: { type },
13653
14458
  ...event ? { event } : {}
13654
14459
  };
13655
14460
  const span = parent ? parent.startSpan(spanArgs) : startSpan(spanArgs);
13656
- const state = operations.get(callId);
14461
+ const state = operations.get(operationKey);
13657
14462
  if (state && type === "llm" /* LLM */) {
13658
14463
  state.hadModelChild = true;
13659
14464
  }
13660
14465
  return span;
13661
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
+ };
13662
14733
  return {
13663
14734
  onStart(event) {
13664
14735
  runSafely("onStart", () => {
13665
14736
  const operationName = operationNameFromId(event.operationId);
13666
- 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({
13667
14741
  name: operationName,
13668
14742
  spanAttributes: { type: "function" /* FUNCTION */ }
13669
- });
13670
- operations.set(event.callId, {
14743
+ }) : wrapperSpan;
14744
+ const operationKey = createOperationKey(event, operationName);
14745
+ registerOperation({
14746
+ callId: event.callId,
13671
14747
  hadModelChild: false,
14748
+ loggedInput: false,
13672
14749
  operationName,
14750
+ operationKey,
14751
+ ownsSpan,
13673
14752
  span,
13674
14753
  startTime: getCurrentUnixTimestamp()
13675
14754
  });
13676
- const metadata = metadataFromEvent(event);
14755
+ if (!ownsSpan) {
14756
+ return;
14757
+ }
14758
+ if (workflowAgent) {
14759
+ workflowOperationKeyStore.enterWith(operationKey);
14760
+ }
14761
+ let metadata = metadataFromEvent(event);
13677
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
+ }
13678
14771
  if (shouldRecordInputs(event)) {
13679
- const { input, outputPromise } = processAISDKCallInput(
13680
- operationInput(event, operationName)
13681
- );
14772
+ const callInput = workflowAgentCallInput ?? operationInput(event, operationName);
14773
+ const { input, outputPromise } = workflowAgent ? processAISDKWorkflowAgentCallInput(callInput) : processAISDKCallInput(callInput);
13682
14774
  logPayload.input = input;
13683
- 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") {
13684
14780
  outputPromise.then((resolvedData) => {
13685
14781
  span.log({
13686
14782
  input: {
@@ -13697,41 +14793,67 @@ function braintrustAISDKTelemetry() {
13697
14793
  },
13698
14794
  onLanguageModelCallStart(event) {
13699
14795
  runSafely("onLanguageModelCallStart", () => {
13700
- const state = operations.get(event.callId);
13701
- const openSpans = modelSpans.get(event.callId);
13702
- 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) {
13703
14817
  for (const span2 of openSpans) {
13704
14818
  span2.end();
13705
14819
  }
13706
- modelSpans.delete(event.callId);
14820
+ modelSpans.delete(operationKey);
13707
14821
  }
13708
14822
  const span = startChildSpan(
13709
- event.callId,
13710
- state?.operationName === "streamText" ? "doStream" : "doGenerate",
14823
+ operationKey ?? event.callId,
14824
+ operationName === "streamText" ? "doStream" : "doGenerate",
13711
14825
  "llm" /* LLM */,
13712
14826
  {
13713
14827
  ...shouldRecordInputs(event) ? {
13714
- input: processAISDKCallInput(
13715
- operationInput(
13716
- event,
13717
- state?.operationName ?? "generateText"
13718
- )
13719
- ).input
14828
+ input: processedInput
13720
14829
  } : {},
13721
- metadata: metadataFromEvent(event)
14830
+ metadata: workflowAgent ? {
14831
+ ...metadataFromEvent(event),
14832
+ ...extractWorkflowMetadataFromCallParams(callInput)
14833
+ } : metadataFromEvent(event)
13722
14834
  }
13723
14835
  );
13724
- const spans = modelSpans.get(event.callId) ?? [];
14836
+ const spanKey = operationKey ?? event.callId;
14837
+ const spans = modelSpans.get(spanKey) ?? [];
13725
14838
  spans.push(span);
13726
- modelSpans.set(event.callId, spans);
14839
+ modelSpans.set(spanKey, spans);
13727
14840
  });
13728
14841
  },
13729
14842
  onLanguageModelCallEnd(event) {
13730
14843
  runSafely("onLanguageModelCallEnd", () => {
13731
- 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;
13732
14850
  if (!span) {
13733
14851
  return;
13734
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
+ }
13735
14857
  const result = {
13736
14858
  ...event,
13737
14859
  response: event.responseId ? { id: event.responseId } : void 0
@@ -13747,14 +14869,18 @@ function braintrustAISDKTelemetry() {
13747
14869
  },
13748
14870
  onObjectStepStart(event) {
13749
14871
  runSafely("onObjectStepStart", () => {
13750
- const state = operations.get(event.callId);
13751
- const openSpan = objectSpans.get(event.callId);
13752
- 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) {
13753
14879
  openSpan.end();
13754
- objectSpans.delete(event.callId);
14880
+ objectSpans.delete(operationKey);
13755
14881
  }
13756
14882
  const span = startChildSpan(
13757
- event.callId,
14883
+ operationKey ?? event.callId,
13758
14884
  state?.operationName === "streamObject" ? "doStream" : "doGenerate",
13759
14885
  "llm" /* LLM */,
13760
14886
  {
@@ -13766,40 +14892,25 @@ function braintrustAISDKTelemetry() {
13766
14892
  metadata: metadataFromEvent(event)
13767
14893
  }
13768
14894
  );
13769
- objectSpans.set(event.callId, span);
13770
- });
13771
- },
13772
- onObjectStepFinish(event) {
13773
- runSafely("onObjectStepFinish", () => {
13774
- const span = objectSpans.get(event.callId);
13775
- if (!span) {
13776
- return;
13777
- }
13778
- const result = {
13779
- ...event,
13780
- text: event.objectText
13781
- };
13782
- span.log({
13783
- ...shouldRecordOutputs(event) ? {
13784
- output: processAISDKOutput(result, DEFAULT_DENY_OUTPUT_PATHS)
13785
- } : {},
13786
- metrics: extractTokenMetrics(result)
13787
- });
13788
- span.end();
13789
- objectSpans.delete(event.callId);
14895
+ objectSpans.set(operationKey ?? event.callId, span);
13790
14896
  });
13791
14897
  },
14898
+ onObjectStepEnd,
13792
14899
  onEmbedStart(event) {
13793
14900
  runSafely("onEmbedStart", () => {
13794
- 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
+ }
13795
14906
  for (const [embedCallId, embedState] of embedSpans) {
13796
- if (embedState.callId === event.callId && (state?.operationName === "embed" || embedState.values === event.values)) {
14907
+ if (embedState.operationKey === operationKey && (state?.operationName === "embed" || embedState.values === event.values)) {
13797
14908
  embedState.span.end();
13798
14909
  embedSpans.delete(embedCallId);
13799
14910
  }
13800
14911
  }
13801
14912
  const span = startChildSpan(
13802
- event.callId,
14913
+ operationKey ?? event.callId,
13803
14914
  "doEmbed",
13804
14915
  "llm" /* LLM */,
13805
14916
  {
@@ -13812,44 +14923,27 @@ function braintrustAISDKTelemetry() {
13812
14923
  }
13813
14924
  );
13814
14925
  embedSpans.set(event.embedCallId, {
13815
- callId: event.callId,
14926
+ operationKey: operationKey ?? event.callId,
13816
14927
  span,
13817
14928
  values: event.values
13818
14929
  });
13819
14930
  });
13820
14931
  },
13821
- onEmbedFinish(event) {
13822
- runSafely("onEmbedFinish", () => {
13823
- const state = embedSpans.get(event.embedCallId);
13824
- if (!state) {
13825
- return;
13826
- }
13827
- const result = {
13828
- ...event,
13829
- embeddings: event.embeddings
13830
- };
13831
- state.span.log({
13832
- ...shouldRecordOutputs(event) ? {
13833
- output: processAISDKEmbeddingOutput(
13834
- result,
13835
- DEFAULT_DENY_OUTPUT_PATHS
13836
- )
13837
- } : {},
13838
- metrics: extractTokenMetrics(result)
13839
- });
13840
- state.span.end();
13841
- embedSpans.delete(event.embedCallId);
13842
- });
13843
- },
14932
+ onEmbedEnd,
13844
14933
  onRerankStart(event) {
13845
14934
  runSafely("onRerankStart", () => {
13846
- const openSpan = rerankSpans.get(event.callId);
13847
- 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) {
13848
14942
  openSpan.end();
13849
- rerankSpans.delete(event.callId);
14943
+ rerankSpans.delete(operationKey);
13850
14944
  }
13851
14945
  const span = startChildSpan(
13852
- event.callId,
14946
+ operationKey ?? event.callId,
13853
14947
  "doRerank",
13854
14948
  "llm" /* LLM */,
13855
14949
  {
@@ -13863,41 +14957,23 @@ function braintrustAISDKTelemetry() {
13863
14957
  metadata: metadataFromEvent(event)
13864
14958
  }
13865
14959
  );
13866
- rerankSpans.set(event.callId, span);
13867
- });
13868
- },
13869
- onRerankFinish(event) {
13870
- runSafely("onRerankFinish", () => {
13871
- const span = rerankSpans.get(event.callId);
13872
- if (!span) {
13873
- return;
13874
- }
13875
- const result = {
13876
- ranking: event.ranking?.map((entry) => ({
13877
- originalIndex: entry.index,
13878
- score: entry.relevanceScore
13879
- }))
13880
- };
13881
- span.log({
13882
- ...shouldRecordOutputs(event) ? {
13883
- output: processAISDKRerankOutput(
13884
- result,
13885
- DEFAULT_DENY_OUTPUT_PATHS
13886
- )
13887
- } : {}
13888
- });
13889
- span.end();
13890
- rerankSpans.delete(event.callId);
14960
+ rerankSpans.set(operationKey ?? event.callId, span);
13891
14961
  });
13892
14962
  },
14963
+ onRerankEnd,
13893
14964
  onToolExecutionStart(event) {
13894
14965
  runSafely("onToolExecutionStart", () => {
14966
+ const operationKey = operationKeyFromEvent(event);
14967
+ const state = operationKey ? operations.get(operationKey) : void 0;
14968
+ if (shouldSkipTelemetryChildren(state)) {
14969
+ return;
14970
+ }
13895
14971
  const toolCallId = event.toolCall.toolCallId;
13896
- if (!toolCallId) {
14972
+ if (!operationKey || !toolCallId) {
13897
14973
  return;
13898
14974
  }
13899
14975
  const span = startChildSpan(
13900
- event.callId,
14976
+ operationKey,
13901
14977
  event.toolCall.toolName || "tool",
13902
14978
  "tool" /* TOOL */,
13903
14979
  {
@@ -13911,7 +14987,7 @@ function braintrustAISDKTelemetry() {
13911
14987
  }
13912
14988
  }
13913
14989
  );
13914
- toolSpans.set(toolCallId, { callId: event.callId, span });
14990
+ toolSpans.set(toolCallId, { operationKey, span });
13915
14991
  });
13916
14992
  },
13917
14993
  onToolExecutionEnd(event) {
@@ -13922,14 +14998,17 @@ function braintrustAISDKTelemetry() {
13922
14998
  return;
13923
14999
  }
13924
15000
  const toolOutput = event.toolOutput;
13925
- 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;
13926
15004
  state.span.log({
13927
- error: toolOutput.error instanceof Error ? toolOutput.error.message : String(toolOutput?.error),
15005
+ error: error instanceof Error ? error.message : String(error),
13928
15006
  metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
13929
15007
  });
13930
15008
  } else {
15009
+ const output = toolOutput && "output" in toolOutput ? toolOutput.output : event.output;
13931
15010
  state.span.log({
13932
- ...shouldRecordOutputs(event) ? { output: toolOutput?.output } : {},
15011
+ ...shouldRecordOutputs(event) ? { output } : {},
13933
15012
  metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
13934
15013
  });
13935
15014
  }
@@ -13943,83 +15022,46 @@ function braintrustAISDKTelemetry() {
13943
15022
  if (!callId) {
13944
15023
  return;
13945
15024
  }
13946
- const state = operations.get(callId);
15025
+ const operationKey = operationKeyForCallId(callId);
15026
+ const state = operationKey ? operations.get(operationKey) : void 0;
13947
15027
  if (!state || state.firstChunkTime !== void 0) {
13948
15028
  return;
13949
15029
  }
13950
15030
  state.firstChunkTime = getCurrentUnixTimestamp();
13951
15031
  });
13952
15032
  },
13953
- onFinish(event) {
13954
- runSafely("onFinish", () => {
13955
- const state = operations.get(event.callId);
13956
- 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) {
13957
15039
  return;
13958
15040
  }
13959
- const result = finishResult(event, state.operationName);
13960
- const metrics = state.hadModelChild ? {} : extractTokenMetrics(result);
13961
- if (state.firstChunkTime !== void 0) {
13962
- 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();
13963
15046
  }
13964
- state.span.log({
13965
- ...shouldRecordOutputs(event) ? {
13966
- output: finishOutput(result, state.operationName)
13967
- } : {},
13968
- metrics
13969
- });
13970
- state.span.end();
13971
- operations.delete(event.callId);
15047
+ deleteOperation(operationKey);
13972
15048
  });
13973
15049
  },
13974
15050
  onError(event) {
13975
15051
  runSafely("onError", () => {
13976
15052
  const errorEvent = isObject(event) ? event : {};
13977
- const callId = typeof errorEvent.callId === "string" ? errorEvent.callId : void 0;
13978
- if (!callId) {
13979
- return;
13980
- }
13981
- const state = operations.get(callId);
13982
- if (!state) {
15053
+ const operationKey = operationKeyFromEvent(errorEvent, "finish");
15054
+ const state = operationKey ? operations.get(operationKey) : void 0;
15055
+ if (!operationKey || !state) {
13983
15056
  return;
13984
15057
  }
13985
15058
  const error = errorEvent.error ?? event;
13986
- const openModelSpans = modelSpans.get(callId);
13987
- if (openModelSpans) {
13988
- for (const span of openModelSpans) {
13989
- logError(span, error);
13990
- span.end();
13991
- }
13992
- modelSpans.delete(callId);
13993
- }
13994
- const openObjectSpan = objectSpans.get(callId);
13995
- if (openObjectSpan) {
13996
- logError(openObjectSpan, error);
13997
- openObjectSpan.end();
13998
- objectSpans.delete(callId);
13999
- }
14000
- for (const [embedCallId, embedState] of embedSpans) {
14001
- if (embedState.callId === callId) {
14002
- logError(embedState.span, error);
14003
- embedState.span.end();
14004
- embedSpans.delete(embedCallId);
14005
- }
14006
- }
14007
- const openRerankSpan = rerankSpans.get(callId);
14008
- if (openRerankSpan) {
14009
- logError(openRerankSpan, error);
14010
- openRerankSpan.end();
14011
- rerankSpans.delete(callId);
14012
- }
14013
- for (const [toolCallId, toolState] of toolSpans) {
14014
- if (toolState.callId === callId) {
14015
- logError(toolState.span, error);
14016
- toolState.span.end();
14017
- toolSpans.delete(toolCallId);
14018
- }
15059
+ closeOpenChildSpans(operationKey, error);
15060
+ if (state.ownsSpan) {
15061
+ logError(state.span, error);
15062
+ state.span.end();
14019
15063
  }
14020
- logError(state.span, error);
14021
- state.span.end();
14022
- operations.delete(callId);
15064
+ deleteOperation(operationKey);
14023
15065
  });
14024
15066
  },
14025
15067
  executeTool({ toolCallId, execute }) {
@@ -14034,7 +15076,16 @@ function shouldRecordInputs(event) {
14034
15076
  function shouldRecordOutputs(event) {
14035
15077
  return event.recordOutputs !== false;
14036
15078
  }
15079
+ function hasPromptLikeInput(input) {
15080
+ if (!isObject(input)) {
15081
+ return false;
15082
+ }
15083
+ return input.prompt !== void 0 || input.messages !== void 0;
15084
+ }
14037
15085
  function operationNameFromId(operationId) {
15086
+ if (operationId === "ai.workflowAgent.stream") {
15087
+ return "WorkflowAgent.stream";
15088
+ }
14038
15089
  return operationId?.startsWith("ai.") ? operationId.slice("ai.".length) : operationId || "ai-sdk";
14039
15090
  }
14040
15091
  function modelFromEvent(event) {
@@ -14080,6 +15131,7 @@ function operationInput(event, operationName) {
14080
15131
  }
14081
15132
  return {
14082
15133
  model: modelFromEvent(event),
15134
+ instructions: event.instructions,
14083
15135
  system: event.system,
14084
15136
  prompt: event.prompt,
14085
15137
  messages: event.messages,
@@ -14128,6 +15180,30 @@ function finishResult(event, operationName) {
14128
15180
  }
14129
15181
  return event;
14130
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
+ }
14131
15207
  function finishOutput(result, operationName) {
14132
15208
  if (operationName === "embed" || operationName === "embedMany") {
14133
15209
  return processAISDKEmbeddingOutput(
@@ -14204,6 +15280,10 @@ var aiSDKChannels = defineChannels("ai", {
14204
15280
  channelName: "ToolLoopAgent.stream",
14205
15281
  kind: "async"
14206
15282
  }),
15283
+ workflowAgentStream: channel({
15284
+ channelName: "WorkflowAgent.stream",
15285
+ kind: "async"
15286
+ }),
14207
15287
  v7CreateTelemetryDispatcher: channel({
14208
15288
  channelName: "createTelemetryDispatcher",
14209
15289
  kind: "sync-stream"
@@ -14214,14 +15294,19 @@ var aiSDKChannels = defineChannels("ai", {
14214
15294
  var DEFAULT_DENY_OUTPUT_PATHS = [
14215
15295
  // v3
14216
15296
  "roundtrips[].request.body",
15297
+ "roundtrips[].request.headers",
14217
15298
  "roundtrips[].response.headers",
14218
15299
  "rawResponse.headers",
14219
15300
  "responseMessages",
14220
15301
  // v5
14221
15302
  "request.body",
15303
+ "request.headers",
15304
+ "responses[].headers",
14222
15305
  "response.body",
14223
15306
  "response.headers",
14224
15307
  "steps[].request.body",
15308
+ "steps[].request.headers",
15309
+ "steps[].responses[].headers",
14225
15310
  "steps[].response.body",
14226
15311
  "steps[].response.headers"
14227
15312
  ];
@@ -14233,6 +15318,18 @@ var AUTO_PATCHED_V7_TELEMETRY_DISPATCHER = /* @__PURE__ */ Symbol.for(
14233
15318
  var RUNTIME_DENY_OUTPUT_PATHS = /* @__PURE__ */ Symbol.for(
14234
15319
  "braintrust.ai-sdk.deny-output-paths"
14235
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
+ ];
14236
15333
  var AI_SDK_V7_TELEMETRY_CALLBACKS = [
14237
15334
  "onStart",
14238
15335
  "onStepStart",
@@ -14241,14 +15338,16 @@ var AI_SDK_V7_TELEMETRY_CALLBACKS = [
14241
15338
  "onToolExecutionStart",
14242
15339
  "onToolExecutionEnd",
14243
15340
  "onChunk",
15341
+ "onStepEnd",
14244
15342
  "onStepFinish",
14245
15343
  "onObjectStepStart",
14246
- "onObjectStepFinish",
15344
+ "onObjectStepEnd",
14247
15345
  "onEmbedStart",
14248
- "onEmbedFinish",
15346
+ "onEmbedEnd",
14249
15347
  "onRerankStart",
14250
- "onRerankFinish",
14251
- "onFinish",
15348
+ "onRerankEnd",
15349
+ "onEnd",
15350
+ "onAbort",
14252
15351
  "onError"
14253
15352
  ];
14254
15353
  var AISDKPlugin = class extends BasePlugin {
@@ -14406,7 +15505,9 @@ var AISDKPlugin = class extends BasePlugin {
14406
15505
  traceStreamingChannel(aiSDKChannels.agentGenerate, {
14407
15506
  name: "Agent.generate",
14408
15507
  type: "function" /* FUNCTION */,
14409
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
15508
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
15509
+ agentOwner: true
15510
+ }),
14410
15511
  extractOutput: (result, endEvent) => {
14411
15512
  finalizeAISDKChildTracing(endEvent);
14412
15513
  return processAISDKOutput(
@@ -14422,7 +15523,9 @@ var AISDKPlugin = class extends BasePlugin {
14422
15523
  traceStreamingChannel(aiSDKChannels.agentStream, {
14423
15524
  name: "Agent.stream",
14424
15525
  type: "function" /* FUNCTION */,
14425
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
15526
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
15527
+ agentOwner: true
15528
+ }),
14426
15529
  extractOutput: (result, endEvent) => processAISDKOutput(
14427
15530
  result,
14428
15531
  resolveDenyOutputPaths(endEvent, denyOutputPaths)
@@ -14442,7 +15545,9 @@ var AISDKPlugin = class extends BasePlugin {
14442
15545
  traceSyncStreamChannel(aiSDKChannels.agentStreamSync, {
14443
15546
  name: "Agent.stream",
14444
15547
  type: "function" /* FUNCTION */,
14445
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
15548
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
15549
+ agentOwner: true
15550
+ }),
14446
15551
  patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
14447
15552
  defaultDenyOutputPaths: denyOutputPaths,
14448
15553
  endEvent,
@@ -14456,7 +15561,9 @@ var AISDKPlugin = class extends BasePlugin {
14456
15561
  traceStreamingChannel(aiSDKChannels.toolLoopAgentGenerate, {
14457
15562
  name: "ToolLoopAgent.generate",
14458
15563
  type: "function" /* FUNCTION */,
14459
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
15564
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
15565
+ agentOwner: true
15566
+ }),
14460
15567
  extractOutput: (result, endEvent) => {
14461
15568
  finalizeAISDKChildTracing(endEvent);
14462
15569
  return processAISDKOutput(
@@ -14472,7 +15579,9 @@ var AISDKPlugin = class extends BasePlugin {
14472
15579
  traceStreamingChannel(aiSDKChannels.toolLoopAgentStream, {
14473
15580
  name: "ToolLoopAgent.stream",
14474
15581
  type: "function" /* FUNCTION */,
14475
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
15582
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
15583
+ agentOwner: true
15584
+ }),
14476
15585
  extractOutput: (result, endEvent) => processAISDKOutput(
14477
15586
  result,
14478
15587
  resolveDenyOutputPaths(endEvent, denyOutputPaths)
@@ -14488,6 +15597,42 @@ var AISDKPlugin = class extends BasePlugin {
14488
15597
  })
14489
15598
  })
14490
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
+ );
14491
15636
  }
14492
15637
  };
14493
15638
  function subscribeToAISDKV7TelemetryDispatcher() {
@@ -14499,7 +15644,11 @@ function subscribeToAISDKV7TelemetryDispatcher() {
14499
15644
  if (telemetryOptions?.isEnabled === false) {
14500
15645
  return;
14501
15646
  }
14502
- patchAISDKV7TelemetryDispatcher(event.result, telemetry);
15647
+ patchAISDKV7TelemetryDispatcher(
15648
+ event.result,
15649
+ telemetry,
15650
+ telemetryOptions
15651
+ );
14503
15652
  }
14504
15653
  };
14505
15654
  channel2.subscribe(handlers);
@@ -14507,7 +15656,7 @@ function subscribeToAISDKV7TelemetryDispatcher() {
14507
15656
  channel2.unsubscribe(handlers);
14508
15657
  };
14509
15658
  }
14510
- function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
15659
+ function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry, telemetryOptions) {
14511
15660
  if (!isObject(dispatcher)) {
14512
15661
  return;
14513
15662
  }
@@ -14516,6 +15665,54 @@ function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
14516
15665
  return;
14517
15666
  }
14518
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
+ };
14519
15716
  for (const key of AI_SDK_V7_TELEMETRY_CALLBACKS) {
14520
15717
  const braintrustCallback = telemetry[key];
14521
15718
  if (typeof braintrustCallback !== "function") {
@@ -14524,11 +15721,17 @@ function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
14524
15721
  const existingCallback = dispatcherRecord[key];
14525
15722
  dispatcherRecord[key] = (event) => {
14526
15723
  const existingResult = typeof existingCallback === "function" ? existingCallback.call(dispatcher, event) : void 0;
14527
- const braintrustResult = braintrustCallback.call(telemetry, event);
14528
- const pending = [existingResult, braintrustResult].filter(isPromiseLike);
14529
- if (pending.length > 0) {
14530
- 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 {
14531
15733
  }
15734
+ return existingResult;
14532
15735
  };
14533
15736
  }
14534
15737
  const braintrustExecuteTool = telemetry.executeTool;
@@ -14538,6 +15741,7 @@ function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
14538
15741
  const existingExecuteTool = dispatcherRecord.executeTool;
14539
15742
  dispatcherRecord.executeTool = (args) => braintrustExecuteTool.call(telemetry, {
14540
15743
  ...args,
15744
+ ...operationKey ? { [BRAINTRUST_AI_SDK_V7_OPERATION_KEY]: operationKey } : {},
14541
15745
  execute: () => typeof existingExecuteTool === "function" ? existingExecuteTool.call(dispatcher, args) : args.execute()
14542
15746
  });
14543
15747
  }
@@ -14636,6 +15840,8 @@ var serializeOutputObject = (output, model) => {
14636
15840
  var processInputAttachmentsSync = (input) => {
14637
15841
  if (!input) return { input };
14638
15842
  const processed = { ...input };
15843
+ delete processed.headers;
15844
+ delete processed.experimental_output;
14639
15845
  if (input.messages && Array.isArray(input.messages)) {
14640
15846
  processed.messages = input.messages.map(processMessage);
14641
15847
  }
@@ -14669,10 +15875,10 @@ var processInputAttachmentsSync = (input) => {
14669
15875
  processed.output = serialized;
14670
15876
  }
14671
15877
  }
14672
- if ("prepareCall" in processed && typeof processed.prepareCall === "function") {
14673
- processed.prepareCall = "[Function]";
14674
- }
14675
- return { input: processed, outputPromise };
15878
+ return {
15879
+ input: sanitizeAISDKCallInputValue(processed),
15880
+ outputPromise
15881
+ };
14676
15882
  };
14677
15883
  var processMessage = (message) => {
14678
15884
  if (!message || typeof message !== "object") return message;
@@ -14836,7 +16042,21 @@ var convertDataToAttachment = (data, mimeType, filename) => {
14836
16042
  function processAISDKCallInput(params) {
14837
16043
  return processInputAttachmentsSync(params);
14838
16044
  }
14839
- 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 = {}) {
14840
16060
  const { input, outputPromise } = processAISDKCallInput(params);
14841
16061
  if (outputPromise && input && typeof input === "object") {
14842
16062
  outputPromise.then((resolvedData) => {
@@ -14855,7 +16075,29 @@ function prepareAISDKCallInput(params, event, span, defaultDenyOutputPaths) {
14855
16075
  event.self,
14856
16076
  span,
14857
16077
  defaultDenyOutputPaths,
14858
- 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 }
14859
16101
  );
14860
16102
  event.modelWrapped = childTracing.modelWrapped;
14861
16103
  if (childTracing.cleanup) {
@@ -14892,6 +16134,9 @@ function extractTopLevelAISDKMetrics(result, event, startTime) {
14892
16134
  function hasModelChildTracing(event) {
14893
16135
  return event?.modelWrapped === true || event?.__braintrust_ai_sdk_model_wrapped === true;
14894
16136
  }
16137
+ function serializeToolExecutionInput(args) {
16138
+ return args.length > 0 ? args[0] : args;
16139
+ }
14895
16140
  function createAISDKIntegrationMetadata() {
14896
16141
  return {
14897
16142
  braintrust: {
@@ -14903,6 +16148,13 @@ function createAISDKIntegrationMetadata() {
14903
16148
  function resolveModelFromSelf(self) {
14904
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;
14905
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
+ }
14906
16158
  function extractBaseMetadata(model, self) {
14907
16159
  const metadata = createAISDKIntegrationMetadata();
14908
16160
  const { model: modelId, provider } = serializeModelWithProvider(
@@ -14918,12 +16170,175 @@ function extractBaseMetadata(model, self) {
14918
16170
  }
14919
16171
  function extractMetadataFromCallParams(params, self) {
14920
16172
  const metadata = extractBaseMetadata(params.model, self);
14921
- const tools = serializeAISDKToolsForLogging(params.tools);
16173
+ const tools = serializeAISDKToolsForLogging(
16174
+ params.tools ?? resolveToolsFromSelf(self)
16175
+ );
14922
16176
  if (tools) {
14923
16177
  metadata.tools = tools;
14924
16178
  }
14925
16179
  return metadata;
14926
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
+ }
14927
16342
  function extractMetadataFromEmbedParams(params, self) {
14928
16343
  return extractBaseMetadata(params.model, self);
14929
16344
  }
@@ -14937,72 +16352,273 @@ function extractMetadataFromRerankParams(params, self) {
14937
16352
  }
14938
16353
  return metadata;
14939
16354
  }
14940
- 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 = {}) {
14941
16421
  const cleanup = [];
14942
- const patchedModels = /* @__PURE__ */ new WeakSet();
16422
+ const patchedModels = /* @__PURE__ */ new WeakMap();
14943
16423
  const patchedTools = /* @__PURE__ */ new WeakSet();
14944
16424
  let modelWrapped = false;
14945
16425
  const patchModel = (model) => {
14946
16426
  const resolvedModel = resolveAISDKModel(model, aiSDK);
14947
- 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") {
14948
16428
  return resolvedModel;
14949
16429
  }
14950
- patchedModels.add(resolvedModel);
14951
- resolvedModel[AUTO_PATCHED_MODEL] = true;
16430
+ const existingWrappedModel = patchedModels.get(resolvedModel);
16431
+ if (existingWrappedModel) {
16432
+ modelWrapped = true;
16433
+ return existingWrappedModel;
16434
+ }
14952
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
+ }
14953
16482
  const originalDoGenerate = resolvedModel.doGenerate;
14954
16483
  const originalDoStream = resolvedModel.doStream;
14955
- const baseMetadata = buildAISDKChildMetadata(resolvedModel);
14956
- resolvedModel.doGenerate = async function doGeneratePatched(options) {
14957
- 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(
14958
16508
  async (span) => {
14959
- const result = await Reflect.apply(
14960
- originalDoGenerate,
14961
- resolvedModel,
14962
- [options]
14963
- );
14964
- span.log({
14965
- output: processAISDKOutput(result, denyOutputPaths),
14966
- metrics: extractTokenMetrics(result),
14967
- ...buildResolvedMetadataPayload(result)
14968
- });
14969
- 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
+ }
14970
16536
  },
14971
16537
  {
14972
16538
  name: "doGenerate",
14973
16539
  spanAttributes: {
14974
16540
  type: "llm" /* LLM */
14975
16541
  },
14976
- event: {
14977
- input: processAISDKCallInput(options).input,
14978
- metadata: baseMetadata
14979
- }
16542
+ event: buildAISDKModelStartEvent(
16543
+ callOptions,
16544
+ activeEntry.baseMetadata,
16545
+ {
16546
+ workflowAgent: activeEntry.childTracingOptions.workflowAgent
16547
+ }
16548
+ )
14980
16549
  }
14981
16550
  );
14982
16551
  };
14983
16552
  if (originalDoStream) {
14984
- resolvedModel.doStream = async function doStreamPatched(options) {
14985
- 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({
14986
16560
  name: "doStream",
14987
16561
  spanAttributes: {
14988
16562
  type: "llm" /* LLM */
14989
16563
  },
14990
- event: {
14991
- input: processAISDKCallInput(options).input,
14992
- metadata: baseMetadata
14993
- }
16564
+ event: buildAISDKModelStartEvent(
16565
+ callOptions,
16566
+ activeEntry.baseMetadata,
16567
+ {
16568
+ workflowAgent: activeEntry.childTracingOptions.workflowAgent
16569
+ }
16570
+ )
14994
16571
  });
16572
+ activeEntry.openSpans.add(span);
14995
16573
  const streamStartTime = getCurrentUnixTimestamp();
14996
16574
  const result = await withCurrent(
14997
16575
  span,
14998
- () => Reflect.apply(originalDoStream, resolvedModel, [options])
16576
+ () => Reflect.apply(originalDoStream, resolvedModel, [callOptions])
14999
16577
  );
15000
16578
  let firstChunkTime;
15001
16579
  const output = {};
15002
16580
  let text = "";
15003
16581
  let reasoning = "";
15004
- const toolCalls = [];
16582
+ const toolCalls2 = [];
15005
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
+ };
15006
16622
  const transformStream = new TransformStream({
15007
16623
  transform(chunk, controller) {
15008
16624
  if (firstChunkTime === void 0 && isAISDKContentStreamChunk(chunk)) {
@@ -15020,7 +16636,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
15020
16636
  }
15021
16637
  break;
15022
16638
  case "tool-call":
15023
- toolCalls.push(chunk);
16639
+ toolCalls2.push(chunk);
15024
16640
  break;
15025
16641
  case "object":
15026
16642
  object = chunk.object;
@@ -15040,33 +16656,15 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
15040
16656
  }
15041
16657
  break;
15042
16658
  case "finish":
15043
- output.text = text;
15044
- output.reasoning = reasoning;
15045
- output.toolCalls = toolCalls;
15046
16659
  output.finishReason = chunk.finishReason;
15047
16660
  output.usage = chunk.usage;
15048
- if (object !== void 0) {
15049
- output.object = object;
15050
- }
15051
- const metrics = extractTokenMetrics(output);
15052
- if (firstChunkTime !== void 0) {
15053
- metrics.time_to_first_token = Math.max(
15054
- firstChunkTime - streamStartTime,
15055
- 1e-6
15056
- );
15057
- }
15058
- span.log({
15059
- output: processAISDKOutput(
15060
- output,
15061
- denyOutputPaths
15062
- ),
15063
- metrics,
15064
- ...buildResolvedMetadataPayload(output)
15065
- });
15066
- span.end();
16661
+ logAndEndStreamSpan();
15067
16662
  break;
15068
16663
  }
15069
16664
  controller.enqueue(chunk);
16665
+ },
16666
+ flush() {
16667
+ logAndEndStreamSpan("ai_sdk_stream_finished_without_usage");
15070
16668
  }
15071
16669
  });
15072
16670
  return {
@@ -15076,32 +16674,79 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
15076
16674
  };
15077
16675
  }
15078
16676
  cleanup.push(() => {
15079
- resolvedModel.doGenerate = originalDoGenerate;
15080
- if (originalDoStream) {
15081
- resolvedModel.doStream = originalDoStream;
15082
- }
15083
- delete resolvedModel[AUTO_PATCHED_MODEL];
16677
+ cleanupModelEntry(state, wrappedModelRecord);
15084
16678
  });
15085
- return resolvedModel;
16679
+ patchedModels.set(resolvedModel, wrappedModel);
16680
+ patchedModels.set(wrappedModel, wrappedModel);
16681
+ return wrappedModel;
15086
16682
  };
15087
16683
  const patchTool = (tool, name) => {
15088
- 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)) {
15089
16685
  return;
15090
16686
  }
15091
16687
  patchedTools.add(tool);
15092
- tool[AUTO_PATCHED_TOOL] = true;
15093
- 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;
15094
16735
  tool.execute = function executePatched(...args) {
16736
+ const activeEntry = activeAISDKChildPatchEntry(state.entries);
15095
16737
  const result = Reflect.apply(originalExecute, this, args);
16738
+ if (!activeEntry) {
16739
+ return result;
16740
+ }
15096
16741
  if (isAsyncGenerator(result)) {
15097
16742
  return (async function* () {
15098
- const span = parentSpan.startSpan({
15099
- name,
16743
+ const span = activeEntry.parentSpan.startSpan({
16744
+ name: activeEntry.name,
15100
16745
  spanAttributes: {
15101
16746
  type: "tool" /* TOOL */
15102
16747
  }
15103
16748
  });
15104
- span.log({ input: args.length === 1 ? args[0] : args });
16749
+ span.log({ input: serializeToolExecutionInput(args) });
15105
16750
  try {
15106
16751
  let lastValue;
15107
16752
  for await (const value of result) {
@@ -15117,15 +16762,15 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
15117
16762
  }
15118
16763
  })();
15119
16764
  }
15120
- return parentSpan.traced(
16765
+ return activeEntry.parentSpan.traced(
15121
16766
  async (span) => {
15122
- span.log({ input: args.length === 1 ? args[0] : args });
16767
+ span.log({ input: serializeToolExecutionInput(args) });
15123
16768
  const awaitedResult = await result;
15124
16769
  span.log({ output: awaitedResult });
15125
16770
  return awaitedResult;
15126
16771
  },
15127
16772
  {
15128
- name,
16773
+ name: activeEntry.name,
15129
16774
  spanAttributes: {
15130
16775
  type: "tool" /* TOOL */
15131
16776
  }
@@ -15133,8 +16778,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
15133
16778
  );
15134
16779
  };
15135
16780
  cleanup.push(() => {
15136
- tool.execute = originalExecute;
15137
- delete tool[AUTO_PATCHED_TOOL];
16781
+ cleanupToolEntry(state);
15138
16782
  });
15139
16783
  };
15140
16784
  const patchTools = (tools) => {
@@ -15153,25 +16797,42 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
15153
16797
  }
15154
16798
  };
15155
16799
  if (params && typeof params === "object") {
15156
- const patchedParamModel = patchModel(params.model);
15157
- if (typeof params.model === "string" && patchedParamModel && typeof patchedParamModel === "object") {
16800
+ const originalParamModel = params.model;
16801
+ const patchedParamModel = patchModel(originalParamModel);
16802
+ if (patchedParamModel && patchedParamModel !== originalParamModel) {
15158
16803
  params.model = patchedParamModel;
16804
+ cleanup.push(() => {
16805
+ params.model = originalParamModel;
16806
+ });
15159
16807
  }
15160
16808
  patchTools(params.tools);
15161
16809
  }
15162
16810
  if (self && typeof self === "object") {
15163
16811
  const selfRecord = self;
15164
16812
  if (selfRecord.model !== void 0) {
15165
- const patchedSelfModel = patchModel(selfRecord.model);
15166
- if (typeof selfRecord.model === "string" && patchedSelfModel && typeof patchedSelfModel === "object") {
16813
+ const originalSelfModel = selfRecord.model;
16814
+ const patchedSelfModel = patchModel(originalSelfModel);
16815
+ if (patchedSelfModel && patchedSelfModel !== originalSelfModel) {
15167
16816
  selfRecord.model = patchedSelfModel;
16817
+ cleanup.push(() => {
16818
+ selfRecord.model = originalSelfModel;
16819
+ });
15168
16820
  }
15169
16821
  }
16822
+ if (selfRecord.tools !== void 0) {
16823
+ patchTools(selfRecord.tools);
16824
+ }
15170
16825
  if (selfRecord.settings && typeof selfRecord.settings === "object") {
15171
16826
  if (selfRecord.settings.model !== void 0) {
15172
- const patchedSettingsModel = patchModel(selfRecord.settings.model);
15173
- 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) {
15174
16830
  selfRecord.settings.model = patchedSettingsModel;
16831
+ cleanup.push(() => {
16832
+ if (selfRecord.settings) {
16833
+ selfRecord.settings.model = originalSettingsModel;
16834
+ }
16835
+ });
15175
16836
  }
15176
16837
  }
15177
16838
  if (selfRecord.settings.tools !== void 0) {
@@ -15268,99 +16929,190 @@ function isAISDKContentAsyncIterableChunk(chunk) {
15268
16929
  return isObject(part) && typeof part.type !== "string";
15269
16930
  }
15270
16931
  function patchAISDKStreamingResult(args) {
15271
- const { defaultDenyOutputPaths, endEvent, result, span, startTime } = args;
16932
+ const {
16933
+ defaultDenyOutputPaths,
16934
+ endEvent,
16935
+ onComplete,
16936
+ result,
16937
+ span,
16938
+ startTime
16939
+ } = args;
15272
16940
  if (!result || typeof result !== "object") {
15273
16941
  return false;
15274
16942
  }
15275
16943
  const resultRecord = result;
15276
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;
15277
17060
  if (isReadableStreamLike(resultRecord.baseStream)) {
15278
- let firstChunkTime2;
15279
- const wrappedBaseStream = resultRecord.baseStream.pipeThrough(
17061
+ let firstChunkTime;
17062
+ const transformedBaseStream = resultRecord.baseStream.pipeThrough(
15280
17063
  new TransformStream({
15281
17064
  transform(chunk, controller) {
15282
- if (firstChunkTime2 === void 0 && isAISDKContentStreamChunk(chunk)) {
15283
- firstChunkTime2 = getCurrentUnixTimestamp();
17065
+ if (firstChunkTime === void 0 && isAISDKContentStreamChunk(chunk)) {
17066
+ firstChunkTime = getCurrentUnixTimestamp();
15284
17067
  }
15285
17068
  controller.enqueue(chunk);
15286
17069
  },
15287
17070
  async flush() {
15288
- const metrics = extractTopLevelAISDKMetrics(result, endEvent);
15289
- if (metrics.time_to_first_token === void 0 && firstChunkTime2 !== void 0) {
15290
- metrics.time_to_first_token = firstChunkTime2 - startTime;
15291
- }
15292
- const output = await processAISDKStreamingOutput(
15293
- result,
15294
- resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
15295
- );
15296
- const metadata = buildResolvedMetadataPayload(result).metadata;
15297
- span.log({
15298
- output,
15299
- ...metadata ? { metadata } : {},
15300
- metrics
15301
- });
15302
- finalizeAISDKChildTracing(endEvent);
15303
- span.end();
17071
+ await logStreamingOutput(firstChunkTime);
15304
17072
  }
15305
17073
  })
15306
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
+ });
15307
17099
  Object.defineProperty(resultRecord, "baseStream", {
15308
17100
  configurable: true,
15309
17101
  enumerable: true,
15310
17102
  value: wrappedBaseStream,
15311
17103
  writable: true
15312
17104
  });
15313
- return true;
17105
+ patched = true;
15314
17106
  }
15315
- const streamField = findAsyncIterableField(resultRecord, [
17107
+ for (const field of [
15316
17108
  "partialObjectStream",
15317
17109
  "textStream",
15318
17110
  "fullStream",
15319
17111
  "stream"
15320
- ]);
15321
- if (!streamField) {
15322
- return false;
17112
+ ]) {
17113
+ patched = patchAsyncIterableField(field) || patched;
15323
17114
  }
15324
- let firstChunkTime;
15325
- const wrappedStream = createPatchedAsyncIterable(streamField.stream, {
15326
- onChunk: (chunk) => {
15327
- if (firstChunkTime === void 0 && isAISDKContentAsyncIterableChunk(chunk)) {
15328
- firstChunkTime = getCurrentUnixTimestamp();
15329
- }
15330
- },
15331
- onComplete: async () => {
15332
- const metrics = extractTopLevelAISDKMetrics(result, endEvent);
15333
- if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
15334
- metrics.time_to_first_token = firstChunkTime - startTime;
15335
- }
15336
- const output = await processAISDKStreamingOutput(
15337
- result,
15338
- resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
15339
- );
15340
- const metadata = buildResolvedMetadataPayload(result).metadata;
15341
- span.log({
15342
- output,
15343
- ...metadata ? { metadata } : {},
15344
- metrics
15345
- });
15346
- finalizeAISDKChildTracing(endEvent);
15347
- span.end();
15348
- },
15349
- onError: (error) => {
15350
- span.log({
15351
- error: error.message
15352
- });
15353
- finalizeAISDKChildTracing(endEvent);
15354
- span.end();
15355
- }
15356
- });
15357
- Object.defineProperty(resultRecord, streamField.field, {
15358
- configurable: true,
15359
- enumerable: true,
15360
- value: wrappedStream,
15361
- writable: true
15362
- });
15363
- return true;
17115
+ return patched;
15364
17116
  }
15365
17117
  function attachKnownResultPromiseHandlers(result) {
15366
17118
  const promiseLikeFields = [
@@ -15392,34 +17144,72 @@ function attachKnownResultPromiseHandlers(result) {
15392
17144
  }
15393
17145
  }
15394
17146
  function isReadableStreamLike(value) {
15395
- return value != null && typeof value === "object" && typeof value.pipeThrough === "function";
15396
- }
15397
- function findAsyncIterableField(result, candidateFields) {
15398
- for (const field of candidateFields) {
15399
- try {
15400
- const stream = result[field];
15401
- if (isAsyncIterable(stream)) {
15402
- 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);
15403
17185
  }
15404
- } catch {
15405
17186
  }
15406
- }
15407
- return null;
17187
+ });
15408
17188
  }
15409
17189
  function createPatchedAsyncIterable(stream, hooks) {
15410
17190
  return {
15411
17191
  async *[Symbol.asyncIterator]() {
17192
+ let completed = false;
15412
17193
  try {
15413
17194
  for await (const chunk of stream) {
15414
17195
  hooks.onChunk(chunk);
15415
17196
  yield chunk;
15416
17197
  }
17198
+ completed = true;
15417
17199
  await hooks.onComplete();
15418
17200
  } catch (error) {
17201
+ completed = true;
15419
17202
  hooks.onError(
15420
17203
  error instanceof Error ? error : new Error(String(error))
15421
17204
  );
15422
17205
  throw error;
17206
+ } finally {
17207
+ if (!completed) {
17208
+ try {
17209
+ await hooks.onCancel?.();
17210
+ } catch {
17211
+ }
17212
+ }
15423
17213
  }
15424
17214
  }
15425
17215
  };
@@ -15494,6 +17284,40 @@ function buildResolvedMetadataPayload(result) {
15494
17284
  }
15495
17285
  return Object.keys(metadata).length > 0 ? { metadata } : {};
15496
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
+ }
15497
17321
  function resolveAISDKModel(model, aiSDK) {
15498
17322
  if (typeof model !== "string") {
15499
17323
  return model;
@@ -15517,7 +17341,45 @@ function isAsyncGenerator(value) {
15517
17341
  function processAISDKOutput(output, denyOutputPaths) {
15518
17342
  if (!output) return output;
15519
17343
  const merged = extractSerializableOutputFields(output);
15520
- 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);
15521
17383
  }
15522
17384
  function processAISDKEmbeddingOutput(output, denyOutputPaths) {
15523
17385
  if (!output || typeof output !== "object") {
@@ -15608,6 +17470,8 @@ function extractTokenMetrics(result) {
15608
17470
  );
15609
17471
  if (totalTokens !== void 0) {
15610
17472
  metrics.tokens = totalTokens;
17473
+ } else if (promptTokens !== void 0 && completionTokens !== void 0) {
17474
+ metrics.tokens = promptTokens + completionTokens;
15611
17475
  }
15612
17476
  const promptCachedTokens = firstNumber2(
15613
17477
  usage.inputTokens?.cacheRead,
@@ -15719,9 +17583,9 @@ function aggregateAISDKChunks(chunks, _result, endEvent) {
15719
17583
  if (finishReason !== void 0) {
15720
17584
  output.finishReason = finishReason;
15721
17585
  }
15722
- const toolCalls = safeSerializableFieldRead(lastChunk, "toolCalls");
15723
- if (toolCalls !== void 0) {
15724
- output.toolCalls = toolCalls;
17586
+ const toolCalls2 = safeSerializableFieldRead(lastChunk, "toolCalls");
17587
+ if (toolCalls2 !== void 0) {
17588
+ output.toolCalls = toolCalls2;
15725
17589
  }
15726
17590
  }
15727
17591
  finalizeAISDKChildTracing(endEvent);
@@ -15731,7 +17595,9 @@ function extractGetterValues(obj) {
15731
17595
  const getterValues = {};
15732
17596
  const getterNames = [
15733
17597
  "content",
17598
+ "messages",
15734
17599
  "text",
17600
+ "output",
15735
17601
  "object",
15736
17602
  "value",
15737
17603
  "values",
@@ -15771,7 +17637,9 @@ function extractGetterValues(obj) {
15771
17637
  function extractSerializableOutputFields(output) {
15772
17638
  const serialized = {};
15773
17639
  const directFieldNames = [
17640
+ "messages",
15774
17641
  "steps",
17642
+ "output",
15775
17643
  "request",
15776
17644
  "responseMessages",
15777
17645
  "warnings",
@@ -15953,7 +17821,7 @@ function parsePath(path) {
15953
17821
  }
15954
17822
  return keys;
15955
17823
  }
15956
- function omitAtPath(obj, keys) {
17824
+ function omitAtPath(obj, keys, deleteLeaf = false) {
15957
17825
  if (keys.length === 0) return;
15958
17826
  const firstKey = keys[0];
15959
17827
  const remainingKeys = keys.slice(1);
@@ -15963,29 +17831,36 @@ function omitAtPath(obj, keys) {
15963
17831
  if (remainingKeys.length > 0) {
15964
17832
  omitAtPath(
15965
17833
  item,
15966
- remainingKeys
17834
+ remainingKeys,
17835
+ deleteLeaf
15967
17836
  );
15968
17837
  }
15969
17838
  });
15970
17839
  }
15971
17840
  } else if (remainingKeys.length === 0) {
15972
17841
  if (obj && typeof obj === "object" && firstKey in obj) {
15973
- obj[firstKey] = "<omitted>";
17842
+ if (deleteLeaf) {
17843
+ delete obj[firstKey];
17844
+ } else {
17845
+ obj[firstKey] = "<omitted>";
17846
+ }
15974
17847
  }
15975
17848
  } else {
15976
17849
  if (obj && typeof obj === "object" && firstKey in obj) {
15977
17850
  omitAtPath(
15978
17851
  obj[firstKey],
15979
- remainingKeys
17852
+ remainingKeys,
17853
+ deleteLeaf
15980
17854
  );
15981
17855
  }
15982
17856
  }
15983
17857
  }
15984
- function omit(obj, paths) {
17858
+ function omit(obj, paths, deletePaths = []) {
15985
17859
  const result = deepCopy(obj);
17860
+ const deletePathSet = new Set(deletePaths);
15986
17861
  for (const path of paths) {
15987
17862
  const keys = parsePath(path);
15988
- omitAtPath(result, keys);
17863
+ omitAtPath(result, keys, deletePathSet.has(path));
15989
17864
  }
15990
17865
  return result;
15991
17866
  }
@@ -20194,8 +22069,8 @@ function getChatToolCallDeltas(value) {
20194
22069
  if (!Array.isArray(value?.tool_calls)) {
20195
22070
  return void 0;
20196
22071
  }
20197
- const toolCalls = value.tool_calls.filter((toolCall) => isObject(toolCall));
20198
- 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;
20199
22074
  }
20200
22075
  function mergeChatToolCallDeltas(toolCallsByIndex, toolCallDeltas) {
20201
22076
  for (const toolDelta of toolCallDeltas) {
@@ -21684,7 +23559,7 @@ function aggregateOpenRouterChatChunks(chunks) {
21684
23559
  let reasoningContent = "";
21685
23560
  let hasReasoningContent = false;
21686
23561
  let reasoningDetails;
21687
- let toolCalls;
23562
+ let toolCalls2;
21688
23563
  let finishReason;
21689
23564
  let metrics = {};
21690
23565
  for (const chunk of chunks) {
@@ -21737,9 +23612,9 @@ function aggregateOpenRouterChatChunks(chunks) {
21737
23612
  continue;
21738
23613
  }
21739
23614
  const toolIndex = toolDelta.index ?? 0;
21740
- const existingToolCall = toolCalls?.[toolIndex];
23615
+ const existingToolCall = toolCalls2?.[toolIndex];
21741
23616
  if (!existingToolCall || toolDelta.id && existingToolCall.id !== void 0 && existingToolCall.id !== toolDelta.id) {
21742
- const nextToolCalls = [...toolCalls || []];
23617
+ const nextToolCalls = [...toolCalls2 || []];
21743
23618
  nextToolCalls[toolIndex] = {
21744
23619
  index: toolIndex,
21745
23620
  id: toolDelta.id,
@@ -21749,7 +23624,7 @@ function aggregateOpenRouterChatChunks(chunks) {
21749
23624
  arguments: toolDelta.function.arguments || ""
21750
23625
  }
21751
23626
  };
21752
- toolCalls = nextToolCalls;
23627
+ toolCalls2 = nextToolCalls;
21753
23628
  continue;
21754
23629
  }
21755
23630
  const current = existingToolCall;
@@ -21775,7 +23650,7 @@ function aggregateOpenRouterChatChunks(chunks) {
21775
23650
  ...hasReasoning || hasReasoningContent ? { reasoning } : {},
21776
23651
  ...hasReasoningContent ? { reasoning_content: reasoningContent } : {},
21777
23652
  ...reasoningDetails ? { reasoning_details: reasoningDetails } : {},
21778
- ...toolCalls ? { tool_calls: toolCalls } : {}
23653
+ ...toolCalls2 ? { tool_calls: toolCalls2 } : {}
21779
23654
  },
21780
23655
  logprobs: null,
21781
23656
  finish_reason: finishReason
@@ -22620,8 +24495,8 @@ function appendMistralContent(accumulator, content) {
22620
24495
  delete accumulator.content;
22621
24496
  }
22622
24497
  function getDeltaToolCalls(delta) {
22623
- const toolCalls = Array.isArray(delta.toolCalls) && delta.toolCalls || Array.isArray(delta.tool_calls) && delta.tool_calls || [];
22624
- 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));
22625
24500
  }
22626
24501
  function getToolCallIndex(toolCall) {
22627
24502
  return typeof toolCall.index === "number" && toolCall.index >= 0 ? toolCall.index : void 0;
@@ -22648,11 +24523,11 @@ function mergeToolCallDeltaPair(current, delta) {
22648
24523
  }
22649
24524
  };
22650
24525
  }
22651
- function mergeToolCallDeltas(toolCalls, deltas) {
24526
+ function mergeToolCallDeltas(toolCalls2, deltas) {
22652
24527
  if (deltas.length === 0) {
22653
- return toolCalls;
24528
+ return toolCalls2;
22654
24529
  }
22655
- const merged = toolCalls ? [...toolCalls] : [];
24530
+ const merged = toolCalls2 ? [...toolCalls2] : [];
22656
24531
  const indexToPosition = /* @__PURE__ */ new Map();
22657
24532
  const idToPosition = /* @__PURE__ */ new Map();
22658
24533
  for (const [position, toolCall] of merged.entries()) {
@@ -23723,12 +25598,12 @@ function extractCohereChatOutput(result) {
23723
25598
  if (typeof result.text !== "string") {
23724
25599
  return void 0;
23725
25600
  }
23726
- const toolCalls = Array.isArray(result.toolCalls) ? result.toolCalls : Array.isArray(result.tool_calls) ? result.tool_calls : void 0;
23727
- 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) {
23728
25603
  return {
23729
25604
  content: result.text,
23730
25605
  role: "assistant",
23731
- toolCalls
25606
+ toolCalls: toolCalls2
23732
25607
  };
23733
25608
  }
23734
25609
  return result.text;
@@ -24061,10 +25936,10 @@ function aggregateCohereChatStreamChunks(chunks) {
24061
25936
  continue;
24062
25937
  }
24063
25938
  if (eventType === "tool-call-start") {
24064
- const toolCalls = isObject(chunk.delta) && isObject(chunk.delta.message) ? toToolCallArray(
25939
+ const toolCalls2 = isObject(chunk.delta) && isObject(chunk.delta.message) ? toToolCallArray(
24065
25940
  Array.isArray(chunk.delta.message.toolCalls) ? chunk.delta.message.toolCalls : chunk.delta.message.toolCalls ?? chunk.delta.message.tool_calls
24066
25941
  ) : [];
24067
- for (const [index, toolCall] of toolCalls.entries()) {
25942
+ for (const [index, toolCall] of toolCalls2.entries()) {
24068
25943
  const normalizedIndex = getToolCallIndex2(
24069
25944
  toolCall,
24070
25945
  typeof chunk.index === "number" ? chunk.index : index
@@ -26034,15 +27909,18 @@ function observeFlue(event, ctx) {
26034
27909
  getObserveBridge().handle(event, ctx);
26035
27910
  }
26036
27911
  var interceptFlueExecution = (operation, ctx, next) => getObserveBridge().intercept(operation, ctx, next);
26037
- var braintrustFlueObserver = Object.assign(
26038
- observeFlue,
26039
- {
27912
+ function braintrustFlueInstrumentation() {
27913
+ return {
26040
27914
  dispose() {
26041
27915
  },
26042
27916
  interceptor: interceptFlueExecution,
26043
27917
  key: FLUE_INSTRUMENTATION_KEY,
26044
27918
  observe: observeFlue
26045
- }
27919
+ };
27920
+ }
27921
+ var braintrustFlueObserver = Object.assign(
27922
+ observeFlue,
27923
+ braintrustFlueInstrumentation()
26046
27924
  );
26047
27925
  var FluePlugin = class extends BasePlugin {
26048
27926
  onEnable() {
@@ -28136,14 +30014,14 @@ function normalizeAssistantMessage(message) {
28136
30014
  const thinking = message.content.flatMap(
28137
30015
  (part) => part.type === "thinking" && !part.redacted ? [part.thinking] : []
28138
30016
  ).join("");
28139
- const toolCalls = message.content.flatMap(
30017
+ const toolCalls2 = message.content.flatMap(
28140
30018
  (part) => part.type === "toolCall" ? [normalizeToolCall(part)] : []
28141
30019
  );
28142
30020
  return {
28143
30021
  role: "assistant",
28144
- content: text || (toolCalls.length > 0 ? null : ""),
30022
+ content: text || (toolCalls2.length > 0 ? null : ""),
28145
30023
  ...thinking ? { reasoning: thinking } : {},
28146
- ...toolCalls.length > 0 ? { tool_calls: toolCalls } : {}
30024
+ ...toolCalls2.length > 0 ? { tool_calls: toolCalls2 } : {}
28147
30025
  };
28148
30026
  }
28149
30027
  function normalizeToolResultMessage(message) {
@@ -29641,8 +31519,10 @@ var exports_exports = {};
29641
31519
  __export(exports_exports, {
29642
31520
  Attachment: () => Attachment,
29643
31521
  AttachmentReference: () => AttachmentReference,
31522
+ BAGGAGE_HEADER: () => BAGGAGE_HEADER,
29644
31523
  BRAINTRUST_CURRENT_SPAN_STORE: () => BRAINTRUST_CURRENT_SPAN_STORE,
29645
31524
  BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME: () => BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME,
31525
+ BRAINTRUST_PARENT_KEY: () => BRAINTRUST_PARENT_KEY,
29646
31526
  BaseAttachment: () => BaseAttachment,
29647
31527
  BaseExperiment: () => BaseExperiment,
29648
31528
  BraintrustLangChainCallbackHandler: () => BraintrustLangChainCallbackHandler,
@@ -29675,6 +31555,7 @@ __export(exports_exports, {
29675
31555
  NOOP_SPAN: () => NOOP_SPAN,
29676
31556
  NOOP_SPAN_PERMALINK: () => NOOP_SPAN_PERMALINK,
29677
31557
  NoopSpan: () => NoopSpan,
31558
+ OTELIDGenerator: () => OTELIDGenerator,
29678
31559
  ObjectFetcher: () => ObjectFetcher,
29679
31560
  Project: () => Project2,
29680
31561
  ProjectNameIdMap: () => ProjectNameIdMap,
@@ -29686,6 +31567,8 @@ __export(exports_exports, {
29686
31567
  ScorerBuilder: () => ScorerBuilder,
29687
31568
  SpanFetcher: () => SpanFetcher,
29688
31569
  SpanImpl: () => SpanImpl,
31570
+ TRACEPARENT_HEADER: () => TRACEPARENT_HEADER,
31571
+ TRACESTATE_HEADER: () => TRACESTATE_HEADER,
29689
31572
  TestBackgroundLogger: () => TestBackgroundLogger,
29690
31573
  ToolBuilder: () => ToolBuilder,
29691
31574
  UUIDGenerator: () => UUIDGenerator,
@@ -29695,7 +31578,9 @@ __export(exports_exports, {
29695
31578
  _internalIso: () => isomorph_default,
29696
31579
  _internalSetInitialState: () => _internalSetInitialState,
29697
31580
  addAzureBlobHeaders: () => addAzureBlobHeaders,
31581
+ agentAssertionScorer: () => agentAssertionScorer,
29698
31582
  braintrustAISDKTelemetry: () => braintrustAISDKTelemetry,
31583
+ braintrustFlueInstrumentation: () => braintrustFlueInstrumentation,
29699
31584
  braintrustFlueObserver: () => braintrustFlueObserver,
29700
31585
  braintrustStreamChunkSchema: () => braintrustStreamChunkSchema,
29701
31586
  buildLocalSummary: () => buildLocalSummary,
@@ -29711,6 +31596,7 @@ __export(exports_exports, {
29711
31596
  devNullWritableStream: () => devNullWritableStream,
29712
31597
  evaluatorDefinitionSchema: () => evaluatorDefinitionSchema,
29713
31598
  evaluatorDefinitionsSchema: () => evaluatorDefinitionsSchema,
31599
+ extractTraceContextFromHeaders: () => extractTraceContextFromHeaders,
29714
31600
  flush: () => flush,
29715
31601
  getContextManager: () => getContextManager,
29716
31602
  getIdGenerator: () => getIdGenerator,
@@ -29724,6 +31610,7 @@ __export(exports_exports, {
29724
31610
  initFunction: () => initFunction,
29725
31611
  initLogger: () => initLogger,
29726
31612
  initNodeTestSuite: () => initNodeTestSuite,
31613
+ injectTraceContext: () => injectTraceContext,
29727
31614
  invoke: () => invoke,
29728
31615
  isTemplateFormat: () => isTemplateFormat,
29729
31616
  loadParameters: () => loadParameters,
@@ -29762,7 +31649,7 @@ __export(exports_exports, {
29762
31649
  traced: () => traced,
29763
31650
  updateSpan: () => updateSpan,
29764
31651
  uploadLogs3OverflowPayload: () => uploadLogs3OverflowPayload,
29765
- utf8ByteLength: () => utf8ByteLength,
31652
+ utf8ByteLength: () => utf8ByteLength2,
29766
31653
  withCurrent: () => withCurrent,
29767
31654
  withDataset: () => withDataset,
29768
31655
  withExperiment: () => withExperiment,
@@ -30355,6 +32242,7 @@ function wrapAISDK(aiSDK, options = {}) {
30355
32242
  case "Agent":
30356
32243
  case "Experimental_Agent":
30357
32244
  case "ToolLoopAgent":
32245
+ case "WorkflowAgent":
30358
32246
  return original ? wrapAgentClass(original, options) : original;
30359
32247
  }
30360
32248
  return original;
@@ -30373,10 +32261,10 @@ var wrapAgentClass = (AgentClass, options = {}) => {
30373
32261
  return new Proxy(instance, {
30374
32262
  get(instanceTarget, prop, instanceReceiver) {
30375
32263
  const original = Reflect.get(instanceTarget, prop, instanceTarget);
30376
- if (prop === "generate") {
32264
+ if (prop === "generate" && typeof original === "function" && instanceTarget.constructor.name !== "WorkflowAgent") {
30377
32265
  return wrapAgentGenerate(original, instanceTarget, options);
30378
32266
  }
30379
- if (prop === "stream") {
32267
+ if (prop === "stream" && typeof original === "function") {
30380
32268
  return wrapAgentStream(original, instanceTarget, options);
30381
32269
  }
30382
32270
  if (typeof original === "function") {
@@ -30391,7 +32279,7 @@ var wrapAgentClass = (AgentClass, options = {}) => {
30391
32279
  var wrapAgentGenerate = (generate, instance, options = {}) => {
30392
32280
  const defaultName = `${instance.constructor.name}.generate`;
30393
32281
  return async (params) => makeGenerateTextWrapper(
30394
- aiSDKChannels.generateText,
32282
+ generateChannelForAgent(instance.constructor.name),
30395
32283
  defaultName,
30396
32284
  generate.bind(instance),
30397
32285
  {
@@ -30401,19 +32289,42 @@ var wrapAgentGenerate = (generate, instance, options = {}) => {
30401
32289
  options
30402
32290
  )({ ...instance.settings, ...params });
30403
32291
  };
32292
+ function generateChannelForAgent(agentName) {
32293
+ if (agentName === "ToolLoopAgent") {
32294
+ return aiSDKChannels.toolLoopAgentGenerate;
32295
+ }
32296
+ return aiSDKChannels.agentGenerate;
32297
+ }
30404
32298
  var wrapAgentStream = (stream, instance, options = {}) => {
30405
32299
  const defaultName = `${instance.constructor.name}.stream`;
30406
- return (params) => makeStreamWrapper(
30407
- aiSDKChannels.agentStream,
30408
- defaultName,
30409
- stream.bind(instance),
30410
- {
30411
- self: instance,
30412
- spanType: "function" /* FUNCTION */
30413
- },
30414
- options
30415
- )({ ...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
+ };
30416
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
+ }
30417
32328
  var makeGenerateTextWrapper = (channel2, name, generateText, contextOptions = {}, options = {}) => {
30418
32329
  const wrapper = async function(allParams) {
30419
32330
  const { span_info, ...params } = allParams;
@@ -30675,7 +32586,7 @@ var BraintrustLanguageModelWrapper = class {
30675
32586
  let time_to_first_token = void 0;
30676
32587
  let usage = void 0;
30677
32588
  let fullText = void 0;
30678
- const toolCalls = {};
32589
+ const toolCalls2 = {};
30679
32590
  let finishReason = void 0;
30680
32591
  return {
30681
32592
  ...ret,
@@ -30694,7 +32605,7 @@ var BraintrustLanguageModelWrapper = class {
30694
32605
  fullText += chunk.textDelta;
30695
32606
  break;
30696
32607
  case "tool-call":
30697
- toolCalls[chunk.toolCallId] = {
32608
+ toolCalls2[chunk.toolCallId] = {
30698
32609
  toolCallType: chunk.toolCallType,
30699
32610
  toolCallId: chunk.toolCallId,
30700
32611
  toolName: chunk.toolName,
@@ -30702,15 +32613,15 @@ var BraintrustLanguageModelWrapper = class {
30702
32613
  };
30703
32614
  break;
30704
32615
  case "tool-call-delta":
30705
- if (toolCalls[chunk.toolCallId] === void 0) {
30706
- toolCalls[chunk.toolCallId] = {
32616
+ if (toolCalls2[chunk.toolCallId] === void 0) {
32617
+ toolCalls2[chunk.toolCallId] = {
30707
32618
  toolCallType: chunk.toolCallType,
30708
32619
  toolCallId: chunk.toolCallId,
30709
32620
  toolName: chunk.toolName,
30710
32621
  args: ""
30711
32622
  };
30712
32623
  }
30713
- toolCalls[chunk.toolCallId].args += chunk.argsTextDelta;
32624
+ toolCalls2[chunk.toolCallId].args += chunk.argsTextDelta;
30714
32625
  break;
30715
32626
  case "finish":
30716
32627
  usage = chunk.usage;
@@ -30723,7 +32634,7 @@ var BraintrustLanguageModelWrapper = class {
30723
32634
  span.log({
30724
32635
  output: postProcessOutput(
30725
32636
  fullText,
30726
- Object.keys(toolCalls).length > 0 ? Object.values(toolCalls) : void 0,
32637
+ Object.keys(toolCalls2).length > 0 ? Object.values(toolCalls2) : void 0,
30727
32638
  finishReason
30728
32639
  ),
30729
32640
  metrics: {
@@ -30824,15 +32735,15 @@ function postProcessPrompt(prompt) {
30824
32735
  }
30825
32736
  });
30826
32737
  }
30827
- function postProcessOutput(text, toolCalls, finishReason) {
32738
+ function postProcessOutput(text, toolCalls2, finishReason) {
30828
32739
  return [
30829
32740
  {
30830
32741
  index: 0,
30831
32742
  message: {
30832
32743
  role: "assistant",
30833
32744
  content: text ?? "",
30834
- ...toolCalls && toolCalls.length > 0 ? {
30835
- tool_calls: toolCalls.map((toolCall) => ({
32745
+ ...toolCalls2 && toolCalls2.length > 0 ? {
32746
+ tool_calls: toolCalls2.map((toolCall) => ({
30836
32747
  id: toolCall.toolCallId,
30837
32748
  function: {
30838
32749
  name: toolCall.toolName,
@@ -30931,29 +32842,29 @@ function normalizeFinishReason(reason) {
30931
32842
  if (typeof reason !== "string") return void 0;
30932
32843
  return reason.replace(/-/g, "_");
30933
32844
  }
30934
- function buildAssistantOutputWithToolCalls(result, toolCalls) {
32845
+ function buildAssistantOutputWithToolCalls(result, toolCalls2) {
30935
32846
  return [
30936
32847
  {
30937
32848
  index: 0,
30938
32849
  logprobs: null,
30939
- finish_reason: normalizeFinishReason(result?.finishReason) ?? (toolCalls.length ? "tool_calls" : void 0),
32850
+ finish_reason: normalizeFinishReason(result?.finishReason) ?? (toolCalls2.length ? "tool_calls" : void 0),
30940
32851
  message: {
30941
32852
  role: "assistant",
30942
- tool_calls: toolCalls.length > 0 ? toolCalls : void 0
32853
+ tool_calls: toolCalls2.length > 0 ? toolCalls2 : void 0
30943
32854
  }
30944
32855
  }
30945
32856
  ];
30946
32857
  }
30947
32858
  function extractToolCallsFromSteps(steps) {
30948
- const toolCalls = [];
30949
- if (!Array.isArray(steps)) return toolCalls;
32859
+ const toolCalls2 = [];
32860
+ if (!Array.isArray(steps)) return toolCalls2;
30950
32861
  let idx = 0;
30951
32862
  for (const step of steps) {
30952
32863
  const blocks = step?.content;
30953
32864
  if (!Array.isArray(blocks)) continue;
30954
32865
  for (const block of blocks) {
30955
32866
  if (block && typeof block === "object" && block.type === "tool-call") {
30956
- toolCalls.push({
32867
+ toolCalls2.push({
30957
32868
  id: block.toolCallId,
30958
32869
  type: "function",
30959
32870
  index: idx++,
@@ -30965,7 +32876,7 @@ function extractToolCallsFromSteps(steps) {
30965
32876
  }
30966
32877
  }
30967
32878
  }
30968
- return toolCalls;
32879
+ return toolCalls2;
30969
32880
  }
30970
32881
  function extractToolCallsFromBlocks(blocks) {
30971
32882
  if (!Array.isArray(blocks)) return [];
@@ -31031,12 +32942,12 @@ function BraintrustMiddleware(config = {}) {
31031
32942
  metadata.model = modelId;
31032
32943
  }
31033
32944
  }
31034
- let toolCalls = extractToolCallsFromSteps(result?.steps);
31035
- if (!toolCalls || toolCalls.length === 0) {
31036
- toolCalls = extractToolCallsFromBlocks(result?.content);
32945
+ let toolCalls2 = extractToolCallsFromSteps(result?.steps);
32946
+ if (!toolCalls2 || toolCalls2.length === 0) {
32947
+ toolCalls2 = extractToolCallsFromBlocks(result?.content);
31037
32948
  }
31038
32949
  span.log({
31039
- output: toolCalls.length > 0 ? buildAssistantOutputWithToolCalls(result, toolCalls) : result?.content,
32950
+ output: toolCalls2.length > 0 ? buildAssistantOutputWithToolCalls(result, toolCalls2) : result?.content,
31040
32951
  metadata,
31041
32952
  metrics: normalizeUsageMetrics(
31042
32953
  result.usage,
@@ -31125,13 +33036,13 @@ function BraintrustMiddleware(config = {}) {
31125
33036
  metadata.model = model;
31126
33037
  }
31127
33038
  if (toolBlocks.length > 0) {
31128
- const toolCalls = extractToolCallsFromSteps([
33039
+ const toolCalls2 = extractToolCallsFromSteps([
31129
33040
  { content: toolBlocks }
31130
33041
  ]);
31131
- if (toolCalls.length > 0) {
33042
+ if (toolCalls2.length > 0) {
31132
33043
  output = buildAssistantOutputWithToolCalls(
31133
33044
  resultForDetection,
31134
- toolCalls
33045
+ toolCalls2
31135
33046
  );
31136
33047
  }
31137
33048
  }
@@ -31766,9 +33677,9 @@ function isModuleNamespace3(obj) {
31766
33677
  const descriptor = Object.getOwnPropertyDescriptor(obj, keys[0]);
31767
33678
  return descriptor ? !descriptor.configurable && !descriptor.writable : false;
31768
33679
  }
31769
- function wrapCursorAgentClass(Agent) {
33680
+ function wrapCursorAgentClass(Agent2) {
31770
33681
  const cache = /* @__PURE__ */ new Map();
31771
- return new Proxy(Agent, {
33682
+ return new Proxy(Agent2, {
31772
33683
  get(target, prop, receiver) {
31773
33684
  if (cache.has(prop)) {
31774
33685
  return cache.get(prop);
@@ -35316,15 +37227,21 @@ var waterfall$1 = awaitify(waterfall);
35316
37227
 
35317
37228
  // src/trace.ts
35318
37229
  var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
35319
- constructor(objectType, _objectId, rootSpanId, _state, spanTypeFilter, includeScorers = false) {
37230
+ constructor(objectType, _objectId, rootSpanId, _state, spanTypeFilter, includeScorers = false, brainstoreRealtime = true) {
35320
37231
  const filterExpr = _SpanFetcher.buildFilter(
35321
37232
  rootSpanId,
35322
37233
  spanTypeFilter,
35323
37234
  includeScorers
35324
37235
  );
35325
- super(objectType, void 0, void 0, {
35326
- filter: filterExpr
35327
- });
37236
+ super(
37237
+ objectType,
37238
+ void 0,
37239
+ void 0,
37240
+ {
37241
+ filter: filterExpr
37242
+ },
37243
+ brainstoreRealtime
37244
+ );
35328
37245
  this._objectId = _objectId;
35329
37246
  this.rootSpanId = rootSpanId;
35330
37247
  this._state = _state;
@@ -35378,7 +37295,7 @@ var CachedSpanFetcher = class {
35378
37295
  spanCache = /* @__PURE__ */ new Map();
35379
37296
  allFetched = false;
35380
37297
  fetchFn;
35381
- constructor(objectTypeOrFetchFn, objectId, rootSpanId, getState) {
37298
+ constructor(objectTypeOrFetchFn, objectId, rootSpanId, getState, brainstoreRealtime = true) {
35382
37299
  if (typeof objectTypeOrFetchFn === "function") {
35383
37300
  this.fetchFn = (spanType) => objectTypeOrFetchFn(spanType);
35384
37301
  } else {
@@ -35391,7 +37308,8 @@ var CachedSpanFetcher = class {
35391
37308
  rootSpanId,
35392
37309
  state,
35393
37310
  spanType,
35394
- includeScorers
37311
+ includeScorers,
37312
+ brainstoreRealtime
35395
37313
  );
35396
37314
  const rows = await fetcher.fetchedData();
35397
37315
  return rows.map((row) => ({
@@ -36221,7 +38139,7 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
36221
38139
  }
36222
38140
  };
36223
38141
  const parentStr = state.currentParent.getStore();
36224
- const parentComponents = parentStr ? SpanComponentsV3.fromStr(parentStr) : null;
38142
+ const parentComponents = typeof parentStr === "string" ? SpanComponentsV4.fromStr(parentStr) : null;
36225
38143
  const trace = state ? new LocalTrace({
36226
38144
  objectType: parentComponents ? spanObjectTypeV3ToTypedString(
36227
38145
  parentComponents.data.object_type
@@ -36747,6 +38665,350 @@ var defaultReporter = {
36747
38665
  }
36748
38666
  };
36749
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
+
36750
39012
  // src/dataset-pipeline.ts
36751
39013
  function DatasetPipeline(definition) {
36752
39014
  if (!globalThis.__braintrust_dataset_pipelines) {