braintrust 3.20.0 → 3.22.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 +6 -0
  3. package/dev/dist/index.d.mts +1338 -199
  4. package/dev/dist/index.d.ts +1338 -199
  5. package/dev/dist/index.js +2904 -997
  6. package/dev/dist/index.mjs +2418 -511
  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 +824 -56
  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 +4411 -719
  49. package/dist/browser.d.ts +4411 -719
  50. package/dist/browser.js +4274 -480
  51. package/dist/browser.mjs +4274 -480
  52. package/dist/{chunk-LPC4W2WX.js → chunk-BFGIH2ZJ.js} +4 -0
  53. package/dist/{chunk-Y7W7WP6H.mjs → chunk-KMGUTPB7.mjs} +4 -0
  54. package/dist/{chunk-POCCIJAL.js → chunk-MWVVR5LR.js} +3278 -1334
  55. package/dist/{chunk-F73OMF66.mjs → chunk-ZG2O3XVF.mjs} +2542 -598
  56. package/dist/cli.js +2338 -419
  57. package/dist/edge-light.d.mts +1 -1
  58. package/dist/edge-light.d.ts +1 -1
  59. package/dist/edge-light.js +4274 -480
  60. package/dist/edge-light.mjs +4274 -480
  61. package/dist/index.d.mts +4926 -1234
  62. package/dist/index.d.ts +4926 -1234
  63. package/dist/index.js +2303 -435
  64. package/dist/index.mjs +1914 -46
  65. package/dist/instrumentation/index.d.mts +1026 -20
  66. package/dist/instrumentation/index.d.ts +1026 -20
  67. package/dist/instrumentation/index.js +3864 -483
  68. package/dist/instrumentation/index.mjs +3862 -483
  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 +4274 -480
  74. package/dist/workerd.mjs +4274 -480
  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 +16 -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
@@ -589,8 +589,291 @@ var UUIDGenerator = class extends IDGenerator {
589
589
  return true;
590
590
  }
591
591
  };
592
+ function generateHexId(bytes) {
593
+ let result = "";
594
+ for (let i = 0; i < bytes; i++) {
595
+ result += Math.floor(Math.random() * 256).toString(16).padStart(2, "0");
596
+ }
597
+ return result;
598
+ }
599
+ var OTELIDGenerator = class extends IDGenerator {
600
+ getSpanId() {
601
+ return generateHexId(8);
602
+ }
603
+ getTraceId() {
604
+ return generateHexId(16);
605
+ }
606
+ shareRootSpanId() {
607
+ return false;
608
+ }
609
+ };
610
+ function parseEnvBool(name) {
611
+ const raw = isomorph_default.getEnv(name);
612
+ if (raw === void 0 || raw === null) {
613
+ return false;
614
+ }
615
+ const normalized = raw.trim().toLowerCase();
616
+ return normalized === "true" || normalized === "1" || normalized === "yes" || normalized === "y" || normalized === "on";
617
+ }
618
+ var _warnedLegacyUuidConflict = false;
619
+ function resolveUseLegacyUuidIds() {
620
+ const legacy = parseEnvBool("BRAINTRUST_LEGACY_IDS");
621
+ if (parseEnvBool("BRAINTRUST_OTEL_COMPAT")) {
622
+ if (legacy && !_warnedLegacyUuidConflict) {
623
+ _warnedLegacyUuidConflict = true;
624
+ debugLogger.warn(
625
+ "BRAINTRUST_LEGACY_IDS is ignored because BRAINTRUST_OTEL_COMPAT requires OpenTelemetry-compatible hex span IDs. Using hex IDs."
626
+ );
627
+ }
628
+ return false;
629
+ }
630
+ return legacy;
631
+ }
592
632
  function getIdGenerator() {
593
- return globalThis.BRAINTRUST_ID_GENERATOR !== void 0 ? new globalThis.BRAINTRUST_ID_GENERATOR() : new UUIDGenerator();
633
+ if (globalThis.BRAINTRUST_ID_GENERATOR !== void 0) {
634
+ return new globalThis.BRAINTRUST_ID_GENERATOR();
635
+ }
636
+ return resolveUseLegacyUuidIds() ? new UUIDGenerator() : new OTELIDGenerator();
637
+ }
638
+
639
+ // src/propagation.ts
640
+ var TRACEPARENT_HEADER = "traceparent";
641
+ var TRACESTATE_HEADER = "tracestate";
642
+ var BAGGAGE_HEADER = "baggage";
643
+ var BRAINTRUST_PARENT_KEY = "braintrust.parent";
644
+ var DEFAULT_TRACE_FLAGS = "01";
645
+ var TRACEPARENT_RE = /^00-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$/;
646
+ var ZERO_TRACE_ID = "0".repeat(32);
647
+ var ZERO_SPAN_ID = "0".repeat(16);
648
+ var MAX_BAGGAGE_LENGTH = 8192;
649
+ var MAX_BAGGAGE_MEMBERS = 64;
650
+ var _utf8Encoder = new TextEncoder();
651
+ function utf8ByteLength(value) {
652
+ return _utf8Encoder.encode(value).length;
653
+ }
654
+ function capBaggageToMemberBoundary(value) {
655
+ const totalBytes = utf8ByteLength(value);
656
+ const withinBytes = totalBytes <= MAX_BAGGAGE_LENGTH;
657
+ let commaCount = 0;
658
+ for (let i = 0; i < value.length; i++) {
659
+ if (value.charCodeAt(i) === 44) {
660
+ commaCount++;
661
+ }
662
+ }
663
+ const withinMembers = commaCount < MAX_BAGGAGE_MEMBERS;
664
+ if (withinBytes && withinMembers) {
665
+ return value;
666
+ }
667
+ const kept = [];
668
+ let length = 0;
669
+ for (const rawMember of value.split(",")) {
670
+ if (kept.length >= MAX_BAGGAGE_MEMBERS) {
671
+ break;
672
+ }
673
+ const cost = utf8ByteLength(rawMember) + (kept.length ? 1 : 0);
674
+ if (length + cost > MAX_BAGGAGE_LENGTH) {
675
+ break;
676
+ }
677
+ kept.push(rawMember);
678
+ length += cost;
679
+ }
680
+ if (!kept.length) {
681
+ return "";
682
+ }
683
+ return kept.join(",");
684
+ }
685
+ function isTraceContextHeaderTupleArray(value) {
686
+ return Array.isArray(value) && value.every(
687
+ (item) => Array.isArray(item) && typeof item[0] === "string" && typeof item[1] === "string"
688
+ );
689
+ }
690
+ function isListHeader(name) {
691
+ const lowered = name.toLowerCase();
692
+ return lowered === BAGGAGE_HEADER || lowered === TRACESTATE_HEADER;
693
+ }
694
+ function headerValueToString(value, name) {
695
+ if (value === void 0 || value === null) {
696
+ return void 0;
697
+ }
698
+ if (Array.isArray(value)) {
699
+ const stringValues = value.filter((item) => {
700
+ return typeof item === "string";
701
+ });
702
+ if (!stringValues.length) {
703
+ return void 0;
704
+ }
705
+ return isListHeader(name) ? stringValues.join(",") : stringValues[0];
706
+ }
707
+ return typeof value === "string" ? value : String(value);
708
+ }
709
+ function getHeader(headers, name) {
710
+ if (!headers) {
711
+ return void 0;
712
+ }
713
+ if (isTraceContextHeaderTupleArray(headers)) {
714
+ const lowered2 = name.toLowerCase();
715
+ const matches = headers.filter(([key]) => key.toLowerCase() === lowered2).map(([, value]) => value);
716
+ if (!matches.length) {
717
+ return void 0;
718
+ }
719
+ return headerValueToString(matches, name);
720
+ }
721
+ const getter = headers.get;
722
+ if (typeof getter === "function") {
723
+ try {
724
+ const value = headerValueToString(getter.call(headers, name), name);
725
+ if (value !== void 0) {
726
+ return value;
727
+ }
728
+ } catch {
729
+ }
730
+ }
731
+ const nodeGetter = headers.getHeader;
732
+ if (typeof nodeGetter === "function") {
733
+ try {
734
+ const value = headerValueToString(nodeGetter.call(headers, name), name);
735
+ if (value !== void 0) {
736
+ return value;
737
+ }
738
+ } catch {
739
+ }
740
+ }
741
+ const headerBag = headers;
742
+ const exact = headerValueToString(headerBag[name], name);
743
+ if (exact !== void 0) {
744
+ return exact;
745
+ }
746
+ const lowered = name.toLowerCase();
747
+ for (const key of Object.keys(headers)) {
748
+ if (key !== name && key.toLowerCase() === lowered) {
749
+ const value = headerValueToString(headerBag[key], name);
750
+ if (value !== void 0) {
751
+ return value;
752
+ }
753
+ }
754
+ }
755
+ return void 0;
756
+ }
757
+ function isHex(value, length) {
758
+ if (typeof value !== "string" || value.length !== length) {
759
+ return false;
760
+ }
761
+ for (let i = 0; i < value.length; i++) {
762
+ const c = value[i];
763
+ const isDigit = c >= "0" && c <= "9";
764
+ const isLowerHex = c >= "a" && c <= "f";
765
+ if (!isDigit && !isLowerHex) {
766
+ return false;
767
+ }
768
+ }
769
+ return true;
770
+ }
771
+ function parseTraceparent(value) {
772
+ if (!value || typeof value !== "string") {
773
+ return void 0;
774
+ }
775
+ const match = TRACEPARENT_RE.exec(value.trim());
776
+ if (!match) {
777
+ return void 0;
778
+ }
779
+ const traceId = match[1];
780
+ const spanId = match[2];
781
+ const traceFlags = match[3];
782
+ if (traceId === ZERO_TRACE_ID || spanId === ZERO_SPAN_ID) {
783
+ return void 0;
784
+ }
785
+ return { traceId, spanId, traceFlags };
786
+ }
787
+ function formatTraceparent(traceId, spanId, traceFlags = DEFAULT_TRACE_FLAGS) {
788
+ if (!isHex(traceId, 32) || traceId === ZERO_TRACE_ID) {
789
+ return void 0;
790
+ }
791
+ if (!isHex(spanId, 16) || spanId === ZERO_SPAN_ID) {
792
+ return void 0;
793
+ }
794
+ const flags = isHex(traceFlags, 2) ? traceFlags : DEFAULT_TRACE_FLAGS;
795
+ return `00-${traceId}-${spanId}-${flags}`;
796
+ }
797
+ function percentEncode(value) {
798
+ return encodeURIComponent(value);
799
+ }
800
+ function percentDecode(value) {
801
+ if (!value.includes("%")) {
802
+ return value;
803
+ }
804
+ try {
805
+ return decodeURIComponent(value);
806
+ } catch {
807
+ return value;
808
+ }
809
+ }
810
+ function parseBaggage(value) {
811
+ const result = {};
812
+ if (!value || typeof value !== "string") {
813
+ return result;
814
+ }
815
+ const bounded = capBaggageToMemberBoundary(value);
816
+ for (let member of bounded.split(",")) {
817
+ member = member.trim();
818
+ if (!member || !member.includes("=")) {
819
+ continue;
820
+ }
821
+ member = member.split(";", 1)[0];
822
+ const eq = member.indexOf("=");
823
+ const key = percentDecode(member.slice(0, eq).trim());
824
+ const val = member.slice(eq + 1).trim();
825
+ if (!key) {
826
+ continue;
827
+ }
828
+ result[key] = percentDecode(val);
829
+ }
830
+ return result;
831
+ }
832
+ function mergeBaggage(existing, braintrustParent) {
833
+ let btMember = void 0;
834
+ if (braintrustParent) {
835
+ const encodedKey = percentEncode(BRAINTRUST_PARENT_KEY);
836
+ const encodedVal = percentEncode(String(braintrustParent));
837
+ btMember = `${encodedKey}=${encodedVal}`;
838
+ if (utf8ByteLength(btMember) > MAX_BAGGAGE_LENGTH) {
839
+ btMember = void 0;
840
+ }
841
+ }
842
+ let byteBudget = MAX_BAGGAGE_LENGTH;
843
+ let memberBudget = MAX_BAGGAGE_MEMBERS;
844
+ if (btMember !== void 0) {
845
+ byteBudget -= utf8ByteLength(btMember) + 1;
846
+ memberBudget -= 1;
847
+ }
848
+ const relayed = [];
849
+ let length = 0;
850
+ if (existing && typeof existing === "string") {
851
+ for (const rawMember of existing.split(",")) {
852
+ const member = rawMember.trim();
853
+ if (!member || !member.includes("=")) {
854
+ continue;
855
+ }
856
+ const keyPart = member.split(";", 1)[0].split("=", 1)[0];
857
+ const key = percentDecode(keyPart.trim());
858
+ if (key === BRAINTRUST_PARENT_KEY) {
859
+ continue;
860
+ }
861
+ if (relayed.length >= memberBudget) {
862
+ break;
863
+ }
864
+ const cost = utf8ByteLength(member) + (relayed.length ? 1 : 0);
865
+ if (length + cost > byteBudget) {
866
+ break;
867
+ }
868
+ relayed.push(member);
869
+ length += cost;
870
+ }
871
+ }
872
+ const members = btMember !== void 0 ? [...relayed, btMember] : relayed;
873
+ if (!members.length) {
874
+ return void 0;
875
+ }
876
+ return members.join(",");
594
877
  }
595
878
 
596
879
  // util/db_fields.ts
@@ -1198,7 +1481,7 @@ var SpanComponentsV3 = class _SpanComponentsV3 {
1198
1481
  case 3 /* PLAYGROUND_LOGS */:
1199
1482
  return { prompt_session_id: this.data.object_id, log_id: "x" };
1200
1483
  default:
1201
- const _ = this.data.object_type;
1484
+ this.data.object_type;
1202
1485
  throw new Error("Impossible");
1203
1486
  }
1204
1487
  }
@@ -1731,7 +2014,7 @@ var SpanComponentsV4 = class _SpanComponentsV4 {
1731
2014
  case 3 /* PLAYGROUND_LOGS */:
1732
2015
  return { prompt_session_id: this.data.object_id, log_id: "x" };
1733
2016
  default:
1734
- const _ = this.data.object_type;
2017
+ this.data.object_type;
1735
2018
  throw new Error(`Invalid object_type ${this.data.object_type}`);
1736
2019
  }
1737
2020
  }
@@ -1921,7 +2204,8 @@ var AclObjectType = z6.union([
1921
2204
  "role",
1922
2205
  "org_member",
1923
2206
  "project_log",
1924
- "org_project"
2207
+ "org_project",
2208
+ "org_audit_logs"
1925
2209
  ]),
1926
2210
  z6.null()
1927
2211
  ]);
@@ -1947,6 +2231,17 @@ var Acl = z6.object({
1947
2231
  _object_org_id: z6.string().uuid(),
1948
2232
  created: z6.union([z6.string(), z6.null()]).optional()
1949
2233
  });
2234
+ var Agent = z6.object({
2235
+ id: z6.string().uuid(),
2236
+ project_id: z6.string().uuid(),
2237
+ user_id: z6.string().uuid(),
2238
+ created: z6.union([z6.string(), z6.null()]).optional(),
2239
+ name: z6.string(),
2240
+ slug: z6.string(),
2241
+ kind: z6.string(),
2242
+ description: z6.union([z6.string(), z6.null()]).optional(),
2243
+ metadata: z6.union([z6.object({}).partial().passthrough(), z6.null()]).optional()
2244
+ });
1950
2245
  var AISecret = z6.object({
1951
2246
  id: z6.string().uuid(),
1952
2247
  created: z6.union([z6.string(), z6.null()]).optional(),
@@ -2093,6 +2388,7 @@ var AttachmentStatus = z6.object({
2093
2388
  upload_status: UploadStatus,
2094
2389
  error_message: z6.string().optional()
2095
2390
  });
2391
+ var AutomationStatus = z6.enum(["active", "paused"]);
2096
2392
  var FunctionTypeEnum = z6.enum([
2097
2393
  "llm",
2098
2394
  "scorer",
@@ -2138,7 +2434,9 @@ var TopicMapData = z6.object({
2138
2434
  topic_names: z6.record(z6.string()).optional(),
2139
2435
  generation_settings: TopicMapGenerationSettings.optional(),
2140
2436
  disable_reconciliation: z6.boolean().optional(),
2141
- distance_threshold: z6.number().optional()
2437
+ distance_threshold: z6.number().optional(),
2438
+ btql_filter: z6.string().optional(),
2439
+ automation_btql_filter: z6.string().optional()
2142
2440
  });
2143
2441
  var BatchedFacetData = z6.object({
2144
2442
  type: z6.literal("batched_facet"),
@@ -2212,19 +2510,30 @@ var CallEvent = z6.union([
2212
2510
  var ChatCompletionContentPartTextWithTitle = z6.object({
2213
2511
  text: z6.string().default(""),
2214
2512
  type: z6.literal("text"),
2215
- cache_control: z6.object({ type: z6.literal("ephemeral") }).optional()
2513
+ cache_control: z6.object({
2514
+ type: z6.literal("ephemeral"),
2515
+ ttl: z6.enum(["5m", "1h"]).optional()
2516
+ }).optional()
2216
2517
  });
2217
2518
  var ChatCompletionContentPartImageWithTitle = z6.object({
2218
2519
  image_url: z6.object({
2219
2520
  url: z6.string(),
2220
2521
  detail: z6.union([z6.literal("auto"), z6.literal("low"), z6.literal("high")]).optional()
2221
2522
  }),
2222
- type: z6.literal("image_url")
2523
+ type: z6.literal("image_url"),
2524
+ cache_control: z6.object({
2525
+ type: z6.literal("ephemeral"),
2526
+ ttl: z6.enum(["5m", "1h"]).optional()
2527
+ }).optional()
2223
2528
  });
2224
2529
  var ChatCompletionContentPartFileFile = z6.object({ file_data: z6.string(), filename: z6.string(), file_id: z6.string() }).partial();
2225
2530
  var ChatCompletionContentPartFileWithTitle = z6.object({
2226
2531
  file: ChatCompletionContentPartFileFile,
2227
- type: z6.literal("file")
2532
+ type: z6.literal("file"),
2533
+ cache_control: z6.object({
2534
+ type: z6.literal("ephemeral"),
2535
+ ttl: z6.enum(["5m", "1h"]).optional()
2536
+ }).optional()
2228
2537
  });
2229
2538
  var ChatCompletionContentPart = z6.union([
2230
2539
  ChatCompletionContentPartTextWithTitle,
@@ -2234,7 +2543,10 @@ var ChatCompletionContentPart = z6.union([
2234
2543
  var ChatCompletionContentPartText = z6.object({
2235
2544
  text: z6.string().default(""),
2236
2545
  type: z6.literal("text"),
2237
- cache_control: z6.object({ type: z6.literal("ephemeral") }).optional()
2546
+ cache_control: z6.object({
2547
+ type: z6.literal("ephemeral"),
2548
+ ttl: z6.enum(["5m", "1h"]).optional()
2549
+ }).optional()
2238
2550
  });
2239
2551
  var ChatCompletionMessageToolCall = z6.object({
2240
2552
  id: z6.string(),
@@ -2421,7 +2733,7 @@ var DatasetEvent = z6.object({
2421
2733
  origin: ObjectReferenceNullish.optional(),
2422
2734
  comments: z6.union([z6.array(z6.unknown()), z6.null()]).optional(),
2423
2735
  audit_data: z6.union([z6.array(z6.unknown()), z6.null()]).optional(),
2424
- facets: z6.union([z6.object({}).partial().passthrough(), z6.null()]).optional(),
2736
+ facets: z6.union([z6.record(z6.union([z6.string(), z6.null()])), z6.null()]).optional(),
2425
2737
  classifications: z6.union([
2426
2738
  z6.record(
2427
2739
  z6.array(
@@ -2573,7 +2885,7 @@ var ExperimentEvent = z6.object({
2573
2885
  origin: ObjectReferenceNullish.optional(),
2574
2886
  comments: z6.union([z6.array(z6.unknown()), z6.null()]).optional(),
2575
2887
  audit_data: z6.union([z6.array(z6.unknown()), z6.null()]).optional(),
2576
- facets: z6.union([z6.object({}).partial().passthrough(), z6.null()]).optional(),
2888
+ facets: z6.union([z6.record(z6.union([z6.string(), z6.null()])), z6.null()]).optional(),
2577
2889
  classifications: z6.union([
2578
2890
  z6.record(
2579
2891
  z6.array(
@@ -2711,7 +3023,8 @@ var PromptParserNullish = z6.union([
2711
3023
  use_cot: z6.boolean(),
2712
3024
  choice_scores: z6.record(z6.number().gte(0).lte(1)).optional(),
2713
3025
  choice: z6.array(z6.string()).optional(),
2714
- allow_no_match: z6.boolean().optional()
3026
+ allow_no_match: z6.boolean().optional(),
3027
+ allow_skip: z6.boolean().optional()
2715
3028
  }),
2716
3029
  z6.null()
2717
3030
  ]);
@@ -3041,6 +3354,9 @@ var Group = z6.object({
3041
3354
  var GroupScope = z6.object({
3042
3355
  type: z6.literal("group"),
3043
3356
  group_by: z6.string(),
3357
+ interval_seconds: z6.number().gte(1).optional(),
3358
+ max_traces: z6.number().int().gte(1).lte(64).optional(),
3359
+ placement: z6.enum(["first", "each"]),
3044
3360
  idle_seconds: z6.number().optional()
3045
3361
  });
3046
3362
  var IfExists = z6.enum(["error", "ignore", "replace"]);
@@ -3189,6 +3505,10 @@ var RetentionObjectType = z6.enum([
3189
3505
  "experiment",
3190
3506
  "dataset"
3191
3507
  ]);
3508
+ var TopicAutomationFacetModel = z6.union([
3509
+ z6.enum(["brain-facet-latest", "brain-facet-1", "brain-facet-2"]),
3510
+ z6.null()
3511
+ ]);
3192
3512
  var TopicMapFunctionAutomation = z6.object({
3193
3513
  function: SavedFunctionId.and(z6.unknown()),
3194
3514
  btql_filter: z6.union([z6.string(), z6.null()]).optional()
@@ -3201,7 +3521,9 @@ var TopicAutomationDataScope = z6.union([
3201
3521
  ]);
3202
3522
  var TopicAutomationConfig = z6.object({
3203
3523
  event_type: z6.literal("topic"),
3524
+ status: AutomationStatus.optional(),
3204
3525
  sampling_rate: z6.number().gte(0).lte(1),
3526
+ facet_model: TopicAutomationFacetModel.optional(),
3205
3527
  facet_functions: z6.array(SavedFunctionId),
3206
3528
  topic_map_functions: z6.array(TopicMapFunctionAutomation),
3207
3529
  scope: z6.union([SpanScope, TraceScope, GroupScope, z6.null()]).optional(),
@@ -3215,6 +3537,19 @@ var TopicAutomationConfig = z6.object({
3215
3537
  z6.null()
3216
3538
  ]).optional()
3217
3539
  });
3540
+ var TopicDigestAutomationConfig = z6.object({
3541
+ event_type: z6.literal("topic_digest"),
3542
+ status: AutomationStatus.optional(),
3543
+ window_seconds: z6.number().int().gte(3600).lte(2592e3).optional().default(86400),
3544
+ scheduled_time_minutes_utc: z6.number().int().gte(0).lte(1439),
3545
+ action: z6.object({
3546
+ type: z6.literal("slack"),
3547
+ workspace_id: z6.string(),
3548
+ channel: z6.string(),
3549
+ message_template: z6.string().optional()
3550
+ }),
3551
+ topic_map_function_ids: z6.array(z6.string()).max(10).optional()
3552
+ });
3218
3553
  var ProjectAutomation = z6.object({
3219
3554
  id: z6.string().uuid(),
3220
3555
  project_id: z6.string().uuid(),
@@ -3239,6 +3574,7 @@ var ProjectAutomation = z6.object({
3239
3574
  }),
3240
3575
  z6.object({
3241
3576
  event_type: z6.literal("btql_export"),
3577
+ status: AutomationStatus.optional(),
3242
3578
  export_definition: z6.union([
3243
3579
  z6.object({ type: z6.literal("log_traces") }),
3244
3580
  z6.object({ type: z6.literal("log_spans") }),
@@ -3261,6 +3597,21 @@ var ProjectAutomation = z6.object({
3261
3597
  ]),
3262
3598
  batch_size: z6.union([z6.number(), z6.null()]).optional()
3263
3599
  }),
3600
+ z6.object({
3601
+ event_type: z6.literal("async_query"),
3602
+ status: AutomationStatus.optional(),
3603
+ created_by_user_id: z6.string().uuid(),
3604
+ object_type: z6.enum([
3605
+ "project_logs",
3606
+ "experiment",
3607
+ "dataset",
3608
+ "playground_logs"
3609
+ ]),
3610
+ object_id: z6.string(),
3611
+ query: z6.string(),
3612
+ format: z6.literal("jsonl"),
3613
+ batch_size: z6.union([z6.number(), z6.null()]).optional()
3614
+ }),
3264
3615
  z6.object({
3265
3616
  event_type: z6.literal("retention"),
3266
3617
  object_type: RetentionObjectType,
@@ -3279,7 +3630,8 @@ var ProjectAutomation = z6.object({
3279
3630
  })
3280
3631
  ])
3281
3632
  }),
3282
- TopicAutomationConfig
3633
+ TopicAutomationConfig,
3634
+ TopicDigestAutomationConfig
3283
3635
  ])
3284
3636
  });
3285
3637
  var ProjectLogsEvent = z6.object({
@@ -3318,7 +3670,7 @@ var ProjectLogsEvent = z6.object({
3318
3670
  comments: z6.union([z6.array(z6.unknown()), z6.null()]).optional(),
3319
3671
  audit_data: z6.union([z6.array(z6.unknown()), z6.null()]).optional(),
3320
3672
  _async_scoring_state: z6.unknown().optional(),
3321
- facets: z6.union([z6.object({}).partial().passthrough(), z6.null()]).optional(),
3673
+ facets: z6.union([z6.record(z6.union([z6.string(), z6.null()])), z6.null()]).optional(),
3322
3674
  classifications: z6.union([
3323
3675
  z6.record(
3324
3676
  z6.array(
@@ -3367,11 +3719,34 @@ var ProjectScoreCategories = z6.union([
3367
3719
  z6.array(z6.string()),
3368
3720
  z6.null()
3369
3721
  ]);
3722
+ var ProjectScoreCondition = z6.union([
3723
+ z6.object({
3724
+ when: z6.object({
3725
+ clauses: z6.union([z6.array(z6.string()), z6.null()]),
3726
+ subspan_clauses: z6.union([z6.array(z6.string()), z6.null()]),
3727
+ trace_clauses: z6.union([z6.array(z6.string()), z6.null()])
3728
+ }).partial(),
3729
+ behavior: z6.literal("hidden").optional().default("hidden")
3730
+ }),
3731
+ z6.null()
3732
+ ]);
3370
3733
  var ProjectScoreConfig = z6.union([
3371
3734
  z6.object({
3372
3735
  multi_select: z6.union([z6.boolean(), z6.null()]),
3373
3736
  destination: z6.union([z6.string(), z6.null()]),
3374
- online: OnlineScoreConfig
3737
+ visibility: z6.union([
3738
+ z6.object({
3739
+ users: z6.union([z6.array(z6.string()), z6.null()]),
3740
+ groups: z6.union([z6.array(z6.string()), z6.null()])
3741
+ }).partial(),
3742
+ z6.null()
3743
+ ]),
3744
+ online: OnlineScoreConfig,
3745
+ condition: ProjectScoreCondition,
3746
+ object_types: z6.union([
3747
+ z6.array(z6.enum(["project_logs", "dataset", "experiment"])),
3748
+ z6.null()
3749
+ ])
3375
3750
  }).partial(),
3376
3751
  z6.null()
3377
3752
  ]);
@@ -3556,8 +3931,7 @@ var User = z6.object({
3556
3931
  family_name: z6.union([z6.string(), z6.null()]).optional(),
3557
3932
  email: z6.union([z6.string(), z6.null()]).optional(),
3558
3933
  avatar_url: z6.union([z6.string(), z6.null()]).optional(),
3559
- created: z6.union([z6.string(), z6.null()]).optional(),
3560
- last_active_at: z6.union([z6.number(), z6.null()]).optional()
3934
+ created: z6.union([z6.string(), z6.null()]).optional()
3561
3935
  });
3562
3936
  var ViewDataSearch = z6.union([
3563
3937
  z6.object({
@@ -4225,13 +4599,23 @@ var LRUCache = class {
4225
4599
  * @returns The cached value if found, undefined otherwise.
4226
4600
  */
4227
4601
  get(key) {
4228
- const value = this.cache.get(key);
4229
- if (value === void 0) {
4602
+ const entry = this.cache.get(key);
4603
+ if (entry === void 0) {
4230
4604
  return void 0;
4231
4605
  }
4232
4606
  this.cache.delete(key);
4233
- this.cache.set(key, value);
4234
- return value;
4607
+ this.cache.set(key, entry);
4608
+ return entry.value;
4609
+ }
4610
+ /**
4611
+ * Checks whether a key exists and marks it as most recently used.
4612
+ */
4613
+ has(key) {
4614
+ if (!this.cache.has(key)) {
4615
+ return false;
4616
+ }
4617
+ this.get(key);
4618
+ return true;
4235
4619
  }
4236
4620
  /**
4237
4621
  * Stores a value in the cache.
@@ -4248,7 +4632,38 @@ var LRUCache = class {
4248
4632
  const first = this.cache.keys().next().value;
4249
4633
  this.cache.delete(first);
4250
4634
  }
4251
- this.cache.set(key, value);
4635
+ this.cache.set(key, { value });
4636
+ }
4637
+ /**
4638
+ * Removes an item from the cache.
4639
+ */
4640
+ delete(key) {
4641
+ return this.cache.delete(key);
4642
+ }
4643
+ /**
4644
+ * Iterates over cache entries from least to most recently used.
4645
+ */
4646
+ *entries() {
4647
+ for (const [key, entry] of this.cache) {
4648
+ yield [key, entry.value];
4649
+ }
4650
+ }
4651
+ /**
4652
+ * Iterates over cache keys from least to most recently used.
4653
+ */
4654
+ keys() {
4655
+ return this.cache.keys();
4656
+ }
4657
+ /**
4658
+ * Iterates over cache values from least to most recently used.
4659
+ */
4660
+ *values() {
4661
+ for (const entry of this.cache.values()) {
4662
+ yield entry.value;
4663
+ }
4664
+ }
4665
+ [Symbol.iterator]() {
4666
+ return this.entries();
4252
4667
  }
4253
4668
  /**
4254
4669
  * Removes all items from the cache.
@@ -4806,6 +5221,9 @@ function applyMaskingToField(maskingFunction, data, fieldName) {
4806
5221
  return `ERROR: Failed to mask field '${fieldName}' - ${errorType}`;
4807
5222
  }
4808
5223
  }
5224
+ var INITIAL_SPAN_WRITE_AS_MERGE = /* @__PURE__ */ Symbol(
5225
+ "braintrust.initial-span-write-as-merge"
5226
+ );
4809
5227
  var BRAINTRUST_CURRENT_SPAN_STORE = /* @__PURE__ */ Symbol.for(
4810
5228
  "braintrust.currentSpanStore"
4811
5229
  );
@@ -4846,7 +5264,10 @@ var BraintrustContextManager = class extends ContextManager {
4846
5264
  }
4847
5265
  };
4848
5266
  function getSpanComponentsClass() {
4849
- return globalThis.BRAINTRUST_SPAN_COMPONENT ? globalThis.BRAINTRUST_SPAN_COMPONENT : SpanComponentsV3;
5267
+ if (globalThis.BRAINTRUST_SPAN_COMPONENT) {
5268
+ return globalThis.BRAINTRUST_SPAN_COMPONENT;
5269
+ }
5270
+ return resolveUseLegacyUuidIds() ? SpanComponentsV3 : SpanComponentsV4;
4850
5271
  }
4851
5272
  function getContextManager() {
4852
5273
  return globalThis.BRAINTRUST_CONTEXT_MANAGER ? new globalThis.BRAINTRUST_CONTEXT_MANAGER() : new BraintrustContextManager();
@@ -4882,6 +5303,9 @@ var NoopSpan = class {
4882
5303
  async export() {
4883
5304
  return "";
4884
5305
  }
5306
+ inject(carrier) {
5307
+ return carrier ?? {};
5308
+ }
4885
5309
  async permalink() {
4886
5310
  return NOOP_SPAN_PERMALINK;
4887
5311
  }
@@ -4932,6 +5356,10 @@ var loginSchema = z8.strictObject({
4932
5356
  debugLogLevelDisabled: z8.boolean().optional()
4933
5357
  });
4934
5358
  var stateNonce = 0;
5359
+ var V1_PROXY_SUFFIX = "/v1/proxy";
5360
+ function normalizeProxyConnUrl(proxyUrl) {
5361
+ return proxyUrl.endsWith(V1_PROXY_SUFFIX) ? proxyUrl.slice(0, proxyUrl.length - V1_PROXY_SUFFIX.length) : proxyUrl;
5362
+ }
4935
5363
  var BraintrustState = class _BraintrustState {
4936
5364
  constructor(loginParams) {
4937
5365
  this.loginParams = loginParams;
@@ -5202,7 +5630,10 @@ var BraintrustState = class _BraintrustState {
5202
5630
  if (!this.proxyUrl) {
5203
5631
  throw new Error("Must initialize proxyUrl before requesting proxyConn");
5204
5632
  }
5205
- this._proxyConn = new HTTPConnection(this.proxyUrl, this.fetch);
5633
+ this._proxyConn = new HTTPConnection(
5634
+ normalizeProxyConnUrl(this.proxyUrl),
5635
+ this.fetch
5636
+ );
5206
5637
  }
5207
5638
  return this._proxyConn;
5208
5639
  }
@@ -5888,7 +6319,7 @@ async function permalink(slug, opts) {
5888
6319
  return state.appUrl;
5889
6320
  };
5890
6321
  try {
5891
- const components = getSpanComponentsClass().fromStr(slug);
6322
+ const components = SpanComponentsV4.fromStr(slug);
5892
6323
  const object_type = spanObjectTypeV3ToString(components.data.object_type);
5893
6324
  const [orgName, appUrl, object_id] = await Promise.all([
5894
6325
  getOrgName(),
@@ -5912,35 +6343,47 @@ function startSpanParentArgs(args) {
5912
6343
  let argParentObjectId = void 0;
5913
6344
  let argParentSpanIds = void 0;
5914
6345
  let argPropagatedEvent = void 0;
5915
- if (args.parent) {
6346
+ let argPropagatedState = void 0;
6347
+ const { parentSlug, propagatedState: parentPropagatedState } = normalizeParent(args.parent, args.state);
6348
+ if (parentSlug) {
5916
6349
  if (args.parentSpanIds) {
5917
6350
  throw new Error("Cannot specify both parent and parentSpanIds");
5918
6351
  }
5919
- const parentComponents = getSpanComponentsClass().fromStr(args.parent);
6352
+ const parentComponents = SpanComponentsV4.fromStr(parentSlug);
5920
6353
  if (args.parentObjectType !== parentComponents.data.object_type) {
5921
6354
  throw new Error(
5922
6355
  `Mismatch between expected span parent object type ${args.parentObjectType} and provided type ${parentComponents.data.object_type}`
5923
6356
  );
5924
6357
  }
5925
6358
  argParentObjectId = args.parentObjectId;
5926
- if (parentComponents.data.row_id) {
6359
+ if (parentComponents.data.row_id && parentSpanIdsUsable(
6360
+ parentComponents.data.span_id,
6361
+ parentComponents.data.root_span_id
6362
+ )) {
5927
6363
  argParentSpanIds = {
5928
6364
  spanId: parentComponents.data.span_id,
5929
6365
  rootSpanId: parentComponents.data.root_span_id
5930
6366
  };
5931
6367
  }
5932
6368
  argPropagatedEvent = args.propagatedEvent ?? (parentComponents.data.propagated_event ?? void 0);
6369
+ const propagatedState = args.propagatedState ?? parentPropagatedState;
6370
+ if (propagatedState) {
6371
+ const { braintrustParent: _ignoredBraintrustParent, ...w3cState } = propagatedState;
6372
+ argPropagatedState = w3cState;
6373
+ }
5933
6374
  } else {
5934
6375
  argParentObjectId = args.parentObjectId;
5935
6376
  argParentSpanIds = args.parentSpanIds;
5936
6377
  argPropagatedEvent = args.propagatedEvent;
6378
+ argPropagatedState = args.propagatedState;
5937
6379
  }
5938
6380
  return {
5939
6381
  parentObjectType: args.parentObjectType,
5940
6382
  parentObjectId: argParentObjectId,
5941
6383
  parentComputeObjectMetadataArgs: args.parentComputeObjectMetadataArgs,
5942
6384
  parentSpanIds: argParentSpanIds,
5943
- propagatedEvent: argPropagatedEvent
6385
+ propagatedEvent: argPropagatedEvent,
6386
+ propagatedState: argPropagatedState
5944
6387
  };
5945
6388
  }
5946
6389
  var Logger = class {
@@ -6141,6 +6584,22 @@ var Logger = class {
6141
6584
  _getLinkBaseUrl() {
6142
6585
  return _getLinkBaseUrl(this.state, this._linkArgs);
6143
6586
  }
6587
+ /**
6588
+ * Return this logger's Braintrust parent string (`project_id:<id>` or
6589
+ * `project_name:<name>`) for the `braintrust.parent` baggage entry, or
6590
+ * undefined when it cannot be determined synchronously.
6591
+ */
6592
+ _getOtelParent() {
6593
+ const id = this.computeMetadataArgs?.project_id || this.lazyId.getSync().value;
6594
+ if (id) {
6595
+ return `project_id:${id}`;
6596
+ }
6597
+ const name = this.computeMetadataArgs?.project_name;
6598
+ if (name) {
6599
+ return `project_name:${name}`;
6600
+ }
6601
+ return void 0;
6602
+ }
6144
6603
  };
6145
6604
  function castLogger(logger, asyncFlush) {
6146
6605
  if (logger === void 0) return void 0;
@@ -6235,12 +6694,12 @@ function stringifyWithOverflowMeta(item) {
6235
6694
  object_ids: pickLogs3OverflowObjectIds(record),
6236
6695
  is_delete: record[OBJECT_DELETE_FIELD] === true,
6237
6696
  input_row: {
6238
- byte_size: utf8ByteLength(str)
6697
+ byte_size: utf8ByteLength2(str)
6239
6698
  }
6240
6699
  }
6241
6700
  };
6242
6701
  }
6243
- function utf8ByteLength(value) {
6702
+ function utf8ByteLength2(value) {
6244
6703
  if (typeof TextEncoder !== "undefined") {
6245
6704
  return new TextEncoder().encode(value).length;
6246
6705
  }
@@ -6571,7 +7030,7 @@ var HTTPBackgroundLogger = class _HTTPBackgroundLogger {
6571
7030
  }) {
6572
7031
  const conn = await this.apiConn.get();
6573
7032
  const dataStr = constructLogs3Data(items);
6574
- const payloadBytes = utf8ByteLength(dataStr);
7033
+ const payloadBytes = utf8ByteLength2(dataStr);
6575
7034
  const useOverflow = canUseOverflow && payloadBytes > maxRequestSize;
6576
7035
  if (this.allPublishPayloadsDir) {
6577
7036
  await _HTTPBackgroundLogger.writePayloadToDir({
@@ -7163,6 +7622,8 @@ function initDataset(projectOrOptions, optionalOptions) {
7163
7622
  const normalizedVersion = selection.version;
7164
7623
  const normalizedEnvironment = selection.environment;
7165
7624
  const normalizedSnapshotName = selection.snapshotName;
7625
+ const cliInternalBtql = globalThis.__bt_eval_internal_btql;
7626
+ const internalBtql = cliInternalBtql === void 0 ? _internal_btql : _internal_btql === void 0 ? cliInternalBtql : isObject(_internal_btql) ? { ...cliInternalBtql, ..._internal_btql } : _internal_btql;
7166
7627
  const state = stateArg ?? _globalState;
7167
7628
  const lazyMetadata = new LazyValue(
7168
7629
  async () => {
@@ -7214,7 +7675,7 @@ function initDataset(projectOrOptions, optionalOptions) {
7214
7675
  lazyMetadata,
7215
7676
  typeof resolvedVersion === "string" ? resolvedVersion : void 0,
7216
7677
  legacy,
7217
- _internal_btql,
7678
+ internalBtql,
7218
7679
  resolvedVersion instanceof LazyValue || normalizedEnvironment !== void 0 || normalizedSnapshotName !== void 0 ? {
7219
7680
  ...resolvedVersion instanceof LazyValue ? {
7220
7681
  lazyPinnedVersion: resolvedVersion
@@ -7425,87 +7886,324 @@ function currentSpan(options) {
7425
7886
  const state = options?.state ?? _globalState;
7426
7887
  return state.contextManager.getCurrentSpan() ?? NOOP_SPAN;
7427
7888
  }
7428
- function getSpanParentObject(options) {
7889
+ function getSpanParentObjectAndPropagatedState(options) {
7429
7890
  const state = options?.state ?? _globalState;
7430
7891
  const parentSpan = currentSpan({ state });
7431
7892
  if (!Object.is(parentSpan, NOOP_SPAN)) {
7432
- return parentSpan;
7893
+ return { parentObject: parentSpan, propagatedState: void 0 };
7894
+ }
7895
+ const parent = options?.parent ?? state.currentParent.getStore();
7896
+ const { parentSlug, propagatedState } = normalizeParent(parent, state);
7897
+ if (parentSlug) {
7898
+ return {
7899
+ parentObject: SpanComponentsV4.fromStr(parentSlug),
7900
+ propagatedState
7901
+ };
7433
7902
  }
7434
- const parentStr = options?.parent ?? state.currentParent.getStore();
7435
- if (parentStr) return getSpanComponentsClass().fromStr(parentStr);
7436
7903
  const experiment = currentExperiment();
7437
7904
  if (experiment) {
7438
- return experiment;
7905
+ return { parentObject: experiment, propagatedState: void 0 };
7439
7906
  }
7440
7907
  const logger = currentLogger(options);
7441
7908
  if (logger) {
7442
- return logger;
7909
+ return { parentObject: logger, propagatedState: void 0 };
7443
7910
  }
7444
- return NOOP_SPAN;
7911
+ return { parentObject: NOOP_SPAN, propagatedState: void 0 };
7445
7912
  }
7446
- function logError(span, error) {
7447
- let errorMessage = "<error>";
7448
- let stackTrace = "";
7449
- if (error instanceof Error) {
7450
- errorMessage = error.message;
7451
- stackTrace = error.stack || "";
7452
- } else {
7453
- errorMessage = String(error);
7454
- }
7455
- span.log({ error: `${errorMessage}
7456
-
7457
- ${stackTrace}` });
7913
+ function getSpanParentObject(options) {
7914
+ return getSpanParentObjectAndPropagatedState(options).parentObject;
7458
7915
  }
7459
- function traced(callback, args) {
7460
- const { span, isSyncFlushLogger } = startSpanAndIsLogger(args);
7461
- const ret = runCatchFinally(
7462
- () => {
7463
- if (args?.setCurrent ?? true) {
7464
- return withCurrent(span, callback);
7465
- } else {
7466
- return callback(span);
7467
- }
7468
- },
7469
- (e) => {
7470
- logError(span, e);
7471
- throw e;
7472
- },
7473
- () => span.end()
7474
- );
7475
- if (args?.asyncFlush === void 0 || args?.asyncFlush) {
7476
- return ret;
7477
- } else {
7478
- return (async () => {
7479
- const awaitedRet = await ret;
7480
- if (isSyncFlushLogger) {
7481
- await span.flush();
7482
- }
7483
- return awaitedRet;
7484
- })();
7916
+ function currentBraintrustParent(state) {
7917
+ const resolvedState = state ?? _globalState;
7918
+ const experiment = currentExperiment({ state: resolvedState });
7919
+ if (experiment) {
7920
+ try {
7921
+ return experiment._getOtelParent() ?? void 0;
7922
+ } catch {
7923
+ return void 0;
7924
+ }
7485
7925
  }
7926
+ const logger = currentLogger({ state: resolvedState });
7927
+ if (logger) {
7928
+ try {
7929
+ return logger._getOtelParent() ?? void 0;
7930
+ } catch {
7931
+ return void 0;
7932
+ }
7933
+ }
7934
+ return void 0;
7486
7935
  }
7487
- function startSpan(args) {
7488
- return startSpanAndIsLogger(args).span;
7936
+ function braintrustParentToComponents(braintrustParent) {
7937
+ if (!braintrustParent) {
7938
+ return void 0;
7939
+ }
7940
+ if (braintrustParent.startsWith("project_id:")) {
7941
+ const objectId = braintrustParent.slice("project_id:".length);
7942
+ return objectId ? {
7943
+ objectType: 2 /* PROJECT_LOGS */,
7944
+ objectId,
7945
+ computeArgs: void 0
7946
+ } : void 0;
7947
+ }
7948
+ if (braintrustParent.startsWith("project_name:")) {
7949
+ const name = braintrustParent.slice("project_name:".length);
7950
+ return name ? {
7951
+ objectType: 2 /* PROJECT_LOGS */,
7952
+ objectId: void 0,
7953
+ computeArgs: { project_name: name }
7954
+ } : void 0;
7955
+ }
7956
+ if (braintrustParent.startsWith("experiment_id:")) {
7957
+ const objectId = braintrustParent.slice("experiment_id:".length);
7958
+ return objectId ? {
7959
+ objectType: 1 /* EXPERIMENT */,
7960
+ objectId,
7961
+ computeArgs: void 0
7962
+ } : void 0;
7963
+ }
7964
+ return void 0;
7489
7965
  }
7490
- async function flush(options) {
7491
- const state = options?.state ?? _globalState;
7492
- return await state.bgLogger().flush();
7966
+ function isMutableHeaderTupleArray(carrier) {
7967
+ return Array.isArray(carrier) && carrier.every((item) => Array.isArray(item) && typeof item[0] === "string");
7493
7968
  }
7494
- function startSpanAndIsLogger(args) {
7969
+ function setHeader(carrier, name, value) {
7970
+ if (isMutableHeaderTupleArray(carrier)) {
7971
+ const lowered2 = name.toLowerCase();
7972
+ for (let i = carrier.length - 1; i >= 0; i--) {
7973
+ if (carrier[i][0].toLowerCase() === lowered2) {
7974
+ carrier.splice(i, 1);
7975
+ }
7976
+ }
7977
+ carrier.push([name, value]);
7978
+ return;
7979
+ }
7980
+ const setter = carrier.set;
7981
+ if (typeof setter === "function") {
7982
+ const deleter = carrier.delete;
7983
+ if (typeof deleter === "function") {
7984
+ try {
7985
+ deleter.call(carrier, name);
7986
+ } catch {
7987
+ }
7988
+ }
7989
+ setter.call(carrier, name, value);
7990
+ return;
7991
+ }
7992
+ const nodeSetter = carrier.setHeader;
7993
+ if (typeof nodeSetter === "function") {
7994
+ const remover = carrier.removeHeader;
7995
+ if (typeof remover === "function") {
7996
+ try {
7997
+ remover.call(carrier, name);
7998
+ } catch {
7999
+ }
8000
+ }
8001
+ nodeSetter.call(carrier, name, value);
8002
+ return;
8003
+ }
8004
+ const headerSetter = carrier.header;
8005
+ if (typeof headerSetter === "function") {
8006
+ const deleter = carrier.delete;
8007
+ if (typeof deleter === "function") {
8008
+ try {
8009
+ deleter.call(carrier, name);
8010
+ } catch {
8011
+ }
8012
+ }
8013
+ const remover = carrier.removeHeader;
8014
+ if (typeof remover === "function") {
8015
+ try {
8016
+ remover.call(carrier, name);
8017
+ } catch {
8018
+ }
8019
+ }
8020
+ headerSetter.call(carrier, name, value);
8021
+ return;
8022
+ }
8023
+ const headerBag = carrier;
8024
+ const lowered = name.toLowerCase();
8025
+ for (const key of Object.keys(headerBag)) {
8026
+ if (key !== name && key.toLowerCase() === lowered) {
8027
+ delete headerBag[key];
8028
+ }
8029
+ }
8030
+ headerBag[name] = value;
8031
+ }
8032
+ function deleteHeader(carrier, name) {
8033
+ const lowered = name.toLowerCase();
8034
+ if (isMutableHeaderTupleArray(carrier)) {
8035
+ for (let i = carrier.length - 1; i >= 0; i--) {
8036
+ if (carrier[i][0].toLowerCase() === lowered) {
8037
+ carrier.splice(i, 1);
8038
+ }
8039
+ }
8040
+ return;
8041
+ }
8042
+ const deleter = carrier.delete;
8043
+ if (typeof deleter === "function") {
8044
+ try {
8045
+ deleter.call(carrier, name);
8046
+ return;
8047
+ } catch {
8048
+ }
8049
+ }
8050
+ const remover = carrier.removeHeader;
8051
+ if (typeof remover === "function") {
8052
+ try {
8053
+ remover.call(carrier, name);
8054
+ return;
8055
+ } catch {
8056
+ }
8057
+ }
8058
+ const headerBag = carrier;
8059
+ for (const key of Object.keys(headerBag)) {
8060
+ if (key.toLowerCase() === lowered) {
8061
+ delete headerBag[key];
8062
+ }
8063
+ }
8064
+ }
8065
+ function _injectIntoCarrier(carrier, args) {
8066
+ const traceFlags = args.propagatedState?.traceFlags;
8067
+ const traceparent = traceFlags ? formatTraceparent(args.traceId, args.spanId, traceFlags) : formatTraceparent(args.traceId, args.spanId);
8068
+ if (traceparent === void 0) {
8069
+ return;
8070
+ }
8071
+ setHeader(carrier, TRACEPARENT_HEADER, traceparent);
8072
+ const tracestate = args.propagatedState?.tracestate;
8073
+ if (tracestate) {
8074
+ setHeader(carrier, TRACESTATE_HEADER, tracestate);
8075
+ }
8076
+ const existing = getHeader(carrier, BAGGAGE_HEADER);
8077
+ const baggageValue = mergeBaggage(existing, args.braintrustParent);
8078
+ if (baggageValue !== void 0) {
8079
+ setHeader(carrier, BAGGAGE_HEADER, baggageValue);
8080
+ } else if (existing !== void 0) {
8081
+ deleteHeader(carrier, BAGGAGE_HEADER);
8082
+ }
8083
+ }
8084
+ function resolveW3cParent(context, state) {
8085
+ const traceparent = getHeader(context, TRACEPARENT_HEADER);
8086
+ const parsed = traceparent ? parseTraceparent(traceparent) : void 0;
8087
+ if (parsed === void 0) {
8088
+ return { parentSlug: void 0, propagatedState: void 0 };
8089
+ }
8090
+ const { traceId, spanId, traceFlags } = parsed;
8091
+ let braintrustParent = void 0;
8092
+ const baggageValue = getHeader(context, BAGGAGE_HEADER);
8093
+ if (baggageValue) {
8094
+ braintrustParent = parseBaggage(baggageValue)[BRAINTRUST_PARENT_KEY];
8095
+ }
8096
+ if (!braintrustParent) {
8097
+ braintrustParent = currentBraintrustParent(state);
8098
+ }
8099
+ if (!braintrustParent) {
8100
+ debugLogger.warn(
8101
+ "Received traceparent without a braintrust.parent and no active logger/experiment; cannot route the trace. Starting a fresh local span instead."
8102
+ );
8103
+ return { parentSlug: void 0, propagatedState: void 0 };
8104
+ }
8105
+ const parsedParent = braintrustParentToComponents(braintrustParent);
8106
+ if (parsedParent === void 0) {
8107
+ debugLogger.warn(
8108
+ `Invalid braintrust.parent: ${JSON.stringify(braintrustParent)}`
8109
+ );
8110
+ return { parentSlug: void 0, propagatedState: void 0 };
8111
+ }
8112
+ const { objectType, objectId, computeArgs } = parsedParent;
8113
+ const tracestate = getHeader(context, TRACESTATE_HEADER);
8114
+ const slug = new SpanComponentsV4({
8115
+ object_type: objectType,
8116
+ ...computeArgs ? { compute_object_metadata_args: computeArgs } : { object_id: objectId },
8117
+ row_id: "bt-propagation",
8118
+ // non-empty to enable span_id/root_span_id
8119
+ span_id: spanId,
8120
+ root_span_id: traceId
8121
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
8122
+ }).toStr();
8123
+ return {
8124
+ parentSlug: slug,
8125
+ propagatedState: { tracestate, traceFlags, braintrustParent }
8126
+ };
8127
+ }
8128
+ function normalizeParent(parent, state) {
8129
+ if (parent && typeof parent === "object") {
8130
+ return resolveW3cParent(parent, state);
8131
+ }
8132
+ return {
8133
+ parentSlug: parent ?? void 0,
8134
+ propagatedState: void 0
8135
+ };
8136
+ }
8137
+ function parentSpanIdsUsable(spanId, rootSpanId) {
8138
+ return Boolean(spanId) && Boolean(rootSpanId);
8139
+ }
8140
+ function logError(span, error) {
8141
+ let errorMessage = "<error>";
8142
+ let stackTrace = "";
8143
+ if (error instanceof Error) {
8144
+ errorMessage = error.message;
8145
+ stackTrace = error.stack || "";
8146
+ } else {
8147
+ errorMessage = String(error);
8148
+ }
8149
+ span.log({ error: `${errorMessage}
8150
+
8151
+ ${stackTrace}` });
8152
+ }
8153
+ function traced(callback, args) {
8154
+ const { span, isSyncFlushLogger } = startSpanAndIsLogger(args);
8155
+ const ret = runCatchFinally(
8156
+ () => {
8157
+ if (args?.setCurrent ?? true) {
8158
+ return withCurrent(span, callback);
8159
+ } else {
8160
+ return callback(span);
8161
+ }
8162
+ },
8163
+ (e) => {
8164
+ logError(span, e);
8165
+ throw e;
8166
+ },
8167
+ () => span.end()
8168
+ );
8169
+ if (args?.asyncFlush === void 0 || args?.asyncFlush) {
8170
+ return ret;
8171
+ } else {
8172
+ return (async () => {
8173
+ const awaitedRet = await ret;
8174
+ if (isSyncFlushLogger) {
8175
+ await span.flush();
8176
+ }
8177
+ return awaitedRet;
8178
+ })();
8179
+ }
8180
+ }
8181
+ function startSpan(args) {
8182
+ return startSpanAndIsLogger(args).span;
8183
+ }
8184
+ async function flush(options) {
8185
+ const state = options?.state ?? _globalState;
8186
+ return await state.bgLogger().flush();
8187
+ }
8188
+ function startSpanAndIsLogger(args) {
7495
8189
  const state = args?.state ?? _globalState;
7496
- const parentObject = getSpanParentObject({
8190
+ const { parentObject, propagatedState } = getSpanParentObjectAndPropagatedState({
7497
8191
  asyncFlush: args?.asyncFlush,
7498
8192
  parent: args?.parent,
7499
8193
  state
7500
8194
  });
7501
8195
  if (parentObject instanceof SpanComponentsV3 || parentObject instanceof SpanComponentsV4) {
7502
- const parentSpanIds = parentObject.data.row_id ? {
8196
+ const parentSpanIds = parentObject.data.row_id && parentSpanIdsUsable(
8197
+ parentObject.data.span_id,
8198
+ parentObject.data.root_span_id
8199
+ ) ? {
7503
8200
  spanId: parentObject.data.span_id,
7504
8201
  rootSpanId: parentObject.data.root_span_id
7505
8202
  } : void 0;
8203
+ const { parent: _ignoredParent, ...spanArgs } = args ?? {};
7506
8204
  const span = new SpanImpl({
7507
8205
  state,
7508
- ...args,
8206
+ ...spanArgs,
7509
8207
  parentObjectType: parentObject.data.object_type,
7510
8208
  parentObjectId: new LazyValue(
7511
8209
  spanComponentsToObjectIdLambda(state, parentObject)
@@ -7513,7 +8211,8 @@ function startSpanAndIsLogger(args) {
7513
8211
  parentComputeObjectMetadataArgs: parentObject.data.compute_object_metadata_args ?? void 0,
7514
8212
  parentSpanIds,
7515
8213
  propagatedEvent: args?.propagatedEvent ?? // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
7516
- (parentObject.data.propagated_event ?? void 0)
8214
+ (parentObject.data.propagated_event ?? void 0),
8215
+ propagatedState
7517
8216
  });
7518
8217
  return {
7519
8218
  span,
@@ -7756,11 +8455,12 @@ function validateAndSanitizeExperimentLogFullArgs(event, hasDataset) {
7756
8455
  var DEFAULT_FETCH_BATCH_SIZE = 1e3;
7757
8456
  var MAX_BTQL_ITERATIONS = 1e4;
7758
8457
  var ObjectFetcher = class {
7759
- constructor(objectType, pinnedVersion, mutateRecord, _internal_btql) {
8458
+ constructor(objectType, pinnedVersion, mutateRecord, _internal_btql, _internalBrainstoreRealtime = true) {
7760
8459
  this.objectType = objectType;
7761
8460
  this.pinnedVersion = pinnedVersion;
7762
8461
  this.mutateRecord = mutateRecord;
7763
8462
  this._internal_btql = _internal_btql;
8463
+ this._internalBrainstoreRealtime = _internalBrainstoreRealtime;
7764
8464
  }
7765
8465
  _fetchedData = void 0;
7766
8466
  get id() {
@@ -7819,7 +8519,7 @@ var ObjectFetcher = class {
7819
8519
  ...internalBtqlWithoutReservedQueryKeys
7820
8520
  },
7821
8521
  use_columnstore: false,
7822
- brainstore_realtime: true,
8522
+ brainstore_realtime: this._internalBrainstoreRealtime,
7823
8523
  query_source: `js_sdk_object_fetcher_${this.objectType}`,
7824
8524
  ...this.pinnedVersion !== void 0 ? {
7825
8525
  version: this.pinnedVersion
@@ -8168,6 +8868,15 @@ View complete results in Braintrust or run experiment.summarize() again.`
8168
8868
  object_id: await this.id
8169
8869
  }).toStr();
8170
8870
  }
8871
+ /**
8872
+ * Return this experiment's Braintrust parent string (`experiment_id:<id>`) for
8873
+ * the `braintrust.parent` baggage entry, or undefined when it cannot be
8874
+ * determined synchronously.
8875
+ */
8876
+ _getOtelParent() {
8877
+ const id = this.lazyId.getSync().value;
8878
+ return id ? `experiment_id:${id}` : void 0;
8879
+ }
8171
8880
  /**
8172
8881
  * Flush any pending rows to the server.
8173
8882
  */
@@ -8210,7 +8919,8 @@ var ReadonlyExperiment = class extends ObjectFetcher {
8210
8919
  async *asDataset(options) {
8211
8920
  const records = this.fetch(options);
8212
8921
  for await (const record of records) {
8213
- if (record.root_span_id !== record.span_id) {
8922
+ const isRoot = record.is_root ?? record.root_span_id === record.span_id;
8923
+ if (!isRoot) {
8214
8924
  continue;
8215
8925
  }
8216
8926
  const { output, expected: expectedRecord, metadata } = record;
@@ -8272,9 +8982,16 @@ var SpanImpl = class _SpanImpl {
8272
8982
  _spanId;
8273
8983
  _rootSpanId;
8274
8984
  _spanParents;
8985
+ // Inbound W3C trace-context state (tracestate + raw traceparent flags) to
8986
+ // forward on outbound propagation. Captured at the span that received it (via
8987
+ // extractTraceContextFromHeaders) and inherited by all subspans, so that any
8988
+ // inject() within the trace re-emits the upstream state unchanged, per the W3C
8989
+ // Trace Context spec. Not interpreted.
8990
+ _propagatedState;
8275
8991
  kind = "span";
8276
8992
  constructor(args) {
8277
8993
  this._state = args.state;
8994
+ this._propagatedState = args.propagatedState;
8278
8995
  const spanAttributes = args.spanAttributes ?? {};
8279
8996
  const rawEvent = args.event ?? {};
8280
8997
  const type = args.type ?? (args.parentSpanIds ? void 0 : args.defaultRootType);
@@ -8325,7 +9042,7 @@ var SpanImpl = class _SpanImpl {
8325
9042
  this._spanId = resolvedIds.spanId;
8326
9043
  this._rootSpanId = resolvedIds.rootSpanId;
8327
9044
  this._spanParents = resolvedIds.spanParents;
8328
- this.isMerge = false;
9045
+ this.isMerge = args[INITIAL_SPAN_WRITE_AS_MERGE] === true;
8329
9046
  this.logInternal({ event, internalData });
8330
9047
  this.isMerge = true;
8331
9048
  }
@@ -8390,7 +9107,7 @@ var SpanImpl = class _SpanImpl {
8390
9107
  tags: partialRecord.tags,
8391
9108
  span_id: this._spanId,
8392
9109
  span_parents: this._spanParents,
8393
- is_root: this._spanId === this._rootSpanId,
9110
+ is_root: !this._spanParents || this._spanParents.length === 0,
8394
9111
  span_attributes: partialRecord.span_attributes
8395
9112
  };
8396
9113
  this._state.spanCache.queueWrite(
@@ -8452,7 +9169,8 @@ var SpanImpl = class _SpanImpl {
8452
9169
  parentObjectId: this.parentObjectId,
8453
9170
  parentComputeObjectMetadataArgs: this.parentComputeObjectMetadataArgs,
8454
9171
  parentSpanIds,
8455
- propagatedEvent: args?.propagatedEvent ?? this.propagatedEvent
9172
+ propagatedEvent: args?.propagatedEvent ?? this.propagatedEvent,
9173
+ propagatedState: this._propagatedState
8456
9174
  })
8457
9175
  });
8458
9176
  }
@@ -8471,7 +9189,8 @@ var SpanImpl = class _SpanImpl {
8471
9189
  parentObjectId: this.parentObjectId,
8472
9190
  parentComputeObjectMetadataArgs: this.parentComputeObjectMetadataArgs,
8473
9191
  parentSpanIds,
8474
- propagatedEvent: args?.propagatedEvent ?? this.propagatedEvent
9192
+ propagatedEvent: args?.propagatedEvent ?? this.propagatedEvent,
9193
+ propagatedState: this._propagatedState
8475
9194
  }),
8476
9195
  spanId
8477
9196
  });
@@ -8499,6 +9218,42 @@ var SpanImpl = class _SpanImpl {
8499
9218
  propagated_event: this.propagatedEvent
8500
9219
  }).toStr();
8501
9220
  }
9221
+ /**
9222
+ * Return this span's Braintrust parent string (`project_id:<id>`,
9223
+ * `project_name:<name>`, or `experiment_id:<id>`) for the `braintrust.parent`
9224
+ * baggage entry, or undefined when it cannot be determined synchronously.
9225
+ */
9226
+ _getOtelParent() {
9227
+ if (this.parentObjectType === 2 /* PROJECT_LOGS */) {
9228
+ const id = this.parentComputeObjectMetadataArgs?.project_id || this.parentObjectId.getSync().value;
9229
+ const name = this.parentComputeObjectMetadataArgs?.project_name;
9230
+ if (id) {
9231
+ return `project_id:${id}`;
9232
+ } else if (name) {
9233
+ return `project_name:${name}`;
9234
+ }
9235
+ } else if (this.parentObjectType === 1 /* EXPERIMENT */) {
9236
+ const id = this.parentComputeObjectMetadataArgs?.experiment_id || this.parentObjectId.getSync().value;
9237
+ if (id) {
9238
+ return `experiment_id:${id}`;
9239
+ }
9240
+ }
9241
+ return void 0;
9242
+ }
9243
+ inject(carrier) {
9244
+ const resolvedCarrier = carrier ?? {};
9245
+ try {
9246
+ _injectIntoCarrier(resolvedCarrier, {
9247
+ traceId: this._rootSpanId,
9248
+ spanId: this._spanId,
9249
+ braintrustParent: this._getOtelParent() ?? this._propagatedState?.braintrustParent,
9250
+ propagatedState: this._propagatedState
9251
+ });
9252
+ } catch (e) {
9253
+ debugLogger.warn(`Error injecting trace context: ${e}`);
9254
+ }
9255
+ return resolvedCarrier;
9256
+ }
8502
9257
  async permalink() {
8503
9258
  return await permalink(await this.export(), {
8504
9259
  state: this._state
@@ -8634,6 +9389,7 @@ var Dataset2 = class extends ObjectFetcher {
8634
9389
  _internal_btql
8635
9390
  );
8636
9391
  this.state = state;
9392
+ void this.__braintrust_dataset_marker;
8637
9393
  this.lazyMetadata = lazyMetadata;
8638
9394
  this.lazyPinnedVersion = pinState?.lazyPinnedVersion;
8639
9395
  this.pinnedEnvironment = pinState?.pinnedEnvironment;
@@ -9148,6 +9904,7 @@ var Prompt2 = class _Prompt {
9148
9904
  this.metadata = metadata;
9149
9905
  this.defaults = defaults;
9150
9906
  this.noTrace = noTrace;
9907
+ void this.__braintrust_prompt_marker;
9151
9908
  }
9152
9909
  parsedPromptData;
9153
9910
  hasParsedPromptData = false;
@@ -9384,6 +10141,7 @@ var Prompt2 = class _Prompt {
9384
10141
  var RemoteEvalParameters = class {
9385
10142
  constructor(metadata) {
9386
10143
  this.metadata = metadata;
10144
+ void this.__braintrust_parameters_marker;
9387
10145
  }
9388
10146
  __braintrust_parameters_marker = true;
9389
10147
  get id() {
@@ -10255,6 +11013,22 @@ function runStreamingCompletionHook(args) {
10255
11013
  );
10256
11014
  }
10257
11015
  }
11016
+ function runStreamingErrorHook(args) {
11017
+ if (!args.config.onError) {
11018
+ return;
11019
+ }
11020
+ try {
11021
+ args.config.onError({
11022
+ channelName: args.channelName,
11023
+ error: args.error,
11024
+ event: args.event,
11025
+ span: args.span,
11026
+ startTime: args.startTime
11027
+ });
11028
+ } catch (error) {
11029
+ debugLogger.error(`Error in onError hook for ${args.channelName}:`, error);
11030
+ }
11031
+ }
10258
11032
  function traceAsyncChannel(channel2, config) {
10259
11033
  const tracingChannel2 = channel2.tracingChannel();
10260
11034
  const states = /* @__PURE__ */ new WeakMap();
@@ -10416,6 +11190,14 @@ function traceStreamingChannel(channel2, config) {
10416
11190
  }
10417
11191
  },
10418
11192
  onError: (error) => {
11193
+ runStreamingErrorHook({
11194
+ channelName,
11195
+ config,
11196
+ error,
11197
+ event: asyncEndEvent,
11198
+ span,
11199
+ startTime
11200
+ });
10419
11201
  span.log({
10420
11202
  error: error.message
10421
11203
  });
@@ -10473,6 +11255,17 @@ function traceStreamingChannel(channel2, config) {
10473
11255
  }
10474
11256
  },
10475
11257
  error: (event) => {
11258
+ const spanData = states.get(event);
11259
+ if (spanData) {
11260
+ runStreamingErrorHook({
11261
+ channelName,
11262
+ config,
11263
+ error: event.error,
11264
+ event,
11265
+ span: spanData.span,
11266
+ startTime: spanData.startTime
11267
+ });
11268
+ }
10476
11269
  logErrorAndEnd(states, event);
10477
11270
  }
10478
11271
  };
@@ -12835,14 +13628,45 @@ function serializeAISDKToolsForLogging(tools) {
12835
13628
  return serialized;
12836
13629
  }
12837
13630
 
13631
+ // src/vendor-sdk-types/ai-sdk-v7-telemetry.ts
13632
+ var BRAINTRUST_AI_SDK_V7_OPERATION_KEY = /* @__PURE__ */ Symbol.for(
13633
+ "braintrust.ai-sdk.v7.telemetry-operation-key"
13634
+ );
13635
+
13636
+ // src/wrappers/ai-sdk/workflow-agent-context.ts
13637
+ var workflowAgentWrapperSpans = /* @__PURE__ */ new Map();
13638
+ function registerWorkflowAgentWrapperSpan(span) {
13639
+ if (span.spanId) {
13640
+ workflowAgentWrapperSpans.set(span.spanId, span);
13641
+ }
13642
+ }
13643
+ function unregisterWorkflowAgentWrapperSpan(span) {
13644
+ if (span.spanId) {
13645
+ workflowAgentWrapperSpans.delete(span.spanId);
13646
+ }
13647
+ }
13648
+ function currentWorkflowAgentWrapperSpan() {
13649
+ const parentSpanIds = _internalGetGlobalState().contextManager.getParentSpanIds()?.spanParents ?? [];
13650
+ for (const parentSpanId of parentSpanIds) {
13651
+ const span = workflowAgentWrapperSpans.get(parentSpanId);
13652
+ if (span) {
13653
+ return span;
13654
+ }
13655
+ }
13656
+ return void 0;
13657
+ }
13658
+
12838
13659
  // src/wrappers/ai-sdk/telemetry.ts
12839
13660
  function braintrustAISDKTelemetry() {
12840
13661
  const operations = /* @__PURE__ */ new Map();
13662
+ const operationKeysByCallId = /* @__PURE__ */ new Map();
13663
+ const workflowOperationKeyStore = isomorph_default.newAsyncLocalStorage();
12841
13664
  const modelSpans = /* @__PURE__ */ new Map();
12842
13665
  const objectSpans = /* @__PURE__ */ new Map();
12843
13666
  const embedSpans = /* @__PURE__ */ new Map();
12844
13667
  const rerankSpans = /* @__PURE__ */ new Map();
12845
13668
  const toolSpans = /* @__PURE__ */ new Map();
13669
+ let workflowAgentOperationCounter = 0;
12846
13670
  const runSafely = (name, callback) => {
12847
13671
  try {
12848
13672
  callback();
@@ -12850,139 +13674,413 @@ function braintrustAISDKTelemetry() {
12850
13674
  console.error(`Error in Braintrust AI SDK telemetry ${name}:`, error);
12851
13675
  }
12852
13676
  };
12853
- const startChildSpan = (callId, name, type, event) => {
12854
- const parent = operations.get(callId)?.span;
13677
+ const startChildSpan = (operationKey, name, type, event) => {
13678
+ const parent = operations.get(operationKey)?.span;
12855
13679
  const spanArgs = {
12856
13680
  name,
12857
13681
  spanAttributes: { type },
12858
13682
  ...event ? { event } : {}
12859
13683
  };
12860
13684
  const span = parent ? parent.startSpan(spanArgs) : startSpan(spanArgs);
12861
- const state = operations.get(callId);
13685
+ const state = operations.get(operationKey);
12862
13686
  if (state && type === "llm" /* LLM */) {
12863
13687
  state.hadModelChild = true;
12864
13688
  }
12865
13689
  return span;
12866
13690
  };
12867
- return {
12868
- onStart(event) {
12869
- runSafely("onStart", () => {
12870
- const operationName = operationNameFromId(event.operationId);
12871
- const span = startSpan({
12872
- name: operationName,
12873
- spanAttributes: { type: "function" /* FUNCTION */ }
12874
- });
12875
- operations.set(event.callId, {
12876
- hadModelChild: false,
12877
- operationName,
12878
- span,
12879
- startTime: getCurrentUnixTimestamp()
12880
- });
12881
- const metadata = metadataFromEvent(event);
12882
- const logPayload = { metadata };
12883
- if (shouldRecordInputs(event)) {
12884
- const { input, outputPromise } = processAISDKCallInput(
12885
- operationInput(event, operationName)
12886
- );
12887
- logPayload.input = input;
12888
- if (outputPromise && input && typeof input === "object") {
12889
- outputPromise.then((resolvedData) => {
12890
- span.log({
12891
- input: {
12892
- ...input,
12893
- ...resolvedData
12894
- }
12895
- });
12896
- }).catch(() => {
12897
- });
12898
- }
13691
+ const registerOperation = (state) => {
13692
+ operations.set(state.operationKey, state);
13693
+ const keys = operationKeysByCallId.get(state.callId) ?? [];
13694
+ keys.push(state.operationKey);
13695
+ operationKeysByCallId.set(state.callId, keys);
13696
+ };
13697
+ const deleteOperation = (operationKey) => {
13698
+ const state = operations.get(operationKey);
13699
+ if (!state) {
13700
+ return;
13701
+ }
13702
+ operations.delete(operationKey);
13703
+ if (workflowOperationKeyStore.getStore() === operationKey) {
13704
+ workflowOperationKeyStore.enterWith(void 0);
13705
+ }
13706
+ const keys = operationKeysByCallId.get(state.callId);
13707
+ if (!keys) {
13708
+ return;
13709
+ }
13710
+ const index = keys.indexOf(operationKey);
13711
+ if (index >= 0) {
13712
+ keys.splice(index, 1);
13713
+ }
13714
+ if (keys.length === 0) {
13715
+ operationKeysByCallId.delete(state.callId);
13716
+ }
13717
+ };
13718
+ const explicitOperationKey = (event) => {
13719
+ if (!isObject(event)) {
13720
+ return void 0;
13721
+ }
13722
+ const key = event[BRAINTRUST_AI_SDK_V7_OPERATION_KEY];
13723
+ return typeof key === "string" ? key : void 0;
13724
+ };
13725
+ const createOperationKey = (event, operationName) => {
13726
+ const explicit = explicitOperationKey(event);
13727
+ if (explicit) {
13728
+ return explicit;
13729
+ }
13730
+ if (operationName === "WorkflowAgent.stream") {
13731
+ workflowAgentOperationCounter += 1;
13732
+ return `${event.callId}:${workflowAgentOperationCounter}`;
13733
+ }
13734
+ return event.callId;
13735
+ };
13736
+ const operationKeyForCallId = (callId, mode = "active") => {
13737
+ const keys = operationKeysByCallId.get(callId);
13738
+ if (!keys || keys.length === 0) {
13739
+ return operations.has(callId) ? callId : void 0;
13740
+ }
13741
+ if (keys.length === 1) {
13742
+ return keys[0];
13743
+ }
13744
+ const wrapperSpan = currentWorkflowAgentWrapperSpan();
13745
+ if (wrapperSpan?.spanId) {
13746
+ const key = keys.find(
13747
+ (candidate) => operations.get(candidate)?.span.spanId === wrapperSpan.spanId
13748
+ );
13749
+ if (key) {
13750
+ return key;
13751
+ }
13752
+ }
13753
+ const workflowOperationKey = workflowOperationKeyStore.getStore();
13754
+ if (workflowOperationKey && keys.includes(workflowOperationKey)) {
13755
+ return workflowOperationKey;
13756
+ }
13757
+ if (callId === "workflow-agent") {
13758
+ return void 0;
13759
+ }
13760
+ return mode === "finish" ? keys[0] : keys[keys.length - 1];
13761
+ };
13762
+ const operationKeyFromEvent = (event, mode = "active") => {
13763
+ const explicit = explicitOperationKey(event);
13764
+ if (explicit && operations.has(explicit)) {
13765
+ return explicit;
13766
+ }
13767
+ if (isObject(event)) {
13768
+ const callId = event.callId;
13769
+ if (typeof callId === "string") {
13770
+ const operationKey = operationKeyForCallId(callId, mode);
13771
+ if (operationKey) {
13772
+ return operationKey;
12899
13773
  }
12900
- span.log(logPayload);
12901
- });
12902
- },
12903
- onLanguageModelCallStart(event) {
12904
- runSafely("onLanguageModelCallStart", () => {
12905
- const state = operations.get(event.callId);
12906
- const openSpans = modelSpans.get(event.callId);
12907
- if (openSpans) {
12908
- for (const span2 of openSpans) {
12909
- span2.end();
12910
- }
12911
- modelSpans.delete(event.callId);
13774
+ const workflowOperationKey2 = workflowOperationKeyStore.getStore();
13775
+ if (workflowOperationKey2 && operations.has(workflowOperationKey2)) {
13776
+ return workflowOperationKey2;
12912
13777
  }
12913
- const span = startChildSpan(
12914
- event.callId,
12915
- state?.operationName === "streamText" ? "doStream" : "doGenerate",
12916
- "llm" /* LLM */,
12917
- {
12918
- ...shouldRecordInputs(event) ? {
12919
- input: processAISDKCallInput(
12920
- operationInput(
12921
- event,
12922
- state?.operationName ?? "generateText"
12923
- )
12924
- ).input
12925
- } : {},
12926
- metadata: metadataFromEvent(event)
12927
- }
12928
- );
12929
- const spans = modelSpans.get(event.callId) ?? [];
12930
- spans.push(span);
12931
- modelSpans.set(event.callId, spans);
12932
- });
12933
- },
12934
- onLanguageModelCallEnd(event) {
12935
- runSafely("onLanguageModelCallEnd", () => {
12936
- const span = shiftModelSpan(modelSpans, event.callId);
12937
- if (!span) {
12938
- return;
13778
+ return callId === "workflow-agent" ? void 0 : callId;
13779
+ }
13780
+ }
13781
+ const workflowOperationKey = workflowOperationKeyStore.getStore();
13782
+ if (workflowOperationKey && operations.has(workflowOperationKey)) {
13783
+ return workflowOperationKey;
13784
+ }
13785
+ const wrapperSpan = currentWorkflowAgentWrapperSpan();
13786
+ if (wrapperSpan?.spanId) {
13787
+ for (const [operationKey, state] of operations) {
13788
+ if (state.operationName === "WorkflowAgent.stream" && state.span.spanId === wrapperSpan.spanId) {
13789
+ return operationKey;
12939
13790
  }
12940
- const result = {
12941
- ...event,
12942
- response: event.responseId ? { id: event.responseId } : void 0
12943
- };
12944
- span.log({
12945
- ...shouldRecordOutputs(event) ? {
12946
- output: processAISDKOutput(result, DEFAULT_DENY_OUTPUT_PATHS)
12947
- } : {},
12948
- metrics: extractTokenMetrics(result)
12949
- });
12950
- span.end();
12951
- });
12952
- },
12953
- onObjectStepStart(event) {
12954
- runSafely("onObjectStepStart", () => {
12955
- const state = operations.get(event.callId);
12956
- const openSpan = objectSpans.get(event.callId);
12957
- if (openSpan) {
12958
- openSpan.end();
12959
- objectSpans.delete(event.callId);
13791
+ }
13792
+ }
13793
+ const workflowAgentKeys = operationKeysByCallId.get("workflow-agent");
13794
+ if (workflowAgentKeys?.length === 1) {
13795
+ return workflowAgentKeys[0];
13796
+ }
13797
+ if (operations.size === 1) {
13798
+ return operations.keys().next().value;
13799
+ }
13800
+ return void 0;
13801
+ };
13802
+ const closeOpenChildSpans = (operationKey, error) => {
13803
+ const openModelSpans = modelSpans.get(operationKey);
13804
+ if (openModelSpans) {
13805
+ for (const span of openModelSpans) {
13806
+ if (error !== void 0) {
13807
+ logError(span, error);
13808
+ }
13809
+ span.end();
13810
+ }
13811
+ modelSpans.delete(operationKey);
13812
+ }
13813
+ const openObjectSpan = objectSpans.get(operationKey);
13814
+ if (openObjectSpan) {
13815
+ if (error !== void 0) {
13816
+ logError(openObjectSpan, error);
13817
+ }
13818
+ openObjectSpan.end();
13819
+ objectSpans.delete(operationKey);
13820
+ }
13821
+ for (const [embedCallId, embedState] of embedSpans) {
13822
+ if (embedState.operationKey === operationKey) {
13823
+ if (error !== void 0) {
13824
+ logError(embedState.span, error);
13825
+ }
13826
+ embedState.span.end();
13827
+ embedSpans.delete(embedCallId);
13828
+ }
13829
+ }
13830
+ const openRerankSpan = rerankSpans.get(operationKey);
13831
+ if (openRerankSpan) {
13832
+ if (error !== void 0) {
13833
+ logError(openRerankSpan, error);
13834
+ }
13835
+ openRerankSpan.end();
13836
+ rerankSpans.delete(operationKey);
13837
+ }
13838
+ for (const [toolCallId, toolState] of toolSpans) {
13839
+ if (toolState.operationKey === operationKey) {
13840
+ if (error !== void 0) {
13841
+ logError(toolState.span, error);
13842
+ }
13843
+ toolState.span.end();
13844
+ toolSpans.delete(toolCallId);
13845
+ }
13846
+ }
13847
+ };
13848
+ const abortReasonFromEvent = (event) => {
13849
+ if (isObject(event)) {
13850
+ const abortEvent = event;
13851
+ if (abortEvent.error !== void 0) {
13852
+ return abortEvent.error;
13853
+ }
13854
+ if (abortEvent.reason !== void 0) {
13855
+ return abortEvent.reason;
13856
+ }
13857
+ }
13858
+ return new Error("AI SDK operation aborted");
13859
+ };
13860
+ const shouldSkipTelemetryChildren = (state) => state?.operationName === "WorkflowAgent.stream" && !state.ownsSpan;
13861
+ const onObjectStepEnd = (event) => {
13862
+ runSafely("onObjectStepEnd", () => {
13863
+ const operationKey = operationKeyFromEvent(event);
13864
+ const span = operationKey ? objectSpans.get(operationKey) : void 0;
13865
+ if (!operationKey || !span) {
13866
+ return;
13867
+ }
13868
+ const result = {
13869
+ ...event,
13870
+ text: event.objectText
13871
+ };
13872
+ span.log({
13873
+ ...shouldRecordOutputs(event) ? {
13874
+ output: processAISDKOutput(result, DEFAULT_DENY_OUTPUT_PATHS)
13875
+ } : {},
13876
+ metrics: extractTokenMetrics(result)
13877
+ });
13878
+ span.end();
13879
+ objectSpans.delete(operationKey);
13880
+ });
13881
+ };
13882
+ const onEmbedEnd = (event) => {
13883
+ runSafely("onEmbedEnd", () => {
13884
+ const state = embedSpans.get(event.embedCallId);
13885
+ if (!state) {
13886
+ return;
13887
+ }
13888
+ const result = {
13889
+ ...event,
13890
+ embeddings: event.embeddings
13891
+ };
13892
+ state.span.log({
13893
+ ...shouldRecordOutputs(event) ? {
13894
+ output: processAISDKEmbeddingOutput(
13895
+ result,
13896
+ DEFAULT_DENY_OUTPUT_PATHS
13897
+ )
13898
+ } : {},
13899
+ metrics: extractTokenMetrics(result)
13900
+ });
13901
+ state.span.end();
13902
+ embedSpans.delete(event.embedCallId);
13903
+ });
13904
+ };
13905
+ const onRerankEnd = (event) => {
13906
+ runSafely("onRerankEnd", () => {
13907
+ const operationKey = operationKeyFromEvent(event);
13908
+ const span = operationKey ? rerankSpans.get(operationKey) : void 0;
13909
+ if (!operationKey || !span) {
13910
+ return;
13911
+ }
13912
+ const result = {
13913
+ ranking: event.ranking?.map((entry) => ({
13914
+ originalIndex: entry.index,
13915
+ score: entry.relevanceScore
13916
+ }))
13917
+ };
13918
+ span.log({
13919
+ ...shouldRecordOutputs(event) ? {
13920
+ output: processAISDKRerankOutput(
13921
+ result,
13922
+ DEFAULT_DENY_OUTPUT_PATHS
13923
+ )
13924
+ } : {}
13925
+ });
13926
+ span.end();
13927
+ rerankSpans.delete(operationKey);
13928
+ });
13929
+ };
13930
+ const onEnd = (event) => {
13931
+ runSafely("onEnd", () => {
13932
+ const operationKey = operationKeyFromEvent(event, "finish");
13933
+ const state = operationKey ? operations.get(operationKey) : void 0;
13934
+ if (!state) {
13935
+ return;
13936
+ }
13937
+ if (!state.ownsSpan) {
13938
+ deleteOperation(state.operationKey);
13939
+ return;
13940
+ }
13941
+ const result = finishResult(event, state.operationName);
13942
+ const metrics = state.hadModelChild ? {} : extractTokenMetrics(result);
13943
+ const timeToFirstToken = state.operationName === "WorkflowAgent.stream" ? void 0 : extractTimeToFirstToken(result, state);
13944
+ if (timeToFirstToken !== void 0) {
13945
+ metrics.time_to_first_token = timeToFirstToken;
13946
+ }
13947
+ state.span.log({
13948
+ ...shouldRecordOutputs(event) ? {
13949
+ output: finishOutput(result, state.operationName)
13950
+ } : {},
13951
+ metrics
13952
+ });
13953
+ state.span.end();
13954
+ deleteOperation(state.operationKey);
13955
+ });
13956
+ };
13957
+ return {
13958
+ onStart(event) {
13959
+ runSafely("onStart", () => {
13960
+ const operationName = operationNameFromId(event.operationId);
13961
+ const workflowAgent = operationName === "WorkflowAgent.stream";
13962
+ const wrapperSpan = workflowAgent ? currentWorkflowAgentWrapperSpan() : void 0;
13963
+ const ownsSpan = !wrapperSpan;
13964
+ const span = ownsSpan ? startSpan({
13965
+ name: operationName,
13966
+ spanAttributes: { type: "function" /* FUNCTION */ }
13967
+ }) : wrapperSpan;
13968
+ const operationKey = createOperationKey(event, operationName);
13969
+ registerOperation({
13970
+ callId: event.callId,
13971
+ hadModelChild: false,
13972
+ loggedInput: false,
13973
+ operationName,
13974
+ operationKey,
13975
+ ownsSpan,
13976
+ span,
13977
+ startTime: getCurrentUnixTimestamp()
13978
+ });
13979
+ if (!ownsSpan) {
13980
+ return;
13981
+ }
13982
+ if (workflowAgent) {
13983
+ workflowOperationKeyStore.enterWith(operationKey);
13984
+ }
13985
+ let metadata = metadataFromEvent(event);
13986
+ const logPayload = { metadata };
13987
+ const workflowAgentCallInput = workflowAgent ? operationInput(event, operationName) : void 0;
13988
+ if (workflowAgentCallInput) {
13989
+ metadata = {
13990
+ ...metadata,
13991
+ ...extractWorkflowMetadataFromCallParams(workflowAgentCallInput)
13992
+ };
13993
+ logPayload.metadata = metadata;
13994
+ }
13995
+ if (shouldRecordInputs(event)) {
13996
+ const callInput = workflowAgentCallInput ?? operationInput(event, operationName);
13997
+ const { input, outputPromise } = workflowAgent ? processAISDKWorkflowAgentCallInput(callInput) : processAISDKCallInput(callInput);
13998
+ logPayload.input = input;
13999
+ const state = operations.get(operationKey);
14000
+ if (state) {
14001
+ state.loggedInput = hasPromptLikeInput(input);
14002
+ }
14003
+ if (outputPromise && !workflowAgent && input && typeof input === "object") {
14004
+ outputPromise.then((resolvedData) => {
14005
+ span.log({
14006
+ input: {
14007
+ ...input,
14008
+ ...resolvedData
14009
+ }
14010
+ });
14011
+ }).catch(() => {
14012
+ });
14013
+ }
14014
+ }
14015
+ span.log(logPayload);
14016
+ });
14017
+ },
14018
+ onLanguageModelCallStart(event) {
14019
+ runSafely("onLanguageModelCallStart", () => {
14020
+ const operationKey = operationKeyFromEvent(event);
14021
+ const state = operationKey ? operations.get(operationKey) : void 0;
14022
+ if (shouldSkipTelemetryChildren(state)) {
14023
+ return;
14024
+ }
14025
+ const operationName = state?.operationName ?? "generateText";
14026
+ const callInput = operationInput(event, operationName);
14027
+ const workflowAgent = operationName === "WorkflowAgent.stream";
14028
+ const processedInput = shouldRecordInputs(event) && workflowAgent ? processAISDKWorkflowAgentModelCallInput(callInput).input : shouldRecordInputs(event) ? processAISDKCallInput(callInput).input : void 0;
14029
+ if (workflowAgent && state?.ownsSpan && !state.loggedInput && hasPromptLikeInput(processedInput)) {
14030
+ state.span.log({
14031
+ input: processedInput,
14032
+ metadata: {
14033
+ ...metadataFromEvent(event),
14034
+ ...extractWorkflowMetadataFromCallParams(callInput)
14035
+ }
14036
+ });
14037
+ state.loggedInput = true;
14038
+ }
14039
+ const openSpans = operationKey ? modelSpans.get(operationKey) : void 0;
14040
+ if (operationKey && openSpans) {
14041
+ for (const span2 of openSpans) {
14042
+ span2.end();
14043
+ }
14044
+ modelSpans.delete(operationKey);
12960
14045
  }
12961
14046
  const span = startChildSpan(
12962
- event.callId,
12963
- state?.operationName === "streamObject" ? "doStream" : "doGenerate",
14047
+ operationKey ?? event.callId,
14048
+ operationName === "streamText" ? "doStream" : "doGenerate",
12964
14049
  "llm" /* LLM */,
12965
14050
  {
12966
14051
  ...shouldRecordInputs(event) ? {
12967
- input: {
12968
- prompt: event.promptMessages
12969
- }
14052
+ input: processedInput
12970
14053
  } : {},
12971
- metadata: metadataFromEvent(event)
14054
+ metadata: workflowAgent ? {
14055
+ ...metadataFromEvent(event),
14056
+ ...extractWorkflowMetadataFromCallParams(callInput)
14057
+ } : metadataFromEvent(event)
12972
14058
  }
12973
14059
  );
12974
- objectSpans.set(event.callId, span);
14060
+ const spanKey = operationKey ?? event.callId;
14061
+ const spans = modelSpans.get(spanKey) ?? [];
14062
+ spans.push(span);
14063
+ modelSpans.set(spanKey, spans);
12975
14064
  });
12976
14065
  },
12977
- onObjectStepFinish(event) {
12978
- runSafely("onObjectStepFinish", () => {
12979
- const span = objectSpans.get(event.callId);
14066
+ onLanguageModelCallEnd(event) {
14067
+ runSafely("onLanguageModelCallEnd", () => {
14068
+ const operationKey = operationKeyFromEvent(event);
14069
+ const state = operationKey ? operations.get(operationKey) : void 0;
14070
+ if (shouldSkipTelemetryChildren(state)) {
14071
+ return;
14072
+ }
14073
+ const span = operationKey ? shiftModelSpan(modelSpans, operationKey) : void 0;
12980
14074
  if (!span) {
12981
14075
  return;
12982
14076
  }
14077
+ const timeToFirstOutputMs = safePerformance(event)?.timeToFirstOutputMs;
14078
+ if (state?.operationName === "streamText" && state.firstChunkTime === void 0 && typeof timeToFirstOutputMs === "number") {
14079
+ state.firstChunkTime = state.startTime + timeToFirstOutputMs / 1e3;
14080
+ }
12983
14081
  const result = {
12984
14082
  ...event,
12985
- text: event.objectText
14083
+ response: event.responseId ? { id: event.responseId } : void 0
12986
14084
  };
12987
14085
  span.log({
12988
14086
  ...shouldRecordOutputs(event) ? {
@@ -12991,20 +14089,52 @@ function braintrustAISDKTelemetry() {
12991
14089
  metrics: extractTokenMetrics(result)
12992
14090
  });
12993
14091
  span.end();
12994
- objectSpans.delete(event.callId);
12995
14092
  });
12996
14093
  },
14094
+ onObjectStepStart(event) {
14095
+ runSafely("onObjectStepStart", () => {
14096
+ const operationKey = operationKeyFromEvent(event);
14097
+ const state = operationKey ? operations.get(operationKey) : void 0;
14098
+ if (shouldSkipTelemetryChildren(state)) {
14099
+ return;
14100
+ }
14101
+ const openSpan = operationKey ? objectSpans.get(operationKey) : void 0;
14102
+ if (operationKey && openSpan) {
14103
+ openSpan.end();
14104
+ objectSpans.delete(operationKey);
14105
+ }
14106
+ const span = startChildSpan(
14107
+ operationKey ?? event.callId,
14108
+ state?.operationName === "streamObject" ? "doStream" : "doGenerate",
14109
+ "llm" /* LLM */,
14110
+ {
14111
+ ...shouldRecordInputs(event) ? {
14112
+ input: {
14113
+ prompt: event.promptMessages
14114
+ }
14115
+ } : {},
14116
+ metadata: metadataFromEvent(event)
14117
+ }
14118
+ );
14119
+ objectSpans.set(operationKey ?? event.callId, span);
14120
+ });
14121
+ },
14122
+ onObjectStepEnd,
12997
14123
  onEmbedStart(event) {
12998
14124
  runSafely("onEmbedStart", () => {
12999
- const state = operations.get(event.callId);
14125
+ const operationKey = operationKeyFromEvent(event);
14126
+ const state = operationKey ? operations.get(operationKey) : void 0;
14127
+ if (shouldSkipTelemetryChildren(state)) {
14128
+ return;
14129
+ }
13000
14130
  for (const [embedCallId, embedState] of embedSpans) {
13001
- if (embedState.callId === event.callId && (state?.operationName === "embed" || embedState.values === event.values)) {
14131
+ if (embedState.operationKey === operationKey && (state?.operationName === "embed" || embedState.values === event.values)) {
13002
14132
  embedState.span.end();
13003
14133
  embedSpans.delete(embedCallId);
13004
14134
  }
13005
14135
  }
13006
14136
  const span = startChildSpan(
13007
- event.callId,
14137
+ operationKey ?? event.callId,
13008
14138
  "doEmbed",
13009
14139
  "llm" /* LLM */,
13010
14140
  {
@@ -13017,44 +14147,27 @@ function braintrustAISDKTelemetry() {
13017
14147
  }
13018
14148
  );
13019
14149
  embedSpans.set(event.embedCallId, {
13020
- callId: event.callId,
14150
+ operationKey: operationKey ?? event.callId,
13021
14151
  span,
13022
14152
  values: event.values
13023
14153
  });
13024
14154
  });
13025
14155
  },
13026
- onEmbedFinish(event) {
13027
- runSafely("onEmbedFinish", () => {
13028
- const state = embedSpans.get(event.embedCallId);
13029
- if (!state) {
13030
- return;
13031
- }
13032
- const result = {
13033
- ...event,
13034
- embeddings: event.embeddings
13035
- };
13036
- state.span.log({
13037
- ...shouldRecordOutputs(event) ? {
13038
- output: processAISDKEmbeddingOutput(
13039
- result,
13040
- DEFAULT_DENY_OUTPUT_PATHS
13041
- )
13042
- } : {},
13043
- metrics: extractTokenMetrics(result)
13044
- });
13045
- state.span.end();
13046
- embedSpans.delete(event.embedCallId);
13047
- });
13048
- },
14156
+ onEmbedEnd,
13049
14157
  onRerankStart(event) {
13050
14158
  runSafely("onRerankStart", () => {
13051
- const openSpan = rerankSpans.get(event.callId);
13052
- if (openSpan) {
14159
+ const operationKey = operationKeyFromEvent(event);
14160
+ const state = operationKey ? operations.get(operationKey) : void 0;
14161
+ if (shouldSkipTelemetryChildren(state)) {
14162
+ return;
14163
+ }
14164
+ const openSpan = operationKey ? rerankSpans.get(operationKey) : void 0;
14165
+ if (operationKey && openSpan) {
13053
14166
  openSpan.end();
13054
- rerankSpans.delete(event.callId);
14167
+ rerankSpans.delete(operationKey);
13055
14168
  }
13056
14169
  const span = startChildSpan(
13057
- event.callId,
14170
+ operationKey ?? event.callId,
13058
14171
  "doRerank",
13059
14172
  "llm" /* LLM */,
13060
14173
  {
@@ -13068,41 +14181,23 @@ function braintrustAISDKTelemetry() {
13068
14181
  metadata: metadataFromEvent(event)
13069
14182
  }
13070
14183
  );
13071
- rerankSpans.set(event.callId, span);
13072
- });
13073
- },
13074
- onRerankFinish(event) {
13075
- runSafely("onRerankFinish", () => {
13076
- const span = rerankSpans.get(event.callId);
13077
- if (!span) {
13078
- return;
13079
- }
13080
- const result = {
13081
- ranking: event.ranking?.map((entry) => ({
13082
- originalIndex: entry.index,
13083
- score: entry.relevanceScore
13084
- }))
13085
- };
13086
- span.log({
13087
- ...shouldRecordOutputs(event) ? {
13088
- output: processAISDKRerankOutput(
13089
- result,
13090
- DEFAULT_DENY_OUTPUT_PATHS
13091
- )
13092
- } : {}
13093
- });
13094
- span.end();
13095
- rerankSpans.delete(event.callId);
14184
+ rerankSpans.set(operationKey ?? event.callId, span);
13096
14185
  });
13097
14186
  },
14187
+ onRerankEnd,
13098
14188
  onToolExecutionStart(event) {
13099
14189
  runSafely("onToolExecutionStart", () => {
14190
+ const operationKey = operationKeyFromEvent(event);
14191
+ const state = operationKey ? operations.get(operationKey) : void 0;
14192
+ if (shouldSkipTelemetryChildren(state)) {
14193
+ return;
14194
+ }
13100
14195
  const toolCallId = event.toolCall.toolCallId;
13101
- if (!toolCallId) {
14196
+ if (!operationKey || !toolCallId) {
13102
14197
  return;
13103
14198
  }
13104
14199
  const span = startChildSpan(
13105
- event.callId,
14200
+ operationKey,
13106
14201
  event.toolCall.toolName || "tool",
13107
14202
  "tool" /* TOOL */,
13108
14203
  {
@@ -13116,7 +14211,7 @@ function braintrustAISDKTelemetry() {
13116
14211
  }
13117
14212
  }
13118
14213
  );
13119
- toolSpans.set(toolCallId, { callId: event.callId, span });
14214
+ toolSpans.set(toolCallId, { operationKey, span });
13120
14215
  });
13121
14216
  },
13122
14217
  onToolExecutionEnd(event) {
@@ -13127,14 +14222,17 @@ function braintrustAISDKTelemetry() {
13127
14222
  return;
13128
14223
  }
13129
14224
  const toolOutput = event.toolOutput;
13130
- if (toolOutput?.type === "tool-error") {
14225
+ const workflowToolError = event.success === false && "error" in event ? event.error : void 0;
14226
+ if (toolOutput?.type === "tool-error" || workflowToolError !== void 0) {
14227
+ const error = toolOutput?.error ?? workflowToolError;
13131
14228
  state.span.log({
13132
- error: toolOutput.error instanceof Error ? toolOutput.error.message : String(toolOutput?.error),
14229
+ error: error instanceof Error ? error.message : String(error),
13133
14230
  metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
13134
14231
  });
13135
14232
  } else {
14233
+ const output = toolOutput && "output" in toolOutput ? toolOutput.output : event.output;
13136
14234
  state.span.log({
13137
- ...shouldRecordOutputs(event) ? { output: toolOutput?.output } : {},
14235
+ ...shouldRecordOutputs(event) ? { output } : {},
13138
14236
  metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
13139
14237
  });
13140
14238
  }
@@ -13148,83 +14246,46 @@ function braintrustAISDKTelemetry() {
13148
14246
  if (!callId) {
13149
14247
  return;
13150
14248
  }
13151
- const state = operations.get(callId);
14249
+ const operationKey = operationKeyForCallId(callId);
14250
+ const state = operationKey ? operations.get(operationKey) : void 0;
13152
14251
  if (!state || state.firstChunkTime !== void 0) {
13153
14252
  return;
13154
14253
  }
13155
14254
  state.firstChunkTime = getCurrentUnixTimestamp();
13156
14255
  });
13157
14256
  },
13158
- onFinish(event) {
13159
- runSafely("onFinish", () => {
13160
- const state = operations.get(event.callId);
13161
- if (!state) {
14257
+ onEnd,
14258
+ onAbort(event) {
14259
+ runSafely("onAbort", () => {
14260
+ const operationKey = operationKeyFromEvent(event, "finish");
14261
+ const state = operationKey ? operations.get(operationKey) : void 0;
14262
+ if (!operationKey || !state) {
13162
14263
  return;
13163
14264
  }
13164
- const result = finishResult(event, state.operationName);
13165
- const metrics = state.hadModelChild ? {} : extractTokenMetrics(result);
13166
- if (state.firstChunkTime !== void 0) {
13167
- metrics.time_to_first_token = state.firstChunkTime - state.startTime;
14265
+ const error = abortReasonFromEvent(event);
14266
+ closeOpenChildSpans(operationKey, error);
14267
+ if (state.ownsSpan) {
14268
+ logError(state.span, error);
14269
+ state.span.end();
13168
14270
  }
13169
- state.span.log({
13170
- ...shouldRecordOutputs(event) ? {
13171
- output: finishOutput(result, state.operationName)
13172
- } : {},
13173
- metrics
13174
- });
13175
- state.span.end();
13176
- operations.delete(event.callId);
14271
+ deleteOperation(operationKey);
13177
14272
  });
13178
14273
  },
13179
14274
  onError(event) {
13180
14275
  runSafely("onError", () => {
13181
14276
  const errorEvent = isObject(event) ? event : {};
13182
- const callId = typeof errorEvent.callId === "string" ? errorEvent.callId : void 0;
13183
- if (!callId) {
13184
- return;
13185
- }
13186
- const state = operations.get(callId);
13187
- if (!state) {
14277
+ const operationKey = operationKeyFromEvent(errorEvent, "finish");
14278
+ const state = operationKey ? operations.get(operationKey) : void 0;
14279
+ if (!operationKey || !state) {
13188
14280
  return;
13189
14281
  }
13190
14282
  const error = errorEvent.error ?? event;
13191
- const openModelSpans = modelSpans.get(callId);
13192
- if (openModelSpans) {
13193
- for (const span of openModelSpans) {
13194
- logError(span, error);
13195
- span.end();
13196
- }
13197
- modelSpans.delete(callId);
13198
- }
13199
- const openObjectSpan = objectSpans.get(callId);
13200
- if (openObjectSpan) {
13201
- logError(openObjectSpan, error);
13202
- openObjectSpan.end();
13203
- objectSpans.delete(callId);
13204
- }
13205
- for (const [embedCallId, embedState] of embedSpans) {
13206
- if (embedState.callId === callId) {
13207
- logError(embedState.span, error);
13208
- embedState.span.end();
13209
- embedSpans.delete(embedCallId);
13210
- }
13211
- }
13212
- const openRerankSpan = rerankSpans.get(callId);
13213
- if (openRerankSpan) {
13214
- logError(openRerankSpan, error);
13215
- openRerankSpan.end();
13216
- rerankSpans.delete(callId);
13217
- }
13218
- for (const [toolCallId, toolState] of toolSpans) {
13219
- if (toolState.callId === callId) {
13220
- logError(toolState.span, error);
13221
- toolState.span.end();
13222
- toolSpans.delete(toolCallId);
13223
- }
14283
+ closeOpenChildSpans(operationKey, error);
14284
+ if (state.ownsSpan) {
14285
+ logError(state.span, error);
14286
+ state.span.end();
13224
14287
  }
13225
- logError(state.span, error);
13226
- state.span.end();
13227
- operations.delete(callId);
14288
+ deleteOperation(operationKey);
13228
14289
  });
13229
14290
  },
13230
14291
  executeTool({ toolCallId, execute }) {
@@ -13239,7 +14300,16 @@ function shouldRecordInputs(event) {
13239
14300
  function shouldRecordOutputs(event) {
13240
14301
  return event.recordOutputs !== false;
13241
14302
  }
14303
+ function hasPromptLikeInput(input) {
14304
+ if (!isObject(input)) {
14305
+ return false;
14306
+ }
14307
+ return input.prompt !== void 0 || input.messages !== void 0;
14308
+ }
13242
14309
  function operationNameFromId(operationId) {
14310
+ if (operationId === "ai.workflowAgent.stream") {
14311
+ return "WorkflowAgent.stream";
14312
+ }
13243
14313
  return operationId?.startsWith("ai.") ? operationId.slice("ai.".length) : operationId || "ai-sdk";
13244
14314
  }
13245
14315
  function modelFromEvent(event) {
@@ -13285,6 +14355,7 @@ function operationInput(event, operationName) {
13285
14355
  }
13286
14356
  return {
13287
14357
  model: modelFromEvent(event),
14358
+ instructions: event.instructions,
13288
14359
  system: event.system,
13289
14360
  prompt: event.prompt,
13290
14361
  messages: event.messages,
@@ -13333,6 +14404,30 @@ function finishResult(event, operationName) {
13333
14404
  }
13334
14405
  return event;
13335
14406
  }
14407
+ function extractTimeToFirstToken(result, state) {
14408
+ if (state.firstChunkTime !== void 0) {
14409
+ return state.firstChunkTime - state.startTime;
14410
+ }
14411
+ const performanceCandidates = [
14412
+ safePerformance(result),
14413
+ safePerformance(result.finalStep),
14414
+ ...Array.isArray(result.steps) ? (result.steps ?? []).map(safePerformance) : []
14415
+ ];
14416
+ for (const performance of performanceCandidates) {
14417
+ const timeToFirstOutputMs = performance?.timeToFirstOutputMs;
14418
+ if (typeof timeToFirstOutputMs === "number") {
14419
+ return timeToFirstOutputMs / 1e3;
14420
+ }
14421
+ }
14422
+ return void 0;
14423
+ }
14424
+ function safePerformance(value) {
14425
+ if (!isObject(value)) {
14426
+ return void 0;
14427
+ }
14428
+ const performance = value.performance;
14429
+ return isObject(performance) ? performance : void 0;
14430
+ }
13336
14431
  function finishOutput(result, operationName) {
13337
14432
  if (operationName === "embed" || operationName === "embedMany") {
13338
14433
  return processAISDKEmbeddingOutput(
@@ -13409,6 +14504,10 @@ var aiSDKChannels = defineChannels("ai", {
13409
14504
  channelName: "ToolLoopAgent.stream",
13410
14505
  kind: "async"
13411
14506
  }),
14507
+ workflowAgentStream: channel({
14508
+ channelName: "WorkflowAgent.stream",
14509
+ kind: "async"
14510
+ }),
13412
14511
  v7CreateTelemetryDispatcher: channel({
13413
14512
  channelName: "createTelemetryDispatcher",
13414
14513
  kind: "sync-stream"
@@ -13419,14 +14518,19 @@ var aiSDKChannels = defineChannels("ai", {
13419
14518
  var DEFAULT_DENY_OUTPUT_PATHS = [
13420
14519
  // v3
13421
14520
  "roundtrips[].request.body",
14521
+ "roundtrips[].request.headers",
13422
14522
  "roundtrips[].response.headers",
13423
14523
  "rawResponse.headers",
13424
14524
  "responseMessages",
13425
14525
  // v5
13426
14526
  "request.body",
14527
+ "request.headers",
14528
+ "responses[].headers",
13427
14529
  "response.body",
13428
14530
  "response.headers",
13429
14531
  "steps[].request.body",
14532
+ "steps[].request.headers",
14533
+ "steps[].responses[].headers",
13430
14534
  "steps[].response.body",
13431
14535
  "steps[].response.headers"
13432
14536
  ];
@@ -13438,6 +14542,18 @@ var AUTO_PATCHED_V7_TELEMETRY_DISPATCHER = /* @__PURE__ */ Symbol.for(
13438
14542
  var RUNTIME_DENY_OUTPUT_PATHS = /* @__PURE__ */ Symbol.for(
13439
14543
  "braintrust.ai-sdk.deny-output-paths"
13440
14544
  );
14545
+ var aiSDKV7TelemetryOperationCounter = 0;
14546
+ var TRANSPORT_PAYLOAD_ROOT_PATHS = [
14547
+ "rawResponse",
14548
+ "request",
14549
+ "response",
14550
+ "responses[]",
14551
+ "roundtrips[].request",
14552
+ "roundtrips[].response",
14553
+ "steps[].request",
14554
+ "steps[].response",
14555
+ "steps[].responses[]"
14556
+ ];
13441
14557
  var AI_SDK_V7_TELEMETRY_CALLBACKS = [
13442
14558
  "onStart",
13443
14559
  "onStepStart",
@@ -13446,14 +14562,16 @@ var AI_SDK_V7_TELEMETRY_CALLBACKS = [
13446
14562
  "onToolExecutionStart",
13447
14563
  "onToolExecutionEnd",
13448
14564
  "onChunk",
14565
+ "onStepEnd",
13449
14566
  "onStepFinish",
13450
14567
  "onObjectStepStart",
13451
- "onObjectStepFinish",
14568
+ "onObjectStepEnd",
13452
14569
  "onEmbedStart",
13453
- "onEmbedFinish",
14570
+ "onEmbedEnd",
13454
14571
  "onRerankStart",
13455
- "onRerankFinish",
13456
- "onFinish",
14572
+ "onRerankEnd",
14573
+ "onEnd",
14574
+ "onAbort",
13457
14575
  "onError"
13458
14576
  ];
13459
14577
  var AISDKPlugin = class extends BasePlugin {
@@ -13611,7 +14729,9 @@ var AISDKPlugin = class extends BasePlugin {
13611
14729
  traceStreamingChannel(aiSDKChannels.agentGenerate, {
13612
14730
  name: "Agent.generate",
13613
14731
  type: "function" /* FUNCTION */,
13614
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
14732
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
14733
+ agentOwner: true
14734
+ }),
13615
14735
  extractOutput: (result, endEvent) => {
13616
14736
  finalizeAISDKChildTracing(endEvent);
13617
14737
  return processAISDKOutput(
@@ -13627,7 +14747,9 @@ var AISDKPlugin = class extends BasePlugin {
13627
14747
  traceStreamingChannel(aiSDKChannels.agentStream, {
13628
14748
  name: "Agent.stream",
13629
14749
  type: "function" /* FUNCTION */,
13630
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
14750
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
14751
+ agentOwner: true
14752
+ }),
13631
14753
  extractOutput: (result, endEvent) => processAISDKOutput(
13632
14754
  result,
13633
14755
  resolveDenyOutputPaths(endEvent, denyOutputPaths)
@@ -13647,7 +14769,9 @@ var AISDKPlugin = class extends BasePlugin {
13647
14769
  traceSyncStreamChannel(aiSDKChannels.agentStreamSync, {
13648
14770
  name: "Agent.stream",
13649
14771
  type: "function" /* FUNCTION */,
13650
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
14772
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
14773
+ agentOwner: true
14774
+ }),
13651
14775
  patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
13652
14776
  defaultDenyOutputPaths: denyOutputPaths,
13653
14777
  endEvent,
@@ -13661,7 +14785,9 @@ var AISDKPlugin = class extends BasePlugin {
13661
14785
  traceStreamingChannel(aiSDKChannels.toolLoopAgentGenerate, {
13662
14786
  name: "ToolLoopAgent.generate",
13663
14787
  type: "function" /* FUNCTION */,
13664
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
14788
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
14789
+ agentOwner: true
14790
+ }),
13665
14791
  extractOutput: (result, endEvent) => {
13666
14792
  finalizeAISDKChildTracing(endEvent);
13667
14793
  return processAISDKOutput(
@@ -13677,7 +14803,9 @@ var AISDKPlugin = class extends BasePlugin {
13677
14803
  traceStreamingChannel(aiSDKChannels.toolLoopAgentStream, {
13678
14804
  name: "ToolLoopAgent.stream",
13679
14805
  type: "function" /* FUNCTION */,
13680
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
14806
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
14807
+ agentOwner: true
14808
+ }),
13681
14809
  extractOutput: (result, endEvent) => processAISDKOutput(
13682
14810
  result,
13683
14811
  resolveDenyOutputPaths(endEvent, denyOutputPaths)
@@ -13693,6 +14821,42 @@ var AISDKPlugin = class extends BasePlugin {
13693
14821
  })
13694
14822
  })
13695
14823
  );
14824
+ this.unsubscribers.push(
14825
+ traceStreamingChannel(aiSDKChannels.workflowAgentStream, {
14826
+ name: "WorkflowAgent.stream",
14827
+ type: "function" /* FUNCTION */,
14828
+ extractInput: ([params], event, span) => prepareAISDKWorkflowAgentStreamInput(
14829
+ params,
14830
+ event,
14831
+ span,
14832
+ denyOutputPaths
14833
+ ),
14834
+ extractOutput: (result, endEvent) => {
14835
+ finalizeAISDKChildTracing(endEvent);
14836
+ return processAISDKOutput(
14837
+ result,
14838
+ resolveDenyOutputPaths(endEvent, denyOutputPaths)
14839
+ );
14840
+ },
14841
+ extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
14842
+ aggregateChunks: aggregateAISDKChunks,
14843
+ onComplete: ({ span }) => {
14844
+ unregisterWorkflowAgentWrapperSpan(span);
14845
+ },
14846
+ onError: ({ event, span }) => {
14847
+ finalizeAISDKChildTracing(event);
14848
+ unregisterWorkflowAgentWrapperSpan(span);
14849
+ },
14850
+ patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
14851
+ defaultDenyOutputPaths: denyOutputPaths,
14852
+ endEvent,
14853
+ onComplete: () => unregisterWorkflowAgentWrapperSpan(span),
14854
+ result,
14855
+ span,
14856
+ startTime
14857
+ })
14858
+ })
14859
+ );
13696
14860
  }
13697
14861
  };
13698
14862
  function subscribeToAISDKV7TelemetryDispatcher() {
@@ -13704,7 +14868,11 @@ function subscribeToAISDKV7TelemetryDispatcher() {
13704
14868
  if (telemetryOptions?.isEnabled === false) {
13705
14869
  return;
13706
14870
  }
13707
- patchAISDKV7TelemetryDispatcher(event.result, telemetry);
14871
+ patchAISDKV7TelemetryDispatcher(
14872
+ event.result,
14873
+ telemetry,
14874
+ telemetryOptions
14875
+ );
13708
14876
  }
13709
14877
  };
13710
14878
  channel2.subscribe(handlers);
@@ -13712,7 +14880,7 @@ function subscribeToAISDKV7TelemetryDispatcher() {
13712
14880
  channel2.unsubscribe(handlers);
13713
14881
  };
13714
14882
  }
13715
- function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
14883
+ function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry, telemetryOptions) {
13716
14884
  if (!isObject(dispatcher)) {
13717
14885
  return;
13718
14886
  }
@@ -13721,6 +14889,54 @@ function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
13721
14889
  return;
13722
14890
  }
13723
14891
  dispatcherRecord[AUTO_PATCHED_V7_TELEMETRY_DISPATCHER] = true;
14892
+ let operationKey;
14893
+ const telemetryEventFields = {};
14894
+ if (typeof telemetryOptions?.recordInputs === "boolean") {
14895
+ telemetryEventFields.recordInputs = telemetryOptions.recordInputs;
14896
+ }
14897
+ if (typeof telemetryOptions?.recordOutputs === "boolean") {
14898
+ telemetryEventFields.recordOutputs = telemetryOptions.recordOutputs;
14899
+ }
14900
+ if (typeof telemetryOptions?.functionId === "string") {
14901
+ telemetryEventFields.functionId = telemetryOptions.functionId;
14902
+ }
14903
+ const eventWithOperationKey = (event) => {
14904
+ if (!isObject(event)) {
14905
+ return event;
14906
+ }
14907
+ const eventRecord = event;
14908
+ const callId = typeof eventRecord.callId === "string" ? eventRecord.callId : "unknown";
14909
+ operationKey ??= `${callId}:${++aiSDKV7TelemetryOperationCounter}`;
14910
+ if (Object.keys(telemetryEventFields).length > 0) {
14911
+ const augmentedEvent = {
14912
+ ...telemetryEventFields,
14913
+ ...event
14914
+ };
14915
+ try {
14916
+ Object.defineProperty(augmentedEvent, BRAINTRUST_AI_SDK_V7_OPERATION_KEY, {
14917
+ configurable: true,
14918
+ enumerable: false,
14919
+ value: operationKey
14920
+ });
14921
+ } catch {
14922
+ augmentedEvent[BRAINTRUST_AI_SDK_V7_OPERATION_KEY] = operationKey;
14923
+ }
14924
+ return augmentedEvent;
14925
+ }
14926
+ try {
14927
+ Object.defineProperty(eventRecord, BRAINTRUST_AI_SDK_V7_OPERATION_KEY, {
14928
+ configurable: true,
14929
+ enumerable: false,
14930
+ value: operationKey
14931
+ });
14932
+ return event;
14933
+ } catch {
14934
+ return {
14935
+ ...event,
14936
+ [BRAINTRUST_AI_SDK_V7_OPERATION_KEY]: operationKey
14937
+ };
14938
+ }
14939
+ };
13724
14940
  for (const key of AI_SDK_V7_TELEMETRY_CALLBACKS) {
13725
14941
  const braintrustCallback = telemetry[key];
13726
14942
  if (typeof braintrustCallback !== "function") {
@@ -13729,11 +14945,17 @@ function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
13729
14945
  const existingCallback = dispatcherRecord[key];
13730
14946
  dispatcherRecord[key] = (event) => {
13731
14947
  const existingResult = typeof existingCallback === "function" ? existingCallback.call(dispatcher, event) : void 0;
13732
- const braintrustResult = braintrustCallback.call(telemetry, event);
13733
- const pending = [existingResult, braintrustResult].filter(isPromiseLike);
13734
- if (pending.length > 0) {
13735
- return Promise.allSettled(pending).then(() => void 0);
14948
+ try {
14949
+ const braintrustResult = braintrustCallback.call(
14950
+ telemetry,
14951
+ eventWithOperationKey(event)
14952
+ );
14953
+ if (isPromiseLike(braintrustResult)) {
14954
+ void Promise.resolve(braintrustResult).catch(() => void 0);
14955
+ }
14956
+ } catch {
13736
14957
  }
14958
+ return existingResult;
13737
14959
  };
13738
14960
  }
13739
14961
  const braintrustExecuteTool = telemetry.executeTool;
@@ -13743,6 +14965,7 @@ function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
13743
14965
  const existingExecuteTool = dispatcherRecord.executeTool;
13744
14966
  dispatcherRecord.executeTool = (args) => braintrustExecuteTool.call(telemetry, {
13745
14967
  ...args,
14968
+ ...operationKey ? { [BRAINTRUST_AI_SDK_V7_OPERATION_KEY]: operationKey } : {},
13746
14969
  execute: () => typeof existingExecuteTool === "function" ? existingExecuteTool.call(dispatcher, args) : args.execute()
13747
14970
  });
13748
14971
  }
@@ -13841,6 +15064,8 @@ var serializeOutputObject = (output, model) => {
13841
15064
  var processInputAttachmentsSync = (input) => {
13842
15065
  if (!input) return { input };
13843
15066
  const processed = { ...input };
15067
+ delete processed.headers;
15068
+ delete processed.experimental_output;
13844
15069
  if (input.messages && Array.isArray(input.messages)) {
13845
15070
  processed.messages = input.messages.map(processMessage);
13846
15071
  }
@@ -13874,10 +15099,10 @@ var processInputAttachmentsSync = (input) => {
13874
15099
  processed.output = serialized;
13875
15100
  }
13876
15101
  }
13877
- if ("prepareCall" in processed && typeof processed.prepareCall === "function") {
13878
- processed.prepareCall = "[Function]";
13879
- }
13880
- return { input: processed, outputPromise };
15102
+ return {
15103
+ input: sanitizeAISDKCallInputValue(processed),
15104
+ outputPromise
15105
+ };
13881
15106
  };
13882
15107
  var processMessage = (message) => {
13883
15108
  if (!message || typeof message !== "object") return message;
@@ -14041,7 +15266,21 @@ var convertDataToAttachment = (data, mimeType, filename) => {
14041
15266
  function processAISDKCallInput(params) {
14042
15267
  return processInputAttachmentsSync(params);
14043
15268
  }
14044
- function prepareAISDKCallInput(params, event, span, defaultDenyOutputPaths) {
15269
+ function processAISDKWorkflowAgentCallInput(params) {
15270
+ const processed = processAISDKCallInput(params);
15271
+ return {
15272
+ ...processed,
15273
+ input: extractWorkflowAgentInput(processed.input)
15274
+ };
15275
+ }
15276
+ function processAISDKWorkflowAgentModelCallInput(params) {
15277
+ const processed = processAISDKCallInput(params);
15278
+ return {
15279
+ ...processed,
15280
+ input: extractWorkflowAgentModelInput(processed.input)
15281
+ };
15282
+ }
15283
+ function prepareAISDKCallInput(params, event, span, defaultDenyOutputPaths, childTracingOptions = {}) {
14045
15284
  const { input, outputPromise } = processAISDKCallInput(params);
14046
15285
  if (outputPromise && input && typeof input === "object") {
14047
15286
  outputPromise.then((resolvedData) => {
@@ -14060,7 +15299,29 @@ function prepareAISDKCallInput(params, event, span, defaultDenyOutputPaths) {
14060
15299
  event.self,
14061
15300
  span,
14062
15301
  defaultDenyOutputPaths,
14063
- event.aiSDK
15302
+ event.aiSDK,
15303
+ childTracingOptions
15304
+ );
15305
+ event.modelWrapped = childTracing.modelWrapped;
15306
+ if (childTracing.cleanup) {
15307
+ event.__braintrust_ai_sdk_cleanup = childTracing.cleanup;
15308
+ }
15309
+ return {
15310
+ input,
15311
+ metadata
15312
+ };
15313
+ }
15314
+ function prepareAISDKWorkflowAgentStreamInput(params, event, span, defaultDenyOutputPaths) {
15315
+ registerWorkflowAgentWrapperSpan(span);
15316
+ const { input } = processAISDKWorkflowAgentCallInput(params);
15317
+ const metadata = extractWorkflowMetadataFromCallParams(params, event.self);
15318
+ const childTracing = prepareAISDKChildTracing(
15319
+ params,
15320
+ event.self,
15321
+ span,
15322
+ defaultDenyOutputPaths,
15323
+ event.aiSDK,
15324
+ { agentOwner: true, workflowAgent: true }
14064
15325
  );
14065
15326
  event.modelWrapped = childTracing.modelWrapped;
14066
15327
  if (childTracing.cleanup) {
@@ -14097,6 +15358,9 @@ function extractTopLevelAISDKMetrics(result, event, startTime) {
14097
15358
  function hasModelChildTracing(event) {
14098
15359
  return event?.modelWrapped === true || event?.__braintrust_ai_sdk_model_wrapped === true;
14099
15360
  }
15361
+ function serializeToolExecutionInput(args) {
15362
+ return args.length > 0 ? args[0] : args;
15363
+ }
14100
15364
  function createAISDKIntegrationMetadata() {
14101
15365
  return {
14102
15366
  braintrust: {
@@ -14108,6 +15372,13 @@ function createAISDKIntegrationMetadata() {
14108
15372
  function resolveModelFromSelf(self) {
14109
15373
  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;
14110
15374
  }
15375
+ function resolveToolsFromSelf(self) {
15376
+ if (!self || typeof self !== "object") {
15377
+ return void 0;
15378
+ }
15379
+ const selfRecord = self;
15380
+ return selfRecord.tools ?? selfRecord.settings?.tools;
15381
+ }
14111
15382
  function extractBaseMetadata(model, self) {
14112
15383
  const metadata = createAISDKIntegrationMetadata();
14113
15384
  const { model: modelId, provider } = serializeModelWithProvider(
@@ -14123,12 +15394,175 @@ function extractBaseMetadata(model, self) {
14123
15394
  }
14124
15395
  function extractMetadataFromCallParams(params, self) {
14125
15396
  const metadata = extractBaseMetadata(params.model, self);
14126
- const tools = serializeAISDKToolsForLogging(params.tools);
15397
+ const tools = serializeAISDKToolsForLogging(
15398
+ params.tools ?? resolveToolsFromSelf(self)
15399
+ );
14127
15400
  if (tools) {
14128
15401
  metadata.tools = tools;
14129
15402
  }
14130
15403
  return metadata;
14131
15404
  }
15405
+ function extractWorkflowMetadataFromCallParams(params, self) {
15406
+ const metadata = extractMetadataFromCallParams(params, self);
15407
+ const options = extractAISDKCallOptionsForMetadata(params);
15408
+ if (Object.keys(options).length > 0) {
15409
+ metadata.options = options;
15410
+ }
15411
+ return metadata;
15412
+ }
15413
+ function extractWorkflowAgentInput(params) {
15414
+ const input = {};
15415
+ if (params.instructions !== void 0) {
15416
+ input.instructions = params.instructions;
15417
+ }
15418
+ if (params.system !== void 0) {
15419
+ input.system = params.system;
15420
+ }
15421
+ if (Array.isArray(params.messages)) {
15422
+ return { ...input, messages: params.messages };
15423
+ }
15424
+ if (typeof params.prompt === "string") {
15425
+ return { ...input, prompt: params.prompt };
15426
+ }
15427
+ if (Array.isArray(params.prompt)) {
15428
+ return { ...input, prompt: params.prompt };
15429
+ }
15430
+ return input;
15431
+ }
15432
+ function extractWorkflowAgentModelInput(params) {
15433
+ const input = {};
15434
+ if (params.instructions !== void 0) {
15435
+ input.instructions = params.instructions;
15436
+ }
15437
+ if (params.system !== void 0) {
15438
+ input.system = params.system;
15439
+ }
15440
+ if (Array.isArray(params.messages)) {
15441
+ return { ...input, messages: params.messages };
15442
+ }
15443
+ if (typeof params.prompt === "string") {
15444
+ return { ...input, prompt: params.prompt };
15445
+ }
15446
+ if (Array.isArray(params.prompt)) {
15447
+ return { ...input, messages: params.prompt };
15448
+ }
15449
+ return input;
15450
+ }
15451
+ function sanitizeAISDKCallInputValue(value, depth = 0) {
15452
+ if (value === void 0 || typeof value === "function") {
15453
+ return void 0;
15454
+ }
15455
+ if (value === null || typeof value !== "object") {
15456
+ return value;
15457
+ }
15458
+ if (isPromiseLike(value)) {
15459
+ return "[Promise]";
15460
+ }
15461
+ if (typeof AbortSignal !== "undefined" && value instanceof AbortSignal) {
15462
+ return "[AbortSignal]";
15463
+ }
15464
+ if (depth >= 8) {
15465
+ return "[Object]";
15466
+ }
15467
+ if (Array.isArray(value)) {
15468
+ return value.map((item) => sanitizeAISDKCallInputValue(item, depth + 1)).filter((item) => item !== void 0);
15469
+ }
15470
+ if (!isObject(value)) {
15471
+ return value;
15472
+ }
15473
+ const prototype = Object.getPrototypeOf(value);
15474
+ if (prototype !== Object.prototype && prototype !== null) {
15475
+ return value;
15476
+ }
15477
+ const sanitized = {};
15478
+ for (const [key, nested] of Object.entries(value)) {
15479
+ if (key === "__proto__" || key === "constructor" || key === "prototype" || key.toLowerCase() === "headers") {
15480
+ continue;
15481
+ }
15482
+ const sanitizedNested = sanitizeAISDKCallInputValue(nested, depth + 1);
15483
+ if (sanitizedNested !== void 0) {
15484
+ sanitized[key] = sanitizedNested;
15485
+ }
15486
+ }
15487
+ return sanitized;
15488
+ }
15489
+ function extractAISDKCallOptionsForMetadata(params) {
15490
+ const options = {};
15491
+ const inputOrTopLevelKeys = /* @__PURE__ */ new Set([
15492
+ "model",
15493
+ "instructions",
15494
+ "messages",
15495
+ "prompt",
15496
+ "system",
15497
+ "tools",
15498
+ "headers",
15499
+ "abortSignal",
15500
+ "signal",
15501
+ "experimental_output"
15502
+ ]);
15503
+ for (const [key, value] of Object.entries(params)) {
15504
+ if (inputOrTopLevelKeys.has(key) || key === "__proto__" || key === "constructor" || key === "prototype" || /^on[A-Z]/.test(key) && typeof value === "function") {
15505
+ continue;
15506
+ }
15507
+ const sanitized = sanitizeAISDKMetadataValue(value);
15508
+ if (sanitized !== void 0) {
15509
+ options[key] = sanitized;
15510
+ }
15511
+ }
15512
+ return options;
15513
+ }
15514
+ function sanitizeAISDKMetadataValue(value, depth = 0) {
15515
+ if (value === void 0) {
15516
+ return void 0;
15517
+ }
15518
+ if (typeof value === "function") {
15519
+ return "[Function]";
15520
+ }
15521
+ if (value === null || typeof value !== "object") {
15522
+ return value;
15523
+ }
15524
+ if (isPromiseLike(value)) {
15525
+ return "[Promise]";
15526
+ }
15527
+ if (typeof AbortSignal !== "undefined" && value instanceof AbortSignal) {
15528
+ return "[AbortSignal]";
15529
+ }
15530
+ if (depth >= 8) {
15531
+ return "[Object]";
15532
+ }
15533
+ if (Array.isArray(value)) {
15534
+ return value.map((item) => sanitizeAISDKMetadataValue(item, depth + 1)).filter((item) => item !== void 0);
15535
+ }
15536
+ if (!isObject(value)) {
15537
+ return value;
15538
+ }
15539
+ const sanitized = {};
15540
+ for (const [key, nested] of Object.entries(value)) {
15541
+ if (key === "__proto__" || key === "constructor" || key === "prototype" || key.toLowerCase() === "headers") {
15542
+ continue;
15543
+ }
15544
+ const sanitizedNested = sanitizeAISDKMetadataValue(nested, depth + 1);
15545
+ if (sanitizedNested !== void 0) {
15546
+ sanitized[key] = sanitizedNested;
15547
+ }
15548
+ }
15549
+ return sanitized;
15550
+ }
15551
+ function buildAISDKModelStartEvent(callOptions, baseMetadata, options) {
15552
+ if (!options.workflowAgent) {
15553
+ return {
15554
+ input: processAISDKCallInput(callOptions).input,
15555
+ metadata: baseMetadata
15556
+ };
15557
+ }
15558
+ return {
15559
+ input: processAISDKWorkflowAgentModelCallInput(callOptions).input,
15560
+ metadata: {
15561
+ ...baseMetadata,
15562
+ ...extractWorkflowMetadataFromCallParams(callOptions)
15563
+ }
15564
+ };
15565
+ }
14132
15566
  function extractMetadataFromEmbedParams(params, self) {
14133
15567
  return extractBaseMetadata(params.model, self);
14134
15568
  }
@@ -14142,65 +15576,228 @@ function extractMetadataFromRerankParams(params, self) {
14142
15576
  }
14143
15577
  return metadata;
14144
15578
  }
14145
- function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiSDK) {
15579
+ function activeAISDKChildPatchEntry(entries) {
15580
+ const activeSpan = currentSpan();
15581
+ const activeSpanId = activeSpan.spanId;
15582
+ if (activeSpanId) {
15583
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
15584
+ const entry = entries[index];
15585
+ if (entry?.activeSpanIds.has(activeSpanId)) {
15586
+ return entry;
15587
+ }
15588
+ }
15589
+ }
15590
+ const activeParentSpanIds = activeSpan.spanParents ?? [];
15591
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
15592
+ const entry = entries[index];
15593
+ if (entry?.parentSpan.spanId && activeParentSpanIds.includes(entry.parentSpan.spanId)) {
15594
+ return entry;
15595
+ }
15596
+ }
15597
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
15598
+ const entry = entries[index];
15599
+ if (entry?.parentSpan.spanId === activeSpanId) {
15600
+ return entry;
15601
+ }
15602
+ }
15603
+ return entries[entries.length - 1];
15604
+ }
15605
+ function attachNestedAISDKChildPatchEntry(entries, nestedSpan, cleanup) {
15606
+ const activeSpanId = currentSpan().spanId;
15607
+ if (!activeSpanId || activeSpanId === nestedSpan.spanId) {
15608
+ return false;
15609
+ }
15610
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
15611
+ const entry = entries[index];
15612
+ if (entry?.parentSpan.spanId === activeSpanId || entry?.activeSpanIds.has(activeSpanId)) {
15613
+ entry.activeSpanIds.add(nestedSpan.spanId);
15614
+ cleanup.push(() => {
15615
+ entry.activeSpanIds.delete(nestedSpan.spanId);
15616
+ });
15617
+ return true;
15618
+ }
15619
+ }
15620
+ return false;
15621
+ }
15622
+ function shadowActiveAISDKChildPatchEntry(entries, entry, nestedSpan, cleanup) {
15623
+ const activeSpanId = currentSpan().spanId;
15624
+ if (!activeSpanId || activeSpanId === nestedSpan.spanId) {
15625
+ return;
15626
+ }
15627
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
15628
+ const existingEntry = entries[index];
15629
+ if (existingEntry?.parentSpan.spanId === activeSpanId || existingEntry?.activeSpanIds.has(activeSpanId)) {
15630
+ entry.activeSpanIds.add(activeSpanId);
15631
+ cleanup.push(() => {
15632
+ entry.activeSpanIds.delete(activeSpanId);
15633
+ });
15634
+ return;
15635
+ }
15636
+ }
15637
+ }
15638
+ function closeOpenAISDKModelPatchSpans(entry) {
15639
+ for (const span of entry.openSpans) {
15640
+ span.end();
15641
+ }
15642
+ entry.openSpans.clear();
15643
+ }
15644
+ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiSDK, childTracingOptions = {}) {
14146
15645
  const cleanup = [];
14147
- const patchedModels = /* @__PURE__ */ new WeakSet();
15646
+ const patchedModels = /* @__PURE__ */ new WeakMap();
14148
15647
  const patchedTools = /* @__PURE__ */ new WeakSet();
14149
15648
  let modelWrapped = false;
14150
15649
  const patchModel = (model) => {
14151
15650
  const resolvedModel = resolveAISDKModel(model, aiSDK);
14152
- if (!resolvedModel || typeof resolvedModel !== "object" || typeof resolvedModel.doGenerate !== "function" || patchedModels.has(resolvedModel) || resolvedModel[AUTO_PATCHED_MODEL]) {
15651
+ if (!resolvedModel || typeof resolvedModel !== "object" || typeof resolvedModel.doGenerate !== "function") {
14153
15652
  return resolvedModel;
14154
15653
  }
14155
- patchedModels.add(resolvedModel);
14156
- resolvedModel[AUTO_PATCHED_MODEL] = true;
15654
+ const existingWrappedModel = patchedModels.get(resolvedModel);
15655
+ if (existingWrappedModel) {
15656
+ modelWrapped = true;
15657
+ return existingWrappedModel;
15658
+ }
14157
15659
  modelWrapped = true;
15660
+ const modelRecord = resolvedModel;
15661
+ const entry = {
15662
+ activeSpanIds: /* @__PURE__ */ new Set([parentSpan.spanId]),
15663
+ baseMetadata: buildAISDKChildMetadata(resolvedModel),
15664
+ childTracingOptions,
15665
+ denyOutputPaths,
15666
+ openSpans: /* @__PURE__ */ new Set(),
15667
+ parentSpan
15668
+ };
15669
+ const cleanupModelEntry = (state2, patchedModel) => {
15670
+ closeOpenAISDKModelPatchSpans(entry);
15671
+ const index = state2.entries.indexOf(entry);
15672
+ if (index >= 0) {
15673
+ state2.entries.splice(index, 1);
15674
+ }
15675
+ if (state2.entries.length > 0) {
15676
+ return;
15677
+ }
15678
+ patchedModel.doGenerate = state2.originalDoGenerate;
15679
+ patchedModel.doStream = state2.originalDoStream;
15680
+ delete patchedModel[AUTO_PATCHED_MODEL];
15681
+ };
15682
+ const existingState = modelRecord[AUTO_PATCHED_MODEL];
15683
+ if (existingState) {
15684
+ patchedModels.set(resolvedModel, resolvedModel);
15685
+ if (childTracingOptions.agentOwner && attachNestedAISDKChildPatchEntry(
15686
+ existingState.entries,
15687
+ parentSpan,
15688
+ cleanup
15689
+ )) {
15690
+ return resolvedModel;
15691
+ }
15692
+ if (!childTracingOptions.agentOwner) {
15693
+ shadowActiveAISDKChildPatchEntry(
15694
+ existingState.entries,
15695
+ entry,
15696
+ parentSpan,
15697
+ cleanup
15698
+ );
15699
+ }
15700
+ existingState.entries.push(entry);
15701
+ cleanup.push(() => {
15702
+ cleanupModelEntry(existingState, modelRecord);
15703
+ });
15704
+ return resolvedModel;
15705
+ }
14158
15706
  const originalDoGenerate = resolvedModel.doGenerate;
14159
15707
  const originalDoStream = resolvedModel.doStream;
14160
- const baseMetadata = buildAISDKChildMetadata(resolvedModel);
14161
- resolvedModel.doGenerate = async function doGeneratePatched(options) {
14162
- return parentSpan.traced(
15708
+ const wrappedModel = Object.create(
15709
+ Object.getPrototypeOf(resolvedModel)
15710
+ );
15711
+ Object.defineProperties(
15712
+ wrappedModel,
15713
+ Object.getOwnPropertyDescriptors(resolvedModel)
15714
+ );
15715
+ const wrappedModelRecord = wrappedModel;
15716
+ const state = {
15717
+ entries: [entry],
15718
+ originalDoGenerate,
15719
+ originalDoStream
15720
+ };
15721
+ Object.defineProperty(wrappedModel, AUTO_PATCHED_MODEL, {
15722
+ configurable: true,
15723
+ value: state
15724
+ });
15725
+ wrappedModel.doGenerate = async function doGeneratePatched(callOptions) {
15726
+ const activeEntry = activeAISDKChildPatchEntry(state.entries);
15727
+ if (!activeEntry) {
15728
+ return Reflect.apply(originalDoGenerate, resolvedModel, [callOptions]);
15729
+ }
15730
+ closeOpenAISDKModelPatchSpans(activeEntry);
15731
+ return activeEntry.parentSpan.traced(
14163
15732
  async (span) => {
14164
- const result = await Reflect.apply(
14165
- originalDoGenerate,
14166
- resolvedModel,
14167
- [options]
14168
- );
14169
- span.log({
14170
- output: processAISDKOutput(result, denyOutputPaths),
14171
- metrics: extractTokenMetrics(result),
14172
- ...buildResolvedMetadataPayload(result)
14173
- });
14174
- return result;
15733
+ activeEntry.openSpans.add(span);
15734
+ try {
15735
+ const result = await Reflect.apply(
15736
+ originalDoGenerate,
15737
+ resolvedModel,
15738
+ [callOptions]
15739
+ );
15740
+ const output = processAISDKOutput(
15741
+ result,
15742
+ activeEntry.denyOutputPaths
15743
+ );
15744
+ const metrics = extractTokenMetrics(result);
15745
+ const metadataPayload = buildResolvedMetadataPayload(result);
15746
+ const missingUsageMetadata = buildMissingUsageMetadata(
15747
+ output,
15748
+ metrics,
15749
+ "ai_sdk_result_missing_usage"
15750
+ );
15751
+ span.log({
15752
+ output,
15753
+ metrics,
15754
+ ...mergeMetadataPayload(metadataPayload, missingUsageMetadata)
15755
+ });
15756
+ return result;
15757
+ } finally {
15758
+ activeEntry.openSpans.delete(span);
15759
+ }
14175
15760
  },
14176
15761
  {
14177
15762
  name: "doGenerate",
14178
15763
  spanAttributes: {
14179
15764
  type: "llm" /* LLM */
14180
15765
  },
14181
- event: {
14182
- input: processAISDKCallInput(options).input,
14183
- metadata: baseMetadata
14184
- }
15766
+ event: buildAISDKModelStartEvent(
15767
+ callOptions,
15768
+ activeEntry.baseMetadata,
15769
+ {
15770
+ workflowAgent: activeEntry.childTracingOptions.workflowAgent
15771
+ }
15772
+ )
14185
15773
  }
14186
15774
  );
14187
15775
  };
14188
15776
  if (originalDoStream) {
14189
- resolvedModel.doStream = async function doStreamPatched(options) {
14190
- const span = parentSpan.startSpan({
15777
+ wrappedModel.doStream = async function doStreamPatched(callOptions) {
15778
+ const activeEntry = activeAISDKChildPatchEntry(state.entries);
15779
+ if (!activeEntry) {
15780
+ return Reflect.apply(originalDoStream, resolvedModel, [callOptions]);
15781
+ }
15782
+ closeOpenAISDKModelPatchSpans(activeEntry);
15783
+ const span = activeEntry.parentSpan.startSpan({
14191
15784
  name: "doStream",
14192
15785
  spanAttributes: {
14193
15786
  type: "llm" /* LLM */
14194
15787
  },
14195
- event: {
14196
- input: processAISDKCallInput(options).input,
14197
- metadata: baseMetadata
14198
- }
15788
+ event: buildAISDKModelStartEvent(
15789
+ callOptions,
15790
+ activeEntry.baseMetadata,
15791
+ {
15792
+ workflowAgent: activeEntry.childTracingOptions.workflowAgent
15793
+ }
15794
+ )
14199
15795
  });
15796
+ activeEntry.openSpans.add(span);
14200
15797
  const streamStartTime = getCurrentUnixTimestamp();
14201
15798
  const result = await withCurrent(
14202
15799
  span,
14203
- () => Reflect.apply(originalDoStream, resolvedModel, [options])
15800
+ () => Reflect.apply(originalDoStream, resolvedModel, [callOptions])
14204
15801
  );
14205
15802
  let firstChunkTime;
14206
15803
  const output = {};
@@ -14208,6 +15805,44 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
14208
15805
  let reasoning = "";
14209
15806
  const toolCalls = [];
14210
15807
  let object = void 0;
15808
+ let streamSpanEnded = false;
15809
+ const logAndEndStreamSpan = (usageUnavailableReason) => {
15810
+ if (streamSpanEnded) {
15811
+ return;
15812
+ }
15813
+ output.text = text;
15814
+ output.reasoning = reasoning;
15815
+ output.toolCalls = toolCalls;
15816
+ if (object !== void 0) {
15817
+ output.object = object;
15818
+ }
15819
+ const metrics = extractTokenMetrics(output);
15820
+ if (firstChunkTime !== void 0 && !activeEntry.childTracingOptions.workflowAgent) {
15821
+ metrics.time_to_first_token = Math.max(
15822
+ firstChunkTime - streamStartTime,
15823
+ 1e-6
15824
+ );
15825
+ }
15826
+ const metadataPayload = buildResolvedMetadataPayload(
15827
+ output
15828
+ );
15829
+ const missingUsageMetadata = usageUnavailableReason ? { usage_unavailable_reason: usageUnavailableReason } : buildMissingUsageMetadata(
15830
+ output,
15831
+ metrics,
15832
+ "ai_sdk_result_missing_usage"
15833
+ );
15834
+ span.log({
15835
+ output: processAISDKOutput(
15836
+ output,
15837
+ activeEntry.denyOutputPaths
15838
+ ),
15839
+ metrics,
15840
+ ...mergeMetadataPayload(metadataPayload, missingUsageMetadata)
15841
+ });
15842
+ activeEntry.openSpans.delete(span);
15843
+ span.end();
15844
+ streamSpanEnded = true;
15845
+ };
14211
15846
  const transformStream = new TransformStream({
14212
15847
  transform(chunk, controller) {
14213
15848
  if (firstChunkTime === void 0 && isAISDKContentStreamChunk(chunk)) {
@@ -14245,33 +15880,15 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
14245
15880
  }
14246
15881
  break;
14247
15882
  case "finish":
14248
- output.text = text;
14249
- output.reasoning = reasoning;
14250
- output.toolCalls = toolCalls;
14251
15883
  output.finishReason = chunk.finishReason;
14252
15884
  output.usage = chunk.usage;
14253
- if (object !== void 0) {
14254
- output.object = object;
14255
- }
14256
- const metrics = extractTokenMetrics(output);
14257
- if (firstChunkTime !== void 0) {
14258
- metrics.time_to_first_token = Math.max(
14259
- firstChunkTime - streamStartTime,
14260
- 1e-6
14261
- );
14262
- }
14263
- span.log({
14264
- output: processAISDKOutput(
14265
- output,
14266
- denyOutputPaths
14267
- ),
14268
- metrics,
14269
- ...buildResolvedMetadataPayload(output)
14270
- });
14271
- span.end();
15885
+ logAndEndStreamSpan();
14272
15886
  break;
14273
15887
  }
14274
15888
  controller.enqueue(chunk);
15889
+ },
15890
+ flush() {
15891
+ logAndEndStreamSpan("ai_sdk_stream_finished_without_usage");
14275
15892
  }
14276
15893
  });
14277
15894
  return {
@@ -14281,32 +15898,79 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
14281
15898
  };
14282
15899
  }
14283
15900
  cleanup.push(() => {
14284
- resolvedModel.doGenerate = originalDoGenerate;
14285
- if (originalDoStream) {
14286
- resolvedModel.doStream = originalDoStream;
14287
- }
14288
- delete resolvedModel[AUTO_PATCHED_MODEL];
15901
+ cleanupModelEntry(state, wrappedModelRecord);
14289
15902
  });
14290
- return resolvedModel;
15903
+ patchedModels.set(resolvedModel, wrappedModel);
15904
+ patchedModels.set(wrappedModel, wrappedModel);
15905
+ return wrappedModel;
14291
15906
  };
14292
15907
  const patchTool = (tool, name) => {
14293
- if (tool == null || typeof tool !== "object" || !("execute" in tool) || typeof tool.execute !== "function" || patchedTools.has(tool) || tool[AUTO_PATCHED_TOOL]) {
15908
+ if (tool == null || typeof tool !== "object" || !("execute" in tool) || typeof tool.execute !== "function" || patchedTools.has(tool)) {
14294
15909
  return;
14295
15910
  }
14296
15911
  patchedTools.add(tool);
14297
- tool[AUTO_PATCHED_TOOL] = true;
14298
- const originalExecute = tool.execute;
15912
+ const toolRecord = tool;
15913
+ const entry = {
15914
+ activeSpanIds: /* @__PURE__ */ new Set([parentSpan.spanId]),
15915
+ childTracingOptions,
15916
+ name,
15917
+ parentSpan
15918
+ };
15919
+ const cleanupToolEntry = (state2) => {
15920
+ const index = state2.entries.indexOf(entry);
15921
+ if (index >= 0) {
15922
+ state2.entries.splice(index, 1);
15923
+ }
15924
+ if (state2.entries.length > 0) {
15925
+ return;
15926
+ }
15927
+ tool.execute = state2.originalExecute;
15928
+ delete toolRecord[AUTO_PATCHED_TOOL];
15929
+ };
15930
+ const existingState = toolRecord[AUTO_PATCHED_TOOL];
15931
+ if (existingState) {
15932
+ if (childTracingOptions.agentOwner && attachNestedAISDKChildPatchEntry(
15933
+ existingState.entries,
15934
+ parentSpan,
15935
+ cleanup
15936
+ )) {
15937
+ return;
15938
+ }
15939
+ if (!childTracingOptions.agentOwner) {
15940
+ shadowActiveAISDKChildPatchEntry(
15941
+ existingState.entries,
15942
+ entry,
15943
+ parentSpan,
15944
+ cleanup
15945
+ );
15946
+ }
15947
+ existingState.entries.push(entry);
15948
+ cleanup.push(() => {
15949
+ cleanupToolEntry(existingState);
15950
+ });
15951
+ return;
15952
+ }
15953
+ const originalExecute = toolRecord.execute;
15954
+ const state = {
15955
+ entries: [entry],
15956
+ originalExecute
15957
+ };
15958
+ toolRecord[AUTO_PATCHED_TOOL] = state;
14299
15959
  tool.execute = function executePatched(...args) {
15960
+ const activeEntry = activeAISDKChildPatchEntry(state.entries);
14300
15961
  const result = Reflect.apply(originalExecute, this, args);
15962
+ if (!activeEntry) {
15963
+ return result;
15964
+ }
14301
15965
  if (isAsyncGenerator(result)) {
14302
15966
  return (async function* () {
14303
- const span = parentSpan.startSpan({
14304
- name,
15967
+ const span = activeEntry.parentSpan.startSpan({
15968
+ name: activeEntry.name,
14305
15969
  spanAttributes: {
14306
15970
  type: "tool" /* TOOL */
14307
15971
  }
14308
15972
  });
14309
- span.log({ input: args.length === 1 ? args[0] : args });
15973
+ span.log({ input: serializeToolExecutionInput(args) });
14310
15974
  try {
14311
15975
  let lastValue;
14312
15976
  for await (const value of result) {
@@ -14322,15 +15986,15 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
14322
15986
  }
14323
15987
  })();
14324
15988
  }
14325
- return parentSpan.traced(
15989
+ return activeEntry.parentSpan.traced(
14326
15990
  async (span) => {
14327
- span.log({ input: args.length === 1 ? args[0] : args });
15991
+ span.log({ input: serializeToolExecutionInput(args) });
14328
15992
  const awaitedResult = await result;
14329
15993
  span.log({ output: awaitedResult });
14330
15994
  return awaitedResult;
14331
15995
  },
14332
15996
  {
14333
- name,
15997
+ name: activeEntry.name,
14334
15998
  spanAttributes: {
14335
15999
  type: "tool" /* TOOL */
14336
16000
  }
@@ -14338,8 +16002,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
14338
16002
  );
14339
16003
  };
14340
16004
  cleanup.push(() => {
14341
- tool.execute = originalExecute;
14342
- delete tool[AUTO_PATCHED_TOOL];
16005
+ cleanupToolEntry(state);
14343
16006
  });
14344
16007
  };
14345
16008
  const patchTools = (tools) => {
@@ -14358,25 +16021,42 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
14358
16021
  }
14359
16022
  };
14360
16023
  if (params && typeof params === "object") {
14361
- const patchedParamModel = patchModel(params.model);
14362
- if (typeof params.model === "string" && patchedParamModel && typeof patchedParamModel === "object") {
16024
+ const originalParamModel = params.model;
16025
+ const patchedParamModel = patchModel(originalParamModel);
16026
+ if (patchedParamModel && patchedParamModel !== originalParamModel) {
14363
16027
  params.model = patchedParamModel;
16028
+ cleanup.push(() => {
16029
+ params.model = originalParamModel;
16030
+ });
14364
16031
  }
14365
16032
  patchTools(params.tools);
14366
16033
  }
14367
16034
  if (self && typeof self === "object") {
14368
16035
  const selfRecord = self;
14369
16036
  if (selfRecord.model !== void 0) {
14370
- const patchedSelfModel = patchModel(selfRecord.model);
14371
- if (typeof selfRecord.model === "string" && patchedSelfModel && typeof patchedSelfModel === "object") {
16037
+ const originalSelfModel = selfRecord.model;
16038
+ const patchedSelfModel = patchModel(originalSelfModel);
16039
+ if (patchedSelfModel && patchedSelfModel !== originalSelfModel) {
14372
16040
  selfRecord.model = patchedSelfModel;
16041
+ cleanup.push(() => {
16042
+ selfRecord.model = originalSelfModel;
16043
+ });
14373
16044
  }
14374
16045
  }
16046
+ if (selfRecord.tools !== void 0) {
16047
+ patchTools(selfRecord.tools);
16048
+ }
14375
16049
  if (selfRecord.settings && typeof selfRecord.settings === "object") {
14376
16050
  if (selfRecord.settings.model !== void 0) {
14377
- const patchedSettingsModel = patchModel(selfRecord.settings.model);
14378
- if (typeof selfRecord.settings.model === "string" && patchedSettingsModel && typeof patchedSettingsModel === "object") {
16051
+ const originalSettingsModel = selfRecord.settings.model;
16052
+ const patchedSettingsModel = patchModel(originalSettingsModel);
16053
+ if (patchedSettingsModel && patchedSettingsModel !== originalSettingsModel) {
14379
16054
  selfRecord.settings.model = patchedSettingsModel;
16055
+ cleanup.push(() => {
16056
+ if (selfRecord.settings) {
16057
+ selfRecord.settings.model = originalSettingsModel;
16058
+ }
16059
+ });
14380
16060
  }
14381
16061
  }
14382
16062
  if (selfRecord.settings.tools !== void 0) {
@@ -14473,99 +16153,190 @@ function isAISDKContentAsyncIterableChunk(chunk) {
14473
16153
  return isObject(part) && typeof part.type !== "string";
14474
16154
  }
14475
16155
  function patchAISDKStreamingResult(args) {
14476
- const { defaultDenyOutputPaths, endEvent, result, span, startTime } = args;
16156
+ const {
16157
+ defaultDenyOutputPaths,
16158
+ endEvent,
16159
+ onComplete,
16160
+ result,
16161
+ span,
16162
+ startTime
16163
+ } = args;
14477
16164
  if (!result || typeof result !== "object") {
14478
16165
  return false;
14479
16166
  }
14480
16167
  const resultRecord = result;
14481
16168
  attachKnownResultPromiseHandlers(resultRecord);
16169
+ let finalized = false;
16170
+ const finalize = () => {
16171
+ if (finalized) {
16172
+ return;
16173
+ }
16174
+ finalized = true;
16175
+ finalizeAISDKChildTracing(endEvent);
16176
+ span.end();
16177
+ onComplete?.();
16178
+ };
16179
+ let outputLogged = false;
16180
+ const logStreamingOutput = async (firstChunkTime) => {
16181
+ if (outputLogged) {
16182
+ return;
16183
+ }
16184
+ outputLogged = true;
16185
+ try {
16186
+ const metrics = extractTopLevelAISDKMetrics(result, endEvent);
16187
+ if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
16188
+ metrics.time_to_first_token = firstChunkTime - startTime;
16189
+ }
16190
+ const output = await processAISDKStreamingOutput(
16191
+ result,
16192
+ resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
16193
+ );
16194
+ const metadata = buildResolvedMetadataPayload(result).metadata;
16195
+ span.log({
16196
+ output,
16197
+ ...metadata ? { metadata } : {},
16198
+ metrics
16199
+ });
16200
+ } catch (error) {
16201
+ span.log({ error: toLoggedError(error) });
16202
+ } finally {
16203
+ finalize();
16204
+ }
16205
+ };
16206
+ const createAsyncIterableHooks = () => {
16207
+ let firstChunkTime;
16208
+ return {
16209
+ onChunk: (chunk) => {
16210
+ if (firstChunkTime === void 0 && isAISDKContentAsyncIterableChunk(chunk)) {
16211
+ firstChunkTime = getCurrentUnixTimestamp();
16212
+ }
16213
+ },
16214
+ onComplete: async () => {
16215
+ await logStreamingOutput(firstChunkTime);
16216
+ },
16217
+ onError: (error) => {
16218
+ if (!outputLogged) {
16219
+ outputLogged = true;
16220
+ span.log({
16221
+ error: error.message
16222
+ });
16223
+ }
16224
+ finalize();
16225
+ },
16226
+ onCancel: finalize
16227
+ };
16228
+ };
16229
+ const patchAsyncIterable = (stream) => isReadableStreamLike(stream) ? createPatchedReadableStream(stream, createAsyncIterableHooks()) : createPatchedAsyncIterable(stream, createAsyncIterableHooks());
16230
+ const patchAsyncIterableField = (field) => {
16231
+ let descriptorOwner = resultRecord;
16232
+ let descriptor;
16233
+ while (descriptorOwner) {
16234
+ descriptor = Object.getOwnPropertyDescriptor(descriptorOwner, field);
16235
+ if (descriptor) {
16236
+ break;
16237
+ }
16238
+ descriptorOwner = Object.getPrototypeOf(descriptorOwner);
16239
+ }
16240
+ if (!descriptor || descriptorOwner === resultRecord && !descriptor.configurable) {
16241
+ return false;
16242
+ }
16243
+ if ("value" in descriptor) {
16244
+ if (!isAsyncIterable(descriptor.value)) {
16245
+ return false;
16246
+ }
16247
+ try {
16248
+ Object.defineProperty(resultRecord, field, {
16249
+ configurable: descriptorOwner === resultRecord ? descriptor.configurable : true,
16250
+ enumerable: descriptor.enumerable,
16251
+ value: patchAsyncIterable(descriptor.value),
16252
+ writable: descriptor.writable
16253
+ });
16254
+ return true;
16255
+ } catch {
16256
+ return false;
16257
+ }
16258
+ }
16259
+ if (typeof descriptor.get !== "function") {
16260
+ return false;
16261
+ }
16262
+ const originalGet = descriptor.get;
16263
+ const originalSet = descriptor.set;
16264
+ try {
16265
+ Object.defineProperty(resultRecord, field, {
16266
+ configurable: descriptorOwner === resultRecord ? descriptor.configurable : true,
16267
+ enumerable: descriptor.enumerable,
16268
+ get() {
16269
+ const stream = originalGet.call(this);
16270
+ return isAsyncIterable(stream) ? patchAsyncIterable(stream) : stream;
16271
+ },
16272
+ ...originalSet ? {
16273
+ set(value) {
16274
+ originalSet.call(this, value);
16275
+ }
16276
+ } : {}
16277
+ });
16278
+ return true;
16279
+ } catch {
16280
+ return false;
16281
+ }
16282
+ };
16283
+ let patched = false;
14482
16284
  if (isReadableStreamLike(resultRecord.baseStream)) {
14483
- let firstChunkTime2;
14484
- const wrappedBaseStream = resultRecord.baseStream.pipeThrough(
16285
+ let firstChunkTime;
16286
+ const transformedBaseStream = resultRecord.baseStream.pipeThrough(
14485
16287
  new TransformStream({
14486
16288
  transform(chunk, controller) {
14487
- if (firstChunkTime2 === void 0 && isAISDKContentStreamChunk(chunk)) {
14488
- firstChunkTime2 = getCurrentUnixTimestamp();
16289
+ if (firstChunkTime === void 0 && isAISDKContentStreamChunk(chunk)) {
16290
+ firstChunkTime = getCurrentUnixTimestamp();
14489
16291
  }
14490
16292
  controller.enqueue(chunk);
14491
16293
  },
14492
16294
  async flush() {
14493
- const metrics = extractTopLevelAISDKMetrics(result, endEvent);
14494
- if (metrics.time_to_first_token === void 0 && firstChunkTime2 !== void 0) {
14495
- metrics.time_to_first_token = firstChunkTime2 - startTime;
14496
- }
14497
- const output = await processAISDKStreamingOutput(
14498
- result,
14499
- resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
14500
- );
14501
- const metadata = buildResolvedMetadataPayload(result).metadata;
14502
- span.log({
14503
- output,
14504
- ...metadata ? { metadata } : {},
14505
- metrics
14506
- });
14507
- finalizeAISDKChildTracing(endEvent);
14508
- span.end();
16295
+ await logStreamingOutput(firstChunkTime);
14509
16296
  }
14510
16297
  })
14511
16298
  );
16299
+ const reader = transformedBaseStream.getReader();
16300
+ const wrappedBaseStream = new ReadableStream({
16301
+ async pull(controller) {
16302
+ try {
16303
+ const { done, value } = await reader.read();
16304
+ if (done) {
16305
+ controller.close();
16306
+ return;
16307
+ }
16308
+ controller.enqueue(value);
16309
+ } catch (error) {
16310
+ span.log({ error: toLoggedError(error) });
16311
+ finalize();
16312
+ controller.error(error);
16313
+ }
16314
+ },
16315
+ async cancel(reason) {
16316
+ try {
16317
+ finalize();
16318
+ } finally {
16319
+ await reader.cancel(reason);
16320
+ }
16321
+ }
16322
+ });
14512
16323
  Object.defineProperty(resultRecord, "baseStream", {
14513
16324
  configurable: true,
14514
16325
  enumerable: true,
14515
16326
  value: wrappedBaseStream,
14516
16327
  writable: true
14517
16328
  });
14518
- return true;
16329
+ patched = true;
14519
16330
  }
14520
- const streamField = findAsyncIterableField(resultRecord, [
16331
+ for (const field of [
14521
16332
  "partialObjectStream",
14522
16333
  "textStream",
14523
16334
  "fullStream",
14524
16335
  "stream"
14525
- ]);
14526
- if (!streamField) {
14527
- return false;
16336
+ ]) {
16337
+ patched = patchAsyncIterableField(field) || patched;
14528
16338
  }
14529
- let firstChunkTime;
14530
- const wrappedStream = createPatchedAsyncIterable(streamField.stream, {
14531
- onChunk: (chunk) => {
14532
- if (firstChunkTime === void 0 && isAISDKContentAsyncIterableChunk(chunk)) {
14533
- firstChunkTime = getCurrentUnixTimestamp();
14534
- }
14535
- },
14536
- onComplete: async () => {
14537
- const metrics = extractTopLevelAISDKMetrics(result, endEvent);
14538
- if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
14539
- metrics.time_to_first_token = firstChunkTime - startTime;
14540
- }
14541
- const output = await processAISDKStreamingOutput(
14542
- result,
14543
- resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
14544
- );
14545
- const metadata = buildResolvedMetadataPayload(result).metadata;
14546
- span.log({
14547
- output,
14548
- ...metadata ? { metadata } : {},
14549
- metrics
14550
- });
14551
- finalizeAISDKChildTracing(endEvent);
14552
- span.end();
14553
- },
14554
- onError: (error) => {
14555
- span.log({
14556
- error: error.message
14557
- });
14558
- finalizeAISDKChildTracing(endEvent);
14559
- span.end();
14560
- }
14561
- });
14562
- Object.defineProperty(resultRecord, streamField.field, {
14563
- configurable: true,
14564
- enumerable: true,
14565
- value: wrappedStream,
14566
- writable: true
14567
- });
14568
- return true;
16339
+ return patched;
14569
16340
  }
14570
16341
  function attachKnownResultPromiseHandlers(result) {
14571
16342
  const promiseLikeFields = [
@@ -14597,34 +16368,72 @@ function attachKnownResultPromiseHandlers(result) {
14597
16368
  }
14598
16369
  }
14599
16370
  function isReadableStreamLike(value) {
14600
- return value != null && typeof value === "object" && typeof value.pipeThrough === "function";
14601
- }
14602
- function findAsyncIterableField(result, candidateFields) {
14603
- for (const field of candidateFields) {
14604
- try {
14605
- const stream = result[field];
14606
- if (isAsyncIterable(stream)) {
14607
- return { field, stream };
16371
+ return value != null && typeof value === "object" && typeof value.getReader === "function" && typeof value.pipeThrough === "function";
16372
+ }
16373
+ function createPatchedReadableStream(stream, hooks) {
16374
+ let reader;
16375
+ let completed = false;
16376
+ return new ReadableStream({
16377
+ async pull(controller) {
16378
+ reader ??= stream.getReader();
16379
+ try {
16380
+ const { done, value } = await reader.read();
16381
+ if (done) {
16382
+ completed = true;
16383
+ await hooks.onComplete();
16384
+ controller.close();
16385
+ return;
16386
+ }
16387
+ hooks.onChunk(value);
16388
+ controller.enqueue(value);
16389
+ } catch (error) {
16390
+ completed = true;
16391
+ hooks.onError(
16392
+ error instanceof Error ? error : new Error(String(error))
16393
+ );
16394
+ controller.error(error);
16395
+ }
16396
+ },
16397
+ async cancel(reason) {
16398
+ if (!completed) {
16399
+ completed = true;
16400
+ try {
16401
+ await hooks.onCancel?.();
16402
+ } catch {
16403
+ }
16404
+ }
16405
+ if (reader) {
16406
+ await reader.cancel(reason);
16407
+ } else if (stream.cancel) {
16408
+ await stream.cancel(reason);
14608
16409
  }
14609
- } catch {
14610
16410
  }
14611
- }
14612
- return null;
16411
+ });
14613
16412
  }
14614
16413
  function createPatchedAsyncIterable(stream, hooks) {
14615
16414
  return {
14616
16415
  async *[Symbol.asyncIterator]() {
16416
+ let completed = false;
14617
16417
  try {
14618
16418
  for await (const chunk of stream) {
14619
16419
  hooks.onChunk(chunk);
14620
16420
  yield chunk;
14621
16421
  }
16422
+ completed = true;
14622
16423
  await hooks.onComplete();
14623
16424
  } catch (error) {
16425
+ completed = true;
14624
16426
  hooks.onError(
14625
16427
  error instanceof Error ? error : new Error(String(error))
14626
16428
  );
14627
16429
  throw error;
16430
+ } finally {
16431
+ if (!completed) {
16432
+ try {
16433
+ await hooks.onCancel?.();
16434
+ } catch {
16435
+ }
16436
+ }
14628
16437
  }
14629
16438
  }
14630
16439
  };
@@ -14699,6 +16508,40 @@ function buildResolvedMetadataPayload(result) {
14699
16508
  }
14700
16509
  return Object.keys(metadata).length > 0 ? { metadata } : {};
14701
16510
  }
16511
+ function mergeMetadataPayload(metadataPayload, extraMetadata) {
16512
+ if (!extraMetadata || Object.keys(extraMetadata).length === 0) {
16513
+ return metadataPayload;
16514
+ }
16515
+ return {
16516
+ metadata: {
16517
+ ...metadataPayload.metadata ?? {},
16518
+ ...extraMetadata
16519
+ }
16520
+ };
16521
+ }
16522
+ function buildMissingUsageMetadata(output, metrics, reason) {
16523
+ if (!hasLoggedOutput(output) || hasTokenUsageMetrics(metrics)) {
16524
+ return void 0;
16525
+ }
16526
+ return { usage_unavailable_reason: reason };
16527
+ }
16528
+ function hasLoggedOutput(output) {
16529
+ if (output === null || output === void 0) {
16530
+ return false;
16531
+ }
16532
+ if (Array.isArray(output)) {
16533
+ return output.length > 0;
16534
+ }
16535
+ if (typeof output === "object") {
16536
+ return Object.keys(output).length > 0;
16537
+ }
16538
+ return true;
16539
+ }
16540
+ function hasTokenUsageMetrics(metrics) {
16541
+ return Object.keys(metrics).some(
16542
+ (key) => key !== "estimated_cost" && key !== "time_to_first_token"
16543
+ );
16544
+ }
14702
16545
  function resolveAISDKModel(model, aiSDK) {
14703
16546
  if (typeof model !== "string") {
14704
16547
  return model;
@@ -14722,7 +16565,45 @@ function isAsyncGenerator(value) {
14722
16565
  function processAISDKOutput(output, denyOutputPaths) {
14723
16566
  if (!output) return output;
14724
16567
  const merged = extractSerializableOutputFields(output);
14725
- return normalizeAISDKLoggedOutput(omit(merged, denyOutputPaths));
16568
+ const deleteOutputPaths = denyOutputPaths.filter(
16569
+ (path2) => path2.toLowerCase().endsWith("headers")
16570
+ );
16571
+ const sanitized = omit(merged, denyOutputPaths, deleteOutputPaths);
16572
+ for (const path2 of TRANSPORT_PAYLOAD_ROOT_PATHS) {
16573
+ const stack = [{ obj: sanitized, keys: parsePath(path2) }];
16574
+ while (stack.length > 0) {
16575
+ const entry = stack.pop();
16576
+ if (!entry || entry.keys.length === 0) {
16577
+ continue;
16578
+ }
16579
+ const firstKey = entry.keys[0];
16580
+ const remainingKeys = entry.keys.slice(1);
16581
+ if (firstKey === "[]") {
16582
+ if (Array.isArray(entry.obj)) {
16583
+ for (const item of entry.obj) {
16584
+ stack.push({
16585
+ obj: item,
16586
+ keys: remainingKeys
16587
+ });
16588
+ }
16589
+ }
16590
+ continue;
16591
+ }
16592
+ if (!entry.obj || typeof entry.obj !== "object" || !(firstKey in entry.obj)) {
16593
+ continue;
16594
+ }
16595
+ const record = entry.obj;
16596
+ if (remainingKeys.length === 0) {
16597
+ record[firstKey] = sanitizeAISDKMetadataValue(record[firstKey]);
16598
+ continue;
16599
+ }
16600
+ stack.push({
16601
+ obj: record[firstKey],
16602
+ keys: remainingKeys
16603
+ });
16604
+ }
16605
+ }
16606
+ return normalizeAISDKLoggedOutput(sanitized);
14726
16607
  }
14727
16608
  function processAISDKEmbeddingOutput(output, denyOutputPaths) {
14728
16609
  if (!output || typeof output !== "object") {
@@ -14813,6 +16694,8 @@ function extractTokenMetrics(result) {
14813
16694
  );
14814
16695
  if (totalTokens !== void 0) {
14815
16696
  metrics.tokens = totalTokens;
16697
+ } else if (promptTokens !== void 0 && completionTokens !== void 0) {
16698
+ metrics.tokens = promptTokens + completionTokens;
14816
16699
  }
14817
16700
  const promptCachedTokens = firstNumber2(
14818
16701
  usage.inputTokens?.cacheRead,
@@ -14936,7 +16819,9 @@ function extractGetterValues(obj) {
14936
16819
  const getterValues = {};
14937
16820
  const getterNames = [
14938
16821
  "content",
16822
+ "messages",
14939
16823
  "text",
16824
+ "output",
14940
16825
  "object",
14941
16826
  "value",
14942
16827
  "values",
@@ -14976,7 +16861,9 @@ function extractGetterValues(obj) {
14976
16861
  function extractSerializableOutputFields(output) {
14977
16862
  const serialized = {};
14978
16863
  const directFieldNames = [
16864
+ "messages",
14979
16865
  "steps",
16866
+ "output",
14980
16867
  "request",
14981
16868
  "responseMessages",
14982
16869
  "warnings",
@@ -15158,7 +17045,7 @@ function parsePath(path2) {
15158
17045
  }
15159
17046
  return keys;
15160
17047
  }
15161
- function omitAtPath(obj, keys) {
17048
+ function omitAtPath(obj, keys, deleteLeaf = false) {
15162
17049
  if (keys.length === 0) return;
15163
17050
  const firstKey = keys[0];
15164
17051
  const remainingKeys = keys.slice(1);
@@ -15168,29 +17055,36 @@ function omitAtPath(obj, keys) {
15168
17055
  if (remainingKeys.length > 0) {
15169
17056
  omitAtPath(
15170
17057
  item,
15171
- remainingKeys
17058
+ remainingKeys,
17059
+ deleteLeaf
15172
17060
  );
15173
17061
  }
15174
17062
  });
15175
17063
  }
15176
17064
  } else if (remainingKeys.length === 0) {
15177
17065
  if (obj && typeof obj === "object" && firstKey in obj) {
15178
- obj[firstKey] = "<omitted>";
17066
+ if (deleteLeaf) {
17067
+ delete obj[firstKey];
17068
+ } else {
17069
+ obj[firstKey] = "<omitted>";
17070
+ }
15179
17071
  }
15180
17072
  } else {
15181
17073
  if (obj && typeof obj === "object" && firstKey in obj) {
15182
17074
  omitAtPath(
15183
17075
  obj[firstKey],
15184
- remainingKeys
17076
+ remainingKeys,
17077
+ deleteLeaf
15185
17078
  );
15186
17079
  }
15187
17080
  }
15188
17081
  }
15189
- function omit(obj, paths) {
17082
+ function omit(obj, paths, deletePaths = []) {
15190
17083
  const result = deepCopy(obj);
17084
+ const deletePathSet = new Set(deletePaths);
15191
17085
  for (const path2 of paths) {
15192
17086
  const keys = parsePath(path2);
15193
- omitAtPath(result, keys);
17087
+ omitAtPath(result, keys, deletePathSet.has(path2));
15194
17088
  }
15195
17089
  return result;
15196
17090
  }
@@ -28999,7 +30893,13 @@ var BraintrustObservabilityExporter = class {
28999
30893
  const args = {
29000
30894
  name: exported.name,
29001
30895
  spanAttributes: { type: spanTypeFor(exported.type) },
29002
- startTime: epochSeconds(exported.startTime)
30896
+ startTime: epochSeconds(exported.startTime),
30897
+ // Use the Mastra span id as the Braintrust row id so that
30898
+ // `logFeedback({ id: <mastra span id> })` (and Mastra's score events)
30899
+ // attach to the right row. Without this, `SpanImpl` auto-generates a
30900
+ // row id (`this._id = eventId ?? idGenerator.getSpanId()`) that no
30901
+ // external caller could know.
30902
+ event: { id: exported.id }
29003
30903
  };
29004
30904
  const parentRecord = exported.parentSpanId ? this.spans.get(exported.parentSpanId) : void 0;
29005
30905
  if (!this.capturedParent) {
@@ -30277,15 +32177,21 @@ async function invoke(args) {
30277
32177
 
30278
32178
  // src/trace.ts
30279
32179
  var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
30280
- constructor(objectType, _objectId, rootSpanId, _state, spanTypeFilter, includeScorers = false) {
32180
+ constructor(objectType, _objectId, rootSpanId, _state, spanTypeFilter, includeScorers = false, brainstoreRealtime = true) {
30281
32181
  const filterExpr = _SpanFetcher.buildFilter(
30282
32182
  rootSpanId,
30283
32183
  spanTypeFilter,
30284
32184
  includeScorers
30285
32185
  );
30286
- super(objectType, void 0, void 0, {
30287
- filter: filterExpr
30288
- });
32186
+ super(
32187
+ objectType,
32188
+ void 0,
32189
+ void 0,
32190
+ {
32191
+ filter: filterExpr
32192
+ },
32193
+ brainstoreRealtime
32194
+ );
30289
32195
  this._objectId = _objectId;
30290
32196
  this.rootSpanId = rootSpanId;
30291
32197
  this._state = _state;
@@ -30339,7 +32245,7 @@ var CachedSpanFetcher = class {
30339
32245
  spanCache = /* @__PURE__ */ new Map();
30340
32246
  allFetched = false;
30341
32247
  fetchFn;
30342
- constructor(objectTypeOrFetchFn, objectId, rootSpanId, getState) {
32248
+ constructor(objectTypeOrFetchFn, objectId, rootSpanId, getState, brainstoreRealtime = true) {
30343
32249
  if (typeof objectTypeOrFetchFn === "function") {
30344
32250
  this.fetchFn = (spanType) => objectTypeOrFetchFn(spanType);
30345
32251
  } else {
@@ -30352,7 +32258,8 @@ var CachedSpanFetcher = class {
30352
32258
  rootSpanId,
30353
32259
  state,
30354
32260
  spanType,
30355
- includeScorers
32261
+ includeScorers,
32262
+ brainstoreRealtime
30356
32263
  );
30357
32264
  const rows = await fetcher.fetchedData();
30358
32265
  return rows.map((row) => ({
@@ -31160,7 +33067,7 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
31160
33067
  }
31161
33068
  };
31162
33069
  const parentStr = state.currentParent.getStore();
31163
- const parentComponents = parentStr ? SpanComponentsV3.fromStr(parentStr) : null;
33070
+ const parentComponents = typeof parentStr === "string" ? SpanComponentsV4.fromStr(parentStr) : null;
31164
33071
  const trace = state ? new LocalTrace({
31165
33072
  objectType: parentComponents ? spanObjectTypeV3ToTypedString(
31166
33073
  parentComponents.data.object_type
@@ -31820,7 +33727,7 @@ var MAIN_ORIGIN = "https://www.braintrust.dev";
31820
33727
  var WHITELISTED_ORIGINS = [
31821
33728
  MAIN_ORIGIN,
31822
33729
  "https://www.braintrustdata.com",
31823
- new RegExp("https://.*.preview.braintrust.dev")
33730
+ new RegExp("^https://[^/]+\\.preview\\.braintrust\\.dev$")
31824
33731
  ].concat(
31825
33732
  process.env.WHITELISTED_ORIGIN ? [process.env.WHITELISTED_ORIGIN] : []
31826
33733
  ).concat(