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
@@ -33,6 +33,7 @@ __export(index_exports, {
33
33
  BasePlugin: () => BasePlugin,
34
34
  BraintrustPlugin: () => BraintrustPlugin,
35
35
  OpenAIAgentsTraceProcessor: () => OpenAIAgentsTraceProcessor,
36
+ braintrustFlueInstrumentation: () => braintrustFlueInstrumentation,
36
37
  braintrustFlueObserver: () => braintrustFlueObserver,
37
38
  configureInstrumentation: () => configureInstrumentation,
38
39
  createChannelName: () => createChannelName,
@@ -542,8 +543,291 @@ var UUIDGenerator = class extends IDGenerator {
542
543
  return true;
543
544
  }
544
545
  };
546
+ function generateHexId(bytes) {
547
+ let result = "";
548
+ for (let i = 0; i < bytes; i++) {
549
+ result += Math.floor(Math.random() * 256).toString(16).padStart(2, "0");
550
+ }
551
+ return result;
552
+ }
553
+ var OTELIDGenerator = class extends IDGenerator {
554
+ getSpanId() {
555
+ return generateHexId(8);
556
+ }
557
+ getTraceId() {
558
+ return generateHexId(16);
559
+ }
560
+ shareRootSpanId() {
561
+ return false;
562
+ }
563
+ };
564
+ function parseEnvBool(name) {
565
+ const raw = isomorph_default.getEnv(name);
566
+ if (raw === void 0 || raw === null) {
567
+ return false;
568
+ }
569
+ const normalized = raw.trim().toLowerCase();
570
+ return normalized === "true" || normalized === "1" || normalized === "yes" || normalized === "y" || normalized === "on";
571
+ }
572
+ var _warnedLegacyUuidConflict = false;
573
+ function resolveUseLegacyUuidIds() {
574
+ const legacy = parseEnvBool("BRAINTRUST_LEGACY_IDS");
575
+ if (parseEnvBool("BRAINTRUST_OTEL_COMPAT")) {
576
+ if (legacy && !_warnedLegacyUuidConflict) {
577
+ _warnedLegacyUuidConflict = true;
578
+ debugLogger.warn(
579
+ "BRAINTRUST_LEGACY_IDS is ignored because BRAINTRUST_OTEL_COMPAT requires OpenTelemetry-compatible hex span IDs. Using hex IDs."
580
+ );
581
+ }
582
+ return false;
583
+ }
584
+ return legacy;
585
+ }
545
586
  function getIdGenerator() {
546
- return globalThis.BRAINTRUST_ID_GENERATOR !== void 0 ? new globalThis.BRAINTRUST_ID_GENERATOR() : new UUIDGenerator();
587
+ if (globalThis.BRAINTRUST_ID_GENERATOR !== void 0) {
588
+ return new globalThis.BRAINTRUST_ID_GENERATOR();
589
+ }
590
+ return resolveUseLegacyUuidIds() ? new UUIDGenerator() : new OTELIDGenerator();
591
+ }
592
+
593
+ // src/propagation.ts
594
+ var TRACEPARENT_HEADER = "traceparent";
595
+ var TRACESTATE_HEADER = "tracestate";
596
+ var BAGGAGE_HEADER = "baggage";
597
+ var BRAINTRUST_PARENT_KEY = "braintrust.parent";
598
+ var DEFAULT_TRACE_FLAGS = "01";
599
+ var TRACEPARENT_RE = /^00-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$/;
600
+ var ZERO_TRACE_ID = "0".repeat(32);
601
+ var ZERO_SPAN_ID = "0".repeat(16);
602
+ var MAX_BAGGAGE_LENGTH = 8192;
603
+ var MAX_BAGGAGE_MEMBERS = 64;
604
+ var _utf8Encoder = new TextEncoder();
605
+ function utf8ByteLength(value) {
606
+ return _utf8Encoder.encode(value).length;
607
+ }
608
+ function capBaggageToMemberBoundary(value) {
609
+ const totalBytes = utf8ByteLength(value);
610
+ const withinBytes = totalBytes <= MAX_BAGGAGE_LENGTH;
611
+ let commaCount = 0;
612
+ for (let i = 0; i < value.length; i++) {
613
+ if (value.charCodeAt(i) === 44) {
614
+ commaCount++;
615
+ }
616
+ }
617
+ const withinMembers = commaCount < MAX_BAGGAGE_MEMBERS;
618
+ if (withinBytes && withinMembers) {
619
+ return value;
620
+ }
621
+ const kept = [];
622
+ let length = 0;
623
+ for (const rawMember of value.split(",")) {
624
+ if (kept.length >= MAX_BAGGAGE_MEMBERS) {
625
+ break;
626
+ }
627
+ const cost = utf8ByteLength(rawMember) + (kept.length ? 1 : 0);
628
+ if (length + cost > MAX_BAGGAGE_LENGTH) {
629
+ break;
630
+ }
631
+ kept.push(rawMember);
632
+ length += cost;
633
+ }
634
+ if (!kept.length) {
635
+ return "";
636
+ }
637
+ return kept.join(",");
638
+ }
639
+ function isTraceContextHeaderTupleArray(value) {
640
+ return Array.isArray(value) && value.every(
641
+ (item) => Array.isArray(item) && typeof item[0] === "string" && typeof item[1] === "string"
642
+ );
643
+ }
644
+ function isListHeader(name) {
645
+ const lowered = name.toLowerCase();
646
+ return lowered === BAGGAGE_HEADER || lowered === TRACESTATE_HEADER;
647
+ }
648
+ function headerValueToString(value, name) {
649
+ if (value === void 0 || value === null) {
650
+ return void 0;
651
+ }
652
+ if (Array.isArray(value)) {
653
+ const stringValues = value.filter((item) => {
654
+ return typeof item === "string";
655
+ });
656
+ if (!stringValues.length) {
657
+ return void 0;
658
+ }
659
+ return isListHeader(name) ? stringValues.join(",") : stringValues[0];
660
+ }
661
+ return typeof value === "string" ? value : String(value);
662
+ }
663
+ function getHeader(headers, name) {
664
+ if (!headers) {
665
+ return void 0;
666
+ }
667
+ if (isTraceContextHeaderTupleArray(headers)) {
668
+ const lowered2 = name.toLowerCase();
669
+ const matches = headers.filter(([key]) => key.toLowerCase() === lowered2).map(([, value]) => value);
670
+ if (!matches.length) {
671
+ return void 0;
672
+ }
673
+ return headerValueToString(matches, name);
674
+ }
675
+ const getter = headers.get;
676
+ if (typeof getter === "function") {
677
+ try {
678
+ const value = headerValueToString(getter.call(headers, name), name);
679
+ if (value !== void 0) {
680
+ return value;
681
+ }
682
+ } catch {
683
+ }
684
+ }
685
+ const nodeGetter = headers.getHeader;
686
+ if (typeof nodeGetter === "function") {
687
+ try {
688
+ const value = headerValueToString(nodeGetter.call(headers, name), name);
689
+ if (value !== void 0) {
690
+ return value;
691
+ }
692
+ } catch {
693
+ }
694
+ }
695
+ const headerBag = headers;
696
+ const exact = headerValueToString(headerBag[name], name);
697
+ if (exact !== void 0) {
698
+ return exact;
699
+ }
700
+ const lowered = name.toLowerCase();
701
+ for (const key of Object.keys(headers)) {
702
+ if (key !== name && key.toLowerCase() === lowered) {
703
+ const value = headerValueToString(headerBag[key], name);
704
+ if (value !== void 0) {
705
+ return value;
706
+ }
707
+ }
708
+ }
709
+ return void 0;
710
+ }
711
+ function isHex(value, length) {
712
+ if (typeof value !== "string" || value.length !== length) {
713
+ return false;
714
+ }
715
+ for (let i = 0; i < value.length; i++) {
716
+ const c = value[i];
717
+ const isDigit = c >= "0" && c <= "9";
718
+ const isLowerHex = c >= "a" && c <= "f";
719
+ if (!isDigit && !isLowerHex) {
720
+ return false;
721
+ }
722
+ }
723
+ return true;
724
+ }
725
+ function parseTraceparent(value) {
726
+ if (!value || typeof value !== "string") {
727
+ return void 0;
728
+ }
729
+ const match = TRACEPARENT_RE.exec(value.trim());
730
+ if (!match) {
731
+ return void 0;
732
+ }
733
+ const traceId = match[1];
734
+ const spanId = match[2];
735
+ const traceFlags = match[3];
736
+ if (traceId === ZERO_TRACE_ID || spanId === ZERO_SPAN_ID) {
737
+ return void 0;
738
+ }
739
+ return { traceId, spanId, traceFlags };
740
+ }
741
+ function formatTraceparent(traceId, spanId, traceFlags = DEFAULT_TRACE_FLAGS) {
742
+ if (!isHex(traceId, 32) || traceId === ZERO_TRACE_ID) {
743
+ return void 0;
744
+ }
745
+ if (!isHex(spanId, 16) || spanId === ZERO_SPAN_ID) {
746
+ return void 0;
747
+ }
748
+ const flags = isHex(traceFlags, 2) ? traceFlags : DEFAULT_TRACE_FLAGS;
749
+ return `00-${traceId}-${spanId}-${flags}`;
750
+ }
751
+ function percentEncode(value) {
752
+ return encodeURIComponent(value);
753
+ }
754
+ function percentDecode(value) {
755
+ if (!value.includes("%")) {
756
+ return value;
757
+ }
758
+ try {
759
+ return decodeURIComponent(value);
760
+ } catch {
761
+ return value;
762
+ }
763
+ }
764
+ function parseBaggage(value) {
765
+ const result = {};
766
+ if (!value || typeof value !== "string") {
767
+ return result;
768
+ }
769
+ const bounded = capBaggageToMemberBoundary(value);
770
+ for (let member of bounded.split(",")) {
771
+ member = member.trim();
772
+ if (!member || !member.includes("=")) {
773
+ continue;
774
+ }
775
+ member = member.split(";", 1)[0];
776
+ const eq = member.indexOf("=");
777
+ const key = percentDecode(member.slice(0, eq).trim());
778
+ const val = member.slice(eq + 1).trim();
779
+ if (!key) {
780
+ continue;
781
+ }
782
+ result[key] = percentDecode(val);
783
+ }
784
+ return result;
785
+ }
786
+ function mergeBaggage(existing, braintrustParent) {
787
+ let btMember = void 0;
788
+ if (braintrustParent) {
789
+ const encodedKey = percentEncode(BRAINTRUST_PARENT_KEY);
790
+ const encodedVal = percentEncode(String(braintrustParent));
791
+ btMember = `${encodedKey}=${encodedVal}`;
792
+ if (utf8ByteLength(btMember) > MAX_BAGGAGE_LENGTH) {
793
+ btMember = void 0;
794
+ }
795
+ }
796
+ let byteBudget = MAX_BAGGAGE_LENGTH;
797
+ let memberBudget = MAX_BAGGAGE_MEMBERS;
798
+ if (btMember !== void 0) {
799
+ byteBudget -= utf8ByteLength(btMember) + 1;
800
+ memberBudget -= 1;
801
+ }
802
+ const relayed = [];
803
+ let length = 0;
804
+ if (existing && typeof existing === "string") {
805
+ for (const rawMember of existing.split(",")) {
806
+ const member = rawMember.trim();
807
+ if (!member || !member.includes("=")) {
808
+ continue;
809
+ }
810
+ const keyPart = member.split(";", 1)[0].split("=", 1)[0];
811
+ const key = percentDecode(keyPart.trim());
812
+ if (key === BRAINTRUST_PARENT_KEY) {
813
+ continue;
814
+ }
815
+ if (relayed.length >= memberBudget) {
816
+ break;
817
+ }
818
+ const cost = utf8ByteLength(member) + (relayed.length ? 1 : 0);
819
+ if (length + cost > byteBudget) {
820
+ break;
821
+ }
822
+ relayed.push(member);
823
+ length += cost;
824
+ }
825
+ }
826
+ const members = btMember !== void 0 ? [...relayed, btMember] : relayed;
827
+ if (!members.length) {
828
+ return void 0;
829
+ }
830
+ return members.join(",");
547
831
  }
548
832
 
549
833
  // util/db_fields.ts
@@ -1151,7 +1435,7 @@ var SpanComponentsV3 = class _SpanComponentsV3 {
1151
1435
  case 3 /* PLAYGROUND_LOGS */:
1152
1436
  return { prompt_session_id: this.data.object_id, log_id: "x" };
1153
1437
  default:
1154
- const _ = this.data.object_type;
1438
+ this.data.object_type;
1155
1439
  throw new Error("Impossible");
1156
1440
  }
1157
1441
  }
@@ -1593,7 +1877,7 @@ var SpanComponentsV4 = class _SpanComponentsV4 {
1593
1877
  case 3 /* PLAYGROUND_LOGS */:
1594
1878
  return { prompt_session_id: this.data.object_id, log_id: "x" };
1595
1879
  default:
1596
- const _ = this.data.object_type;
1880
+ this.data.object_type;
1597
1881
  throw new Error(`Invalid object_type ${this.data.object_type}`);
1598
1882
  }
1599
1883
  }
@@ -1726,7 +2010,8 @@ var AclObjectType = import_v36.z.union([
1726
2010
  "role",
1727
2011
  "org_member",
1728
2012
  "project_log",
1729
- "org_project"
2013
+ "org_project",
2014
+ "org_audit_logs"
1730
2015
  ]),
1731
2016
  import_v36.z.null()
1732
2017
  ]);
@@ -1752,6 +2037,17 @@ var Acl = import_v36.z.object({
1752
2037
  _object_org_id: import_v36.z.string().uuid(),
1753
2038
  created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional()
1754
2039
  });
2040
+ var Agent = import_v36.z.object({
2041
+ id: import_v36.z.string().uuid(),
2042
+ project_id: import_v36.z.string().uuid(),
2043
+ user_id: import_v36.z.string().uuid(),
2044
+ created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2045
+ name: import_v36.z.string(),
2046
+ slug: import_v36.z.string(),
2047
+ kind: import_v36.z.string(),
2048
+ description: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2049
+ metadata: import_v36.z.union([import_v36.z.object({}).partial().passthrough(), import_v36.z.null()]).optional()
2050
+ });
1755
2051
  var AISecret = import_v36.z.object({
1756
2052
  id: import_v36.z.string().uuid(),
1757
2053
  created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
@@ -1898,6 +2194,7 @@ var AttachmentStatus = import_v36.z.object({
1898
2194
  upload_status: UploadStatus,
1899
2195
  error_message: import_v36.z.string().optional()
1900
2196
  });
2197
+ var AutomationStatus = import_v36.z.enum(["active", "paused"]);
1901
2198
  var FunctionTypeEnum = import_v36.z.enum([
1902
2199
  "llm",
1903
2200
  "scorer",
@@ -1943,7 +2240,9 @@ var TopicMapData = import_v36.z.object({
1943
2240
  topic_names: import_v36.z.record(import_v36.z.string()).optional(),
1944
2241
  generation_settings: TopicMapGenerationSettings.optional(),
1945
2242
  disable_reconciliation: import_v36.z.boolean().optional(),
1946
- distance_threshold: import_v36.z.number().optional()
2243
+ distance_threshold: import_v36.z.number().optional(),
2244
+ btql_filter: import_v36.z.string().optional(),
2245
+ automation_btql_filter: import_v36.z.string().optional()
1947
2246
  });
1948
2247
  var BatchedFacetData = import_v36.z.object({
1949
2248
  type: import_v36.z.literal("batched_facet"),
@@ -2226,7 +2525,7 @@ var DatasetEvent = import_v36.z.object({
2226
2525
  origin: ObjectReferenceNullish.optional(),
2227
2526
  comments: import_v36.z.union([import_v36.z.array(import_v36.z.unknown()), import_v36.z.null()]).optional(),
2228
2527
  audit_data: import_v36.z.union([import_v36.z.array(import_v36.z.unknown()), import_v36.z.null()]).optional(),
2229
- facets: import_v36.z.union([import_v36.z.object({}).partial().passthrough(), import_v36.z.null()]).optional(),
2528
+ 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(),
2230
2529
  classifications: import_v36.z.union([
2231
2530
  import_v36.z.record(
2232
2531
  import_v36.z.array(
@@ -2378,7 +2677,7 @@ var ExperimentEvent = import_v36.z.object({
2378
2677
  origin: ObjectReferenceNullish.optional(),
2379
2678
  comments: import_v36.z.union([import_v36.z.array(import_v36.z.unknown()), import_v36.z.null()]).optional(),
2380
2679
  audit_data: import_v36.z.union([import_v36.z.array(import_v36.z.unknown()), import_v36.z.null()]).optional(),
2381
- facets: import_v36.z.union([import_v36.z.object({}).partial().passthrough(), import_v36.z.null()]).optional(),
2680
+ 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(),
2382
2681
  classifications: import_v36.z.union([
2383
2682
  import_v36.z.record(
2384
2683
  import_v36.z.array(
@@ -2516,7 +2815,8 @@ var PromptParserNullish = import_v36.z.union([
2516
2815
  use_cot: import_v36.z.boolean(),
2517
2816
  choice_scores: import_v36.z.record(import_v36.z.number().gte(0).lte(1)).optional(),
2518
2817
  choice: import_v36.z.array(import_v36.z.string()).optional(),
2519
- allow_no_match: import_v36.z.boolean().optional()
2818
+ allow_no_match: import_v36.z.boolean().optional(),
2819
+ allow_skip: import_v36.z.boolean().optional()
2520
2820
  }),
2521
2821
  import_v36.z.null()
2522
2822
  ]);
@@ -2846,6 +3146,9 @@ var Group = import_v36.z.object({
2846
3146
  var GroupScope = import_v36.z.object({
2847
3147
  type: import_v36.z.literal("group"),
2848
3148
  group_by: import_v36.z.string(),
3149
+ interval_seconds: import_v36.z.number().gte(1).optional(),
3150
+ max_traces: import_v36.z.number().int().gte(1).lte(64).optional(),
3151
+ placement: import_v36.z.enum(["first", "each"]),
2849
3152
  idle_seconds: import_v36.z.number().optional()
2850
3153
  });
2851
3154
  var IfExists = import_v36.z.enum(["error", "ignore", "replace"]);
@@ -2994,6 +3297,10 @@ var RetentionObjectType = import_v36.z.enum([
2994
3297
  "experiment",
2995
3298
  "dataset"
2996
3299
  ]);
3300
+ var TopicAutomationFacetModel = import_v36.z.union([
3301
+ import_v36.z.enum(["brain-facet-latest", "brain-facet-1", "brain-facet-2"]),
3302
+ import_v36.z.null()
3303
+ ]);
2997
3304
  var TopicMapFunctionAutomation = import_v36.z.object({
2998
3305
  function: SavedFunctionId.and(import_v36.z.unknown()),
2999
3306
  btql_filter: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional()
@@ -3006,7 +3313,9 @@ var TopicAutomationDataScope = import_v36.z.union([
3006
3313
  ]);
3007
3314
  var TopicAutomationConfig = import_v36.z.object({
3008
3315
  event_type: import_v36.z.literal("topic"),
3316
+ status: AutomationStatus.optional(),
3009
3317
  sampling_rate: import_v36.z.number().gte(0).lte(1),
3318
+ facet_model: TopicAutomationFacetModel.optional(),
3010
3319
  facet_functions: import_v36.z.array(SavedFunctionId),
3011
3320
  topic_map_functions: import_v36.z.array(TopicMapFunctionAutomation),
3012
3321
  scope: import_v36.z.union([SpanScope, TraceScope, GroupScope, import_v36.z.null()]).optional(),
@@ -3020,6 +3329,19 @@ var TopicAutomationConfig = import_v36.z.object({
3020
3329
  import_v36.z.null()
3021
3330
  ]).optional()
3022
3331
  });
3332
+ var TopicDigestAutomationConfig = import_v36.z.object({
3333
+ event_type: import_v36.z.literal("topic_digest"),
3334
+ status: AutomationStatus.optional(),
3335
+ window_seconds: import_v36.z.number().int().gte(3600).lte(2592e3).optional().default(86400),
3336
+ scheduled_time_minutes_utc: import_v36.z.number().int().gte(0).lte(1439),
3337
+ action: import_v36.z.object({
3338
+ type: import_v36.z.literal("slack"),
3339
+ workspace_id: import_v36.z.string(),
3340
+ channel: import_v36.z.string(),
3341
+ message_template: import_v36.z.string().optional()
3342
+ }),
3343
+ topic_map_function_ids: import_v36.z.array(import_v36.z.string()).max(10).optional()
3344
+ });
3023
3345
  var ProjectAutomation = import_v36.z.object({
3024
3346
  id: import_v36.z.string().uuid(),
3025
3347
  project_id: import_v36.z.string().uuid(),
@@ -3044,6 +3366,7 @@ var ProjectAutomation = import_v36.z.object({
3044
3366
  }),
3045
3367
  import_v36.z.object({
3046
3368
  event_type: import_v36.z.literal("btql_export"),
3369
+ status: AutomationStatus.optional(),
3047
3370
  export_definition: import_v36.z.union([
3048
3371
  import_v36.z.object({ type: import_v36.z.literal("log_traces") }),
3049
3372
  import_v36.z.object({ type: import_v36.z.literal("log_spans") }),
@@ -3066,6 +3389,21 @@ var ProjectAutomation = import_v36.z.object({
3066
3389
  ]),
3067
3390
  batch_size: import_v36.z.union([import_v36.z.number(), import_v36.z.null()]).optional()
3068
3391
  }),
3392
+ import_v36.z.object({
3393
+ event_type: import_v36.z.literal("async_query"),
3394
+ status: AutomationStatus.optional(),
3395
+ created_by_user_id: import_v36.z.string().uuid(),
3396
+ object_type: import_v36.z.enum([
3397
+ "project_logs",
3398
+ "experiment",
3399
+ "dataset",
3400
+ "playground_logs"
3401
+ ]),
3402
+ object_id: import_v36.z.string(),
3403
+ query: import_v36.z.string(),
3404
+ format: import_v36.z.literal("jsonl"),
3405
+ batch_size: import_v36.z.union([import_v36.z.number(), import_v36.z.null()]).optional()
3406
+ }),
3069
3407
  import_v36.z.object({
3070
3408
  event_type: import_v36.z.literal("retention"),
3071
3409
  object_type: RetentionObjectType,
@@ -3084,7 +3422,8 @@ var ProjectAutomation = import_v36.z.object({
3084
3422
  })
3085
3423
  ])
3086
3424
  }),
3087
- TopicAutomationConfig
3425
+ TopicAutomationConfig,
3426
+ TopicDigestAutomationConfig
3088
3427
  ])
3089
3428
  });
3090
3429
  var ProjectLogsEvent = import_v36.z.object({
@@ -3123,7 +3462,7 @@ var ProjectLogsEvent = import_v36.z.object({
3123
3462
  comments: import_v36.z.union([import_v36.z.array(import_v36.z.unknown()), import_v36.z.null()]).optional(),
3124
3463
  audit_data: import_v36.z.union([import_v36.z.array(import_v36.z.unknown()), import_v36.z.null()]).optional(),
3125
3464
  _async_scoring_state: import_v36.z.unknown().optional(),
3126
- facets: import_v36.z.union([import_v36.z.object({}).partial().passthrough(), import_v36.z.null()]).optional(),
3465
+ 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(),
3127
3466
  classifications: import_v36.z.union([
3128
3467
  import_v36.z.record(
3129
3468
  import_v36.z.array(
@@ -3172,11 +3511,34 @@ var ProjectScoreCategories = import_v36.z.union([
3172
3511
  import_v36.z.array(import_v36.z.string()),
3173
3512
  import_v36.z.null()
3174
3513
  ]);
3514
+ var ProjectScoreCondition = import_v36.z.union([
3515
+ import_v36.z.object({
3516
+ when: import_v36.z.object({
3517
+ clauses: import_v36.z.union([import_v36.z.array(import_v36.z.string()), import_v36.z.null()]),
3518
+ subspan_clauses: import_v36.z.union([import_v36.z.array(import_v36.z.string()), import_v36.z.null()]),
3519
+ trace_clauses: import_v36.z.union([import_v36.z.array(import_v36.z.string()), import_v36.z.null()])
3520
+ }).partial(),
3521
+ behavior: import_v36.z.literal("hidden").optional().default("hidden")
3522
+ }),
3523
+ import_v36.z.null()
3524
+ ]);
3175
3525
  var ProjectScoreConfig = import_v36.z.union([
3176
3526
  import_v36.z.object({
3177
3527
  multi_select: import_v36.z.union([import_v36.z.boolean(), import_v36.z.null()]),
3178
3528
  destination: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
3179
- online: OnlineScoreConfig
3529
+ visibility: import_v36.z.union([
3530
+ import_v36.z.object({
3531
+ users: import_v36.z.union([import_v36.z.array(import_v36.z.string()), import_v36.z.null()]),
3532
+ groups: import_v36.z.union([import_v36.z.array(import_v36.z.string()), import_v36.z.null()])
3533
+ }).partial(),
3534
+ import_v36.z.null()
3535
+ ]),
3536
+ online: OnlineScoreConfig,
3537
+ condition: ProjectScoreCondition,
3538
+ object_types: import_v36.z.union([
3539
+ import_v36.z.array(import_v36.z.enum(["project_logs", "dataset", "experiment"])),
3540
+ import_v36.z.null()
3541
+ ])
3180
3542
  }).partial(),
3181
3543
  import_v36.z.null()
3182
3544
  ]);
@@ -3361,8 +3723,7 @@ var User = import_v36.z.object({
3361
3723
  family_name: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3362
3724
  email: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3363
3725
  avatar_url: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3364
- created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3365
- last_active_at: import_v36.z.union([import_v36.z.number(), import_v36.z.null()]).optional()
3726
+ created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional()
3366
3727
  });
3367
3728
  var ViewDataSearch = import_v36.z.union([
3368
3729
  import_v36.z.object({
@@ -4621,7 +4982,10 @@ var BraintrustContextManager = class extends ContextManager {
4621
4982
  }
4622
4983
  };
4623
4984
  function getSpanComponentsClass() {
4624
- return globalThis.BRAINTRUST_SPAN_COMPONENT ? globalThis.BRAINTRUST_SPAN_COMPONENT : SpanComponentsV3;
4985
+ if (globalThis.BRAINTRUST_SPAN_COMPONENT) {
4986
+ return globalThis.BRAINTRUST_SPAN_COMPONENT;
4987
+ }
4988
+ return resolveUseLegacyUuidIds() ? SpanComponentsV3 : SpanComponentsV4;
4625
4989
  }
4626
4990
  function getContextManager() {
4627
4991
  return globalThis.BRAINTRUST_CONTEXT_MANAGER ? new globalThis.BRAINTRUST_CONTEXT_MANAGER() : new BraintrustContextManager();
@@ -4657,6 +5021,9 @@ var NoopSpan = class {
4657
5021
  async export() {
4658
5022
  return "";
4659
5023
  }
5024
+ inject(carrier) {
5025
+ return carrier ?? {};
5026
+ }
4660
5027
  async permalink() {
4661
5028
  return NOOP_SPAN_PERMALINK;
4662
5029
  }
@@ -4707,6 +5074,10 @@ var loginSchema = import_v38.z.strictObject({
4707
5074
  debugLogLevelDisabled: import_v38.z.boolean().optional()
4708
5075
  });
4709
5076
  var stateNonce = 0;
5077
+ var V1_PROXY_SUFFIX = "/v1/proxy";
5078
+ function normalizeProxyConnUrl(proxyUrl) {
5079
+ return proxyUrl.endsWith(V1_PROXY_SUFFIX) ? proxyUrl.slice(0, proxyUrl.length - V1_PROXY_SUFFIX.length) : proxyUrl;
5080
+ }
4710
5081
  var BraintrustState = class _BraintrustState {
4711
5082
  constructor(loginParams) {
4712
5083
  this.loginParams = loginParams;
@@ -4977,7 +5348,10 @@ var BraintrustState = class _BraintrustState {
4977
5348
  if (!this.proxyUrl) {
4978
5349
  throw new Error("Must initialize proxyUrl before requesting proxyConn");
4979
5350
  }
4980
- this._proxyConn = new HTTPConnection(this.proxyUrl, this.fetch);
5351
+ this._proxyConn = new HTTPConnection(
5352
+ normalizeProxyConnUrl(this.proxyUrl),
5353
+ this.fetch
5354
+ );
4981
5355
  }
4982
5356
  return this._proxyConn;
4983
5357
  }
@@ -5650,7 +6024,7 @@ async function permalink(slug, opts) {
5650
6024
  return state.appUrl;
5651
6025
  };
5652
6026
  try {
5653
- const components = getSpanComponentsClass().fromStr(slug);
6027
+ const components = SpanComponentsV4.fromStr(slug);
5654
6028
  const object_type = spanObjectTypeV3ToString(components.data.object_type);
5655
6029
  const [orgName, appUrl, object_id] = await Promise.all([
5656
6030
  getOrgName(),
@@ -5674,35 +6048,47 @@ function startSpanParentArgs(args) {
5674
6048
  let argParentObjectId = void 0;
5675
6049
  let argParentSpanIds = void 0;
5676
6050
  let argPropagatedEvent = void 0;
5677
- if (args.parent) {
6051
+ let argPropagatedState = void 0;
6052
+ const { parentSlug, propagatedState: parentPropagatedState } = normalizeParent(args.parent, args.state);
6053
+ if (parentSlug) {
5678
6054
  if (args.parentSpanIds) {
5679
6055
  throw new Error("Cannot specify both parent and parentSpanIds");
5680
6056
  }
5681
- const parentComponents = getSpanComponentsClass().fromStr(args.parent);
6057
+ const parentComponents = SpanComponentsV4.fromStr(parentSlug);
5682
6058
  if (args.parentObjectType !== parentComponents.data.object_type) {
5683
6059
  throw new Error(
5684
6060
  `Mismatch between expected span parent object type ${args.parentObjectType} and provided type ${parentComponents.data.object_type}`
5685
6061
  );
5686
6062
  }
5687
6063
  argParentObjectId = args.parentObjectId;
5688
- if (parentComponents.data.row_id) {
6064
+ if (parentComponents.data.row_id && parentSpanIdsUsable(
6065
+ parentComponents.data.span_id,
6066
+ parentComponents.data.root_span_id
6067
+ )) {
5689
6068
  argParentSpanIds = {
5690
6069
  spanId: parentComponents.data.span_id,
5691
6070
  rootSpanId: parentComponents.data.root_span_id
5692
6071
  };
5693
6072
  }
5694
6073
  argPropagatedEvent = args.propagatedEvent ?? (parentComponents.data.propagated_event ?? void 0);
6074
+ const propagatedState = args.propagatedState ?? parentPropagatedState;
6075
+ if (propagatedState) {
6076
+ const { braintrustParent: _ignoredBraintrustParent, ...w3cState } = propagatedState;
6077
+ argPropagatedState = w3cState;
6078
+ }
5695
6079
  } else {
5696
6080
  argParentObjectId = args.parentObjectId;
5697
6081
  argParentSpanIds = args.parentSpanIds;
5698
6082
  argPropagatedEvent = args.propagatedEvent;
6083
+ argPropagatedState = args.propagatedState;
5699
6084
  }
5700
6085
  return {
5701
6086
  parentObjectType: args.parentObjectType,
5702
6087
  parentObjectId: argParentObjectId,
5703
6088
  parentComputeObjectMetadataArgs: args.parentComputeObjectMetadataArgs,
5704
6089
  parentSpanIds: argParentSpanIds,
5705
- propagatedEvent: argPropagatedEvent
6090
+ propagatedEvent: argPropagatedEvent,
6091
+ propagatedState: argPropagatedState
5706
6092
  };
5707
6093
  }
5708
6094
  var Logger = class {
@@ -5903,6 +6289,22 @@ var Logger = class {
5903
6289
  _getLinkBaseUrl() {
5904
6290
  return _getLinkBaseUrl(this.state, this._linkArgs);
5905
6291
  }
6292
+ /**
6293
+ * Return this logger's Braintrust parent string (`project_id:<id>` or
6294
+ * `project_name:<name>`) for the `braintrust.parent` baggage entry, or
6295
+ * undefined when it cannot be determined synchronously.
6296
+ */
6297
+ _getOtelParent() {
6298
+ const id = this.computeMetadataArgs?.project_id || this.lazyId.getSync().value;
6299
+ if (id) {
6300
+ return `project_id:${id}`;
6301
+ }
6302
+ const name = this.computeMetadataArgs?.project_name;
6303
+ if (name) {
6304
+ return `project_name:${name}`;
6305
+ }
6306
+ return void 0;
6307
+ }
5906
6308
  };
5907
6309
  function castLogger(logger, asyncFlush) {
5908
6310
  if (logger === void 0) return void 0;
@@ -5997,12 +6399,12 @@ function stringifyWithOverflowMeta(item) {
5997
6399
  object_ids: pickLogs3OverflowObjectIds(record),
5998
6400
  is_delete: record[OBJECT_DELETE_FIELD] === true,
5999
6401
  input_row: {
6000
- byte_size: utf8ByteLength(str)
6402
+ byte_size: utf8ByteLength2(str)
6001
6403
  }
6002
6404
  }
6003
6405
  };
6004
6406
  }
6005
- function utf8ByteLength(value) {
6407
+ function utf8ByteLength2(value) {
6006
6408
  if (typeof TextEncoder !== "undefined") {
6007
6409
  return new TextEncoder().encode(value).length;
6008
6410
  }
@@ -6333,7 +6735,7 @@ var HTTPBackgroundLogger = class _HTTPBackgroundLogger {
6333
6735
  }) {
6334
6736
  const conn = await this.apiConn.get();
6335
6737
  const dataStr = constructLogs3Data(items);
6336
- const payloadBytes = utf8ByteLength(dataStr);
6738
+ const payloadBytes = utf8ByteLength2(dataStr);
6337
6739
  const useOverflow = canUseOverflow && payloadBytes > maxRequestSize;
6338
6740
  if (this.allPublishPayloadsDir) {
6339
6741
  await _HTTPBackgroundLogger.writePayloadToDir({
@@ -6716,100 +7118,335 @@ function currentSpan(options) {
6716
7118
  const state = options?.state ?? _globalState;
6717
7119
  return state.contextManager.getCurrentSpan() ?? NOOP_SPAN;
6718
7120
  }
6719
- function getSpanParentObject(options) {
7121
+ function getSpanParentObjectAndPropagatedState(options) {
6720
7122
  const state = options?.state ?? _globalState;
6721
7123
  const parentSpan = currentSpan({ state });
6722
7124
  if (!Object.is(parentSpan, NOOP_SPAN)) {
6723
- return parentSpan;
7125
+ return { parentObject: parentSpan, propagatedState: void 0 };
7126
+ }
7127
+ const parent = options?.parent ?? state.currentParent.getStore();
7128
+ const { parentSlug, propagatedState } = normalizeParent(parent, state);
7129
+ if (parentSlug) {
7130
+ return {
7131
+ parentObject: SpanComponentsV4.fromStr(parentSlug),
7132
+ propagatedState
7133
+ };
6724
7134
  }
6725
- const parentStr = options?.parent ?? state.currentParent.getStore();
6726
- if (parentStr) return getSpanComponentsClass().fromStr(parentStr);
6727
7135
  const experiment = currentExperiment();
6728
7136
  if (experiment) {
6729
- return experiment;
7137
+ return { parentObject: experiment, propagatedState: void 0 };
6730
7138
  }
6731
7139
  const logger = currentLogger(options);
6732
7140
  if (logger) {
6733
- return logger;
7141
+ return { parentObject: logger, propagatedState: void 0 };
6734
7142
  }
6735
- return NOOP_SPAN;
7143
+ return { parentObject: NOOP_SPAN, propagatedState: void 0 };
6736
7144
  }
6737
- function logError(span, error) {
6738
- let errorMessage = "<error>";
6739
- let stackTrace = "";
6740
- if (error instanceof Error) {
6741
- errorMessage = error.message;
6742
- stackTrace = error.stack || "";
6743
- } else {
6744
- errorMessage = String(error);
7145
+ function currentBraintrustParent(state) {
7146
+ const resolvedState = state ?? _globalState;
7147
+ const experiment = currentExperiment({ state: resolvedState });
7148
+ if (experiment) {
7149
+ try {
7150
+ return experiment._getOtelParent() ?? void 0;
7151
+ } catch {
7152
+ return void 0;
7153
+ }
6745
7154
  }
6746
- span.log({ error: `${errorMessage}
6747
-
6748
- ${stackTrace}` });
6749
- }
6750
- function startSpan(args) {
6751
- return startSpanAndIsLogger(args).span;
6752
- }
6753
- async function flush(options) {
6754
- const state = options?.state ?? _globalState;
6755
- return await state.bgLogger().flush();
7155
+ const logger = currentLogger({ state: resolvedState });
7156
+ if (logger) {
7157
+ try {
7158
+ return logger._getOtelParent() ?? void 0;
7159
+ } catch {
7160
+ return void 0;
7161
+ }
7162
+ }
7163
+ return void 0;
6756
7164
  }
6757
- function startSpanAndIsLogger(args) {
6758
- const state = args?.state ?? _globalState;
6759
- const parentObject = getSpanParentObject({
6760
- asyncFlush: args?.asyncFlush,
6761
- parent: args?.parent,
6762
- state
6763
- });
6764
- if (parentObject instanceof SpanComponentsV3 || parentObject instanceof SpanComponentsV4) {
6765
- const parentSpanIds = parentObject.data.row_id ? {
6766
- spanId: parentObject.data.span_id,
6767
- rootSpanId: parentObject.data.root_span_id
7165
+ function braintrustParentToComponents(braintrustParent) {
7166
+ if (!braintrustParent) {
7167
+ return void 0;
7168
+ }
7169
+ if (braintrustParent.startsWith("project_id:")) {
7170
+ const objectId = braintrustParent.slice("project_id:".length);
7171
+ return objectId ? {
7172
+ objectType: 2 /* PROJECT_LOGS */,
7173
+ objectId,
7174
+ computeArgs: void 0
7175
+ } : void 0;
7176
+ }
7177
+ if (braintrustParent.startsWith("project_name:")) {
7178
+ const name = braintrustParent.slice("project_name:".length);
7179
+ return name ? {
7180
+ objectType: 2 /* PROJECT_LOGS */,
7181
+ objectId: void 0,
7182
+ computeArgs: { project_name: name }
7183
+ } : void 0;
7184
+ }
7185
+ if (braintrustParent.startsWith("experiment_id:")) {
7186
+ const objectId = braintrustParent.slice("experiment_id:".length);
7187
+ return objectId ? {
7188
+ objectType: 1 /* EXPERIMENT */,
7189
+ objectId,
7190
+ computeArgs: void 0
6768
7191
  } : void 0;
6769
- const span = new SpanImpl({
6770
- state,
6771
- ...args,
6772
- parentObjectType: parentObject.data.object_type,
6773
- parentObjectId: new LazyValue(
6774
- spanComponentsToObjectIdLambda(state, parentObject)
6775
- ),
6776
- parentComputeObjectMetadataArgs: parentObject.data.compute_object_metadata_args ?? void 0,
6777
- parentSpanIds,
6778
- propagatedEvent: args?.propagatedEvent ?? // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
6779
- (parentObject.data.propagated_event ?? void 0)
6780
- });
6781
- return {
6782
- span,
6783
- isSyncFlushLogger: parentObject.data.object_type === 2 /* PROJECT_LOGS */ && // Since there's no parent logger here, we're free to choose the async flush
6784
- // behavior, and therefore propagate along whatever we get from the arguments
6785
- args?.asyncFlush === false
6786
- };
6787
- } else {
6788
- const span = parentObject.startSpan(args);
6789
- return {
6790
- span,
6791
- isSyncFlushLogger: parentObject.kind === "logger" && parentObject.asyncFlush === false
6792
- };
6793
7192
  }
7193
+ return void 0;
6794
7194
  }
6795
- function withCurrent(span, callback, state = void 0) {
6796
- const currentState = state ?? _globalState;
6797
- return currentState.contextManager.runInContext(span, () => callback(span));
7195
+ function isMutableHeaderTupleArray(carrier) {
7196
+ return Array.isArray(carrier) && carrier.every((item) => Array.isArray(item) && typeof item[0] === "string");
6798
7197
  }
6799
- function _saveOrgInfo(state, org_info, org_name) {
6800
- if (org_info.length === 0) {
6801
- throw new LoginInvalidOrgError(
6802
- "This user is not part of any organizations."
6803
- );
7198
+ function setHeader(carrier, name, value) {
7199
+ if (isMutableHeaderTupleArray(carrier)) {
7200
+ const lowered2 = name.toLowerCase();
7201
+ for (let i = carrier.length - 1; i >= 0; i--) {
7202
+ if (carrier[i][0].toLowerCase() === lowered2) {
7203
+ carrier.splice(i, 1);
7204
+ }
7205
+ }
7206
+ carrier.push([name, value]);
7207
+ return;
6804
7208
  }
6805
- for (const org of org_info) {
6806
- if (org_name === void 0 || org.name === org_name) {
6807
- state.orgId = org.id;
6808
- state.orgName = org.name;
6809
- state.apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
6810
- state.proxyUrl = isomorph_default.getEnv("BRAINTRUST_PROXY_URL") ?? org.proxy_url;
6811
- state.gitMetadataSettings = org.git_metadata || void 0;
6812
- break;
7209
+ const setter = carrier.set;
7210
+ if (typeof setter === "function") {
7211
+ const deleter = carrier.delete;
7212
+ if (typeof deleter === "function") {
7213
+ try {
7214
+ deleter.call(carrier, name);
7215
+ } catch {
7216
+ }
7217
+ }
7218
+ setter.call(carrier, name, value);
7219
+ return;
7220
+ }
7221
+ const nodeSetter = carrier.setHeader;
7222
+ if (typeof nodeSetter === "function") {
7223
+ const remover = carrier.removeHeader;
7224
+ if (typeof remover === "function") {
7225
+ try {
7226
+ remover.call(carrier, name);
7227
+ } catch {
7228
+ }
7229
+ }
7230
+ nodeSetter.call(carrier, name, value);
7231
+ return;
7232
+ }
7233
+ const headerSetter = carrier.header;
7234
+ if (typeof headerSetter === "function") {
7235
+ const deleter = carrier.delete;
7236
+ if (typeof deleter === "function") {
7237
+ try {
7238
+ deleter.call(carrier, name);
7239
+ } catch {
7240
+ }
7241
+ }
7242
+ const remover = carrier.removeHeader;
7243
+ if (typeof remover === "function") {
7244
+ try {
7245
+ remover.call(carrier, name);
7246
+ } catch {
7247
+ }
7248
+ }
7249
+ headerSetter.call(carrier, name, value);
7250
+ return;
7251
+ }
7252
+ const headerBag = carrier;
7253
+ const lowered = name.toLowerCase();
7254
+ for (const key of Object.keys(headerBag)) {
7255
+ if (key !== name && key.toLowerCase() === lowered) {
7256
+ delete headerBag[key];
7257
+ }
7258
+ }
7259
+ headerBag[name] = value;
7260
+ }
7261
+ function deleteHeader(carrier, name) {
7262
+ const lowered = name.toLowerCase();
7263
+ if (isMutableHeaderTupleArray(carrier)) {
7264
+ for (let i = carrier.length - 1; i >= 0; i--) {
7265
+ if (carrier[i][0].toLowerCase() === lowered) {
7266
+ carrier.splice(i, 1);
7267
+ }
7268
+ }
7269
+ return;
7270
+ }
7271
+ const deleter = carrier.delete;
7272
+ if (typeof deleter === "function") {
7273
+ try {
7274
+ deleter.call(carrier, name);
7275
+ return;
7276
+ } catch {
7277
+ }
7278
+ }
7279
+ const remover = carrier.removeHeader;
7280
+ if (typeof remover === "function") {
7281
+ try {
7282
+ remover.call(carrier, name);
7283
+ return;
7284
+ } catch {
7285
+ }
7286
+ }
7287
+ const headerBag = carrier;
7288
+ for (const key of Object.keys(headerBag)) {
7289
+ if (key.toLowerCase() === lowered) {
7290
+ delete headerBag[key];
7291
+ }
7292
+ }
7293
+ }
7294
+ function _injectIntoCarrier(carrier, args) {
7295
+ const traceFlags = args.propagatedState?.traceFlags;
7296
+ const traceparent = traceFlags ? formatTraceparent(args.traceId, args.spanId, traceFlags) : formatTraceparent(args.traceId, args.spanId);
7297
+ if (traceparent === void 0) {
7298
+ return;
7299
+ }
7300
+ setHeader(carrier, TRACEPARENT_HEADER, traceparent);
7301
+ const tracestate = args.propagatedState?.tracestate;
7302
+ if (tracestate) {
7303
+ setHeader(carrier, TRACESTATE_HEADER, tracestate);
7304
+ }
7305
+ const existing = getHeader(carrier, BAGGAGE_HEADER);
7306
+ const baggageValue = mergeBaggage(existing, args.braintrustParent);
7307
+ if (baggageValue !== void 0) {
7308
+ setHeader(carrier, BAGGAGE_HEADER, baggageValue);
7309
+ } else if (existing !== void 0) {
7310
+ deleteHeader(carrier, BAGGAGE_HEADER);
7311
+ }
7312
+ }
7313
+ function resolveW3cParent(context, state) {
7314
+ const traceparent = getHeader(context, TRACEPARENT_HEADER);
7315
+ const parsed = traceparent ? parseTraceparent(traceparent) : void 0;
7316
+ if (parsed === void 0) {
7317
+ return { parentSlug: void 0, propagatedState: void 0 };
7318
+ }
7319
+ const { traceId, spanId, traceFlags } = parsed;
7320
+ let braintrustParent = void 0;
7321
+ const baggageValue = getHeader(context, BAGGAGE_HEADER);
7322
+ if (baggageValue) {
7323
+ braintrustParent = parseBaggage(baggageValue)[BRAINTRUST_PARENT_KEY];
7324
+ }
7325
+ if (!braintrustParent) {
7326
+ braintrustParent = currentBraintrustParent(state);
7327
+ }
7328
+ if (!braintrustParent) {
7329
+ debugLogger.warn(
7330
+ "Received traceparent without a braintrust.parent and no active logger/experiment; cannot route the trace. Starting a fresh local span instead."
7331
+ );
7332
+ return { parentSlug: void 0, propagatedState: void 0 };
7333
+ }
7334
+ const parsedParent = braintrustParentToComponents(braintrustParent);
7335
+ if (parsedParent === void 0) {
7336
+ debugLogger.warn(
7337
+ `Invalid braintrust.parent: ${JSON.stringify(braintrustParent)}`
7338
+ );
7339
+ return { parentSlug: void 0, propagatedState: void 0 };
7340
+ }
7341
+ const { objectType, objectId, computeArgs } = parsedParent;
7342
+ const tracestate = getHeader(context, TRACESTATE_HEADER);
7343
+ const slug = new SpanComponentsV4({
7344
+ object_type: objectType,
7345
+ ...computeArgs ? { compute_object_metadata_args: computeArgs } : { object_id: objectId },
7346
+ row_id: "bt-propagation",
7347
+ // non-empty to enable span_id/root_span_id
7348
+ span_id: spanId,
7349
+ root_span_id: traceId
7350
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
7351
+ }).toStr();
7352
+ return {
7353
+ parentSlug: slug,
7354
+ propagatedState: { tracestate, traceFlags, braintrustParent }
7355
+ };
7356
+ }
7357
+ function normalizeParent(parent, state) {
7358
+ if (parent && typeof parent === "object") {
7359
+ return resolveW3cParent(parent, state);
7360
+ }
7361
+ return {
7362
+ parentSlug: parent ?? void 0,
7363
+ propagatedState: void 0
7364
+ };
7365
+ }
7366
+ function parentSpanIdsUsable(spanId, rootSpanId) {
7367
+ return Boolean(spanId) && Boolean(rootSpanId);
7368
+ }
7369
+ function logError(span, error) {
7370
+ let errorMessage = "<error>";
7371
+ let stackTrace = "";
7372
+ if (error instanceof Error) {
7373
+ errorMessage = error.message;
7374
+ stackTrace = error.stack || "";
7375
+ } else {
7376
+ errorMessage = String(error);
7377
+ }
7378
+ span.log({ error: `${errorMessage}
7379
+
7380
+ ${stackTrace}` });
7381
+ }
7382
+ function startSpan(args) {
7383
+ return startSpanAndIsLogger(args).span;
7384
+ }
7385
+ async function flush(options) {
7386
+ const state = options?.state ?? _globalState;
7387
+ return await state.bgLogger().flush();
7388
+ }
7389
+ function startSpanAndIsLogger(args) {
7390
+ const state = args?.state ?? _globalState;
7391
+ const { parentObject, propagatedState } = getSpanParentObjectAndPropagatedState({
7392
+ asyncFlush: args?.asyncFlush,
7393
+ parent: args?.parent,
7394
+ state
7395
+ });
7396
+ if (parentObject instanceof SpanComponentsV3 || parentObject instanceof SpanComponentsV4) {
7397
+ const parentSpanIds = parentObject.data.row_id && parentSpanIdsUsable(
7398
+ parentObject.data.span_id,
7399
+ parentObject.data.root_span_id
7400
+ ) ? {
7401
+ spanId: parentObject.data.span_id,
7402
+ rootSpanId: parentObject.data.root_span_id
7403
+ } : void 0;
7404
+ const { parent: _ignoredParent, ...spanArgs } = args ?? {};
7405
+ const span = new SpanImpl({
7406
+ state,
7407
+ ...spanArgs,
7408
+ parentObjectType: parentObject.data.object_type,
7409
+ parentObjectId: new LazyValue(
7410
+ spanComponentsToObjectIdLambda(state, parentObject)
7411
+ ),
7412
+ parentComputeObjectMetadataArgs: parentObject.data.compute_object_metadata_args ?? void 0,
7413
+ parentSpanIds,
7414
+ propagatedEvent: args?.propagatedEvent ?? // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
7415
+ (parentObject.data.propagated_event ?? void 0),
7416
+ propagatedState
7417
+ });
7418
+ return {
7419
+ span,
7420
+ isSyncFlushLogger: parentObject.data.object_type === 2 /* PROJECT_LOGS */ && // Since there's no parent logger here, we're free to choose the async flush
7421
+ // behavior, and therefore propagate along whatever we get from the arguments
7422
+ args?.asyncFlush === false
7423
+ };
7424
+ } else {
7425
+ const span = parentObject.startSpan(args);
7426
+ return {
7427
+ span,
7428
+ isSyncFlushLogger: parentObject.kind === "logger" && parentObject.asyncFlush === false
7429
+ };
7430
+ }
7431
+ }
7432
+ function withCurrent(span, callback, state = void 0) {
7433
+ const currentState = state ?? _globalState;
7434
+ return currentState.contextManager.runInContext(span, () => callback(span));
7435
+ }
7436
+ function _saveOrgInfo(state, org_info, org_name) {
7437
+ if (org_info.length === 0) {
7438
+ throw new LoginInvalidOrgError(
7439
+ "This user is not part of any organizations."
7440
+ );
7441
+ }
7442
+ for (const org of org_info) {
7443
+ if (org_name === void 0 || org.name === org_name) {
7444
+ state.orgId = org.id;
7445
+ state.orgName = org.name;
7446
+ state.apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
7447
+ state.proxyUrl = isomorph_default.getEnv("BRAINTRUST_PROXY_URL") ?? org.proxy_url;
7448
+ state.gitMetadataSettings = org.git_metadata || void 0;
7449
+ break;
6813
7450
  }
6814
7451
  }
6815
7452
  if (state.orgId === void 0) {
@@ -7003,11 +7640,12 @@ function validateAndSanitizeExperimentLogFullArgs(event, hasDataset) {
7003
7640
  var DEFAULT_FETCH_BATCH_SIZE = 1e3;
7004
7641
  var MAX_BTQL_ITERATIONS = 1e4;
7005
7642
  var ObjectFetcher = class {
7006
- constructor(objectType, pinnedVersion, mutateRecord, _internal_btql) {
7643
+ constructor(objectType, pinnedVersion, mutateRecord, _internal_btql, _internalBrainstoreRealtime = true) {
7007
7644
  this.objectType = objectType;
7008
7645
  this.pinnedVersion = pinnedVersion;
7009
7646
  this.mutateRecord = mutateRecord;
7010
7647
  this._internal_btql = _internal_btql;
7648
+ this._internalBrainstoreRealtime = _internalBrainstoreRealtime;
7011
7649
  }
7012
7650
  _fetchedData = void 0;
7013
7651
  get id() {
@@ -7066,7 +7704,7 @@ var ObjectFetcher = class {
7066
7704
  ...internalBtqlWithoutReservedQueryKeys
7067
7705
  },
7068
7706
  use_columnstore: false,
7069
- brainstore_realtime: true,
7707
+ brainstore_realtime: this._internalBrainstoreRealtime,
7070
7708
  query_source: `js_sdk_object_fetcher_${this.objectType}`,
7071
7709
  ...this.pinnedVersion !== void 0 ? {
7072
7710
  version: this.pinnedVersion
@@ -7415,6 +8053,15 @@ View complete results in Braintrust or run experiment.summarize() again.`
7415
8053
  object_id: await this.id
7416
8054
  }).toStr();
7417
8055
  }
8056
+ /**
8057
+ * Return this experiment's Braintrust parent string (`experiment_id:<id>`) for
8058
+ * the `braintrust.parent` baggage entry, or undefined when it cannot be
8059
+ * determined synchronously.
8060
+ */
8061
+ _getOtelParent() {
8062
+ const id = this.lazyId.getSync().value;
8063
+ return id ? `experiment_id:${id}` : void 0;
8064
+ }
7418
8065
  /**
7419
8066
  * Flush any pending rows to the server.
7420
8067
  */
@@ -7479,9 +8126,16 @@ var SpanImpl = class _SpanImpl {
7479
8126
  _spanId;
7480
8127
  _rootSpanId;
7481
8128
  _spanParents;
8129
+ // Inbound W3C trace-context state (tracestate + raw traceparent flags) to
8130
+ // forward on outbound propagation. Captured at the span that received it (via
8131
+ // extractTraceContextFromHeaders) and inherited by all subspans, so that any
8132
+ // inject() within the trace re-emits the upstream state unchanged, per the W3C
8133
+ // Trace Context spec. Not interpreted.
8134
+ _propagatedState;
7482
8135
  kind = "span";
7483
8136
  constructor(args) {
7484
8137
  this._state = args.state;
8138
+ this._propagatedState = args.propagatedState;
7485
8139
  const spanAttributes = args.spanAttributes ?? {};
7486
8140
  const rawEvent = args.event ?? {};
7487
8141
  const type = args.type ?? (args.parentSpanIds ? void 0 : args.defaultRootType);
@@ -7597,7 +8251,7 @@ var SpanImpl = class _SpanImpl {
7597
8251
  tags: partialRecord.tags,
7598
8252
  span_id: this._spanId,
7599
8253
  span_parents: this._spanParents,
7600
- is_root: this._spanId === this._rootSpanId,
8254
+ is_root: !this._spanParents || this._spanParents.length === 0,
7601
8255
  span_attributes: partialRecord.span_attributes
7602
8256
  };
7603
8257
  this._state.spanCache.queueWrite(
@@ -7659,7 +8313,8 @@ var SpanImpl = class _SpanImpl {
7659
8313
  parentObjectId: this.parentObjectId,
7660
8314
  parentComputeObjectMetadataArgs: this.parentComputeObjectMetadataArgs,
7661
8315
  parentSpanIds,
7662
- propagatedEvent: args?.propagatedEvent ?? this.propagatedEvent
8316
+ propagatedEvent: args?.propagatedEvent ?? this.propagatedEvent,
8317
+ propagatedState: this._propagatedState
7663
8318
  })
7664
8319
  });
7665
8320
  }
@@ -7678,7 +8333,8 @@ var SpanImpl = class _SpanImpl {
7678
8333
  parentObjectId: this.parentObjectId,
7679
8334
  parentComputeObjectMetadataArgs: this.parentComputeObjectMetadataArgs,
7680
8335
  parentSpanIds,
7681
- propagatedEvent: args?.propagatedEvent ?? this.propagatedEvent
8336
+ propagatedEvent: args?.propagatedEvent ?? this.propagatedEvent,
8337
+ propagatedState: this._propagatedState
7682
8338
  }),
7683
8339
  spanId
7684
8340
  });
@@ -7706,6 +8362,42 @@ var SpanImpl = class _SpanImpl {
7706
8362
  propagated_event: this.propagatedEvent
7707
8363
  }).toStr();
7708
8364
  }
8365
+ /**
8366
+ * Return this span's Braintrust parent string (`project_id:<id>`,
8367
+ * `project_name:<name>`, or `experiment_id:<id>`) for the `braintrust.parent`
8368
+ * baggage entry, or undefined when it cannot be determined synchronously.
8369
+ */
8370
+ _getOtelParent() {
8371
+ if (this.parentObjectType === 2 /* PROJECT_LOGS */) {
8372
+ const id = this.parentComputeObjectMetadataArgs?.project_id || this.parentObjectId.getSync().value;
8373
+ const name = this.parentComputeObjectMetadataArgs?.project_name;
8374
+ if (id) {
8375
+ return `project_id:${id}`;
8376
+ } else if (name) {
8377
+ return `project_name:${name}`;
8378
+ }
8379
+ } else if (this.parentObjectType === 1 /* EXPERIMENT */) {
8380
+ const id = this.parentComputeObjectMetadataArgs?.experiment_id || this.parentObjectId.getSync().value;
8381
+ if (id) {
8382
+ return `experiment_id:${id}`;
8383
+ }
8384
+ }
8385
+ return void 0;
8386
+ }
8387
+ inject(carrier) {
8388
+ const resolvedCarrier = carrier ?? {};
8389
+ try {
8390
+ _injectIntoCarrier(resolvedCarrier, {
8391
+ traceId: this._rootSpanId,
8392
+ spanId: this._spanId,
8393
+ braintrustParent: this._getOtelParent() ?? this._propagatedState?.braintrustParent,
8394
+ propagatedState: this._propagatedState
8395
+ });
8396
+ } catch (e) {
8397
+ debugLogger.warn(`Error injecting trace context: ${e}`);
8398
+ }
8399
+ return resolvedCarrier;
8400
+ }
7709
8401
  async permalink() {
7710
8402
  return await permalink(await this.export(), {
7711
8403
  state: this._state
@@ -7841,6 +8533,7 @@ var Dataset2 = class extends ObjectFetcher {
7841
8533
  _internal_btql
7842
8534
  );
7843
8535
  this.state = state;
8536
+ void this.__braintrust_dataset_marker;
7844
8537
  this.lazyMetadata = lazyMetadata;
7845
8538
  this.lazyPinnedVersion = pinState?.lazyPinnedVersion;
7846
8539
  this.pinnedEnvironment = pinState?.pinnedEnvironment;
@@ -8807,6 +9500,22 @@ function runStreamingCompletionHook(args) {
8807
9500
  );
8808
9501
  }
8809
9502
  }
9503
+ function runStreamingErrorHook(args) {
9504
+ if (!args.config.onError) {
9505
+ return;
9506
+ }
9507
+ try {
9508
+ args.config.onError({
9509
+ channelName: args.channelName,
9510
+ error: args.error,
9511
+ event: args.event,
9512
+ span: args.span,
9513
+ startTime: args.startTime
9514
+ });
9515
+ } catch (error) {
9516
+ debugLogger.error(`Error in onError hook for ${args.channelName}:`, error);
9517
+ }
9518
+ }
8810
9519
  function traceAsyncChannel(channel2, config) {
8811
9520
  const tracingChannel = channel2.tracingChannel();
8812
9521
  const states = /* @__PURE__ */ new WeakMap();
@@ -8968,6 +9677,14 @@ function traceStreamingChannel(channel2, config) {
8968
9677
  }
8969
9678
  },
8970
9679
  onError: (error) => {
9680
+ runStreamingErrorHook({
9681
+ channelName,
9682
+ config,
9683
+ error,
9684
+ event: asyncEndEvent,
9685
+ span,
9686
+ startTime
9687
+ });
8971
9688
  span.log({
8972
9689
  error: error.message
8973
9690
  });
@@ -9025,6 +9742,17 @@ function traceStreamingChannel(channel2, config) {
9025
9742
  }
9026
9743
  },
9027
9744
  error: (event) => {
9745
+ const spanData = states.get(event);
9746
+ if (spanData) {
9747
+ runStreamingErrorHook({
9748
+ channelName,
9749
+ config,
9750
+ error: event.error,
9751
+ event,
9752
+ span: spanData.span,
9753
+ startTime: spanData.startTime
9754
+ });
9755
+ }
9028
9756
  logErrorAndEnd(states, event);
9029
9757
  }
9030
9758
  };
@@ -11387,14 +12115,45 @@ function serializeAISDKToolsForLogging(tools) {
11387
12115
  return serialized;
11388
12116
  }
11389
12117
 
12118
+ // src/vendor-sdk-types/ai-sdk-v7-telemetry.ts
12119
+ var BRAINTRUST_AI_SDK_V7_OPERATION_KEY = /* @__PURE__ */ Symbol.for(
12120
+ "braintrust.ai-sdk.v7.telemetry-operation-key"
12121
+ );
12122
+
12123
+ // src/wrappers/ai-sdk/workflow-agent-context.ts
12124
+ var workflowAgentWrapperSpans = /* @__PURE__ */ new Map();
12125
+ function registerWorkflowAgentWrapperSpan(span) {
12126
+ if (span.spanId) {
12127
+ workflowAgentWrapperSpans.set(span.spanId, span);
12128
+ }
12129
+ }
12130
+ function unregisterWorkflowAgentWrapperSpan(span) {
12131
+ if (span.spanId) {
12132
+ workflowAgentWrapperSpans.delete(span.spanId);
12133
+ }
12134
+ }
12135
+ function currentWorkflowAgentWrapperSpan() {
12136
+ const parentSpanIds = _internalGetGlobalState().contextManager.getParentSpanIds()?.spanParents ?? [];
12137
+ for (const parentSpanId of parentSpanIds) {
12138
+ const span = workflowAgentWrapperSpans.get(parentSpanId);
12139
+ if (span) {
12140
+ return span;
12141
+ }
12142
+ }
12143
+ return void 0;
12144
+ }
12145
+
11390
12146
  // src/wrappers/ai-sdk/telemetry.ts
11391
12147
  function braintrustAISDKTelemetry() {
11392
12148
  const operations = /* @__PURE__ */ new Map();
12149
+ const operationKeysByCallId = /* @__PURE__ */ new Map();
12150
+ const workflowOperationKeyStore = isomorph_default.newAsyncLocalStorage();
11393
12151
  const modelSpans = /* @__PURE__ */ new Map();
11394
12152
  const objectSpans = /* @__PURE__ */ new Map();
11395
12153
  const embedSpans = /* @__PURE__ */ new Map();
11396
12154
  const rerankSpans = /* @__PURE__ */ new Map();
11397
12155
  const toolSpans = /* @__PURE__ */ new Map();
12156
+ let workflowAgentOperationCounter = 0;
11398
12157
  const runSafely = (name, callback) => {
11399
12158
  try {
11400
12159
  callback();
@@ -11402,139 +12161,413 @@ function braintrustAISDKTelemetry() {
11402
12161
  console.error(`Error in Braintrust AI SDK telemetry ${name}:`, error);
11403
12162
  }
11404
12163
  };
11405
- const startChildSpan = (callId, name, type, event) => {
11406
- const parent = operations.get(callId)?.span;
12164
+ const startChildSpan = (operationKey, name, type, event) => {
12165
+ const parent = operations.get(operationKey)?.span;
11407
12166
  const spanArgs = {
11408
12167
  name,
11409
12168
  spanAttributes: { type },
11410
12169
  ...event ? { event } : {}
11411
12170
  };
11412
12171
  const span = parent ? parent.startSpan(spanArgs) : startSpan(spanArgs);
11413
- const state = operations.get(callId);
12172
+ const state = operations.get(operationKey);
11414
12173
  if (state && type === "llm" /* LLM */) {
11415
12174
  state.hadModelChild = true;
11416
12175
  }
11417
12176
  return span;
11418
12177
  };
11419
- return {
11420
- onStart(event) {
11421
- runSafely("onStart", () => {
11422
- const operationName = operationNameFromId(event.operationId);
11423
- const span = startSpan({
11424
- name: operationName,
11425
- spanAttributes: { type: "function" /* FUNCTION */ }
11426
- });
11427
- operations.set(event.callId, {
11428
- hadModelChild: false,
11429
- operationName,
11430
- span,
11431
- startTime: getCurrentUnixTimestamp()
11432
- });
11433
- const metadata = metadataFromEvent(event);
11434
- const logPayload = { metadata };
11435
- if (shouldRecordInputs(event)) {
11436
- const { input, outputPromise } = processAISDKCallInput(
11437
- operationInput(event, operationName)
11438
- );
11439
- logPayload.input = input;
11440
- if (outputPromise && input && typeof input === "object") {
11441
- outputPromise.then((resolvedData) => {
11442
- span.log({
11443
- input: {
11444
- ...input,
11445
- ...resolvedData
11446
- }
11447
- });
11448
- }).catch(() => {
11449
- });
11450
- }
12178
+ const registerOperation = (state) => {
12179
+ operations.set(state.operationKey, state);
12180
+ const keys = operationKeysByCallId.get(state.callId) ?? [];
12181
+ keys.push(state.operationKey);
12182
+ operationKeysByCallId.set(state.callId, keys);
12183
+ };
12184
+ const deleteOperation = (operationKey) => {
12185
+ const state = operations.get(operationKey);
12186
+ if (!state) {
12187
+ return;
12188
+ }
12189
+ operations.delete(operationKey);
12190
+ if (workflowOperationKeyStore.getStore() === operationKey) {
12191
+ workflowOperationKeyStore.enterWith(void 0);
12192
+ }
12193
+ const keys = operationKeysByCallId.get(state.callId);
12194
+ if (!keys) {
12195
+ return;
12196
+ }
12197
+ const index = keys.indexOf(operationKey);
12198
+ if (index >= 0) {
12199
+ keys.splice(index, 1);
12200
+ }
12201
+ if (keys.length === 0) {
12202
+ operationKeysByCallId.delete(state.callId);
12203
+ }
12204
+ };
12205
+ const explicitOperationKey = (event) => {
12206
+ if (!isObject(event)) {
12207
+ return void 0;
12208
+ }
12209
+ const key = event[BRAINTRUST_AI_SDK_V7_OPERATION_KEY];
12210
+ return typeof key === "string" ? key : void 0;
12211
+ };
12212
+ const createOperationKey = (event, operationName) => {
12213
+ const explicit = explicitOperationKey(event);
12214
+ if (explicit) {
12215
+ return explicit;
12216
+ }
12217
+ if (operationName === "WorkflowAgent.stream") {
12218
+ workflowAgentOperationCounter += 1;
12219
+ return `${event.callId}:${workflowAgentOperationCounter}`;
12220
+ }
12221
+ return event.callId;
12222
+ };
12223
+ const operationKeyForCallId = (callId, mode = "active") => {
12224
+ const keys = operationKeysByCallId.get(callId);
12225
+ if (!keys || keys.length === 0) {
12226
+ return operations.has(callId) ? callId : void 0;
12227
+ }
12228
+ if (keys.length === 1) {
12229
+ return keys[0];
12230
+ }
12231
+ const wrapperSpan = currentWorkflowAgentWrapperSpan();
12232
+ if (wrapperSpan?.spanId) {
12233
+ const key = keys.find(
12234
+ (candidate) => operations.get(candidate)?.span.spanId === wrapperSpan.spanId
12235
+ );
12236
+ if (key) {
12237
+ return key;
12238
+ }
12239
+ }
12240
+ const workflowOperationKey = workflowOperationKeyStore.getStore();
12241
+ if (workflowOperationKey && keys.includes(workflowOperationKey)) {
12242
+ return workflowOperationKey;
12243
+ }
12244
+ if (callId === "workflow-agent") {
12245
+ return void 0;
12246
+ }
12247
+ return mode === "finish" ? keys[0] : keys[keys.length - 1];
12248
+ };
12249
+ const operationKeyFromEvent = (event, mode = "active") => {
12250
+ const explicit = explicitOperationKey(event);
12251
+ if (explicit && operations.has(explicit)) {
12252
+ return explicit;
12253
+ }
12254
+ if (isObject(event)) {
12255
+ const callId = event.callId;
12256
+ if (typeof callId === "string") {
12257
+ const operationKey = operationKeyForCallId(callId, mode);
12258
+ if (operationKey) {
12259
+ return operationKey;
11451
12260
  }
11452
- span.log(logPayload);
11453
- });
11454
- },
11455
- onLanguageModelCallStart(event) {
11456
- runSafely("onLanguageModelCallStart", () => {
11457
- const state = operations.get(event.callId);
11458
- const openSpans = modelSpans.get(event.callId);
11459
- if (openSpans) {
11460
- for (const span2 of openSpans) {
11461
- span2.end();
11462
- }
11463
- modelSpans.delete(event.callId);
12261
+ const workflowOperationKey2 = workflowOperationKeyStore.getStore();
12262
+ if (workflowOperationKey2 && operations.has(workflowOperationKey2)) {
12263
+ return workflowOperationKey2;
11464
12264
  }
11465
- const span = startChildSpan(
11466
- event.callId,
11467
- state?.operationName === "streamText" ? "doStream" : "doGenerate",
11468
- "llm" /* LLM */,
11469
- {
11470
- ...shouldRecordInputs(event) ? {
11471
- input: processAISDKCallInput(
11472
- operationInput(
11473
- event,
11474
- state?.operationName ?? "generateText"
11475
- )
11476
- ).input
11477
- } : {},
11478
- metadata: metadataFromEvent(event)
11479
- }
11480
- );
11481
- const spans = modelSpans.get(event.callId) ?? [];
11482
- spans.push(span);
11483
- modelSpans.set(event.callId, spans);
11484
- });
11485
- },
11486
- onLanguageModelCallEnd(event) {
11487
- runSafely("onLanguageModelCallEnd", () => {
11488
- const span = shiftModelSpan(modelSpans, event.callId);
11489
- if (!span) {
11490
- return;
12265
+ return callId === "workflow-agent" ? void 0 : callId;
12266
+ }
12267
+ }
12268
+ const workflowOperationKey = workflowOperationKeyStore.getStore();
12269
+ if (workflowOperationKey && operations.has(workflowOperationKey)) {
12270
+ return workflowOperationKey;
12271
+ }
12272
+ const wrapperSpan = currentWorkflowAgentWrapperSpan();
12273
+ if (wrapperSpan?.spanId) {
12274
+ for (const [operationKey, state] of operations) {
12275
+ if (state.operationName === "WorkflowAgent.stream" && state.span.spanId === wrapperSpan.spanId) {
12276
+ return operationKey;
12277
+ }
12278
+ }
12279
+ }
12280
+ const workflowAgentKeys = operationKeysByCallId.get("workflow-agent");
12281
+ if (workflowAgentKeys?.length === 1) {
12282
+ return workflowAgentKeys[0];
12283
+ }
12284
+ if (operations.size === 1) {
12285
+ return operations.keys().next().value;
12286
+ }
12287
+ return void 0;
12288
+ };
12289
+ const closeOpenChildSpans = (operationKey, error) => {
12290
+ const openModelSpans = modelSpans.get(operationKey);
12291
+ if (openModelSpans) {
12292
+ for (const span of openModelSpans) {
12293
+ if (error !== void 0) {
12294
+ logError(span, error);
11491
12295
  }
11492
- const result = {
11493
- ...event,
11494
- response: event.responseId ? { id: event.responseId } : void 0
11495
- };
11496
- span.log({
11497
- ...shouldRecordOutputs(event) ? {
11498
- output: processAISDKOutput(result, DEFAULT_DENY_OUTPUT_PATHS)
11499
- } : {},
11500
- metrics: extractTokenMetrics(result)
11501
- });
11502
12296
  span.end();
12297
+ }
12298
+ modelSpans.delete(operationKey);
12299
+ }
12300
+ const openObjectSpan = objectSpans.get(operationKey);
12301
+ if (openObjectSpan) {
12302
+ if (error !== void 0) {
12303
+ logError(openObjectSpan, error);
12304
+ }
12305
+ openObjectSpan.end();
12306
+ objectSpans.delete(operationKey);
12307
+ }
12308
+ for (const [embedCallId, embedState] of embedSpans) {
12309
+ if (embedState.operationKey === operationKey) {
12310
+ if (error !== void 0) {
12311
+ logError(embedState.span, error);
12312
+ }
12313
+ embedState.span.end();
12314
+ embedSpans.delete(embedCallId);
12315
+ }
12316
+ }
12317
+ const openRerankSpan = rerankSpans.get(operationKey);
12318
+ if (openRerankSpan) {
12319
+ if (error !== void 0) {
12320
+ logError(openRerankSpan, error);
12321
+ }
12322
+ openRerankSpan.end();
12323
+ rerankSpans.delete(operationKey);
12324
+ }
12325
+ for (const [toolCallId, toolState] of toolSpans) {
12326
+ if (toolState.operationKey === operationKey) {
12327
+ if (error !== void 0) {
12328
+ logError(toolState.span, error);
12329
+ }
12330
+ toolState.span.end();
12331
+ toolSpans.delete(toolCallId);
12332
+ }
12333
+ }
12334
+ };
12335
+ const abortReasonFromEvent = (event) => {
12336
+ if (isObject(event)) {
12337
+ const abortEvent = event;
12338
+ if (abortEvent.error !== void 0) {
12339
+ return abortEvent.error;
12340
+ }
12341
+ if (abortEvent.reason !== void 0) {
12342
+ return abortEvent.reason;
12343
+ }
12344
+ }
12345
+ return new Error("AI SDK operation aborted");
12346
+ };
12347
+ const shouldSkipTelemetryChildren = (state) => state?.operationName === "WorkflowAgent.stream" && !state.ownsSpan;
12348
+ const onObjectStepEnd = (event) => {
12349
+ runSafely("onObjectStepEnd", () => {
12350
+ const operationKey = operationKeyFromEvent(event);
12351
+ const span = operationKey ? objectSpans.get(operationKey) : void 0;
12352
+ if (!operationKey || !span) {
12353
+ return;
12354
+ }
12355
+ const result = {
12356
+ ...event,
12357
+ text: event.objectText
12358
+ };
12359
+ span.log({
12360
+ ...shouldRecordOutputs(event) ? {
12361
+ output: processAISDKOutput(result, DEFAULT_DENY_OUTPUT_PATHS)
12362
+ } : {},
12363
+ metrics: extractTokenMetrics(result)
12364
+ });
12365
+ span.end();
12366
+ objectSpans.delete(operationKey);
12367
+ });
12368
+ };
12369
+ const onEmbedEnd = (event) => {
12370
+ runSafely("onEmbedEnd", () => {
12371
+ const state = embedSpans.get(event.embedCallId);
12372
+ if (!state) {
12373
+ return;
12374
+ }
12375
+ const result = {
12376
+ ...event,
12377
+ embeddings: event.embeddings
12378
+ };
12379
+ state.span.log({
12380
+ ...shouldRecordOutputs(event) ? {
12381
+ output: processAISDKEmbeddingOutput(
12382
+ result,
12383
+ DEFAULT_DENY_OUTPUT_PATHS
12384
+ )
12385
+ } : {},
12386
+ metrics: extractTokenMetrics(result)
12387
+ });
12388
+ state.span.end();
12389
+ embedSpans.delete(event.embedCallId);
12390
+ });
12391
+ };
12392
+ const onRerankEnd = (event) => {
12393
+ runSafely("onRerankEnd", () => {
12394
+ const operationKey = operationKeyFromEvent(event);
12395
+ const span = operationKey ? rerankSpans.get(operationKey) : void 0;
12396
+ if (!operationKey || !span) {
12397
+ return;
12398
+ }
12399
+ const result = {
12400
+ ranking: event.ranking?.map((entry) => ({
12401
+ originalIndex: entry.index,
12402
+ score: entry.relevanceScore
12403
+ }))
12404
+ };
12405
+ span.log({
12406
+ ...shouldRecordOutputs(event) ? {
12407
+ output: processAISDKRerankOutput(
12408
+ result,
12409
+ DEFAULT_DENY_OUTPUT_PATHS
12410
+ )
12411
+ } : {}
12412
+ });
12413
+ span.end();
12414
+ rerankSpans.delete(operationKey);
12415
+ });
12416
+ };
12417
+ const onEnd = (event) => {
12418
+ runSafely("onEnd", () => {
12419
+ const operationKey = operationKeyFromEvent(event, "finish");
12420
+ const state = operationKey ? operations.get(operationKey) : void 0;
12421
+ if (!state) {
12422
+ return;
12423
+ }
12424
+ if (!state.ownsSpan) {
12425
+ deleteOperation(state.operationKey);
12426
+ return;
12427
+ }
12428
+ const result = finishResult(event, state.operationName);
12429
+ const metrics = state.hadModelChild ? {} : extractTokenMetrics(result);
12430
+ const timeToFirstToken = state.operationName === "WorkflowAgent.stream" ? void 0 : extractTimeToFirstToken(result, state);
12431
+ if (timeToFirstToken !== void 0) {
12432
+ metrics.time_to_first_token = timeToFirstToken;
12433
+ }
12434
+ state.span.log({
12435
+ ...shouldRecordOutputs(event) ? {
12436
+ output: finishOutput(result, state.operationName)
12437
+ } : {},
12438
+ metrics
12439
+ });
12440
+ state.span.end();
12441
+ deleteOperation(state.operationKey);
12442
+ });
12443
+ };
12444
+ return {
12445
+ onStart(event) {
12446
+ runSafely("onStart", () => {
12447
+ const operationName = operationNameFromId(event.operationId);
12448
+ const workflowAgent = operationName === "WorkflowAgent.stream";
12449
+ const wrapperSpan = workflowAgent ? currentWorkflowAgentWrapperSpan() : void 0;
12450
+ const ownsSpan = !wrapperSpan;
12451
+ const span = ownsSpan ? startSpan({
12452
+ name: operationName,
12453
+ spanAttributes: { type: "function" /* FUNCTION */ }
12454
+ }) : wrapperSpan;
12455
+ const operationKey = createOperationKey(event, operationName);
12456
+ registerOperation({
12457
+ callId: event.callId,
12458
+ hadModelChild: false,
12459
+ loggedInput: false,
12460
+ operationName,
12461
+ operationKey,
12462
+ ownsSpan,
12463
+ span,
12464
+ startTime: getCurrentUnixTimestamp()
12465
+ });
12466
+ if (!ownsSpan) {
12467
+ return;
12468
+ }
12469
+ if (workflowAgent) {
12470
+ workflowOperationKeyStore.enterWith(operationKey);
12471
+ }
12472
+ let metadata = metadataFromEvent(event);
12473
+ const logPayload = { metadata };
12474
+ const workflowAgentCallInput = workflowAgent ? operationInput(event, operationName) : void 0;
12475
+ if (workflowAgentCallInput) {
12476
+ metadata = {
12477
+ ...metadata,
12478
+ ...extractWorkflowMetadataFromCallParams(workflowAgentCallInput)
12479
+ };
12480
+ logPayload.metadata = metadata;
12481
+ }
12482
+ if (shouldRecordInputs(event)) {
12483
+ const callInput = workflowAgentCallInput ?? operationInput(event, operationName);
12484
+ const { input, outputPromise } = workflowAgent ? processAISDKWorkflowAgentCallInput(callInput) : processAISDKCallInput(callInput);
12485
+ logPayload.input = input;
12486
+ const state = operations.get(operationKey);
12487
+ if (state) {
12488
+ state.loggedInput = hasPromptLikeInput(input);
12489
+ }
12490
+ if (outputPromise && !workflowAgent && input && typeof input === "object") {
12491
+ outputPromise.then((resolvedData) => {
12492
+ span.log({
12493
+ input: {
12494
+ ...input,
12495
+ ...resolvedData
12496
+ }
12497
+ });
12498
+ }).catch(() => {
12499
+ });
12500
+ }
12501
+ }
12502
+ span.log(logPayload);
11503
12503
  });
11504
12504
  },
11505
- onObjectStepStart(event) {
11506
- runSafely("onObjectStepStart", () => {
11507
- const state = operations.get(event.callId);
11508
- const openSpan = objectSpans.get(event.callId);
11509
- if (openSpan) {
11510
- openSpan.end();
11511
- objectSpans.delete(event.callId);
12505
+ onLanguageModelCallStart(event) {
12506
+ runSafely("onLanguageModelCallStart", () => {
12507
+ const operationKey = operationKeyFromEvent(event);
12508
+ const state = operationKey ? operations.get(operationKey) : void 0;
12509
+ if (shouldSkipTelemetryChildren(state)) {
12510
+ return;
12511
+ }
12512
+ const operationName = state?.operationName ?? "generateText";
12513
+ const callInput = operationInput(event, operationName);
12514
+ const workflowAgent = operationName === "WorkflowAgent.stream";
12515
+ const processedInput = shouldRecordInputs(event) && workflowAgent ? processAISDKWorkflowAgentModelCallInput(callInput).input : shouldRecordInputs(event) ? processAISDKCallInput(callInput).input : void 0;
12516
+ if (workflowAgent && state?.ownsSpan && !state.loggedInput && hasPromptLikeInput(processedInput)) {
12517
+ state.span.log({
12518
+ input: processedInput,
12519
+ metadata: {
12520
+ ...metadataFromEvent(event),
12521
+ ...extractWorkflowMetadataFromCallParams(callInput)
12522
+ }
12523
+ });
12524
+ state.loggedInput = true;
12525
+ }
12526
+ const openSpans = operationKey ? modelSpans.get(operationKey) : void 0;
12527
+ if (operationKey && openSpans) {
12528
+ for (const span2 of openSpans) {
12529
+ span2.end();
12530
+ }
12531
+ modelSpans.delete(operationKey);
11512
12532
  }
11513
12533
  const span = startChildSpan(
11514
- event.callId,
11515
- state?.operationName === "streamObject" ? "doStream" : "doGenerate",
12534
+ operationKey ?? event.callId,
12535
+ operationName === "streamText" ? "doStream" : "doGenerate",
11516
12536
  "llm" /* LLM */,
11517
12537
  {
11518
12538
  ...shouldRecordInputs(event) ? {
11519
- input: {
11520
- prompt: event.promptMessages
11521
- }
12539
+ input: processedInput
11522
12540
  } : {},
11523
- metadata: metadataFromEvent(event)
12541
+ metadata: workflowAgent ? {
12542
+ ...metadataFromEvent(event),
12543
+ ...extractWorkflowMetadataFromCallParams(callInput)
12544
+ } : metadataFromEvent(event)
11524
12545
  }
11525
12546
  );
11526
- objectSpans.set(event.callId, span);
12547
+ const spanKey = operationKey ?? event.callId;
12548
+ const spans = modelSpans.get(spanKey) ?? [];
12549
+ spans.push(span);
12550
+ modelSpans.set(spanKey, spans);
11527
12551
  });
11528
12552
  },
11529
- onObjectStepFinish(event) {
11530
- runSafely("onObjectStepFinish", () => {
11531
- const span = objectSpans.get(event.callId);
12553
+ onLanguageModelCallEnd(event) {
12554
+ runSafely("onLanguageModelCallEnd", () => {
12555
+ const operationKey = operationKeyFromEvent(event);
12556
+ const state = operationKey ? operations.get(operationKey) : void 0;
12557
+ if (shouldSkipTelemetryChildren(state)) {
12558
+ return;
12559
+ }
12560
+ const span = operationKey ? shiftModelSpan(modelSpans, operationKey) : void 0;
11532
12561
  if (!span) {
11533
12562
  return;
11534
12563
  }
12564
+ const timeToFirstOutputMs = safePerformance(event)?.timeToFirstOutputMs;
12565
+ if (state?.operationName === "streamText" && state.firstChunkTime === void 0 && typeof timeToFirstOutputMs === "number") {
12566
+ state.firstChunkTime = state.startTime + timeToFirstOutputMs / 1e3;
12567
+ }
11535
12568
  const result = {
11536
12569
  ...event,
11537
- text: event.objectText
12570
+ response: event.responseId ? { id: event.responseId } : void 0
11538
12571
  };
11539
12572
  span.log({
11540
12573
  ...shouldRecordOutputs(event) ? {
@@ -11543,20 +12576,52 @@ function braintrustAISDKTelemetry() {
11543
12576
  metrics: extractTokenMetrics(result)
11544
12577
  });
11545
12578
  span.end();
11546
- objectSpans.delete(event.callId);
11547
12579
  });
11548
12580
  },
12581
+ onObjectStepStart(event) {
12582
+ runSafely("onObjectStepStart", () => {
12583
+ const operationKey = operationKeyFromEvent(event);
12584
+ const state = operationKey ? operations.get(operationKey) : void 0;
12585
+ if (shouldSkipTelemetryChildren(state)) {
12586
+ return;
12587
+ }
12588
+ const openSpan = operationKey ? objectSpans.get(operationKey) : void 0;
12589
+ if (operationKey && openSpan) {
12590
+ openSpan.end();
12591
+ objectSpans.delete(operationKey);
12592
+ }
12593
+ const span = startChildSpan(
12594
+ operationKey ?? event.callId,
12595
+ state?.operationName === "streamObject" ? "doStream" : "doGenerate",
12596
+ "llm" /* LLM */,
12597
+ {
12598
+ ...shouldRecordInputs(event) ? {
12599
+ input: {
12600
+ prompt: event.promptMessages
12601
+ }
12602
+ } : {},
12603
+ metadata: metadataFromEvent(event)
12604
+ }
12605
+ );
12606
+ objectSpans.set(operationKey ?? event.callId, span);
12607
+ });
12608
+ },
12609
+ onObjectStepEnd,
11549
12610
  onEmbedStart(event) {
11550
12611
  runSafely("onEmbedStart", () => {
11551
- const state = operations.get(event.callId);
12612
+ const operationKey = operationKeyFromEvent(event);
12613
+ const state = operationKey ? operations.get(operationKey) : void 0;
12614
+ if (shouldSkipTelemetryChildren(state)) {
12615
+ return;
12616
+ }
11552
12617
  for (const [embedCallId, embedState] of embedSpans) {
11553
- if (embedState.callId === event.callId && (state?.operationName === "embed" || embedState.values === event.values)) {
12618
+ if (embedState.operationKey === operationKey && (state?.operationName === "embed" || embedState.values === event.values)) {
11554
12619
  embedState.span.end();
11555
12620
  embedSpans.delete(embedCallId);
11556
12621
  }
11557
12622
  }
11558
12623
  const span = startChildSpan(
11559
- event.callId,
12624
+ operationKey ?? event.callId,
11560
12625
  "doEmbed",
11561
12626
  "llm" /* LLM */,
11562
12627
  {
@@ -11569,44 +12634,27 @@ function braintrustAISDKTelemetry() {
11569
12634
  }
11570
12635
  );
11571
12636
  embedSpans.set(event.embedCallId, {
11572
- callId: event.callId,
12637
+ operationKey: operationKey ?? event.callId,
11573
12638
  span,
11574
12639
  values: event.values
11575
12640
  });
11576
12641
  });
11577
12642
  },
11578
- onEmbedFinish(event) {
11579
- runSafely("onEmbedFinish", () => {
11580
- const state = embedSpans.get(event.embedCallId);
11581
- if (!state) {
11582
- return;
11583
- }
11584
- const result = {
11585
- ...event,
11586
- embeddings: event.embeddings
11587
- };
11588
- state.span.log({
11589
- ...shouldRecordOutputs(event) ? {
11590
- output: processAISDKEmbeddingOutput(
11591
- result,
11592
- DEFAULT_DENY_OUTPUT_PATHS
11593
- )
11594
- } : {},
11595
- metrics: extractTokenMetrics(result)
11596
- });
11597
- state.span.end();
11598
- embedSpans.delete(event.embedCallId);
11599
- });
11600
- },
12643
+ onEmbedEnd,
11601
12644
  onRerankStart(event) {
11602
12645
  runSafely("onRerankStart", () => {
11603
- const openSpan = rerankSpans.get(event.callId);
11604
- if (openSpan) {
12646
+ const operationKey = operationKeyFromEvent(event);
12647
+ const state = operationKey ? operations.get(operationKey) : void 0;
12648
+ if (shouldSkipTelemetryChildren(state)) {
12649
+ return;
12650
+ }
12651
+ const openSpan = operationKey ? rerankSpans.get(operationKey) : void 0;
12652
+ if (operationKey && openSpan) {
11605
12653
  openSpan.end();
11606
- rerankSpans.delete(event.callId);
12654
+ rerankSpans.delete(operationKey);
11607
12655
  }
11608
12656
  const span = startChildSpan(
11609
- event.callId,
12657
+ operationKey ?? event.callId,
11610
12658
  "doRerank",
11611
12659
  "llm" /* LLM */,
11612
12660
  {
@@ -11620,41 +12668,23 @@ function braintrustAISDKTelemetry() {
11620
12668
  metadata: metadataFromEvent(event)
11621
12669
  }
11622
12670
  );
11623
- rerankSpans.set(event.callId, span);
11624
- });
11625
- },
11626
- onRerankFinish(event) {
11627
- runSafely("onRerankFinish", () => {
11628
- const span = rerankSpans.get(event.callId);
11629
- if (!span) {
11630
- return;
11631
- }
11632
- const result = {
11633
- ranking: event.ranking?.map((entry) => ({
11634
- originalIndex: entry.index,
11635
- score: entry.relevanceScore
11636
- }))
11637
- };
11638
- span.log({
11639
- ...shouldRecordOutputs(event) ? {
11640
- output: processAISDKRerankOutput(
11641
- result,
11642
- DEFAULT_DENY_OUTPUT_PATHS
11643
- )
11644
- } : {}
11645
- });
11646
- span.end();
11647
- rerankSpans.delete(event.callId);
12671
+ rerankSpans.set(operationKey ?? event.callId, span);
11648
12672
  });
11649
12673
  },
12674
+ onRerankEnd,
11650
12675
  onToolExecutionStart(event) {
11651
12676
  runSafely("onToolExecutionStart", () => {
12677
+ const operationKey = operationKeyFromEvent(event);
12678
+ const state = operationKey ? operations.get(operationKey) : void 0;
12679
+ if (shouldSkipTelemetryChildren(state)) {
12680
+ return;
12681
+ }
11652
12682
  const toolCallId = event.toolCall.toolCallId;
11653
- if (!toolCallId) {
12683
+ if (!operationKey || !toolCallId) {
11654
12684
  return;
11655
12685
  }
11656
12686
  const span = startChildSpan(
11657
- event.callId,
12687
+ operationKey,
11658
12688
  event.toolCall.toolName || "tool",
11659
12689
  "tool" /* TOOL */,
11660
12690
  {
@@ -11668,7 +12698,7 @@ function braintrustAISDKTelemetry() {
11668
12698
  }
11669
12699
  }
11670
12700
  );
11671
- toolSpans.set(toolCallId, { callId: event.callId, span });
12701
+ toolSpans.set(toolCallId, { operationKey, span });
11672
12702
  });
11673
12703
  },
11674
12704
  onToolExecutionEnd(event) {
@@ -11679,14 +12709,17 @@ function braintrustAISDKTelemetry() {
11679
12709
  return;
11680
12710
  }
11681
12711
  const toolOutput = event.toolOutput;
11682
- if (toolOutput?.type === "tool-error") {
12712
+ const workflowToolError = event.success === false && "error" in event ? event.error : void 0;
12713
+ if (toolOutput?.type === "tool-error" || workflowToolError !== void 0) {
12714
+ const error = toolOutput?.error ?? workflowToolError;
11683
12715
  state.span.log({
11684
- error: toolOutput.error instanceof Error ? toolOutput.error.message : String(toolOutput?.error),
12716
+ error: error instanceof Error ? error.message : String(error),
11685
12717
  metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
11686
12718
  });
11687
12719
  } else {
12720
+ const output = toolOutput && "output" in toolOutput ? toolOutput.output : event.output;
11688
12721
  state.span.log({
11689
- ...shouldRecordOutputs(event) ? { output: toolOutput?.output } : {},
12722
+ ...shouldRecordOutputs(event) ? { output } : {},
11690
12723
  metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
11691
12724
  });
11692
12725
  }
@@ -11700,83 +12733,46 @@ function braintrustAISDKTelemetry() {
11700
12733
  if (!callId) {
11701
12734
  return;
11702
12735
  }
11703
- const state = operations.get(callId);
12736
+ const operationKey = operationKeyForCallId(callId);
12737
+ const state = operationKey ? operations.get(operationKey) : void 0;
11704
12738
  if (!state || state.firstChunkTime !== void 0) {
11705
12739
  return;
11706
12740
  }
11707
12741
  state.firstChunkTime = getCurrentUnixTimestamp();
11708
12742
  });
11709
12743
  },
11710
- onFinish(event) {
11711
- runSafely("onFinish", () => {
11712
- const state = operations.get(event.callId);
11713
- if (!state) {
12744
+ onEnd,
12745
+ onAbort(event) {
12746
+ runSafely("onAbort", () => {
12747
+ const operationKey = operationKeyFromEvent(event, "finish");
12748
+ const state = operationKey ? operations.get(operationKey) : void 0;
12749
+ if (!operationKey || !state) {
11714
12750
  return;
11715
12751
  }
11716
- const result = finishResult(event, state.operationName);
11717
- const metrics = state.hadModelChild ? {} : extractTokenMetrics(result);
11718
- if (state.firstChunkTime !== void 0) {
11719
- metrics.time_to_first_token = state.firstChunkTime - state.startTime;
12752
+ const error = abortReasonFromEvent(event);
12753
+ closeOpenChildSpans(operationKey, error);
12754
+ if (state.ownsSpan) {
12755
+ logError(state.span, error);
12756
+ state.span.end();
11720
12757
  }
11721
- state.span.log({
11722
- ...shouldRecordOutputs(event) ? {
11723
- output: finishOutput(result, state.operationName)
11724
- } : {},
11725
- metrics
11726
- });
11727
- state.span.end();
11728
- operations.delete(event.callId);
12758
+ deleteOperation(operationKey);
11729
12759
  });
11730
12760
  },
11731
12761
  onError(event) {
11732
12762
  runSafely("onError", () => {
11733
12763
  const errorEvent = isObject(event) ? event : {};
11734
- const callId = typeof errorEvent.callId === "string" ? errorEvent.callId : void 0;
11735
- if (!callId) {
11736
- return;
11737
- }
11738
- const state = operations.get(callId);
11739
- if (!state) {
12764
+ const operationKey = operationKeyFromEvent(errorEvent, "finish");
12765
+ const state = operationKey ? operations.get(operationKey) : void 0;
12766
+ if (!operationKey || !state) {
11740
12767
  return;
11741
12768
  }
11742
12769
  const error = errorEvent.error ?? event;
11743
- const openModelSpans = modelSpans.get(callId);
11744
- if (openModelSpans) {
11745
- for (const span of openModelSpans) {
11746
- logError(span, error);
11747
- span.end();
11748
- }
11749
- modelSpans.delete(callId);
11750
- }
11751
- const openObjectSpan = objectSpans.get(callId);
11752
- if (openObjectSpan) {
11753
- logError(openObjectSpan, error);
11754
- openObjectSpan.end();
11755
- objectSpans.delete(callId);
11756
- }
11757
- for (const [embedCallId, embedState] of embedSpans) {
11758
- if (embedState.callId === callId) {
11759
- logError(embedState.span, error);
11760
- embedState.span.end();
11761
- embedSpans.delete(embedCallId);
11762
- }
11763
- }
11764
- const openRerankSpan = rerankSpans.get(callId);
11765
- if (openRerankSpan) {
11766
- logError(openRerankSpan, error);
11767
- openRerankSpan.end();
11768
- rerankSpans.delete(callId);
11769
- }
11770
- for (const [toolCallId, toolState] of toolSpans) {
11771
- if (toolState.callId === callId) {
11772
- logError(toolState.span, error);
11773
- toolState.span.end();
11774
- toolSpans.delete(toolCallId);
11775
- }
12770
+ closeOpenChildSpans(operationKey, error);
12771
+ if (state.ownsSpan) {
12772
+ logError(state.span, error);
12773
+ state.span.end();
11776
12774
  }
11777
- logError(state.span, error);
11778
- state.span.end();
11779
- operations.delete(callId);
12775
+ deleteOperation(operationKey);
11780
12776
  });
11781
12777
  },
11782
12778
  executeTool({ toolCallId, execute }) {
@@ -11791,7 +12787,16 @@ function shouldRecordInputs(event) {
11791
12787
  function shouldRecordOutputs(event) {
11792
12788
  return event.recordOutputs !== false;
11793
12789
  }
12790
+ function hasPromptLikeInput(input) {
12791
+ if (!isObject(input)) {
12792
+ return false;
12793
+ }
12794
+ return input.prompt !== void 0 || input.messages !== void 0;
12795
+ }
11794
12796
  function operationNameFromId(operationId) {
12797
+ if (operationId === "ai.workflowAgent.stream") {
12798
+ return "WorkflowAgent.stream";
12799
+ }
11795
12800
  return operationId?.startsWith("ai.") ? operationId.slice("ai.".length) : operationId || "ai-sdk";
11796
12801
  }
11797
12802
  function modelFromEvent(event) {
@@ -11837,6 +12842,7 @@ function operationInput(event, operationName) {
11837
12842
  }
11838
12843
  return {
11839
12844
  model: modelFromEvent(event),
12845
+ instructions: event.instructions,
11840
12846
  system: event.system,
11841
12847
  prompt: event.prompt,
11842
12848
  messages: event.messages,
@@ -11885,6 +12891,30 @@ function finishResult(event, operationName) {
11885
12891
  }
11886
12892
  return event;
11887
12893
  }
12894
+ function extractTimeToFirstToken(result, state) {
12895
+ if (state.firstChunkTime !== void 0) {
12896
+ return state.firstChunkTime - state.startTime;
12897
+ }
12898
+ const performanceCandidates = [
12899
+ safePerformance(result),
12900
+ safePerformance(result.finalStep),
12901
+ ...Array.isArray(result.steps) ? (result.steps ?? []).map(safePerformance) : []
12902
+ ];
12903
+ for (const performance of performanceCandidates) {
12904
+ const timeToFirstOutputMs = performance?.timeToFirstOutputMs;
12905
+ if (typeof timeToFirstOutputMs === "number") {
12906
+ return timeToFirstOutputMs / 1e3;
12907
+ }
12908
+ }
12909
+ return void 0;
12910
+ }
12911
+ function safePerformance(value) {
12912
+ if (!isObject(value)) {
12913
+ return void 0;
12914
+ }
12915
+ const performance = value.performance;
12916
+ return isObject(performance) ? performance : void 0;
12917
+ }
11888
12918
  function finishOutput(result, operationName) {
11889
12919
  if (operationName === "embed" || operationName === "embedMany") {
11890
12920
  return processAISDKEmbeddingOutput(
@@ -11961,6 +12991,10 @@ var aiSDKChannels = defineChannels("ai", {
11961
12991
  channelName: "ToolLoopAgent.stream",
11962
12992
  kind: "async"
11963
12993
  }),
12994
+ workflowAgentStream: channel({
12995
+ channelName: "WorkflowAgent.stream",
12996
+ kind: "async"
12997
+ }),
11964
12998
  v7CreateTelemetryDispatcher: channel({
11965
12999
  channelName: "createTelemetryDispatcher",
11966
13000
  kind: "sync-stream"
@@ -11971,14 +13005,19 @@ var aiSDKChannels = defineChannels("ai", {
11971
13005
  var DEFAULT_DENY_OUTPUT_PATHS = [
11972
13006
  // v3
11973
13007
  "roundtrips[].request.body",
13008
+ "roundtrips[].request.headers",
11974
13009
  "roundtrips[].response.headers",
11975
13010
  "rawResponse.headers",
11976
13011
  "responseMessages",
11977
13012
  // v5
11978
13013
  "request.body",
13014
+ "request.headers",
13015
+ "responses[].headers",
11979
13016
  "response.body",
11980
13017
  "response.headers",
11981
13018
  "steps[].request.body",
13019
+ "steps[].request.headers",
13020
+ "steps[].responses[].headers",
11982
13021
  "steps[].response.body",
11983
13022
  "steps[].response.headers"
11984
13023
  ];
@@ -11990,6 +13029,18 @@ var AUTO_PATCHED_V7_TELEMETRY_DISPATCHER = /* @__PURE__ */ Symbol.for(
11990
13029
  var RUNTIME_DENY_OUTPUT_PATHS = /* @__PURE__ */ Symbol.for(
11991
13030
  "braintrust.ai-sdk.deny-output-paths"
11992
13031
  );
13032
+ var aiSDKV7TelemetryOperationCounter = 0;
13033
+ var TRANSPORT_PAYLOAD_ROOT_PATHS = [
13034
+ "rawResponse",
13035
+ "request",
13036
+ "response",
13037
+ "responses[]",
13038
+ "roundtrips[].request",
13039
+ "roundtrips[].response",
13040
+ "steps[].request",
13041
+ "steps[].response",
13042
+ "steps[].responses[]"
13043
+ ];
11993
13044
  var AI_SDK_V7_TELEMETRY_CALLBACKS = [
11994
13045
  "onStart",
11995
13046
  "onStepStart",
@@ -11998,14 +13049,16 @@ var AI_SDK_V7_TELEMETRY_CALLBACKS = [
11998
13049
  "onToolExecutionStart",
11999
13050
  "onToolExecutionEnd",
12000
13051
  "onChunk",
13052
+ "onStepEnd",
12001
13053
  "onStepFinish",
12002
13054
  "onObjectStepStart",
12003
- "onObjectStepFinish",
13055
+ "onObjectStepEnd",
12004
13056
  "onEmbedStart",
12005
- "onEmbedFinish",
13057
+ "onEmbedEnd",
12006
13058
  "onRerankStart",
12007
- "onRerankFinish",
12008
- "onFinish",
13059
+ "onRerankEnd",
13060
+ "onEnd",
13061
+ "onAbort",
12009
13062
  "onError"
12010
13063
  ];
12011
13064
  var AISDKPlugin = class extends BasePlugin {
@@ -12163,7 +13216,9 @@ var AISDKPlugin = class extends BasePlugin {
12163
13216
  traceStreamingChannel(aiSDKChannels.agentGenerate, {
12164
13217
  name: "Agent.generate",
12165
13218
  type: "function" /* FUNCTION */,
12166
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
13219
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
13220
+ agentOwner: true
13221
+ }),
12167
13222
  extractOutput: (result, endEvent) => {
12168
13223
  finalizeAISDKChildTracing(endEvent);
12169
13224
  return processAISDKOutput(
@@ -12179,7 +13234,9 @@ var AISDKPlugin = class extends BasePlugin {
12179
13234
  traceStreamingChannel(aiSDKChannels.agentStream, {
12180
13235
  name: "Agent.stream",
12181
13236
  type: "function" /* FUNCTION */,
12182
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
13237
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
13238
+ agentOwner: true
13239
+ }),
12183
13240
  extractOutput: (result, endEvent) => processAISDKOutput(
12184
13241
  result,
12185
13242
  resolveDenyOutputPaths(endEvent, denyOutputPaths)
@@ -12199,7 +13256,9 @@ var AISDKPlugin = class extends BasePlugin {
12199
13256
  traceSyncStreamChannel(aiSDKChannels.agentStreamSync, {
12200
13257
  name: "Agent.stream",
12201
13258
  type: "function" /* FUNCTION */,
12202
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
13259
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
13260
+ agentOwner: true
13261
+ }),
12203
13262
  patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
12204
13263
  defaultDenyOutputPaths: denyOutputPaths,
12205
13264
  endEvent,
@@ -12213,7 +13272,9 @@ var AISDKPlugin = class extends BasePlugin {
12213
13272
  traceStreamingChannel(aiSDKChannels.toolLoopAgentGenerate, {
12214
13273
  name: "ToolLoopAgent.generate",
12215
13274
  type: "function" /* FUNCTION */,
12216
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
13275
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
13276
+ agentOwner: true
13277
+ }),
12217
13278
  extractOutput: (result, endEvent) => {
12218
13279
  finalizeAISDKChildTracing(endEvent);
12219
13280
  return processAISDKOutput(
@@ -12229,7 +13290,9 @@ var AISDKPlugin = class extends BasePlugin {
12229
13290
  traceStreamingChannel(aiSDKChannels.toolLoopAgentStream, {
12230
13291
  name: "ToolLoopAgent.stream",
12231
13292
  type: "function" /* FUNCTION */,
12232
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
13293
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
13294
+ agentOwner: true
13295
+ }),
12233
13296
  extractOutput: (result, endEvent) => processAISDKOutput(
12234
13297
  result,
12235
13298
  resolveDenyOutputPaths(endEvent, denyOutputPaths)
@@ -12245,6 +13308,42 @@ var AISDKPlugin = class extends BasePlugin {
12245
13308
  })
12246
13309
  })
12247
13310
  );
13311
+ this.unsubscribers.push(
13312
+ traceStreamingChannel(aiSDKChannels.workflowAgentStream, {
13313
+ name: "WorkflowAgent.stream",
13314
+ type: "function" /* FUNCTION */,
13315
+ extractInput: ([params], event, span) => prepareAISDKWorkflowAgentStreamInput(
13316
+ params,
13317
+ event,
13318
+ span,
13319
+ denyOutputPaths
13320
+ ),
13321
+ extractOutput: (result, endEvent) => {
13322
+ finalizeAISDKChildTracing(endEvent);
13323
+ return processAISDKOutput(
13324
+ result,
13325
+ resolveDenyOutputPaths(endEvent, denyOutputPaths)
13326
+ );
13327
+ },
13328
+ extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
13329
+ aggregateChunks: aggregateAISDKChunks,
13330
+ onComplete: ({ span }) => {
13331
+ unregisterWorkflowAgentWrapperSpan(span);
13332
+ },
13333
+ onError: ({ event, span }) => {
13334
+ finalizeAISDKChildTracing(event);
13335
+ unregisterWorkflowAgentWrapperSpan(span);
13336
+ },
13337
+ patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
13338
+ defaultDenyOutputPaths: denyOutputPaths,
13339
+ endEvent,
13340
+ onComplete: () => unregisterWorkflowAgentWrapperSpan(span),
13341
+ result,
13342
+ span,
13343
+ startTime
13344
+ })
13345
+ })
13346
+ );
12248
13347
  }
12249
13348
  };
12250
13349
  function subscribeToAISDKV7TelemetryDispatcher() {
@@ -12256,7 +13355,11 @@ function subscribeToAISDKV7TelemetryDispatcher() {
12256
13355
  if (telemetryOptions?.isEnabled === false) {
12257
13356
  return;
12258
13357
  }
12259
- patchAISDKV7TelemetryDispatcher(event.result, telemetry);
13358
+ patchAISDKV7TelemetryDispatcher(
13359
+ event.result,
13360
+ telemetry,
13361
+ telemetryOptions
13362
+ );
12260
13363
  }
12261
13364
  };
12262
13365
  channel2.subscribe(handlers);
@@ -12264,7 +13367,7 @@ function subscribeToAISDKV7TelemetryDispatcher() {
12264
13367
  channel2.unsubscribe(handlers);
12265
13368
  };
12266
13369
  }
12267
- function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
13370
+ function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry, telemetryOptions) {
12268
13371
  if (!isObject(dispatcher)) {
12269
13372
  return;
12270
13373
  }
@@ -12273,6 +13376,54 @@ function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
12273
13376
  return;
12274
13377
  }
12275
13378
  dispatcherRecord[AUTO_PATCHED_V7_TELEMETRY_DISPATCHER] = true;
13379
+ let operationKey;
13380
+ const telemetryEventFields = {};
13381
+ if (typeof telemetryOptions?.recordInputs === "boolean") {
13382
+ telemetryEventFields.recordInputs = telemetryOptions.recordInputs;
13383
+ }
13384
+ if (typeof telemetryOptions?.recordOutputs === "boolean") {
13385
+ telemetryEventFields.recordOutputs = telemetryOptions.recordOutputs;
13386
+ }
13387
+ if (typeof telemetryOptions?.functionId === "string") {
13388
+ telemetryEventFields.functionId = telemetryOptions.functionId;
13389
+ }
13390
+ const eventWithOperationKey = (event) => {
13391
+ if (!isObject(event)) {
13392
+ return event;
13393
+ }
13394
+ const eventRecord = event;
13395
+ const callId = typeof eventRecord.callId === "string" ? eventRecord.callId : "unknown";
13396
+ operationKey ??= `${callId}:${++aiSDKV7TelemetryOperationCounter}`;
13397
+ if (Object.keys(telemetryEventFields).length > 0) {
13398
+ const augmentedEvent = {
13399
+ ...telemetryEventFields,
13400
+ ...event
13401
+ };
13402
+ try {
13403
+ Object.defineProperty(augmentedEvent, BRAINTRUST_AI_SDK_V7_OPERATION_KEY, {
13404
+ configurable: true,
13405
+ enumerable: false,
13406
+ value: operationKey
13407
+ });
13408
+ } catch {
13409
+ augmentedEvent[BRAINTRUST_AI_SDK_V7_OPERATION_KEY] = operationKey;
13410
+ }
13411
+ return augmentedEvent;
13412
+ }
13413
+ try {
13414
+ Object.defineProperty(eventRecord, BRAINTRUST_AI_SDK_V7_OPERATION_KEY, {
13415
+ configurable: true,
13416
+ enumerable: false,
13417
+ value: operationKey
13418
+ });
13419
+ return event;
13420
+ } catch {
13421
+ return {
13422
+ ...event,
13423
+ [BRAINTRUST_AI_SDK_V7_OPERATION_KEY]: operationKey
13424
+ };
13425
+ }
13426
+ };
12276
13427
  for (const key of AI_SDK_V7_TELEMETRY_CALLBACKS) {
12277
13428
  const braintrustCallback = telemetry[key];
12278
13429
  if (typeof braintrustCallback !== "function") {
@@ -12281,11 +13432,17 @@ function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
12281
13432
  const existingCallback = dispatcherRecord[key];
12282
13433
  dispatcherRecord[key] = (event) => {
12283
13434
  const existingResult = typeof existingCallback === "function" ? existingCallback.call(dispatcher, event) : void 0;
12284
- const braintrustResult = braintrustCallback.call(telemetry, event);
12285
- const pending = [existingResult, braintrustResult].filter(isPromiseLike);
12286
- if (pending.length > 0) {
12287
- return Promise.allSettled(pending).then(() => void 0);
13435
+ try {
13436
+ const braintrustResult = braintrustCallback.call(
13437
+ telemetry,
13438
+ eventWithOperationKey(event)
13439
+ );
13440
+ if (isPromiseLike(braintrustResult)) {
13441
+ void Promise.resolve(braintrustResult).catch(() => void 0);
13442
+ }
13443
+ } catch {
12288
13444
  }
13445
+ return existingResult;
12289
13446
  };
12290
13447
  }
12291
13448
  const braintrustExecuteTool = telemetry.executeTool;
@@ -12295,6 +13452,7 @@ function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
12295
13452
  const existingExecuteTool = dispatcherRecord.executeTool;
12296
13453
  dispatcherRecord.executeTool = (args) => braintrustExecuteTool.call(telemetry, {
12297
13454
  ...args,
13455
+ ...operationKey ? { [BRAINTRUST_AI_SDK_V7_OPERATION_KEY]: operationKey } : {},
12298
13456
  execute: () => typeof existingExecuteTool === "function" ? existingExecuteTool.call(dispatcher, args) : args.execute()
12299
13457
  });
12300
13458
  }
@@ -12393,6 +13551,8 @@ var serializeOutputObject = (output, model) => {
12393
13551
  var processInputAttachmentsSync = (input) => {
12394
13552
  if (!input) return { input };
12395
13553
  const processed = { ...input };
13554
+ delete processed.headers;
13555
+ delete processed.experimental_output;
12396
13556
  if (input.messages && Array.isArray(input.messages)) {
12397
13557
  processed.messages = input.messages.map(processMessage);
12398
13558
  }
@@ -12426,10 +13586,10 @@ var processInputAttachmentsSync = (input) => {
12426
13586
  processed.output = serialized;
12427
13587
  }
12428
13588
  }
12429
- if ("prepareCall" in processed && typeof processed.prepareCall === "function") {
12430
- processed.prepareCall = "[Function]";
12431
- }
12432
- return { input: processed, outputPromise };
13589
+ return {
13590
+ input: sanitizeAISDKCallInputValue(processed),
13591
+ outputPromise
13592
+ };
12433
13593
  };
12434
13594
  var processMessage = (message) => {
12435
13595
  if (!message || typeof message !== "object") return message;
@@ -12593,7 +13753,21 @@ var convertDataToAttachment = (data, mimeType, filename) => {
12593
13753
  function processAISDKCallInput(params) {
12594
13754
  return processInputAttachmentsSync(params);
12595
13755
  }
12596
- function prepareAISDKCallInput(params, event, span, defaultDenyOutputPaths) {
13756
+ function processAISDKWorkflowAgentCallInput(params) {
13757
+ const processed = processAISDKCallInput(params);
13758
+ return {
13759
+ ...processed,
13760
+ input: extractWorkflowAgentInput(processed.input)
13761
+ };
13762
+ }
13763
+ function processAISDKWorkflowAgentModelCallInput(params) {
13764
+ const processed = processAISDKCallInput(params);
13765
+ return {
13766
+ ...processed,
13767
+ input: extractWorkflowAgentModelInput(processed.input)
13768
+ };
13769
+ }
13770
+ function prepareAISDKCallInput(params, event, span, defaultDenyOutputPaths, childTracingOptions = {}) {
12597
13771
  const { input, outputPromise } = processAISDKCallInput(params);
12598
13772
  if (outputPromise && input && typeof input === "object") {
12599
13773
  outputPromise.then((resolvedData) => {
@@ -12612,7 +13786,29 @@ function prepareAISDKCallInput(params, event, span, defaultDenyOutputPaths) {
12612
13786
  event.self,
12613
13787
  span,
12614
13788
  defaultDenyOutputPaths,
12615
- event.aiSDK
13789
+ event.aiSDK,
13790
+ childTracingOptions
13791
+ );
13792
+ event.modelWrapped = childTracing.modelWrapped;
13793
+ if (childTracing.cleanup) {
13794
+ event.__braintrust_ai_sdk_cleanup = childTracing.cleanup;
13795
+ }
13796
+ return {
13797
+ input,
13798
+ metadata
13799
+ };
13800
+ }
13801
+ function prepareAISDKWorkflowAgentStreamInput(params, event, span, defaultDenyOutputPaths) {
13802
+ registerWorkflowAgentWrapperSpan(span);
13803
+ const { input } = processAISDKWorkflowAgentCallInput(params);
13804
+ const metadata = extractWorkflowMetadataFromCallParams(params, event.self);
13805
+ const childTracing = prepareAISDKChildTracing(
13806
+ params,
13807
+ event.self,
13808
+ span,
13809
+ defaultDenyOutputPaths,
13810
+ event.aiSDK,
13811
+ { agentOwner: true, workflowAgent: true }
12616
13812
  );
12617
13813
  event.modelWrapped = childTracing.modelWrapped;
12618
13814
  if (childTracing.cleanup) {
@@ -12649,6 +13845,9 @@ function extractTopLevelAISDKMetrics(result, event, startTime) {
12649
13845
  function hasModelChildTracing(event) {
12650
13846
  return event?.modelWrapped === true || event?.__braintrust_ai_sdk_model_wrapped === true;
12651
13847
  }
13848
+ function serializeToolExecutionInput(args) {
13849
+ return args.length > 0 ? args[0] : args;
13850
+ }
12652
13851
  function createAISDKIntegrationMetadata() {
12653
13852
  return {
12654
13853
  braintrust: {
@@ -12660,6 +13859,13 @@ function createAISDKIntegrationMetadata() {
12660
13859
  function resolveModelFromSelf(self) {
12661
13860
  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;
12662
13861
  }
13862
+ function resolveToolsFromSelf(self) {
13863
+ if (!self || typeof self !== "object") {
13864
+ return void 0;
13865
+ }
13866
+ const selfRecord = self;
13867
+ return selfRecord.tools ?? selfRecord.settings?.tools;
13868
+ }
12663
13869
  function extractBaseMetadata(model, self) {
12664
13870
  const metadata = createAISDKIntegrationMetadata();
12665
13871
  const { model: modelId, provider } = serializeModelWithProvider(
@@ -12675,12 +13881,175 @@ function extractBaseMetadata(model, self) {
12675
13881
  }
12676
13882
  function extractMetadataFromCallParams(params, self) {
12677
13883
  const metadata = extractBaseMetadata(params.model, self);
12678
- const tools = serializeAISDKToolsForLogging(params.tools);
13884
+ const tools = serializeAISDKToolsForLogging(
13885
+ params.tools ?? resolveToolsFromSelf(self)
13886
+ );
12679
13887
  if (tools) {
12680
13888
  metadata.tools = tools;
12681
13889
  }
12682
13890
  return metadata;
12683
13891
  }
13892
+ function extractWorkflowMetadataFromCallParams(params, self) {
13893
+ const metadata = extractMetadataFromCallParams(params, self);
13894
+ const options = extractAISDKCallOptionsForMetadata(params);
13895
+ if (Object.keys(options).length > 0) {
13896
+ metadata.options = options;
13897
+ }
13898
+ return metadata;
13899
+ }
13900
+ function extractWorkflowAgentInput(params) {
13901
+ const input = {};
13902
+ if (params.instructions !== void 0) {
13903
+ input.instructions = params.instructions;
13904
+ }
13905
+ if (params.system !== void 0) {
13906
+ input.system = params.system;
13907
+ }
13908
+ if (Array.isArray(params.messages)) {
13909
+ return { ...input, messages: params.messages };
13910
+ }
13911
+ if (typeof params.prompt === "string") {
13912
+ return { ...input, prompt: params.prompt };
13913
+ }
13914
+ if (Array.isArray(params.prompt)) {
13915
+ return { ...input, prompt: params.prompt };
13916
+ }
13917
+ return input;
13918
+ }
13919
+ function extractWorkflowAgentModelInput(params) {
13920
+ const input = {};
13921
+ if (params.instructions !== void 0) {
13922
+ input.instructions = params.instructions;
13923
+ }
13924
+ if (params.system !== void 0) {
13925
+ input.system = params.system;
13926
+ }
13927
+ if (Array.isArray(params.messages)) {
13928
+ return { ...input, messages: params.messages };
13929
+ }
13930
+ if (typeof params.prompt === "string") {
13931
+ return { ...input, prompt: params.prompt };
13932
+ }
13933
+ if (Array.isArray(params.prompt)) {
13934
+ return { ...input, messages: params.prompt };
13935
+ }
13936
+ return input;
13937
+ }
13938
+ function sanitizeAISDKCallInputValue(value, depth = 0) {
13939
+ if (value === void 0 || typeof value === "function") {
13940
+ return void 0;
13941
+ }
13942
+ if (value === null || typeof value !== "object") {
13943
+ return value;
13944
+ }
13945
+ if (isPromiseLike(value)) {
13946
+ return "[Promise]";
13947
+ }
13948
+ if (typeof AbortSignal !== "undefined" && value instanceof AbortSignal) {
13949
+ return "[AbortSignal]";
13950
+ }
13951
+ if (depth >= 8) {
13952
+ return "[Object]";
13953
+ }
13954
+ if (Array.isArray(value)) {
13955
+ return value.map((item) => sanitizeAISDKCallInputValue(item, depth + 1)).filter((item) => item !== void 0);
13956
+ }
13957
+ if (!isObject(value)) {
13958
+ return value;
13959
+ }
13960
+ const prototype = Object.getPrototypeOf(value);
13961
+ if (prototype !== Object.prototype && prototype !== null) {
13962
+ return value;
13963
+ }
13964
+ const sanitized = {};
13965
+ for (const [key, nested] of Object.entries(value)) {
13966
+ if (key === "__proto__" || key === "constructor" || key === "prototype" || key.toLowerCase() === "headers") {
13967
+ continue;
13968
+ }
13969
+ const sanitizedNested = sanitizeAISDKCallInputValue(nested, depth + 1);
13970
+ if (sanitizedNested !== void 0) {
13971
+ sanitized[key] = sanitizedNested;
13972
+ }
13973
+ }
13974
+ return sanitized;
13975
+ }
13976
+ function extractAISDKCallOptionsForMetadata(params) {
13977
+ const options = {};
13978
+ const inputOrTopLevelKeys = /* @__PURE__ */ new Set([
13979
+ "model",
13980
+ "instructions",
13981
+ "messages",
13982
+ "prompt",
13983
+ "system",
13984
+ "tools",
13985
+ "headers",
13986
+ "abortSignal",
13987
+ "signal",
13988
+ "experimental_output"
13989
+ ]);
13990
+ for (const [key, value] of Object.entries(params)) {
13991
+ if (inputOrTopLevelKeys.has(key) || key === "__proto__" || key === "constructor" || key === "prototype" || /^on[A-Z]/.test(key) && typeof value === "function") {
13992
+ continue;
13993
+ }
13994
+ const sanitized = sanitizeAISDKMetadataValue(value);
13995
+ if (sanitized !== void 0) {
13996
+ options[key] = sanitized;
13997
+ }
13998
+ }
13999
+ return options;
14000
+ }
14001
+ function sanitizeAISDKMetadataValue(value, depth = 0) {
14002
+ if (value === void 0) {
14003
+ return void 0;
14004
+ }
14005
+ if (typeof value === "function") {
14006
+ return "[Function]";
14007
+ }
14008
+ if (value === null || typeof value !== "object") {
14009
+ return value;
14010
+ }
14011
+ if (isPromiseLike(value)) {
14012
+ return "[Promise]";
14013
+ }
14014
+ if (typeof AbortSignal !== "undefined" && value instanceof AbortSignal) {
14015
+ return "[AbortSignal]";
14016
+ }
14017
+ if (depth >= 8) {
14018
+ return "[Object]";
14019
+ }
14020
+ if (Array.isArray(value)) {
14021
+ return value.map((item) => sanitizeAISDKMetadataValue(item, depth + 1)).filter((item) => item !== void 0);
14022
+ }
14023
+ if (!isObject(value)) {
14024
+ return value;
14025
+ }
14026
+ const sanitized = {};
14027
+ for (const [key, nested] of Object.entries(value)) {
14028
+ if (key === "__proto__" || key === "constructor" || key === "prototype" || key.toLowerCase() === "headers") {
14029
+ continue;
14030
+ }
14031
+ const sanitizedNested = sanitizeAISDKMetadataValue(nested, depth + 1);
14032
+ if (sanitizedNested !== void 0) {
14033
+ sanitized[key] = sanitizedNested;
14034
+ }
14035
+ }
14036
+ return sanitized;
14037
+ }
14038
+ function buildAISDKModelStartEvent(callOptions, baseMetadata, options) {
14039
+ if (!options.workflowAgent) {
14040
+ return {
14041
+ input: processAISDKCallInput(callOptions).input,
14042
+ metadata: baseMetadata
14043
+ };
14044
+ }
14045
+ return {
14046
+ input: processAISDKWorkflowAgentModelCallInput(callOptions).input,
14047
+ metadata: {
14048
+ ...baseMetadata,
14049
+ ...extractWorkflowMetadataFromCallParams(callOptions)
14050
+ }
14051
+ };
14052
+ }
12684
14053
  function extractMetadataFromEmbedParams(params, self) {
12685
14054
  return extractBaseMetadata(params.model, self);
12686
14055
  }
@@ -12694,65 +14063,228 @@ function extractMetadataFromRerankParams(params, self) {
12694
14063
  }
12695
14064
  return metadata;
12696
14065
  }
12697
- function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiSDK) {
14066
+ function activeAISDKChildPatchEntry(entries) {
14067
+ const activeSpan = currentSpan();
14068
+ const activeSpanId = activeSpan.spanId;
14069
+ if (activeSpanId) {
14070
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
14071
+ const entry = entries[index];
14072
+ if (entry?.activeSpanIds.has(activeSpanId)) {
14073
+ return entry;
14074
+ }
14075
+ }
14076
+ }
14077
+ const activeParentSpanIds = activeSpan.spanParents ?? [];
14078
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
14079
+ const entry = entries[index];
14080
+ if (entry?.parentSpan.spanId && activeParentSpanIds.includes(entry.parentSpan.spanId)) {
14081
+ return entry;
14082
+ }
14083
+ }
14084
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
14085
+ const entry = entries[index];
14086
+ if (entry?.parentSpan.spanId === activeSpanId) {
14087
+ return entry;
14088
+ }
14089
+ }
14090
+ return entries[entries.length - 1];
14091
+ }
14092
+ function attachNestedAISDKChildPatchEntry(entries, nestedSpan, cleanup) {
14093
+ const activeSpanId = currentSpan().spanId;
14094
+ if (!activeSpanId || activeSpanId === nestedSpan.spanId) {
14095
+ return false;
14096
+ }
14097
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
14098
+ const entry = entries[index];
14099
+ if (entry?.parentSpan.spanId === activeSpanId || entry?.activeSpanIds.has(activeSpanId)) {
14100
+ entry.activeSpanIds.add(nestedSpan.spanId);
14101
+ cleanup.push(() => {
14102
+ entry.activeSpanIds.delete(nestedSpan.spanId);
14103
+ });
14104
+ return true;
14105
+ }
14106
+ }
14107
+ return false;
14108
+ }
14109
+ function shadowActiveAISDKChildPatchEntry(entries, entry, nestedSpan, cleanup) {
14110
+ const activeSpanId = currentSpan().spanId;
14111
+ if (!activeSpanId || activeSpanId === nestedSpan.spanId) {
14112
+ return;
14113
+ }
14114
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
14115
+ const existingEntry = entries[index];
14116
+ if (existingEntry?.parentSpan.spanId === activeSpanId || existingEntry?.activeSpanIds.has(activeSpanId)) {
14117
+ entry.activeSpanIds.add(activeSpanId);
14118
+ cleanup.push(() => {
14119
+ entry.activeSpanIds.delete(activeSpanId);
14120
+ });
14121
+ return;
14122
+ }
14123
+ }
14124
+ }
14125
+ function closeOpenAISDKModelPatchSpans(entry) {
14126
+ for (const span of entry.openSpans) {
14127
+ span.end();
14128
+ }
14129
+ entry.openSpans.clear();
14130
+ }
14131
+ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiSDK, childTracingOptions = {}) {
12698
14132
  const cleanup = [];
12699
- const patchedModels = /* @__PURE__ */ new WeakSet();
14133
+ const patchedModels = /* @__PURE__ */ new WeakMap();
12700
14134
  const patchedTools = /* @__PURE__ */ new WeakSet();
12701
14135
  let modelWrapped = false;
12702
14136
  const patchModel = (model) => {
12703
14137
  const resolvedModel = resolveAISDKModel(model, aiSDK);
12704
- if (!resolvedModel || typeof resolvedModel !== "object" || typeof resolvedModel.doGenerate !== "function" || patchedModels.has(resolvedModel) || resolvedModel[AUTO_PATCHED_MODEL]) {
14138
+ if (!resolvedModel || typeof resolvedModel !== "object" || typeof resolvedModel.doGenerate !== "function") {
12705
14139
  return resolvedModel;
12706
14140
  }
12707
- patchedModels.add(resolvedModel);
12708
- resolvedModel[AUTO_PATCHED_MODEL] = true;
14141
+ const existingWrappedModel = patchedModels.get(resolvedModel);
14142
+ if (existingWrappedModel) {
14143
+ modelWrapped = true;
14144
+ return existingWrappedModel;
14145
+ }
12709
14146
  modelWrapped = true;
14147
+ const modelRecord = resolvedModel;
14148
+ const entry = {
14149
+ activeSpanIds: /* @__PURE__ */ new Set([parentSpan.spanId]),
14150
+ baseMetadata: buildAISDKChildMetadata(resolvedModel),
14151
+ childTracingOptions,
14152
+ denyOutputPaths,
14153
+ openSpans: /* @__PURE__ */ new Set(),
14154
+ parentSpan
14155
+ };
14156
+ const cleanupModelEntry = (state2, patchedModel) => {
14157
+ closeOpenAISDKModelPatchSpans(entry);
14158
+ const index = state2.entries.indexOf(entry);
14159
+ if (index >= 0) {
14160
+ state2.entries.splice(index, 1);
14161
+ }
14162
+ if (state2.entries.length > 0) {
14163
+ return;
14164
+ }
14165
+ patchedModel.doGenerate = state2.originalDoGenerate;
14166
+ patchedModel.doStream = state2.originalDoStream;
14167
+ delete patchedModel[AUTO_PATCHED_MODEL];
14168
+ };
14169
+ const existingState = modelRecord[AUTO_PATCHED_MODEL];
14170
+ if (existingState) {
14171
+ patchedModels.set(resolvedModel, resolvedModel);
14172
+ if (childTracingOptions.agentOwner && attachNestedAISDKChildPatchEntry(
14173
+ existingState.entries,
14174
+ parentSpan,
14175
+ cleanup
14176
+ )) {
14177
+ return resolvedModel;
14178
+ }
14179
+ if (!childTracingOptions.agentOwner) {
14180
+ shadowActiveAISDKChildPatchEntry(
14181
+ existingState.entries,
14182
+ entry,
14183
+ parentSpan,
14184
+ cleanup
14185
+ );
14186
+ }
14187
+ existingState.entries.push(entry);
14188
+ cleanup.push(() => {
14189
+ cleanupModelEntry(existingState, modelRecord);
14190
+ });
14191
+ return resolvedModel;
14192
+ }
12710
14193
  const originalDoGenerate = resolvedModel.doGenerate;
12711
14194
  const originalDoStream = resolvedModel.doStream;
12712
- const baseMetadata = buildAISDKChildMetadata(resolvedModel);
12713
- resolvedModel.doGenerate = async function doGeneratePatched(options) {
12714
- return parentSpan.traced(
14195
+ const wrappedModel = Object.create(
14196
+ Object.getPrototypeOf(resolvedModel)
14197
+ );
14198
+ Object.defineProperties(
14199
+ wrappedModel,
14200
+ Object.getOwnPropertyDescriptors(resolvedModel)
14201
+ );
14202
+ const wrappedModelRecord = wrappedModel;
14203
+ const state = {
14204
+ entries: [entry],
14205
+ originalDoGenerate,
14206
+ originalDoStream
14207
+ };
14208
+ Object.defineProperty(wrappedModel, AUTO_PATCHED_MODEL, {
14209
+ configurable: true,
14210
+ value: state
14211
+ });
14212
+ wrappedModel.doGenerate = async function doGeneratePatched(callOptions) {
14213
+ const activeEntry = activeAISDKChildPatchEntry(state.entries);
14214
+ if (!activeEntry) {
14215
+ return Reflect.apply(originalDoGenerate, resolvedModel, [callOptions]);
14216
+ }
14217
+ closeOpenAISDKModelPatchSpans(activeEntry);
14218
+ return activeEntry.parentSpan.traced(
12715
14219
  async (span) => {
12716
- const result = await Reflect.apply(
12717
- originalDoGenerate,
12718
- resolvedModel,
12719
- [options]
12720
- );
12721
- span.log({
12722
- output: processAISDKOutput(result, denyOutputPaths),
12723
- metrics: extractTokenMetrics(result),
12724
- ...buildResolvedMetadataPayload(result)
12725
- });
12726
- return result;
14220
+ activeEntry.openSpans.add(span);
14221
+ try {
14222
+ const result = await Reflect.apply(
14223
+ originalDoGenerate,
14224
+ resolvedModel,
14225
+ [callOptions]
14226
+ );
14227
+ const output = processAISDKOutput(
14228
+ result,
14229
+ activeEntry.denyOutputPaths
14230
+ );
14231
+ const metrics = extractTokenMetrics(result);
14232
+ const metadataPayload = buildResolvedMetadataPayload(result);
14233
+ const missingUsageMetadata = buildMissingUsageMetadata(
14234
+ output,
14235
+ metrics,
14236
+ "ai_sdk_result_missing_usage"
14237
+ );
14238
+ span.log({
14239
+ output,
14240
+ metrics,
14241
+ ...mergeMetadataPayload(metadataPayload, missingUsageMetadata)
14242
+ });
14243
+ return result;
14244
+ } finally {
14245
+ activeEntry.openSpans.delete(span);
14246
+ }
12727
14247
  },
12728
14248
  {
12729
14249
  name: "doGenerate",
12730
14250
  spanAttributes: {
12731
14251
  type: "llm" /* LLM */
12732
14252
  },
12733
- event: {
12734
- input: processAISDKCallInput(options).input,
12735
- metadata: baseMetadata
12736
- }
14253
+ event: buildAISDKModelStartEvent(
14254
+ callOptions,
14255
+ activeEntry.baseMetadata,
14256
+ {
14257
+ workflowAgent: activeEntry.childTracingOptions.workflowAgent
14258
+ }
14259
+ )
12737
14260
  }
12738
14261
  );
12739
14262
  };
12740
14263
  if (originalDoStream) {
12741
- resolvedModel.doStream = async function doStreamPatched(options) {
12742
- const span = parentSpan.startSpan({
14264
+ wrappedModel.doStream = async function doStreamPatched(callOptions) {
14265
+ const activeEntry = activeAISDKChildPatchEntry(state.entries);
14266
+ if (!activeEntry) {
14267
+ return Reflect.apply(originalDoStream, resolvedModel, [callOptions]);
14268
+ }
14269
+ closeOpenAISDKModelPatchSpans(activeEntry);
14270
+ const span = activeEntry.parentSpan.startSpan({
12743
14271
  name: "doStream",
12744
14272
  spanAttributes: {
12745
14273
  type: "llm" /* LLM */
12746
14274
  },
12747
- event: {
12748
- input: processAISDKCallInput(options).input,
12749
- metadata: baseMetadata
12750
- }
14275
+ event: buildAISDKModelStartEvent(
14276
+ callOptions,
14277
+ activeEntry.baseMetadata,
14278
+ {
14279
+ workflowAgent: activeEntry.childTracingOptions.workflowAgent
14280
+ }
14281
+ )
12751
14282
  });
14283
+ activeEntry.openSpans.add(span);
12752
14284
  const streamStartTime = getCurrentUnixTimestamp();
12753
14285
  const result = await withCurrent(
12754
14286
  span,
12755
- () => Reflect.apply(originalDoStream, resolvedModel, [options])
14287
+ () => Reflect.apply(originalDoStream, resolvedModel, [callOptions])
12756
14288
  );
12757
14289
  let firstChunkTime;
12758
14290
  const output = {};
@@ -12760,6 +14292,44 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
12760
14292
  let reasoning = "";
12761
14293
  const toolCalls = [];
12762
14294
  let object = void 0;
14295
+ let streamSpanEnded = false;
14296
+ const logAndEndStreamSpan = (usageUnavailableReason) => {
14297
+ if (streamSpanEnded) {
14298
+ return;
14299
+ }
14300
+ output.text = text;
14301
+ output.reasoning = reasoning;
14302
+ output.toolCalls = toolCalls;
14303
+ if (object !== void 0) {
14304
+ output.object = object;
14305
+ }
14306
+ const metrics = extractTokenMetrics(output);
14307
+ if (firstChunkTime !== void 0 && !activeEntry.childTracingOptions.workflowAgent) {
14308
+ metrics.time_to_first_token = Math.max(
14309
+ firstChunkTime - streamStartTime,
14310
+ 1e-6
14311
+ );
14312
+ }
14313
+ const metadataPayload = buildResolvedMetadataPayload(
14314
+ output
14315
+ );
14316
+ const missingUsageMetadata = usageUnavailableReason ? { usage_unavailable_reason: usageUnavailableReason } : buildMissingUsageMetadata(
14317
+ output,
14318
+ metrics,
14319
+ "ai_sdk_result_missing_usage"
14320
+ );
14321
+ span.log({
14322
+ output: processAISDKOutput(
14323
+ output,
14324
+ activeEntry.denyOutputPaths
14325
+ ),
14326
+ metrics,
14327
+ ...mergeMetadataPayload(metadataPayload, missingUsageMetadata)
14328
+ });
14329
+ activeEntry.openSpans.delete(span);
14330
+ span.end();
14331
+ streamSpanEnded = true;
14332
+ };
12763
14333
  const transformStream = new TransformStream({
12764
14334
  transform(chunk, controller) {
12765
14335
  if (firstChunkTime === void 0 && isAISDKContentStreamChunk(chunk)) {
@@ -12797,33 +14367,15 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
12797
14367
  }
12798
14368
  break;
12799
14369
  case "finish":
12800
- output.text = text;
12801
- output.reasoning = reasoning;
12802
- output.toolCalls = toolCalls;
12803
14370
  output.finishReason = chunk.finishReason;
12804
14371
  output.usage = chunk.usage;
12805
- if (object !== void 0) {
12806
- output.object = object;
12807
- }
12808
- const metrics = extractTokenMetrics(output);
12809
- if (firstChunkTime !== void 0) {
12810
- metrics.time_to_first_token = Math.max(
12811
- firstChunkTime - streamStartTime,
12812
- 1e-6
12813
- );
12814
- }
12815
- span.log({
12816
- output: processAISDKOutput(
12817
- output,
12818
- denyOutputPaths
12819
- ),
12820
- metrics,
12821
- ...buildResolvedMetadataPayload(output)
12822
- });
12823
- span.end();
14372
+ logAndEndStreamSpan();
12824
14373
  break;
12825
14374
  }
12826
14375
  controller.enqueue(chunk);
14376
+ },
14377
+ flush() {
14378
+ logAndEndStreamSpan("ai_sdk_stream_finished_without_usage");
12827
14379
  }
12828
14380
  });
12829
14381
  return {
@@ -12833,32 +14385,79 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
12833
14385
  };
12834
14386
  }
12835
14387
  cleanup.push(() => {
12836
- resolvedModel.doGenerate = originalDoGenerate;
12837
- if (originalDoStream) {
12838
- resolvedModel.doStream = originalDoStream;
12839
- }
12840
- delete resolvedModel[AUTO_PATCHED_MODEL];
14388
+ cleanupModelEntry(state, wrappedModelRecord);
12841
14389
  });
12842
- return resolvedModel;
14390
+ patchedModels.set(resolvedModel, wrappedModel);
14391
+ patchedModels.set(wrappedModel, wrappedModel);
14392
+ return wrappedModel;
12843
14393
  };
12844
14394
  const patchTool = (tool, name) => {
12845
- if (tool == null || typeof tool !== "object" || !("execute" in tool) || typeof tool.execute !== "function" || patchedTools.has(tool) || tool[AUTO_PATCHED_TOOL]) {
14395
+ if (tool == null || typeof tool !== "object" || !("execute" in tool) || typeof tool.execute !== "function" || patchedTools.has(tool)) {
12846
14396
  return;
12847
14397
  }
12848
14398
  patchedTools.add(tool);
12849
- tool[AUTO_PATCHED_TOOL] = true;
12850
- const originalExecute = tool.execute;
14399
+ const toolRecord = tool;
14400
+ const entry = {
14401
+ activeSpanIds: /* @__PURE__ */ new Set([parentSpan.spanId]),
14402
+ childTracingOptions,
14403
+ name,
14404
+ parentSpan
14405
+ };
14406
+ const cleanupToolEntry = (state2) => {
14407
+ const index = state2.entries.indexOf(entry);
14408
+ if (index >= 0) {
14409
+ state2.entries.splice(index, 1);
14410
+ }
14411
+ if (state2.entries.length > 0) {
14412
+ return;
14413
+ }
14414
+ tool.execute = state2.originalExecute;
14415
+ delete toolRecord[AUTO_PATCHED_TOOL];
14416
+ };
14417
+ const existingState = toolRecord[AUTO_PATCHED_TOOL];
14418
+ if (existingState) {
14419
+ if (childTracingOptions.agentOwner && attachNestedAISDKChildPatchEntry(
14420
+ existingState.entries,
14421
+ parentSpan,
14422
+ cleanup
14423
+ )) {
14424
+ return;
14425
+ }
14426
+ if (!childTracingOptions.agentOwner) {
14427
+ shadowActiveAISDKChildPatchEntry(
14428
+ existingState.entries,
14429
+ entry,
14430
+ parentSpan,
14431
+ cleanup
14432
+ );
14433
+ }
14434
+ existingState.entries.push(entry);
14435
+ cleanup.push(() => {
14436
+ cleanupToolEntry(existingState);
14437
+ });
14438
+ return;
14439
+ }
14440
+ const originalExecute = toolRecord.execute;
14441
+ const state = {
14442
+ entries: [entry],
14443
+ originalExecute
14444
+ };
14445
+ toolRecord[AUTO_PATCHED_TOOL] = state;
12851
14446
  tool.execute = function executePatched(...args) {
14447
+ const activeEntry = activeAISDKChildPatchEntry(state.entries);
12852
14448
  const result = Reflect.apply(originalExecute, this, args);
14449
+ if (!activeEntry) {
14450
+ return result;
14451
+ }
12853
14452
  if (isAsyncGenerator(result)) {
12854
14453
  return (async function* () {
12855
- const span = parentSpan.startSpan({
12856
- name,
14454
+ const span = activeEntry.parentSpan.startSpan({
14455
+ name: activeEntry.name,
12857
14456
  spanAttributes: {
12858
14457
  type: "tool" /* TOOL */
12859
14458
  }
12860
14459
  });
12861
- span.log({ input: args.length === 1 ? args[0] : args });
14460
+ span.log({ input: serializeToolExecutionInput(args) });
12862
14461
  try {
12863
14462
  let lastValue;
12864
14463
  for await (const value of result) {
@@ -12874,15 +14473,15 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
12874
14473
  }
12875
14474
  })();
12876
14475
  }
12877
- return parentSpan.traced(
14476
+ return activeEntry.parentSpan.traced(
12878
14477
  async (span) => {
12879
- span.log({ input: args.length === 1 ? args[0] : args });
14478
+ span.log({ input: serializeToolExecutionInput(args) });
12880
14479
  const awaitedResult = await result;
12881
14480
  span.log({ output: awaitedResult });
12882
14481
  return awaitedResult;
12883
14482
  },
12884
14483
  {
12885
- name,
14484
+ name: activeEntry.name,
12886
14485
  spanAttributes: {
12887
14486
  type: "tool" /* TOOL */
12888
14487
  }
@@ -12890,8 +14489,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
12890
14489
  );
12891
14490
  };
12892
14491
  cleanup.push(() => {
12893
- tool.execute = originalExecute;
12894
- delete tool[AUTO_PATCHED_TOOL];
14492
+ cleanupToolEntry(state);
12895
14493
  });
12896
14494
  };
12897
14495
  const patchTools = (tools) => {
@@ -12910,25 +14508,42 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
12910
14508
  }
12911
14509
  };
12912
14510
  if (params && typeof params === "object") {
12913
- const patchedParamModel = patchModel(params.model);
12914
- if (typeof params.model === "string" && patchedParamModel && typeof patchedParamModel === "object") {
14511
+ const originalParamModel = params.model;
14512
+ const patchedParamModel = patchModel(originalParamModel);
14513
+ if (patchedParamModel && patchedParamModel !== originalParamModel) {
12915
14514
  params.model = patchedParamModel;
14515
+ cleanup.push(() => {
14516
+ params.model = originalParamModel;
14517
+ });
12916
14518
  }
12917
14519
  patchTools(params.tools);
12918
14520
  }
12919
14521
  if (self && typeof self === "object") {
12920
14522
  const selfRecord = self;
12921
14523
  if (selfRecord.model !== void 0) {
12922
- const patchedSelfModel = patchModel(selfRecord.model);
12923
- if (typeof selfRecord.model === "string" && patchedSelfModel && typeof patchedSelfModel === "object") {
14524
+ const originalSelfModel = selfRecord.model;
14525
+ const patchedSelfModel = patchModel(originalSelfModel);
14526
+ if (patchedSelfModel && patchedSelfModel !== originalSelfModel) {
12924
14527
  selfRecord.model = patchedSelfModel;
14528
+ cleanup.push(() => {
14529
+ selfRecord.model = originalSelfModel;
14530
+ });
12925
14531
  }
12926
14532
  }
14533
+ if (selfRecord.tools !== void 0) {
14534
+ patchTools(selfRecord.tools);
14535
+ }
12927
14536
  if (selfRecord.settings && typeof selfRecord.settings === "object") {
12928
14537
  if (selfRecord.settings.model !== void 0) {
12929
- const patchedSettingsModel = patchModel(selfRecord.settings.model);
12930
- if (typeof selfRecord.settings.model === "string" && patchedSettingsModel && typeof patchedSettingsModel === "object") {
14538
+ const originalSettingsModel = selfRecord.settings.model;
14539
+ const patchedSettingsModel = patchModel(originalSettingsModel);
14540
+ if (patchedSettingsModel && patchedSettingsModel !== originalSettingsModel) {
12931
14541
  selfRecord.settings.model = patchedSettingsModel;
14542
+ cleanup.push(() => {
14543
+ if (selfRecord.settings) {
14544
+ selfRecord.settings.model = originalSettingsModel;
14545
+ }
14546
+ });
12932
14547
  }
12933
14548
  }
12934
14549
  if (selfRecord.settings.tools !== void 0) {
@@ -13025,99 +14640,190 @@ function isAISDKContentAsyncIterableChunk(chunk) {
13025
14640
  return isObject(part) && typeof part.type !== "string";
13026
14641
  }
13027
14642
  function patchAISDKStreamingResult(args) {
13028
- const { defaultDenyOutputPaths, endEvent, result, span, startTime } = args;
14643
+ const {
14644
+ defaultDenyOutputPaths,
14645
+ endEvent,
14646
+ onComplete,
14647
+ result,
14648
+ span,
14649
+ startTime
14650
+ } = args;
13029
14651
  if (!result || typeof result !== "object") {
13030
14652
  return false;
13031
14653
  }
13032
14654
  const resultRecord = result;
13033
14655
  attachKnownResultPromiseHandlers(resultRecord);
14656
+ let finalized = false;
14657
+ const finalize = () => {
14658
+ if (finalized) {
14659
+ return;
14660
+ }
14661
+ finalized = true;
14662
+ finalizeAISDKChildTracing(endEvent);
14663
+ span.end();
14664
+ onComplete?.();
14665
+ };
14666
+ let outputLogged = false;
14667
+ const logStreamingOutput = async (firstChunkTime) => {
14668
+ if (outputLogged) {
14669
+ return;
14670
+ }
14671
+ outputLogged = true;
14672
+ try {
14673
+ const metrics = extractTopLevelAISDKMetrics(result, endEvent);
14674
+ if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
14675
+ metrics.time_to_first_token = firstChunkTime - startTime;
14676
+ }
14677
+ const output = await processAISDKStreamingOutput(
14678
+ result,
14679
+ resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
14680
+ );
14681
+ const metadata = buildResolvedMetadataPayload(result).metadata;
14682
+ span.log({
14683
+ output,
14684
+ ...metadata ? { metadata } : {},
14685
+ metrics
14686
+ });
14687
+ } catch (error) {
14688
+ span.log({ error: toLoggedError(error) });
14689
+ } finally {
14690
+ finalize();
14691
+ }
14692
+ };
14693
+ const createAsyncIterableHooks = () => {
14694
+ let firstChunkTime;
14695
+ return {
14696
+ onChunk: (chunk) => {
14697
+ if (firstChunkTime === void 0 && isAISDKContentAsyncIterableChunk(chunk)) {
14698
+ firstChunkTime = getCurrentUnixTimestamp();
14699
+ }
14700
+ },
14701
+ onComplete: async () => {
14702
+ await logStreamingOutput(firstChunkTime);
14703
+ },
14704
+ onError: (error) => {
14705
+ if (!outputLogged) {
14706
+ outputLogged = true;
14707
+ span.log({
14708
+ error: error.message
14709
+ });
14710
+ }
14711
+ finalize();
14712
+ },
14713
+ onCancel: finalize
14714
+ };
14715
+ };
14716
+ const patchAsyncIterable = (stream) => isReadableStreamLike(stream) ? createPatchedReadableStream(stream, createAsyncIterableHooks()) : createPatchedAsyncIterable(stream, createAsyncIterableHooks());
14717
+ const patchAsyncIterableField = (field) => {
14718
+ let descriptorOwner = resultRecord;
14719
+ let descriptor;
14720
+ while (descriptorOwner) {
14721
+ descriptor = Object.getOwnPropertyDescriptor(descriptorOwner, field);
14722
+ if (descriptor) {
14723
+ break;
14724
+ }
14725
+ descriptorOwner = Object.getPrototypeOf(descriptorOwner);
14726
+ }
14727
+ if (!descriptor || descriptorOwner === resultRecord && !descriptor.configurable) {
14728
+ return false;
14729
+ }
14730
+ if ("value" in descriptor) {
14731
+ if (!isAsyncIterable(descriptor.value)) {
14732
+ return false;
14733
+ }
14734
+ try {
14735
+ Object.defineProperty(resultRecord, field, {
14736
+ configurable: descriptorOwner === resultRecord ? descriptor.configurable : true,
14737
+ enumerable: descriptor.enumerable,
14738
+ value: patchAsyncIterable(descriptor.value),
14739
+ writable: descriptor.writable
14740
+ });
14741
+ return true;
14742
+ } catch {
14743
+ return false;
14744
+ }
14745
+ }
14746
+ if (typeof descriptor.get !== "function") {
14747
+ return false;
14748
+ }
14749
+ const originalGet = descriptor.get;
14750
+ const originalSet = descriptor.set;
14751
+ try {
14752
+ Object.defineProperty(resultRecord, field, {
14753
+ configurable: descriptorOwner === resultRecord ? descriptor.configurable : true,
14754
+ enumerable: descriptor.enumerable,
14755
+ get() {
14756
+ const stream = originalGet.call(this);
14757
+ return isAsyncIterable(stream) ? patchAsyncIterable(stream) : stream;
14758
+ },
14759
+ ...originalSet ? {
14760
+ set(value) {
14761
+ originalSet.call(this, value);
14762
+ }
14763
+ } : {}
14764
+ });
14765
+ return true;
14766
+ } catch {
14767
+ return false;
14768
+ }
14769
+ };
14770
+ let patched = false;
13034
14771
  if (isReadableStreamLike(resultRecord.baseStream)) {
13035
- let firstChunkTime2;
13036
- const wrappedBaseStream = resultRecord.baseStream.pipeThrough(
14772
+ let firstChunkTime;
14773
+ const transformedBaseStream = resultRecord.baseStream.pipeThrough(
13037
14774
  new TransformStream({
13038
14775
  transform(chunk, controller) {
13039
- if (firstChunkTime2 === void 0 && isAISDKContentStreamChunk(chunk)) {
13040
- firstChunkTime2 = getCurrentUnixTimestamp();
14776
+ if (firstChunkTime === void 0 && isAISDKContentStreamChunk(chunk)) {
14777
+ firstChunkTime = getCurrentUnixTimestamp();
13041
14778
  }
13042
14779
  controller.enqueue(chunk);
13043
14780
  },
13044
14781
  async flush() {
13045
- const metrics = extractTopLevelAISDKMetrics(result, endEvent);
13046
- if (metrics.time_to_first_token === void 0 && firstChunkTime2 !== void 0) {
13047
- metrics.time_to_first_token = firstChunkTime2 - startTime;
13048
- }
13049
- const output = await processAISDKStreamingOutput(
13050
- result,
13051
- resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
13052
- );
13053
- const metadata = buildResolvedMetadataPayload(result).metadata;
13054
- span.log({
13055
- output,
13056
- ...metadata ? { metadata } : {},
13057
- metrics
13058
- });
13059
- finalizeAISDKChildTracing(endEvent);
13060
- span.end();
14782
+ await logStreamingOutput(firstChunkTime);
13061
14783
  }
13062
14784
  })
13063
14785
  );
14786
+ const reader = transformedBaseStream.getReader();
14787
+ const wrappedBaseStream = new ReadableStream({
14788
+ async pull(controller) {
14789
+ try {
14790
+ const { done, value } = await reader.read();
14791
+ if (done) {
14792
+ controller.close();
14793
+ return;
14794
+ }
14795
+ controller.enqueue(value);
14796
+ } catch (error) {
14797
+ span.log({ error: toLoggedError(error) });
14798
+ finalize();
14799
+ controller.error(error);
14800
+ }
14801
+ },
14802
+ async cancel(reason) {
14803
+ try {
14804
+ finalize();
14805
+ } finally {
14806
+ await reader.cancel(reason);
14807
+ }
14808
+ }
14809
+ });
13064
14810
  Object.defineProperty(resultRecord, "baseStream", {
13065
14811
  configurable: true,
13066
14812
  enumerable: true,
13067
14813
  value: wrappedBaseStream,
13068
14814
  writable: true
13069
14815
  });
13070
- return true;
14816
+ patched = true;
13071
14817
  }
13072
- const streamField = findAsyncIterableField(resultRecord, [
14818
+ for (const field of [
13073
14819
  "partialObjectStream",
13074
14820
  "textStream",
13075
14821
  "fullStream",
13076
14822
  "stream"
13077
- ]);
13078
- if (!streamField) {
13079
- return false;
14823
+ ]) {
14824
+ patched = patchAsyncIterableField(field) || patched;
13080
14825
  }
13081
- let firstChunkTime;
13082
- const wrappedStream = createPatchedAsyncIterable(streamField.stream, {
13083
- onChunk: (chunk) => {
13084
- if (firstChunkTime === void 0 && isAISDKContentAsyncIterableChunk(chunk)) {
13085
- firstChunkTime = getCurrentUnixTimestamp();
13086
- }
13087
- },
13088
- onComplete: async () => {
13089
- const metrics = extractTopLevelAISDKMetrics(result, endEvent);
13090
- if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
13091
- metrics.time_to_first_token = firstChunkTime - startTime;
13092
- }
13093
- const output = await processAISDKStreamingOutput(
13094
- result,
13095
- resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
13096
- );
13097
- const metadata = buildResolvedMetadataPayload(result).metadata;
13098
- span.log({
13099
- output,
13100
- ...metadata ? { metadata } : {},
13101
- metrics
13102
- });
13103
- finalizeAISDKChildTracing(endEvent);
13104
- span.end();
13105
- },
13106
- onError: (error) => {
13107
- span.log({
13108
- error: error.message
13109
- });
13110
- finalizeAISDKChildTracing(endEvent);
13111
- span.end();
13112
- }
13113
- });
13114
- Object.defineProperty(resultRecord, streamField.field, {
13115
- configurable: true,
13116
- enumerable: true,
13117
- value: wrappedStream,
13118
- writable: true
13119
- });
13120
- return true;
14826
+ return patched;
13121
14827
  }
13122
14828
  function attachKnownResultPromiseHandlers(result) {
13123
14829
  const promiseLikeFields = [
@@ -13149,34 +14855,72 @@ function attachKnownResultPromiseHandlers(result) {
13149
14855
  }
13150
14856
  }
13151
14857
  function isReadableStreamLike(value) {
13152
- return value != null && typeof value === "object" && typeof value.pipeThrough === "function";
13153
- }
13154
- function findAsyncIterableField(result, candidateFields) {
13155
- for (const field of candidateFields) {
13156
- try {
13157
- const stream = result[field];
13158
- if (isAsyncIterable(stream)) {
13159
- return { field, stream };
14858
+ return value != null && typeof value === "object" && typeof value.getReader === "function" && typeof value.pipeThrough === "function";
14859
+ }
14860
+ function createPatchedReadableStream(stream, hooks) {
14861
+ let reader;
14862
+ let completed = false;
14863
+ return new ReadableStream({
14864
+ async pull(controller) {
14865
+ reader ??= stream.getReader();
14866
+ try {
14867
+ const { done, value } = await reader.read();
14868
+ if (done) {
14869
+ completed = true;
14870
+ await hooks.onComplete();
14871
+ controller.close();
14872
+ return;
14873
+ }
14874
+ hooks.onChunk(value);
14875
+ controller.enqueue(value);
14876
+ } catch (error) {
14877
+ completed = true;
14878
+ hooks.onError(
14879
+ error instanceof Error ? error : new Error(String(error))
14880
+ );
14881
+ controller.error(error);
14882
+ }
14883
+ },
14884
+ async cancel(reason) {
14885
+ if (!completed) {
14886
+ completed = true;
14887
+ try {
14888
+ await hooks.onCancel?.();
14889
+ } catch {
14890
+ }
14891
+ }
14892
+ if (reader) {
14893
+ await reader.cancel(reason);
14894
+ } else if (stream.cancel) {
14895
+ await stream.cancel(reason);
13160
14896
  }
13161
- } catch {
13162
14897
  }
13163
- }
13164
- return null;
14898
+ });
13165
14899
  }
13166
14900
  function createPatchedAsyncIterable(stream, hooks) {
13167
14901
  return {
13168
14902
  async *[Symbol.asyncIterator]() {
14903
+ let completed = false;
13169
14904
  try {
13170
14905
  for await (const chunk of stream) {
13171
14906
  hooks.onChunk(chunk);
13172
14907
  yield chunk;
13173
14908
  }
14909
+ completed = true;
13174
14910
  await hooks.onComplete();
13175
14911
  } catch (error) {
14912
+ completed = true;
13176
14913
  hooks.onError(
13177
14914
  error instanceof Error ? error : new Error(String(error))
13178
14915
  );
13179
14916
  throw error;
14917
+ } finally {
14918
+ if (!completed) {
14919
+ try {
14920
+ await hooks.onCancel?.();
14921
+ } catch {
14922
+ }
14923
+ }
13180
14924
  }
13181
14925
  }
13182
14926
  };
@@ -13251,6 +14995,40 @@ function buildResolvedMetadataPayload(result) {
13251
14995
  }
13252
14996
  return Object.keys(metadata).length > 0 ? { metadata } : {};
13253
14997
  }
14998
+ function mergeMetadataPayload(metadataPayload, extraMetadata) {
14999
+ if (!extraMetadata || Object.keys(extraMetadata).length === 0) {
15000
+ return metadataPayload;
15001
+ }
15002
+ return {
15003
+ metadata: {
15004
+ ...metadataPayload.metadata ?? {},
15005
+ ...extraMetadata
15006
+ }
15007
+ };
15008
+ }
15009
+ function buildMissingUsageMetadata(output, metrics, reason) {
15010
+ if (!hasLoggedOutput(output) || hasTokenUsageMetrics(metrics)) {
15011
+ return void 0;
15012
+ }
15013
+ return { usage_unavailable_reason: reason };
15014
+ }
15015
+ function hasLoggedOutput(output) {
15016
+ if (output === null || output === void 0) {
15017
+ return false;
15018
+ }
15019
+ if (Array.isArray(output)) {
15020
+ return output.length > 0;
15021
+ }
15022
+ if (typeof output === "object") {
15023
+ return Object.keys(output).length > 0;
15024
+ }
15025
+ return true;
15026
+ }
15027
+ function hasTokenUsageMetrics(metrics) {
15028
+ return Object.keys(metrics).some(
15029
+ (key) => key !== "estimated_cost" && key !== "time_to_first_token"
15030
+ );
15031
+ }
13254
15032
  function resolveAISDKModel(model, aiSDK) {
13255
15033
  if (typeof model !== "string") {
13256
15034
  return model;
@@ -13274,7 +15052,45 @@ function isAsyncGenerator(value) {
13274
15052
  function processAISDKOutput(output, denyOutputPaths) {
13275
15053
  if (!output) return output;
13276
15054
  const merged = extractSerializableOutputFields(output);
13277
- return normalizeAISDKLoggedOutput(omit(merged, denyOutputPaths));
15055
+ const deleteOutputPaths = denyOutputPaths.filter(
15056
+ (path) => path.toLowerCase().endsWith("headers")
15057
+ );
15058
+ const sanitized = omit(merged, denyOutputPaths, deleteOutputPaths);
15059
+ for (const path of TRANSPORT_PAYLOAD_ROOT_PATHS) {
15060
+ const stack = [{ obj: sanitized, keys: parsePath(path) }];
15061
+ while (stack.length > 0) {
15062
+ const entry = stack.pop();
15063
+ if (!entry || entry.keys.length === 0) {
15064
+ continue;
15065
+ }
15066
+ const firstKey = entry.keys[0];
15067
+ const remainingKeys = entry.keys.slice(1);
15068
+ if (firstKey === "[]") {
15069
+ if (Array.isArray(entry.obj)) {
15070
+ for (const item of entry.obj) {
15071
+ stack.push({
15072
+ obj: item,
15073
+ keys: remainingKeys
15074
+ });
15075
+ }
15076
+ }
15077
+ continue;
15078
+ }
15079
+ if (!entry.obj || typeof entry.obj !== "object" || !(firstKey in entry.obj)) {
15080
+ continue;
15081
+ }
15082
+ const record = entry.obj;
15083
+ if (remainingKeys.length === 0) {
15084
+ record[firstKey] = sanitizeAISDKMetadataValue(record[firstKey]);
15085
+ continue;
15086
+ }
15087
+ stack.push({
15088
+ obj: record[firstKey],
15089
+ keys: remainingKeys
15090
+ });
15091
+ }
15092
+ }
15093
+ return normalizeAISDKLoggedOutput(sanitized);
13278
15094
  }
13279
15095
  function processAISDKEmbeddingOutput(output, denyOutputPaths) {
13280
15096
  if (!output || typeof output !== "object") {
@@ -13365,6 +15181,8 @@ function extractTokenMetrics(result) {
13365
15181
  );
13366
15182
  if (totalTokens !== void 0) {
13367
15183
  metrics.tokens = totalTokens;
15184
+ } else if (promptTokens !== void 0 && completionTokens !== void 0) {
15185
+ metrics.tokens = promptTokens + completionTokens;
13368
15186
  }
13369
15187
  const promptCachedTokens = firstNumber2(
13370
15188
  usage.inputTokens?.cacheRead,
@@ -13488,7 +15306,9 @@ function extractGetterValues(obj) {
13488
15306
  const getterValues = {};
13489
15307
  const getterNames = [
13490
15308
  "content",
15309
+ "messages",
13491
15310
  "text",
15311
+ "output",
13492
15312
  "object",
13493
15313
  "value",
13494
15314
  "values",
@@ -13528,7 +15348,9 @@ function extractGetterValues(obj) {
13528
15348
  function extractSerializableOutputFields(output) {
13529
15349
  const serialized = {};
13530
15350
  const directFieldNames = [
15351
+ "messages",
13531
15352
  "steps",
15353
+ "output",
13532
15354
  "request",
13533
15355
  "responseMessages",
13534
15356
  "warnings",
@@ -13710,7 +15532,7 @@ function parsePath(path) {
13710
15532
  }
13711
15533
  return keys;
13712
15534
  }
13713
- function omitAtPath(obj, keys) {
15535
+ function omitAtPath(obj, keys, deleteLeaf = false) {
13714
15536
  if (keys.length === 0) return;
13715
15537
  const firstKey = keys[0];
13716
15538
  const remainingKeys = keys.slice(1);
@@ -13720,29 +15542,36 @@ function omitAtPath(obj, keys) {
13720
15542
  if (remainingKeys.length > 0) {
13721
15543
  omitAtPath(
13722
15544
  item,
13723
- remainingKeys
15545
+ remainingKeys,
15546
+ deleteLeaf
13724
15547
  );
13725
15548
  }
13726
15549
  });
13727
15550
  }
13728
15551
  } else if (remainingKeys.length === 0) {
13729
15552
  if (obj && typeof obj === "object" && firstKey in obj) {
13730
- obj[firstKey] = "<omitted>";
15553
+ if (deleteLeaf) {
15554
+ delete obj[firstKey];
15555
+ } else {
15556
+ obj[firstKey] = "<omitted>";
15557
+ }
13731
15558
  }
13732
15559
  } else {
13733
15560
  if (obj && typeof obj === "object" && firstKey in obj) {
13734
15561
  omitAtPath(
13735
15562
  obj[firstKey],
13736
- remainingKeys
15563
+ remainingKeys,
15564
+ deleteLeaf
13737
15565
  );
13738
15566
  }
13739
15567
  }
13740
15568
  }
13741
- function omit(obj, paths) {
15569
+ function omit(obj, paths, deletePaths = []) {
13742
15570
  const result = deepCopy(obj);
15571
+ const deletePathSet = new Set(deletePaths);
13743
15572
  for (const path of paths) {
13744
15573
  const keys = parsePath(path);
13745
- omitAtPath(result, keys);
15574
+ omitAtPath(result, keys, deletePathSet.has(path));
13746
15575
  }
13747
15576
  return result;
13748
15577
  }
@@ -23791,15 +25620,18 @@ function observeFlue(event, ctx) {
23791
25620
  getObserveBridge().handle(event, ctx);
23792
25621
  }
23793
25622
  var interceptFlueExecution = (operation, ctx, next) => getObserveBridge().intercept(operation, ctx, next);
23794
- var braintrustFlueObserver = Object.assign(
23795
- observeFlue,
23796
- {
25623
+ function braintrustFlueInstrumentation() {
25624
+ return {
23797
25625
  dispose() {
23798
25626
  },
23799
25627
  interceptor: interceptFlueExecution,
23800
25628
  key: FLUE_INSTRUMENTATION_KEY,
23801
25629
  observe: observeFlue
23802
- }
25630
+ };
25631
+ }
25632
+ var braintrustFlueObserver = Object.assign(
25633
+ observeFlue,
25634
+ braintrustFlueInstrumentation()
23803
25635
  );
23804
25636
  var FluePlugin = class extends BasePlugin {
23805
25637
  onEnable() {
@@ -27356,6 +29188,7 @@ function configureInstrumentation(config) {
27356
29188
  BasePlugin,
27357
29189
  BraintrustPlugin,
27358
29190
  OpenAIAgentsTraceProcessor,
29191
+ braintrustFlueInstrumentation,
27359
29192
  braintrustFlueObserver,
27360
29193
  configureInstrumentation,
27361
29194
  createChannelName,