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