braintrust 3.26.0 → 3.28.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 (61) hide show
  1. package/dev/dist/index.d.mts +519 -186
  2. package/dev/dist/index.d.ts +519 -186
  3. package/dev/dist/index.js +3727 -1526
  4. package/dev/dist/index.mjs +2815 -614
  5. package/dist/apply-auto-instrumentation.js +372 -261
  6. package/dist/apply-auto-instrumentation.mjs +171 -60
  7. package/dist/auto-instrumentations/bundler/esbuild.cjs +458 -61
  8. package/dist/auto-instrumentations/bundler/esbuild.mjs +5 -4
  9. package/dist/auto-instrumentations/bundler/next.cjs +460 -63
  10. package/dist/auto-instrumentations/bundler/next.mjs +6 -5
  11. package/dist/auto-instrumentations/bundler/rollup.cjs +458 -61
  12. package/dist/auto-instrumentations/bundler/rollup.mjs +5 -4
  13. package/dist/auto-instrumentations/bundler/vite.cjs +487 -62
  14. package/dist/auto-instrumentations/bundler/vite.mjs +34 -5
  15. package/dist/auto-instrumentations/bundler/webpack-loader.cjs +444 -61
  16. package/dist/auto-instrumentations/bundler/webpack.cjs +458 -61
  17. package/dist/auto-instrumentations/bundler/webpack.mjs +6 -5
  18. package/dist/auto-instrumentations/{chunk-6E22MYSW.mjs → chunk-26PKVUKB.mjs} +109 -5
  19. package/dist/auto-instrumentations/{chunk-AKKPLXTP.mjs → chunk-2AMDGD65.mjs} +160 -57
  20. package/dist/auto-instrumentations/{chunk-V5LEODRX.mjs → chunk-HD35AM3M.mjs} +1 -1
  21. package/dist/auto-instrumentations/{chunk-XYN63IG5.mjs → chunk-I55G56ZL.mjs} +21 -58
  22. package/dist/auto-instrumentations/{chunk-NRE4QUQR.mjs → chunk-JPUFNW7X.mjs} +140 -0
  23. package/dist/auto-instrumentations/{chunk-XZHHE4Y3.mjs → chunk-NP7V4XB2.mjs} +157 -3
  24. package/dist/auto-instrumentations/hook.mjs +396 -32
  25. package/dist/auto-instrumentations/index.cjs +298 -2
  26. package/dist/auto-instrumentations/index.d.mts +5 -1
  27. package/dist/auto-instrumentations/index.d.ts +5 -1
  28. package/dist/auto-instrumentations/index.mjs +6 -2
  29. package/dist/auto-instrumentations/loader/cjs-patch.cjs +105 -57
  30. package/dist/auto-instrumentations/loader/cjs-patch.mjs +2 -2
  31. package/dist/auto-instrumentations/loader/esm-hook.mjs +1 -1
  32. package/dist/browser.d.mts +683 -56
  33. package/dist/browser.d.ts +683 -56
  34. package/dist/browser.js +4242 -655
  35. package/dist/browser.mjs +4242 -655
  36. package/dist/{chunk-VYNNEKSA.js → chunk-BBE7SNRV.js} +248 -10
  37. package/dist/{chunk-VRZZQPAA.js → chunk-OBBWQW6K.js} +3351 -1392
  38. package/dist/{chunk-XIZOM2HO.mjs → chunk-UPFNQCGB.mjs} +2419 -460
  39. package/dist/{chunk-PN7EWK66.mjs → chunk-ZHUHZWFY.mjs} +241 -3
  40. package/dist/cli.js +2867 -668
  41. package/dist/edge-light.d.mts +1 -1
  42. package/dist/edge-light.d.ts +1 -1
  43. package/dist/edge-light.js +4242 -655
  44. package/dist/edge-light.mjs +4242 -655
  45. package/dist/index.d.mts +1267 -640
  46. package/dist/index.d.ts +1267 -640
  47. package/dist/index.js +2107 -630
  48. package/dist/index.mjs +1649 -172
  49. package/dist/instrumentation/index.d.mts +198 -6
  50. package/dist/instrumentation/index.d.ts +198 -6
  51. package/dist/instrumentation/index.js +2661 -581
  52. package/dist/instrumentation/index.mjs +2661 -581
  53. package/dist/vitest-evals-reporter.js +45 -43
  54. package/dist/vitest-evals-reporter.mjs +5 -3
  55. package/dist/workerd.d.mts +1 -1
  56. package/dist/workerd.d.ts +1 -1
  57. package/dist/workerd.js +4242 -655
  58. package/dist/workerd.mjs +4242 -655
  59. package/package.json +2 -3
  60. package/util/dist/index.d.mts +1545 -100
  61. package/util/dist/index.d.ts +1545 -100
@@ -49,8 +49,10 @@ var GLOBAL_INSTRUMENTATION_HOOKS_KEY = "__braintrust_instrumentation_hooks";
49
49
  var GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION = 1;
50
50
  var GLOBAL_INSTRUMENTATION_HOOKS_REGISTRY_BRAND = "braintrust.global-instrumentation-hooks.registry";
51
51
  var GLOBAL_INSTRUMENTATION_HOOK_BRAND = "braintrust.global-instrumentation-hooks.hook";
52
+ var GLOBAL_INVOCATION_HOOK_BRAND = "braintrust.global-instrumentation-hooks.invocation-hook";
52
53
  var registryBrand = Symbol.for(GLOBAL_INSTRUMENTATION_HOOKS_REGISTRY_BRAND);
53
54
  var hookBrand = Symbol.for(GLOBAL_INSTRUMENTATION_HOOK_BRAND);
55
+ var invocationHookBrand = Symbol.for(GLOBAL_INVOCATION_HOOK_BRAND);
54
56
  var errorReporter;
55
57
  function setGlobalHookErrorReporter(reporter) {
56
58
  const previousReporter = errorReporter;
@@ -195,12 +197,69 @@ var traceEvents = [
195
197
  "asyncEnd",
196
198
  "error"
197
199
  ];
200
+ function traceInvocation(hook, operator, target, thisArg, args, additional, callbackIndex = -1) {
201
+ const context = {
202
+ ...additional,
203
+ arguments: args,
204
+ self: thisArg
205
+ };
206
+ const invoke = () => hook.invoke(target, thisArg, args, additional);
207
+ if (operator === "traceCallback") {
208
+ return hook.traceCallback(invoke, callbackIndex, context);
209
+ }
210
+ if (operator === "tracePromise") {
211
+ return hook.tracePromise(invoke, context);
212
+ }
213
+ return hook.traceSync(invoke, context);
214
+ }
215
+ var InvocationHook = class {
216
+ interceptors = [];
217
+ get hasInterceptors() {
218
+ return this.interceptors.length > 0;
219
+ }
220
+ intercept(interceptor) {
221
+ if (typeof interceptor !== "function") {
222
+ throw new TypeError("interceptor must be a function");
223
+ }
224
+ this.interceptors = [...this.interceptors, interceptor];
225
+ let active = true;
226
+ return () => {
227
+ if (!active) {
228
+ return;
229
+ }
230
+ active = false;
231
+ const index = this.interceptors.indexOf(interceptor);
232
+ if (index !== -1) {
233
+ this.interceptors = [
234
+ ...this.interceptors.slice(0, index),
235
+ ...this.interceptors.slice(index + 1)
236
+ ];
237
+ }
238
+ };
239
+ }
240
+ invoke(target, thisArg, args, additional) {
241
+ const interceptors = this.interceptors;
242
+ if (interceptors.length === 0) {
243
+ return Reflect.apply(target, thisArg, args);
244
+ }
245
+ let next = target;
246
+ for (let index = interceptors.length - 1; index >= 0; index -= 1) {
247
+ const interceptor = interceptors[index];
248
+ const downstream = next;
249
+ next = function(...nextArgs) {
250
+ return interceptor(downstream, this, nextArgs, additional);
251
+ };
252
+ }
253
+ return Reflect.apply(next, thisArg, args);
254
+ }
255
+ };
198
256
  var TracingHook = class {
199
257
  start;
200
258
  end;
201
259
  asyncStart;
202
260
  asyncEnd;
203
261
  error;
262
+ invocationHook = new InvocationHook();
204
263
  constructor(nameOrChannels) {
205
264
  Object.defineProperty(this, hookBrand, {
206
265
  configurable: false,
@@ -208,6 +267,12 @@ var TracingHook = class {
208
267
  value: GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION,
209
268
  writable: false
210
269
  });
270
+ Object.defineProperty(this, invocationHookBrand, {
271
+ configurable: false,
272
+ enumerable: false,
273
+ value: GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION,
274
+ writable: false
275
+ });
211
276
  if (typeof nameOrChannels === "string") {
212
277
  this.start = new HookChannel(`tracing:${nameOrChannels}:start`);
213
278
  this.end = new HookChannel(`tracing:${nameOrChannels}:end`);
@@ -225,6 +290,26 @@ var TracingHook = class {
225
290
  get hasSubscribers() {
226
291
  return this.start.hasSubscribers || this.end.hasSubscribers || this.asyncStart.hasSubscribers || this.asyncEnd.hasSubscribers || this.error.hasSubscribers;
227
292
  }
293
+ get hasInterceptors() {
294
+ return this.invocationHook.hasInterceptors;
295
+ }
296
+ intercept(interceptor) {
297
+ return this.invocationHook.intercept(interceptor);
298
+ }
299
+ invoke(target, thisArg, args, additional) {
300
+ return this.invocationHook.invoke(target, thisArg, args, additional);
301
+ }
302
+ traceInvocation(operator, target, thisArg, args, additional, callbackIndex = -1) {
303
+ return traceInvocation(
304
+ this,
305
+ operator,
306
+ target,
307
+ thisArg,
308
+ args,
309
+ additional,
310
+ callbackIndex
311
+ );
312
+ }
228
313
  subscribe(handlers) {
229
314
  for (const eventName of traceEvents) {
230
315
  const handler = handlers[eventName];
@@ -446,6 +531,60 @@ function hasTracingHookShape(value) {
446
531
  return false;
447
532
  }
448
533
  }
534
+ function hasInvocationHookShape(value) {
535
+ if (typeof value !== "object" && typeof value !== "function" || value === null) {
536
+ return false;
537
+ }
538
+ try {
539
+ const hook = value;
540
+ return value[invocationHookBrand] === GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION && typeof hook.hasInterceptors === "boolean" && typeof hook.intercept === "function" && typeof hook.invoke === "function";
541
+ } catch {
542
+ return false;
543
+ }
544
+ }
545
+ function installInvocationHook(value) {
546
+ const hasInvocationHook = hasInvocationHookShape(value);
547
+ const invocationHook = new InvocationHook();
548
+ try {
549
+ if (!hasInvocationHook) {
550
+ Object.defineProperties(value, {
551
+ [invocationHookBrand]: {
552
+ configurable: false,
553
+ enumerable: false,
554
+ value: GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION,
555
+ writable: false
556
+ },
557
+ hasInterceptors: {
558
+ configurable: false,
559
+ enumerable: false,
560
+ get: () => invocationHook.hasInterceptors
561
+ },
562
+ intercept: {
563
+ configurable: false,
564
+ enumerable: false,
565
+ value: invocationHook.intercept.bind(invocationHook),
566
+ writable: false
567
+ },
568
+ invoke: {
569
+ configurable: false,
570
+ enumerable: false,
571
+ value: invocationHook.invoke.bind(invocationHook),
572
+ writable: false
573
+ }
574
+ });
575
+ }
576
+ if (typeof value.traceInvocation !== "function") {
577
+ Object.defineProperty(value, "traceInvocation", {
578
+ configurable: false,
579
+ enumerable: false,
580
+ value: traceInvocation.bind(void 0, value),
581
+ writable: false
582
+ });
583
+ }
584
+ } catch (error) {
585
+ reportError(error);
586
+ }
587
+ }
449
588
  function isCompatibleTracingHook(value) {
450
589
  try {
451
590
  return value[hookBrand] === GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION && hasTracingHookShape(value);
@@ -532,6 +671,7 @@ function newGlobalTracingChannel(nameOrChannels) {
532
671
  return inertTracingHook;
533
672
  }
534
673
  if (isCompatibleTracingHook(existing)) {
674
+ installInvocationHook(existing);
535
675
  return existing;
536
676
  }
537
677
  if (existing !== void 0) {
@@ -587,6 +727,114 @@ var iso = {
587
727
  };
588
728
  var isomorph_default = iso;
589
729
 
730
+ // src/debug-logger.ts
731
+ var PREFIX = "[braintrust]";
732
+ var DEBUG_LOG_LEVEL_SYMBOL = /* @__PURE__ */ Symbol.for("braintrust-debug-log-level");
733
+ var LOG_LEVEL_PRIORITY = {
734
+ error: 0,
735
+ warn: 1,
736
+ info: 2,
737
+ debug: 3
738
+ };
739
+ var hasWarnedAboutInvalidEnvValue = false;
740
+ var debugLogStateResolver = void 0;
741
+ function warnInvalidEnvValue(value) {
742
+ if (hasWarnedAboutInvalidEnvValue) {
743
+ return;
744
+ }
745
+ hasWarnedAboutInvalidEnvValue = true;
746
+ console.warn(
747
+ PREFIX,
748
+ `Invalid BRAINTRUST_DEBUG_LOG_LEVEL value "${value}". Expected "error", "warn", "info", or "debug".`
749
+ );
750
+ }
751
+ function normalizeDebugLogLevelOption(option) {
752
+ if (option === false) {
753
+ return void 0;
754
+ }
755
+ if (option === "error" || option === "warn" || option === "info" || option === "debug") {
756
+ return option;
757
+ }
758
+ throw new Error(
759
+ `Invalid debugLogLevel value "${option}". Expected false, "error", "warn", "info", or "debug".`
760
+ );
761
+ }
762
+ function parseDebugLogLevelEnv(value) {
763
+ if (!value) {
764
+ return void 0;
765
+ }
766
+ if (value === "error" || value === "warn" || value === "info" || value === "debug") {
767
+ return value;
768
+ }
769
+ warnInvalidEnvValue(value);
770
+ return void 0;
771
+ }
772
+ function getEnvDebugLogLevel() {
773
+ return parseDebugLogLevelEnv(isomorph_default.getEnv("BRAINTRUST_DEBUG_LOG_LEVEL"));
774
+ }
775
+ function setGlobalDebugLogLevel(level) {
776
+ globalThis[DEBUG_LOG_LEVEL_SYMBOL] = level;
777
+ }
778
+ function setDebugLogStateResolver(resolver) {
779
+ debugLogStateResolver = resolver;
780
+ }
781
+ function resolveDebugLogLevel(state) {
782
+ const stateLevel = state?.getDebugLogLevel?.();
783
+ const hasStateOverride = state?.hasDebugLogLevelOverride?.() ?? false;
784
+ if (hasStateOverride) {
785
+ return stateLevel;
786
+ }
787
+ const globalLevel = (
788
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
789
+ globalThis[DEBUG_LOG_LEVEL_SYMBOL]
790
+ );
791
+ if (globalLevel !== void 0) {
792
+ return globalLevel === false ? void 0 : globalLevel;
793
+ }
794
+ return getEnvDebugLogLevel();
795
+ }
796
+ function emit(method, state, args) {
797
+ const level = resolveDebugLogLevel(state);
798
+ if (!level || LOG_LEVEL_PRIORITY[method] > LOG_LEVEL_PRIORITY[level]) {
799
+ return;
800
+ }
801
+ if (method === "info") {
802
+ console.log(PREFIX, ...args);
803
+ } else if (method === "debug") {
804
+ console.debug(PREFIX, ...args);
805
+ } else if (method === "warn") {
806
+ console.warn(PREFIX, ...args);
807
+ } else {
808
+ console.error(PREFIX, ...args);
809
+ }
810
+ }
811
+ function createDebugLogger(state) {
812
+ const resolveState = () => state ?? debugLogStateResolver?.();
813
+ return {
814
+ info(...args) {
815
+ emit("info", resolveState(), args);
816
+ },
817
+ debug(...args) {
818
+ emit("debug", resolveState(), args);
819
+ },
820
+ warn(...args) {
821
+ emit("warn", resolveState(), args);
822
+ },
823
+ error(...args) {
824
+ emit("error", resolveState(), args);
825
+ }
826
+ };
827
+ }
828
+ var debugLogger = {
829
+ ...createDebugLogger(),
830
+ forState(state) {
831
+ return createDebugLogger(state);
832
+ }
833
+ };
834
+ setGlobalHookErrorReporter((error) => {
835
+ debugLogger.error("Global instrumentation hook error:", error);
836
+ });
837
+
590
838
  // src/instrumentation/core/stream-patcher.ts
591
839
  function isAsyncIterable(value) {
592
840
  return value !== null && typeof value === "object" && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
@@ -611,112 +859,133 @@ function patchStreamIfNeeded(stream, options) {
611
859
  );
612
860
  return stream;
613
861
  }
614
- if (hasAsyncIteratorMethods(stream) && isSelfAsyncIterator(stream)) {
615
- if ("__braintrust_patched_iterator_methods" in stream) {
616
- return stream;
862
+ const chunks = [];
863
+ let completed = false;
864
+ const notifyCancellation = async () => {
865
+ try {
866
+ await (options.onCancel ?? options.onComplete)(chunks);
867
+ } catch (error) {
868
+ debugLogger.error("Error in stream cancellation handler:", error);
617
869
  }
870
+ };
871
+ const patchAbortIfPresent = () => {
618
872
  try {
619
- const originalNext = stream.next.bind(stream);
620
- const originalReturn = typeof stream.return === "function" ? stream.return.bind(stream) : null;
621
- const originalThrow = typeof stream.throw === "function" ? stream.throw.bind(stream) : null;
622
- const chunks = [];
623
- let completed = false;
624
- stream.next = async (...args) => {
625
- try {
626
- const result = await runNextWithWrapper(
627
- options,
628
- () => originalNext(...args)
629
- );
630
- if (result.done) {
873
+ if ("abort" in stream && typeof stream.abort === "function") {
874
+ const originalAbort = stream.abort.bind(stream);
875
+ stream.abort = (...args) => {
876
+ try {
877
+ return originalAbort(...args);
878
+ } finally {
631
879
  if (!completed) {
632
880
  completed = true;
633
- try {
634
- await options.onComplete(chunks);
635
- } catch (error) {
636
- console.error("Error in stream onComplete handler:", error);
637
- }
638
- }
639
- } else {
640
- const chunk = result.value;
641
- const shouldCollect = options.shouldCollect ? options.shouldCollect(chunk) : true;
642
- if (shouldCollect) {
643
- chunks.push(chunk);
644
- if (options.onChunk) {
645
- try {
646
- await options.onChunk(chunk);
647
- } catch (error) {
648
- console.error("Error in stream onChunk handler:", error);
649
- }
650
- }
881
+ void notifyCancellation();
651
882
  }
652
883
  }
653
- return result;
654
- } catch (error) {
655
- if (!completed) {
656
- completed = true;
657
- if (options.onError) {
658
- try {
659
- await options.onError(
660
- error instanceof Error ? error : new Error(String(error)),
661
- chunks
662
- );
663
- } catch (handlerError) {
664
- console.error("Error in stream onError handler:", handlerError);
665
- }
666
- }
667
- }
668
- throw error;
669
- }
670
- };
671
- if (originalReturn) {
672
- stream.return = async (...args) => {
673
- if (!completed) {
674
- completed = true;
675
- try {
676
- await options.onComplete(chunks);
677
- } catch (error) {
678
- console.error("Error in stream onComplete handler:", error);
679
- }
680
- }
681
- return originalReturn(...args);
682
- };
683
- }
684
- if (originalThrow) {
685
- stream.throw = async (...args) => {
686
- if (!completed) {
687
- completed = true;
688
- const rawError = args[0];
689
- const error = rawError instanceof Error ? rawError : new Error(String(rawError));
690
- if (options.onError) {
691
- try {
692
- await options.onError(error, chunks);
693
- } catch (handlerError) {
694
- console.error("Error in stream onError handler:", handlerError);
695
- }
696
- }
697
- }
698
- return originalThrow(...args);
699
884
  };
700
885
  }
701
- Object.defineProperty(stream, "__braintrust_patched_iterator_methods", {
702
- value: true
703
- });
704
- return stream;
705
886
  } catch (error) {
706
- console.warn("Failed to patch stream iterator methods:", error);
887
+ debugLogger.warn("Failed to patch stream abort method:", error);
707
888
  }
708
- }
709
- const originalIteratorFn = stream[Symbol.asyncIterator];
710
- if ("__braintrust_patched" in originalIteratorFn && originalIteratorFn["__braintrust_patched"]) {
711
- return stream;
712
- }
713
- try {
714
- const patchedIteratorFn = function() {
715
- const iterator = originalIteratorFn.call(this);
716
- const originalNext = iterator.next.bind(iterator);
717
- const chunks = [];
718
- let completed = false;
719
- iterator.next = async function(...args) {
889
+ };
890
+ if (hasAsyncIteratorMethods(stream) && isSelfAsyncIterator(stream)) {
891
+ if ("__braintrust_patched_iterator_methods" in stream) {
892
+ return stream;
893
+ }
894
+ try {
895
+ const originalNext = stream.next.bind(stream);
896
+ const originalReturn = typeof stream.return === "function" ? stream.return.bind(stream) : null;
897
+ const originalThrow = typeof stream.throw === "function" ? stream.throw.bind(stream) : null;
898
+ stream.next = async (...args) => {
899
+ try {
900
+ const result = await runNextWithWrapper(
901
+ options,
902
+ () => originalNext(...args)
903
+ );
904
+ if (result.done) {
905
+ if (!completed) {
906
+ completed = true;
907
+ try {
908
+ await options.onComplete(chunks);
909
+ } catch (error) {
910
+ console.error("Error in stream onComplete handler:", error);
911
+ }
912
+ }
913
+ } else {
914
+ const chunk = result.value;
915
+ const shouldCollect = options.shouldCollect ? options.shouldCollect(chunk) : true;
916
+ if (shouldCollect) {
917
+ chunks.push(chunk);
918
+ if (options.onChunk) {
919
+ try {
920
+ await options.onChunk(chunk);
921
+ } catch (error) {
922
+ console.error("Error in stream onChunk handler:", error);
923
+ }
924
+ }
925
+ }
926
+ }
927
+ return result;
928
+ } catch (error) {
929
+ if (!completed) {
930
+ completed = true;
931
+ if (options.onError) {
932
+ try {
933
+ await options.onError(
934
+ error instanceof Error ? error : new Error(String(error)),
935
+ chunks
936
+ );
937
+ } catch (handlerError) {
938
+ console.error("Error in stream onError handler:", handlerError);
939
+ }
940
+ }
941
+ }
942
+ throw error;
943
+ }
944
+ };
945
+ if (originalReturn) {
946
+ stream.return = async (...args) => {
947
+ if (!completed) {
948
+ completed = true;
949
+ await notifyCancellation();
950
+ }
951
+ return originalReturn(...args);
952
+ };
953
+ }
954
+ if (originalThrow) {
955
+ stream.throw = async (...args) => {
956
+ if (!completed) {
957
+ completed = true;
958
+ const rawError = args[0];
959
+ const error = rawError instanceof Error ? rawError : new Error(String(rawError));
960
+ if (options.onError) {
961
+ try {
962
+ await options.onError(error, chunks);
963
+ } catch (handlerError) {
964
+ console.error("Error in stream onError handler:", handlerError);
965
+ }
966
+ }
967
+ }
968
+ return originalThrow(...args);
969
+ };
970
+ }
971
+ Object.defineProperty(stream, "__braintrust_patched_iterator_methods", {
972
+ value: true
973
+ });
974
+ patchAbortIfPresent();
975
+ return stream;
976
+ } catch (error) {
977
+ console.warn("Failed to patch stream iterator methods:", error);
978
+ }
979
+ }
980
+ const originalIteratorFn = stream[Symbol.asyncIterator];
981
+ if ("__braintrust_patched" in originalIteratorFn && originalIteratorFn["__braintrust_patched"]) {
982
+ return stream;
983
+ }
984
+ try {
985
+ const patchedIteratorFn = function() {
986
+ const iterator = originalIteratorFn.call(this);
987
+ const originalNext = iterator.next.bind(iterator);
988
+ iterator.next = async function(...args) {
720
989
  try {
721
990
  const result = await runNextWithWrapper(
722
991
  options,
@@ -768,11 +1037,7 @@ function patchStreamIfNeeded(stream, options) {
768
1037
  iterator.return = async function(...args) {
769
1038
  if (!completed) {
770
1039
  completed = true;
771
- try {
772
- await options.onComplete(chunks);
773
- } catch (error) {
774
- console.error("Error in stream onComplete handler:", error);
775
- }
1040
+ await notifyCancellation();
776
1041
  }
777
1042
  return originalReturn(...args);
778
1043
  };
@@ -801,6 +1066,7 @@ function patchStreamIfNeeded(stream, options) {
801
1066
  value: true
802
1067
  });
803
1068
  stream[Symbol.asyncIterator] = patchedIteratorFn;
1069
+ patchAbortIfPresent();
804
1070
  return stream;
805
1071
  } catch (error) {
806
1072
  console.warn("Failed to patch stream:", error);
@@ -814,114 +1080,6 @@ function runNextWithWrapper(options, callback) {
814
1080
  // src/logger.ts
815
1081
  var import_uuid2 = require("uuid");
816
1082
 
817
- // src/debug-logger.ts
818
- var PREFIX = "[braintrust]";
819
- var DEBUG_LOG_LEVEL_SYMBOL = /* @__PURE__ */ Symbol.for("braintrust-debug-log-level");
820
- var LOG_LEVEL_PRIORITY = {
821
- error: 0,
822
- warn: 1,
823
- info: 2,
824
- debug: 3
825
- };
826
- var hasWarnedAboutInvalidEnvValue = false;
827
- var debugLogStateResolver = void 0;
828
- function warnInvalidEnvValue(value) {
829
- if (hasWarnedAboutInvalidEnvValue) {
830
- return;
831
- }
832
- hasWarnedAboutInvalidEnvValue = true;
833
- console.warn(
834
- PREFIX,
835
- `Invalid BRAINTRUST_DEBUG_LOG_LEVEL value "${value}". Expected "error", "warn", "info", or "debug".`
836
- );
837
- }
838
- function normalizeDebugLogLevelOption(option) {
839
- if (option === false) {
840
- return void 0;
841
- }
842
- if (option === "error" || option === "warn" || option === "info" || option === "debug") {
843
- return option;
844
- }
845
- throw new Error(
846
- `Invalid debugLogLevel value "${option}". Expected false, "error", "warn", "info", or "debug".`
847
- );
848
- }
849
- function parseDebugLogLevelEnv(value) {
850
- if (!value) {
851
- return void 0;
852
- }
853
- if (value === "error" || value === "warn" || value === "info" || value === "debug") {
854
- return value;
855
- }
856
- warnInvalidEnvValue(value);
857
- return void 0;
858
- }
859
- function getEnvDebugLogLevel() {
860
- return parseDebugLogLevelEnv(isomorph_default.getEnv("BRAINTRUST_DEBUG_LOG_LEVEL"));
861
- }
862
- function setGlobalDebugLogLevel(level) {
863
- globalThis[DEBUG_LOG_LEVEL_SYMBOL] = level;
864
- }
865
- function setDebugLogStateResolver(resolver) {
866
- debugLogStateResolver = resolver;
867
- }
868
- function resolveDebugLogLevel(state) {
869
- const stateLevel = state?.getDebugLogLevel?.();
870
- const hasStateOverride = state?.hasDebugLogLevelOverride?.() ?? false;
871
- if (hasStateOverride) {
872
- return stateLevel;
873
- }
874
- const globalLevel = (
875
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
876
- globalThis[DEBUG_LOG_LEVEL_SYMBOL]
877
- );
878
- if (globalLevel !== void 0) {
879
- return globalLevel === false ? void 0 : globalLevel;
880
- }
881
- return getEnvDebugLogLevel();
882
- }
883
- function emit(method, state, args) {
884
- const level = resolveDebugLogLevel(state);
885
- if (!level || LOG_LEVEL_PRIORITY[method] > LOG_LEVEL_PRIORITY[level]) {
886
- return;
887
- }
888
- if (method === "info") {
889
- console.log(PREFIX, ...args);
890
- } else if (method === "debug") {
891
- console.debug(PREFIX, ...args);
892
- } else if (method === "warn") {
893
- console.warn(PREFIX, ...args);
894
- } else {
895
- console.error(PREFIX, ...args);
896
- }
897
- }
898
- function createDebugLogger(state) {
899
- const resolveState = () => state ?? debugLogStateResolver?.();
900
- return {
901
- info(...args) {
902
- emit("info", resolveState(), args);
903
- },
904
- debug(...args) {
905
- emit("debug", resolveState(), args);
906
- },
907
- warn(...args) {
908
- emit("warn", resolveState(), args);
909
- },
910
- error(...args) {
911
- emit("error", resolveState(), args);
912
- }
913
- };
914
- }
915
- var debugLogger = {
916
- ...createDebugLogger(),
917
- forState(state) {
918
- return createDebugLogger(state);
919
- }
920
- };
921
- setGlobalHookErrorReporter((error) => {
922
- debugLogger.error("Global instrumentation hook error:", error);
923
- });
924
-
925
1083
  // src/queue.ts
926
1084
  var DEFAULT_QUEUE_SIZE = 15e3;
927
1085
  var Queue = class {
@@ -2463,7 +2621,8 @@ var AclObjectType = import_v36.z.union([
2463
2621
  "org_member",
2464
2622
  "project_log",
2465
2623
  "org_project",
2466
- "org_audit_logs"
2624
+ "org_audit_logs",
2625
+ "project_group"
2467
2626
  ]),
2468
2627
  import_v36.z.null()
2469
2628
  ]);
@@ -2592,7 +2751,8 @@ var AsyncScoringState = import_v36.z.union([
2592
2751
  token: import_v36.z.string(),
2593
2752
  function_ids: import_v36.z.array(import_v36.z.unknown()),
2594
2753
  skip_logging: import_v36.z.union([import_v36.z.boolean(), import_v36.z.null()]).optional(),
2595
- triggered_functions: import_v36.z.union([import_v36.z.record(TriggeredFunctionState), import_v36.z.null()]).optional()
2754
+ triggered_functions: import_v36.z.union([import_v36.z.record(TriggeredFunctionState), import_v36.z.null()]).optional(),
2755
+ last_triggered_xact_id: import_v36.z.union([import_v36.z.string(), import_v36.z.number(), import_v36.z.null()]).optional()
2596
2756
  }),
2597
2757
  import_v36.z.object({ status: import_v36.z.literal("disabled") }),
2598
2758
  import_v36.z.null(),
@@ -2661,7 +2821,7 @@ var FunctionTypeEnum = import_v36.z.enum([
2661
2821
  "parameters",
2662
2822
  "sandbox"
2663
2823
  ]);
2664
- var NullableSavedFunctionId = import_v36.z.union([
2824
+ var FacetPreprocessorId = import_v36.z.union([
2665
2825
  import_v36.z.object({
2666
2826
  type: import_v36.z.literal("function"),
2667
2827
  id: import_v36.z.string(),
@@ -2672,10 +2832,23 @@ var NullableSavedFunctionId = import_v36.z.union([
2672
2832
  name: import_v36.z.string(),
2673
2833
  function_type: FunctionTypeEnum.optional().default("scorer")
2674
2834
  }),
2835
+ import_v36.z.object({ type: import_v36.z.literal("inline"), code: import_v36.z.string().min(1) }),
2675
2836
  import_v36.z.null()
2676
2837
  ]);
2838
+ var SavedFunctionId = import_v36.z.union([
2839
+ import_v36.z.object({
2840
+ type: import_v36.z.literal("function"),
2841
+ id: import_v36.z.string(),
2842
+ version: import_v36.z.string().optional()
2843
+ }),
2844
+ import_v36.z.object({
2845
+ type: import_v36.z.literal("global"),
2846
+ name: import_v36.z.string(),
2847
+ function_type: FunctionTypeEnum.optional().default("scorer")
2848
+ })
2849
+ ]);
2677
2850
  var TopicMapGenerationSettings = import_v36.z.object({
2678
- algorithm: import_v36.z.enum(["hdbscan", "kmeans"]),
2851
+ algorithm: import_v36.z.enum(["hdbscan", "kmeans", "community"]),
2679
2852
  dimension_reduction: import_v36.z.enum(["umap", "pca", "none"]),
2680
2853
  sample_size: import_v36.z.number().int().gt(0).optional(),
2681
2854
  n_clusters: import_v36.z.number().int().gt(0).optional(),
@@ -2687,6 +2860,7 @@ var TopicMapGenerationSettings = import_v36.z.object({
2687
2860
  var TopicMapData = import_v36.z.object({
2688
2861
  type: import_v36.z.literal("topic_map"),
2689
2862
  source_facet: import_v36.z.string(),
2863
+ source_facet_function: SavedFunctionId.and(import_v36.z.unknown()).optional(),
2690
2864
  embedding_model: import_v36.z.string(),
2691
2865
  bundle_key: import_v36.z.string().optional(),
2692
2866
  report_key: import_v36.z.string().optional(),
@@ -2700,7 +2874,7 @@ var TopicMapData = import_v36.z.object({
2700
2874
  });
2701
2875
  var BatchedFacetData = import_v36.z.object({
2702
2876
  type: import_v36.z.literal("batched_facet"),
2703
- preprocessor: NullableSavedFunctionId.and(import_v36.z.unknown()).optional(),
2877
+ preprocessor: FacetPreprocessorId.optional(),
2704
2878
  facets: import_v36.z.array(
2705
2879
  import_v36.z.object({
2706
2880
  name: import_v36.z.string(),
@@ -2961,18 +3135,6 @@ var ObjectReferenceNullish = import_v36.z.union([
2961
3135
  }),
2962
3136
  import_v36.z.null()
2963
3137
  ]);
2964
- var SavedFunctionId = import_v36.z.union([
2965
- import_v36.z.object({
2966
- type: import_v36.z.literal("function"),
2967
- id: import_v36.z.string(),
2968
- version: import_v36.z.string().optional()
2969
- }),
2970
- import_v36.z.object({
2971
- type: import_v36.z.literal("global"),
2972
- name: import_v36.z.string(),
2973
- function_type: FunctionTypeEnum.optional().default("scorer")
2974
- })
2975
- ]);
2976
3138
  var DatasetEvent = import_v36.z.object({
2977
3139
  id: import_v36.z.string(),
2978
3140
  _xact_id: import_v36.z.string(),
@@ -3194,7 +3356,7 @@ var ExtendedSavedFunctionId = import_v36.z.union([
3194
3356
  ]);
3195
3357
  var FacetData = import_v36.z.object({
3196
3358
  type: import_v36.z.literal("facet"),
3197
- preprocessor: NullableSavedFunctionId.and(import_v36.z.unknown()).optional(),
3359
+ preprocessor: FacetPreprocessorId.optional(),
3198
3360
  prompt: import_v36.z.string(),
3199
3361
  model: import_v36.z.string().optional(),
3200
3362
  embedding_model: import_v36.z.string().optional(),
@@ -3699,6 +3861,19 @@ var MessageRole = import_v36.z.enum([
3699
3861
  "model",
3700
3862
  "developer"
3701
3863
  ]);
3864
+ var NullableSavedFunctionId = import_v36.z.union([
3865
+ import_v36.z.object({
3866
+ type: import_v36.z.literal("function"),
3867
+ id: import_v36.z.string(),
3868
+ version: import_v36.z.string().optional()
3869
+ }),
3870
+ import_v36.z.object({
3871
+ type: import_v36.z.literal("global"),
3872
+ name: import_v36.z.string(),
3873
+ function_type: FunctionTypeEnum.optional().default("scorer")
3874
+ }),
3875
+ import_v36.z.null()
3876
+ ]);
3702
3877
  var ObjectReference = import_v36.z.object({
3703
3878
  object_type: import_v36.z.enum([
3704
3879
  "project_logs",
@@ -3720,6 +3895,7 @@ var TraceScope = import_v36.z.object({
3720
3895
  });
3721
3896
  var OnlineScoreConfig = import_v36.z.union([
3722
3897
  import_v36.z.object({
3898
+ status: AutomationStatus.optional(),
3723
3899
  sampling_rate: import_v36.z.number().gte(0).lte(1),
3724
3900
  scorers: import_v36.z.array(SavedFunctionId),
3725
3901
  btql_filter: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
@@ -3800,6 +3976,72 @@ var Project = import_v36.z.object({
3800
3976
  user_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3801
3977
  settings: ProjectSettings.optional()
3802
3978
  });
3979
+ var WindowedAutomationConfig = import_v36.z.object({
3980
+ event_type: import_v36.z.literal("windowed"),
3981
+ product_origin: import_v36.z.union([import_v36.z.literal("patterns"), import_v36.z.null()]).optional(),
3982
+ status: AutomationStatus.optional(),
3983
+ threshold: import_v36.z.object({
3984
+ calculation: import_v36.z.object({
3985
+ type: import_v36.z.literal("btql"),
3986
+ btql_query: import_v36.z.string().min(1),
3987
+ output: import_v36.z.object({
3988
+ type: import_v36.z.literal("scalar"),
3989
+ value_column: import_v36.z.string().min(1)
3990
+ })
3991
+ }),
3992
+ policy: import_v36.z.object({
3993
+ condition: import_v36.z.object({
3994
+ type: import_v36.z.literal("threshold"),
3995
+ operator: import_v36.z.enum(["lt", "lte", "gt", "gte", "eq", "neq"]),
3996
+ threshold: import_v36.z.number()
3997
+ }),
3998
+ pending_seconds: import_v36.z.number().int().gte(0).lte(2592e3),
3999
+ no_data_behavior: import_v36.z.enum(["keep_last", "resolve", "alert"]),
4000
+ renotify_interval_seconds: import_v36.z.union([import_v36.z.number(), import_v36.z.null()]).optional(),
4001
+ notify_on_recovery: import_v36.z.boolean().optional().default(true)
4002
+ })
4003
+ }).optional(),
4004
+ window: import_v36.z.object({
4005
+ window_seconds: import_v36.z.number().int().gte(1).lte(2592e3),
4006
+ schedule: import_v36.z.union([
4007
+ import_v36.z.object({
4008
+ type: import_v36.z.literal("interval"),
4009
+ evaluation_interval_seconds: import_v36.z.number().int().gte(1).lte(2592e3)
4010
+ }),
4011
+ import_v36.z.object({
4012
+ type: import_v36.z.literal("cron"),
4013
+ cron_expression: import_v36.z.string().min(1),
4014
+ timezone: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional()
4015
+ })
4016
+ ]),
4017
+ evaluation_delay_seconds: import_v36.z.number().int().gte(0).lte(2592e3)
4018
+ }),
4019
+ loop: import_v36.z.object({
4020
+ prompt: import_v36.z.string().min(1).max(1e4),
4021
+ include_trigger_input: import_v36.z.boolean().optional().default(false),
4022
+ agent_slug: import_v36.z.string().min(1),
4023
+ auto_approve_tools: import_v36.z.array(import_v36.z.string().min(1)).optional().default([]),
4024
+ harness: import_v36.z.enum(["native", "codex", "claude-code"]).optional(),
4025
+ model: import_v36.z.string().min(1).optional(),
4026
+ reasoning_effort: import_v36.z.enum(["none", "minimal", "low", "medium", "high", "xhigh", "max"]).optional()
4027
+ }).optional(),
4028
+ actions: import_v36.z.array(
4029
+ import_v36.z.union([
4030
+ import_v36.z.object({
4031
+ type: import_v36.z.literal("webhook"),
4032
+ url: import_v36.z.string(),
4033
+ formatting_prompt: import_v36.z.string().min(1).max(1e4).optional()
4034
+ }),
4035
+ import_v36.z.object({
4036
+ type: import_v36.z.literal("slack"),
4037
+ workspace_id: import_v36.z.string(),
4038
+ channel: import_v36.z.string(),
4039
+ message_template: import_v36.z.string().optional(),
4040
+ formatting_prompt: import_v36.z.string().min(1).max(1e4).optional()
4041
+ })
4042
+ ])
4043
+ ).max(20).optional().default([])
4044
+ });
3803
4045
  var TopicAutomationFacetModel = import_v36.z.union([
3804
4046
  import_v36.z.enum(["brain-facet-latest", "brain-facet-1", "brain-facet-2"]),
3805
4047
  import_v36.z.null()
@@ -3841,7 +4083,8 @@ var TopicDigestAutomationConfig = import_v36.z.object({
3841
4083
  type: import_v36.z.literal("slack"),
3842
4084
  workspace_id: import_v36.z.string(),
3843
4085
  channel: import_v36.z.string(),
3844
- message_template: import_v36.z.string().optional()
4086
+ message_template: import_v36.z.string().optional(),
4087
+ formatting_prompt: import_v36.z.string().min(1).max(1e4).optional()
3845
4088
  }),
3846
4089
  topic_map_function_ids: import_v36.z.array(import_v36.z.string()).max(10).optional()
3847
4090
  });
@@ -3855,15 +4098,21 @@ var ProjectAutomation = import_v36.z.object({
3855
4098
  config: import_v36.z.union([
3856
4099
  import_v36.z.object({
3857
4100
  event_type: import_v36.z.literal("logs"),
4101
+ status: AutomationStatus.optional(),
3858
4102
  btql_filter: import_v36.z.string(),
3859
4103
  interval_seconds: import_v36.z.number().gte(1).lte(2592e3),
3860
4104
  action: import_v36.z.union([
3861
- import_v36.z.object({ type: import_v36.z.literal("webhook"), url: import_v36.z.string() }),
4105
+ import_v36.z.object({
4106
+ type: import_v36.z.literal("webhook"),
4107
+ url: import_v36.z.string(),
4108
+ formatting_prompt: import_v36.z.string().min(1).max(1e4).optional()
4109
+ }),
3862
4110
  import_v36.z.object({
3863
4111
  type: import_v36.z.literal("slack"),
3864
4112
  workspace_id: import_v36.z.string(),
3865
4113
  channel: import_v36.z.string(),
3866
- message_template: import_v36.z.string().optional()
4114
+ message_template: import_v36.z.string().optional(),
4115
+ formatting_prompt: import_v36.z.string().min(1).max(1e4).optional()
3867
4116
  })
3868
4117
  ])
3869
4118
  }),
@@ -3914,21 +4163,38 @@ var ProjectAutomation = import_v36.z.object({
3914
4163
  }),
3915
4164
  import_v36.z.object({
3916
4165
  event_type: import_v36.z.literal("environment_update"),
4166
+ status: AutomationStatus.optional(),
3917
4167
  environment_filter: import_v36.z.array(import_v36.z.string()).optional(),
3918
4168
  action: import_v36.z.union([
3919
- import_v36.z.object({ type: import_v36.z.literal("webhook"), url: import_v36.z.string() }),
4169
+ import_v36.z.object({
4170
+ type: import_v36.z.literal("webhook"),
4171
+ url: import_v36.z.string(),
4172
+ formatting_prompt: import_v36.z.string().min(1).max(1e4).optional()
4173
+ }),
3920
4174
  import_v36.z.object({
3921
4175
  type: import_v36.z.literal("slack"),
3922
4176
  workspace_id: import_v36.z.string(),
3923
4177
  channel: import_v36.z.string(),
3924
- message_template: import_v36.z.string().optional()
4178
+ message_template: import_v36.z.string().optional(),
4179
+ formatting_prompt: import_v36.z.string().min(1).max(1e4).optional()
3925
4180
  })
3926
4181
  ])
3927
4182
  }),
4183
+ WindowedAutomationConfig,
3928
4184
  TopicAutomationConfig,
3929
4185
  TopicDigestAutomationConfig
3930
4186
  ])
3931
4187
  });
4188
+ var ProjectGroup = import_v36.z.object({
4189
+ id: import_v36.z.string().uuid(),
4190
+ org_id: import_v36.z.string().uuid(),
4191
+ user_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
4192
+ created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
4193
+ name: import_v36.z.string(),
4194
+ description: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
4195
+ deleted_at: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
4196
+ member_projects: import_v36.z.array(import_v36.z.string().uuid()).max(1e4)
4197
+ });
3932
4198
  var ProjectLogsEvent = import_v36.z.object({
3933
4199
  id: import_v36.z.string(),
3934
4200
  _xact_id: import_v36.z.string(),
@@ -4146,7 +4412,8 @@ var RunEval = import_v36.z.object({
4146
4412
  dataset_environment: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
4147
4413
  _internal_btql: import_v36.z.union([import_v36.z.object({}).partial().passthrough(), import_v36.z.null()]).optional()
4148
4414
  }),
4149
- import_v36.z.object({ data: import_v36.z.array(import_v36.z.unknown()) })
4415
+ import_v36.z.object({ data: import_v36.z.array(import_v36.z.unknown()) }),
4416
+ import_v36.z.object({ experiment_name: import_v36.z.string() })
4150
4417
  ]),
4151
4418
  name: import_v36.z.string().optional(),
4152
4419
  parameters: import_v36.z.object({}).partial().passthrough().optional(),
@@ -4351,7 +4618,9 @@ var View = import_v36.z.object({
4351
4618
  "for_review_datasets"
4352
4619
  ]),
4353
4620
  name: import_v36.z.string(),
4621
+ description: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
4354
4622
  created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
4623
+ updated_at: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
4355
4624
  view_data: ViewData.optional(),
4356
4625
  options: ViewOptions.optional(),
4357
4626
  user_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
@@ -5426,6 +5695,7 @@ var INSTRUMENTATION_NAMES = {
5426
5695
  CLAUDE_AGENT_SDK: "claude-agent-sdk",
5427
5696
  CLOUDFLARE_AI_CHAT: "cloudflare-ai-chat",
5428
5697
  CLOUDFLARE_AGENTS: "cloudflare-agents",
5698
+ CLOUDFLARE_THINK: "cloudflare-think",
5429
5699
  COHERE: "cohere",
5430
5700
  CURSOR_SDK: "cursor-sdk",
5431
5701
  EVE: "eve",
@@ -5440,18 +5710,20 @@ var INSTRUMENTATION_NAMES = {
5440
5710
  LANGSMITH: "langsmith",
5441
5711
  MASTRA: "mastra",
5442
5712
  MISTRAL: "mistral",
5713
+ OLLAMA: "ollama",
5443
5714
  OPENAI: "openai",
5444
5715
  OPENAI_AGENTS: "openai-agents",
5445
5716
  OPENAI_CODEX: "openai-codex",
5446
5717
  OPENROUTER: "openrouter",
5447
5718
  OPENROUTER_AGENT: "openrouter-agent",
5448
5719
  PI_CODING_AGENT: "pi-coding-agent",
5449
- STRANDS_AGENT_SDK: "strands-agent-sdk"
5720
+ STRANDS_AGENT_SDK: "strands-agent-sdk",
5721
+ VOYAGEAI: "voyageai"
5450
5722
  };
5451
5723
  var INTERNAL_SPAN_INSTRUMENTATION_NAME = /* @__PURE__ */ Symbol.for(
5452
5724
  "braintrust.spanInstrumentationName"
5453
5725
  );
5454
- var SDK_VERSION = true ? "3.26.0" : "0.0.0";
5726
+ var SDK_VERSION = true ? "3.28.0" : "0.0.0";
5455
5727
  function withSpanInstrumentationName(args, instrumentationName) {
5456
5728
  return {
5457
5729
  ...args,
@@ -5646,6 +5918,9 @@ function applyMaskingToField(maskingFunction, data, fieldName) {
5646
5918
  var INITIAL_SPAN_WRITE_AS_MERGE = /* @__PURE__ */ Symbol(
5647
5919
  "braintrust.initial-span-write-as-merge"
5648
5920
  );
5921
+ var RESUME_SPAN_WITHOUT_INITIAL_WRITE = /* @__PURE__ */ Symbol(
5922
+ "braintrust.resume-span-without-initial-write"
5923
+ );
5649
5924
  var INTERNAL_SPAN_CONTEXT = /* @__PURE__ */ Symbol("braintrust.internal-span-context");
5650
5925
  var BRAINTRUST_CURRENT_SPAN_STORE = /* @__PURE__ */ Symbol.for(
5651
5926
  "braintrust.currentSpanStore"
@@ -8495,7 +8770,7 @@ var ObjectFetcher = class {
8495
8770
  const objectId = await this.id;
8496
8771
  const batchLimit = batchSize ?? DEFAULT_FETCH_BATCH_SIZE;
8497
8772
  const internalLimit = getInternalBtqlLimit(this._internal_btql);
8498
- const limit = batchSize !== void 0 ? batchSize : internalLimit ?? batchLimit;
8773
+ let remainingLimit = internalLimit;
8499
8774
  const internalBtqlWithoutReservedQueryKeys = Object.fromEntries(
8500
8775
  Object.entries(this._internal_btql ?? {}).filter(
8501
8776
  ([key]) => key !== "cursor" && key !== "limit" && key !== "select" && key !== "from"
@@ -8504,6 +8779,10 @@ var ObjectFetcher = class {
8504
8779
  let cursor = void 0;
8505
8780
  let iterations = 0;
8506
8781
  while (true) {
8782
+ if (remainingLimit !== void 0 && remainingLimit <= 0) {
8783
+ return;
8784
+ }
8785
+ const limit = remainingLimit === void 0 ? batchLimit : Math.min(batchLimit, remainingLimit);
8507
8786
  const resp = await state.apiConn().post(
8508
8787
  `btql`,
8509
8788
  {
@@ -8543,7 +8822,14 @@ var ObjectFetcher = class {
8543
8822
  const respJson = await resp.json();
8544
8823
  const mutate = this.mutateRecord;
8545
8824
  for (const record of respJson.data ?? []) {
8546
- yield mutate ? mutate(record) : record;
8825
+ if (remainingLimit !== void 0 && remainingLimit <= 0) {
8826
+ return;
8827
+ }
8828
+ const mutatedRecord = mutate ? mutate(record) : record;
8829
+ if (remainingLimit !== void 0) {
8830
+ remainingLimit--;
8831
+ }
8832
+ yield mutatedRecord;
8547
8833
  }
8548
8834
  if (!respJson.cursor) {
8549
8835
  break;
@@ -9020,7 +9306,9 @@ var SpanImpl = class _SpanImpl {
9020
9306
  this._rootSpanId = resolvedIds.rootSpanId;
9021
9307
  this._spanParents = resolvedIds.spanParents;
9022
9308
  this.isMerge = args[INITIAL_SPAN_WRITE_AS_MERGE] === true;
9023
- this.logInternal({ event, internalData });
9309
+ if (!args[RESUME_SPAN_WITHOUT_INITIAL_WRITE]) {
9310
+ this.logInternal({ event, internalData });
9311
+ }
9024
9312
  this.isMerge = true;
9025
9313
  }
9026
9314
  getParentInfo() {
@@ -10472,6 +10760,33 @@ function traceStreamingChannel(channel2, config) {
10472
10760
  const { span, startTime } = spanData;
10473
10761
  if (isAsyncIterable(asyncEndEvent.result)) {
10474
10762
  let firstChunkTime;
10763
+ const handleStreamError = (error) => {
10764
+ try {
10765
+ span.log({ error });
10766
+ } catch (loggingError) {
10767
+ debugLogger.error(
10768
+ `Error logging failure for ${channelName}:`,
10769
+ loggingError
10770
+ );
10771
+ }
10772
+ try {
10773
+ span.end();
10774
+ } catch (endingError) {
10775
+ debugLogger.error(
10776
+ `Error ending span for ${channelName}:`,
10777
+ endingError
10778
+ );
10779
+ }
10780
+ states.delete(event);
10781
+ runStreamingErrorHook({
10782
+ channelName,
10783
+ config,
10784
+ error,
10785
+ event: asyncEndEvent,
10786
+ span,
10787
+ startTime
10788
+ });
10789
+ };
10475
10790
  patchStreamIfNeeded(asyncEndEvent.result, {
10476
10791
  onChunk: () => {
10477
10792
  if (firstChunkTime === void 0) {
@@ -10551,33 +10866,12 @@ function traceStreamingChannel(channel2, config) {
10551
10866
  });
10552
10867
  }
10553
10868
  },
10554
- onError: (error) => {
10555
- try {
10556
- span.log({ error });
10557
- } catch (loggingError) {
10558
- debugLogger.error(
10559
- `Error logging failure for ${channelName}:`,
10560
- loggingError
10561
- );
10562
- }
10563
- try {
10564
- span.end();
10565
- } catch (endingError) {
10566
- debugLogger.error(
10567
- `Error ending span for ${channelName}:`,
10568
- endingError
10569
- );
10570
- }
10571
- states.delete(event);
10572
- runStreamingErrorHook({
10573
- channelName,
10574
- config,
10575
- error,
10576
- event: asyncEndEvent,
10577
- span,
10578
- startTime
10579
- });
10580
- }
10869
+ onCancel: () => {
10870
+ const error = new Error("Stream cancelled before completion");
10871
+ error.name = "AbortError";
10872
+ handleStreamError(error);
10873
+ },
10874
+ onError: handleStreamError
10581
10875
  });
10582
10876
  return;
10583
10877
  }
@@ -10893,6 +11187,22 @@ function processInputAttachments(input) {
10893
11187
  };
10894
11188
  }
10895
11189
  }
11190
+ const voyageBase64Key = node.type === "image_base64" ? Object.hasOwn(node, "imageBase64") ? "imageBase64" : "image_base64" : node.type === "video_base64" ? Object.hasOwn(node, "videoBase64") ? "videoBase64" : "video_base64" : void 0;
11191
+ const voyageBase64Value = voyageBase64Key ? node[voyageBase64Key] : void 0;
11192
+ if (voyageBase64Key && typeof voyageBase64Value === "string" && voyageBase64Value.startsWith("data:")) {
11193
+ const mediaType = inferMediaTypeFromDataUrl(
11194
+ voyageBase64Value,
11195
+ node.type === "video_base64" ? "video/mp4" : "image/png"
11196
+ );
11197
+ const filename = `${node.type === "video_base64" ? "video" : "image"}.${getExtensionFromMediaType(mediaType)}`;
11198
+ const attachment = toAttachment(voyageBase64Value, mediaType, filename);
11199
+ if (attachment) {
11200
+ return {
11201
+ ...node,
11202
+ [voyageBase64Key]: attachment
11203
+ };
11204
+ }
11205
+ }
10896
11206
  if (node.type === "file" && node.file && typeof node.file === "object" && typeof node.file.file_data === "string" && node.file.file_data.startsWith("data:")) {
10897
11207
  const mediaType = inferMediaTypeFromDataUrl(
10898
11208
  node.file.file_data,
@@ -10965,11 +11275,21 @@ function defineChannels(pkg, channels, options) {
10965
11275
  const tracingChannel2 = () => isomorph_default.newTracingChannel(
10966
11276
  fullChannelName
10967
11277
  );
11278
+ const intercept2 = (interceptor) => {
11279
+ const hook = tracingChannel2();
11280
+ return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
11281
+ };
11282
+ };
10968
11283
  return [
10969
11284
  key,
10970
11285
  {
10971
11286
  ...asyncSpec,
10972
11287
  instrumentationName,
11288
+ intercept: intercept2,
11289
+ invoke: (target, thisArg, args, additional) => {
11290
+ const hook = tracingChannel2();
11291
+ return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
11292
+ },
10973
11293
  tracingChannel: tracingChannel2,
10974
11294
  tracePromise: (fn, context) => tracingChannel2().tracePromise(
10975
11295
  fn,
@@ -10983,11 +11303,21 @@ function defineChannels(pkg, channels, options) {
10983
11303
  const tracingChannel = () => isomorph_default.newTracingChannel(
10984
11304
  fullChannelName
10985
11305
  );
11306
+ const intercept = (interceptor) => {
11307
+ const hook = tracingChannel();
11308
+ return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
11309
+ };
11310
+ };
10986
11311
  return [
10987
11312
  key,
10988
11313
  {
10989
11314
  ...syncSpec,
10990
11315
  instrumentationName,
11316
+ intercept,
11317
+ invoke: (target, thisArg, args, additional) => {
11318
+ const hook = tracingChannel();
11319
+ return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
11320
+ },
10991
11321
  tracingChannel,
10992
11322
  traceSync: (fn, context) => tracingChannel().traceSync(
10993
11323
  fn,
@@ -12220,12 +12550,30 @@ function logInstrumentationError(context, error) {
12220
12550
 
12221
12551
  // src/wrappers/anthropic-tokens-util.ts
12222
12552
  function finalizeAnthropicTokens(metrics) {
12223
- const prompt_tokens = (metrics.prompt_tokens || 0) + (metrics.prompt_cached_tokens || 0) + (metrics.prompt_cache_creation_tokens || 0);
12224
- return {
12553
+ const hasSplitCacheCreationTokens = metrics.prompt_cache_creation_5m_tokens !== void 0 || metrics.prompt_cache_creation_1h_tokens !== void 0;
12554
+ const splitCacheCreationTokens = (metrics.prompt_cache_creation_5m_tokens || 0) + (metrics.prompt_cache_creation_1h_tokens || 0);
12555
+ const aggregateCacheCreationTokens = metrics.prompt_cache_creation_tokens || 0;
12556
+ const effectiveCacheCreationTokens = Math.max(
12557
+ aggregateCacheCreationTokens,
12558
+ splitCacheCreationTokens
12559
+ );
12560
+ const prompt_tokens = (metrics.prompt_tokens || 0) + (metrics.prompt_cached_tokens || 0) + effectiveCacheCreationTokens;
12561
+ const finalized = {
12225
12562
  ...metrics,
12226
12563
  prompt_tokens,
12227
12564
  tokens: prompt_tokens + (metrics.completion_tokens || 0)
12228
12565
  };
12566
+ if (hasSplitCacheCreationTokens && splitCacheCreationTokens >= aggregateCacheCreationTokens) {
12567
+ delete finalized.prompt_cache_creation_tokens;
12568
+ }
12569
+ return finalized;
12570
+ }
12571
+ function toNumericMetrics(metrics) {
12572
+ return Object.fromEntries(
12573
+ Object.entries(metrics).filter(
12574
+ (entry) => entry[1] !== void 0
12575
+ )
12576
+ );
12229
12577
  }
12230
12578
  function extractAnthropicCacheTokens(cacheReadTokens = 0, cacheCreationTokens = 0) {
12231
12579
  const cacheTokens = {};
@@ -12238,6 +12586,12 @@ function extractAnthropicCacheTokens(cacheReadTokens = 0, cacheCreationTokens =
12238
12586
  return cacheTokens;
12239
12587
  }
12240
12588
 
12589
+ // src/wrappers/anthropic-session-collector.ts
12590
+ var sessionStreamCollectors = /* @__PURE__ */ new WeakMap();
12591
+ function registerAnthropicSessionStreamCollector(stream, collector) {
12592
+ sessionStreamCollectors.set(stream, collector);
12593
+ }
12594
+
12241
12595
  // src/instrumentation/plugins/anthropic-channels.ts
12242
12596
  var anthropicChannels = defineChannels(
12243
12597
  "@anthropic-ai/sdk",
@@ -12253,6 +12607,14 @@ var anthropicChannels = defineChannels(
12253
12607
  betaMessagesToolRunner: channel({
12254
12608
  channelName: "beta.messages.toolRunner",
12255
12609
  kind: "sync-stream"
12610
+ }),
12611
+ betaSessionsEventsStream: channel({
12612
+ channelName: "beta.sessions.events.stream",
12613
+ kind: "async"
12614
+ }),
12615
+ betaSessionsThreadsEventsStream: channel({
12616
+ channelName: "beta.sessions.threads.events.stream",
12617
+ kind: "async"
12256
12618
  })
12257
12619
  },
12258
12620
  { instrumentationName: INSTRUMENTATION_NAMES.ANTHROPIC }
@@ -12266,6 +12628,7 @@ var AnthropicPlugin = class extends BasePlugin {
12266
12628
  onEnable() {
12267
12629
  this.subscribeToAnthropicChannels();
12268
12630
  this.subscribeToAnthropicToolRunner();
12631
+ this.subscribeToAnthropicSessionStreams();
12269
12632
  }
12270
12633
  onDisable() {
12271
12634
  this.unsubscribers = unsubscribeAll(this.unsubscribers);
@@ -12383,7 +12746,411 @@ var AnthropicPlugin = class extends BasePlugin {
12383
12746
  tracingChannel.unsubscribe(handlers);
12384
12747
  });
12385
12748
  }
12749
+ subscribeToAnthropicSessionStreams() {
12750
+ this.subscribeToAnthropicSessionStream(
12751
+ anthropicChannels.betaSessionsEventsStream,
12752
+ false
12753
+ );
12754
+ this.subscribeToAnthropicSessionStream(
12755
+ anthropicChannels.betaSessionsThreadsEventsStream,
12756
+ true
12757
+ );
12758
+ }
12759
+ subscribeToAnthropicSessionStream(channel2, isThread) {
12760
+ const tracingChannel = channel2.tracingChannel();
12761
+ const pending = /* @__PURE__ */ new WeakSet();
12762
+ const handlers = {
12763
+ start: (event) => {
12764
+ if (isAutoInstrumentationSuppressed()) {
12765
+ return;
12766
+ }
12767
+ pending.add(event);
12768
+ },
12769
+ asyncEnd: (event) => {
12770
+ if (!pending.delete(event)) {
12771
+ return;
12772
+ }
12773
+ const stream = event.result;
12774
+ if (!isAsyncIterable(stream)) {
12775
+ return;
12776
+ }
12777
+ registerAnthropicSessionStreamCollector(stream, () => {
12778
+ wrapAnthropicSessionEventStream(stream, isThread);
12779
+ });
12780
+ },
12781
+ error: (event) => {
12782
+ pending.delete(event);
12783
+ }
12784
+ };
12785
+ tracingChannel.subscribe(handlers);
12786
+ this.unsubscribers.push(() => tracingChannel.unsubscribe(handlers));
12787
+ }
12386
12788
  };
12789
+ function wrapAnthropicSessionEventStream(stream, isThread) {
12790
+ const state = {
12791
+ history: [],
12792
+ isThread,
12793
+ pendingInput: [],
12794
+ seenEventIds: /* @__PURE__ */ new Set()
12795
+ };
12796
+ patchStreamIfNeeded(stream, {
12797
+ onChunk: (event) => handleAnthropicSessionEvent(state, event),
12798
+ onComplete: () => finalizeAnthropicSessionTurn(state),
12799
+ onError: (error) => finalizeAnthropicSessionTurn(state, error)
12800
+ });
12801
+ return stream;
12802
+ }
12803
+ function handleAnthropicSessionEvent(state, event) {
12804
+ try {
12805
+ if (typeof event.id === "string" && event.type !== "event_delta" && state.seenEventIds.has(event.id)) {
12806
+ return;
12807
+ }
12808
+ if (typeof event.id === "string" && event.type !== "event_delta") {
12809
+ state.seenEventIds.add(event.id);
12810
+ }
12811
+ switch (event.type) {
12812
+ case "user.message":
12813
+ case "system.message":
12814
+ recordAnthropicSessionInput(
12815
+ state,
12816
+ event
12817
+ );
12818
+ break;
12819
+ case "session.status_running":
12820
+ if (!state.isThread) {
12821
+ ensureAnthropicSessionTurn(state);
12822
+ }
12823
+ break;
12824
+ case "session.thread_status_running":
12825
+ if (state.isThread) {
12826
+ ensureAnthropicSessionTurn(state);
12827
+ }
12828
+ break;
12829
+ case "span.model_request_start":
12830
+ if (typeof event.id === "string") {
12831
+ startAnthropicSessionModel(state, event.id);
12832
+ }
12833
+ break;
12834
+ case "event_delta":
12835
+ recordAnthropicSessionFirstToken(state, event);
12836
+ break;
12837
+ case "agent.message":
12838
+ recordAnthropicSessionMessage(
12839
+ state,
12840
+ event
12841
+ );
12842
+ break;
12843
+ case "agent.custom_tool_use":
12844
+ case "agent.mcp_tool_use":
12845
+ case "agent.tool_use":
12846
+ startAnthropicSessionTool(state, event);
12847
+ break;
12848
+ case "user.tool_confirmation":
12849
+ recordAnthropicSessionToolConfirmation(state, event);
12850
+ break;
12851
+ case "agent.mcp_tool_result":
12852
+ case "agent.tool_result":
12853
+ case "user.custom_tool_result":
12854
+ case "user.tool_result":
12855
+ finalizeAnthropicSessionTool(
12856
+ state,
12857
+ event
12858
+ );
12859
+ break;
12860
+ case "span.model_request_end":
12861
+ finalizeAnthropicSessionModel(
12862
+ state,
12863
+ event
12864
+ );
12865
+ break;
12866
+ case "session.status_idle":
12867
+ case "session.thread_status_idle": {
12868
+ if (event.type === "session.status_idle" && state.isThread || event.type === "session.thread_status_idle" && !state.isThread) {
12869
+ break;
12870
+ }
12871
+ const stopReason = isObject(event.stop_reason) ? event.stop_reason.type : void 0;
12872
+ if (stopReason === "end_turn") {
12873
+ finalizeAnthropicSessionTurn(state);
12874
+ } else if (stopReason === "retries_exhausted") {
12875
+ finalizeAnthropicSessionTurn(
12876
+ state,
12877
+ "Anthropic session retries exhausted"
12878
+ );
12879
+ }
12880
+ break;
12881
+ }
12882
+ case "session.error":
12883
+ finalizeAnthropicSessionTurn(state, event.error);
12884
+ break;
12885
+ case "session.deleted":
12886
+ case "session.status_terminated":
12887
+ case "session.thread_status_terminated":
12888
+ if (event.type === "session.deleted" || event.type === "session.status_terminated" && !state.isThread || event.type === "session.thread_status_terminated" && state.isThread) {
12889
+ finalizeAnthropicSessionTurn(state);
12890
+ }
12891
+ break;
12892
+ default:
12893
+ break;
12894
+ }
12895
+ } catch (error) {
12896
+ debugLogger.debug("Error processing Anthropic Sessions event:", error);
12897
+ }
12898
+ }
12899
+ function ensureAnthropicSessionTurn(state) {
12900
+ if (state.activeTurn) {
12901
+ return state.activeTurn;
12902
+ }
12903
+ const input = state.pendingInput;
12904
+ state.pendingInput = [];
12905
+ const span = startSpan(
12906
+ withSpanInstrumentationName(
12907
+ {
12908
+ event: {
12909
+ ...input.length > 0 ? { input } : {},
12910
+ metadata: { provider: "anthropic" }
12911
+ },
12912
+ name: state.isThread ? "anthropic.beta.sessions.thread.turn" : "anthropic.beta.sessions.turn",
12913
+ spanAttributes: { type: "task" /* TASK */ }
12914
+ },
12915
+ INSTRUMENTATION_NAMES.ANTHROPIC
12916
+ )
12917
+ );
12918
+ state.activeTurn = {
12919
+ activeTools: /* @__PURE__ */ new Map(),
12920
+ input: input.slice(),
12921
+ metrics: {},
12922
+ span
12923
+ };
12924
+ return state.activeTurn;
12925
+ }
12926
+ function recordAnthropicSessionInput(state, event) {
12927
+ const content = processAttachmentsInInput(event.content);
12928
+ const message = {
12929
+ role: event.type === "system.message" ? "system" : "user",
12930
+ content
12931
+ };
12932
+ state.history.push(message);
12933
+ if (state.activeTurn) {
12934
+ state.activeTurn.input.push(message);
12935
+ } else {
12936
+ state.pendingInput.push(message);
12937
+ }
12938
+ }
12939
+ function startAnthropicSessionModel(state, startEventId) {
12940
+ const turn = ensureAnthropicSessionTurn(state);
12941
+ if (turn.activeModel) {
12942
+ finalizeAnthropicSessionModelState(state, turn);
12943
+ }
12944
+ const span = withCurrent(
12945
+ turn.span,
12946
+ () => startSpan(
12947
+ withSpanInstrumentationName(
12948
+ {
12949
+ event: {
12950
+ ...state.history.length > 0 ? { input: state.history.slice() } : {},
12951
+ metadata: { provider: "anthropic" }
12952
+ },
12953
+ name: "anthropic.messages.create",
12954
+ spanAttributes: { type: "llm" /* LLM */ }
12955
+ },
12956
+ INSTRUMENTATION_NAMES.ANTHROPIC
12957
+ )
12958
+ )
12959
+ );
12960
+ turn.activeModel = {
12961
+ output: [],
12962
+ span,
12963
+ startEventId,
12964
+ startTime: getCurrentUnixTimestamp()
12965
+ };
12966
+ }
12967
+ function recordAnthropicSessionFirstToken(state, event) {
12968
+ const model = state.activeTurn?.activeModel;
12969
+ if (!model || model.firstTokenTime !== void 0 || !isObject(event.delta) || !isObject(event.delta.content) || typeof event.delta.content.text !== "string") {
12970
+ return;
12971
+ }
12972
+ model.firstTokenTime = getCurrentUnixTimestamp();
12973
+ }
12974
+ function recordAnthropicSessionMessage(state, event) {
12975
+ const turn = ensureAnthropicSessionTurn(state);
12976
+ const content = processAttachmentsInInput(
12977
+ event.content
12978
+ );
12979
+ if (turn.activeModel) {
12980
+ turn.activeModel.output.push(...content);
12981
+ } else {
12982
+ const output = { role: "assistant", content };
12983
+ turn.lastOutput = output;
12984
+ state.history.push(output);
12985
+ }
12986
+ }
12987
+ function startAnthropicSessionTool(state, event) {
12988
+ const turn = ensureAnthropicSessionTurn(state);
12989
+ if (turn.activeModel) {
12990
+ turn.activeModel.output.push({
12991
+ type: "tool_use",
12992
+ id: event.id,
12993
+ name: event.name,
12994
+ input: event.input
12995
+ });
12996
+ }
12997
+ const existing = turn.activeTools.get(event.id);
12998
+ if (existing) {
12999
+ existing.span.end();
13000
+ turn.activeTools.delete(event.id);
13001
+ }
13002
+ const span = withCurrent(
13003
+ turn.span,
13004
+ () => startSpan(
13005
+ withSpanInstrumentationName(
13006
+ {
13007
+ event: { input: event.input },
13008
+ name: event.name,
13009
+ spanAttributes: { type: "tool" /* TOOL */ }
13010
+ },
13011
+ INSTRUMENTATION_NAMES.ANTHROPIC
13012
+ )
13013
+ )
13014
+ );
13015
+ const toolState = {
13016
+ approval: event.evaluated_permission === "allow" ? "approved" : event.evaluated_permission === "deny" ? "denied" : void 0,
13017
+ span
13018
+ };
13019
+ turn.activeTools.set(event.id, toolState);
13020
+ if (toolState.approval === "denied") {
13021
+ finalizeAnthropicSessionToolState(toolState);
13022
+ turn.activeTools.delete(event.id);
13023
+ }
13024
+ }
13025
+ function recordAnthropicSessionToolConfirmation(state, event) {
13026
+ if (typeof event.tool_use_id !== "string" || event.result !== "allow" && event.result !== "deny") {
13027
+ return;
13028
+ }
13029
+ const turn = state.activeTurn;
13030
+ const tool = turn?.activeTools.get(event.tool_use_id);
13031
+ if (!turn || !tool) {
13032
+ return;
13033
+ }
13034
+ tool.approval = event.result === "allow" ? "approved" : "denied";
13035
+ if (tool.approval === "denied") {
13036
+ finalizeAnthropicSessionToolState(tool);
13037
+ turn.activeTools.delete(event.tool_use_id);
13038
+ }
13039
+ }
13040
+ function finalizeAnthropicSessionTool(state, event) {
13041
+ const toolUseId = event.tool_use_id ?? event.mcp_tool_use_id ?? event.custom_tool_use_id;
13042
+ if (!toolUseId) {
13043
+ return;
13044
+ }
13045
+ const content = processAttachmentsInInput(event.content);
13046
+ const turn = state.activeTurn;
13047
+ const tool = turn?.activeTools.get(toolUseId);
13048
+ if (turn && tool) {
13049
+ finalizeAnthropicSessionToolState(tool, event, content);
13050
+ turn.activeTools.delete(toolUseId);
13051
+ }
13052
+ const toolResult = {
13053
+ type: "tool_result",
13054
+ tool_use_id: toolUseId,
13055
+ ...content !== void 0 ? { content } : {},
13056
+ ...event.is_error === true ? { is_error: true } : {}
13057
+ };
13058
+ state.history.push({
13059
+ role: "user",
13060
+ content: [toolResult]
13061
+ });
13062
+ }
13063
+ function finalizeAnthropicSessionToolState(state, event, content = event?.content) {
13064
+ safeAnthropicSessionLog(state.span, {
13065
+ ...event?.is_error === true ? {
13066
+ error: content ?? "Anthropic session tool execution failed"
13067
+ } : {},
13068
+ ...state.approval ? { metadata: { tool_approval: state.approval } } : {},
13069
+ ...content !== void 0 ? { output: content } : {}
13070
+ });
13071
+ state.span.end();
13072
+ }
13073
+ function finalizeAnthropicSessionModel(state, event) {
13074
+ const turn = state.activeTurn;
13075
+ const model = turn?.activeModel;
13076
+ if (!turn || !model || model.startEventId !== event.model_request_start_id) {
13077
+ return;
13078
+ }
13079
+ finalizeAnthropicSessionModelState(state, turn, event);
13080
+ }
13081
+ function finalizeAnthropicSessionModelState(state, turn, event) {
13082
+ const model = turn.activeModel;
13083
+ if (!model) {
13084
+ return;
13085
+ }
13086
+ turn.activeModel = void 0;
13087
+ const metrics = event ? parseAnthropicSessionModelUsage(event.model_usage) : {};
13088
+ if (model.firstTokenTime !== void 0) {
13089
+ metrics.time_to_first_token = model.firstTokenTime - model.startTime;
13090
+ }
13091
+ const output = model.output.length > 0 ? { role: "assistant", content: model.output } : void 0;
13092
+ safeAnthropicSessionLog(model.span, {
13093
+ ...event?.is_error ? { error: "Anthropic session model request failed" } : {},
13094
+ ...Object.keys(metrics).length > 0 ? { metrics } : {},
13095
+ ...output ? { output } : {}
13096
+ });
13097
+ model.span.end();
13098
+ if (output) {
13099
+ turn.lastOutput = output;
13100
+ state.history.push(output);
13101
+ }
13102
+ for (const key of [
13103
+ "prompt_tokens",
13104
+ "completion_tokens",
13105
+ "tokens",
13106
+ "prompt_cached_tokens",
13107
+ "prompt_cache_creation_tokens"
13108
+ ]) {
13109
+ const value = metrics[key];
13110
+ if (typeof value === "number") {
13111
+ turn.metrics[key] = (turn.metrics[key] ?? 0) + value;
13112
+ }
13113
+ }
13114
+ }
13115
+ function parseAnthropicSessionModelUsage(usage) {
13116
+ const finalized = finalizeAnthropicTokens({
13117
+ completion_tokens: usage.output_tokens,
13118
+ prompt_cache_creation_tokens: usage.cache_creation_input_tokens,
13119
+ prompt_cached_tokens: usage.cache_read_input_tokens,
13120
+ prompt_tokens: usage.input_tokens
13121
+ });
13122
+ return Object.fromEntries(
13123
+ Object.entries(finalized).filter(
13124
+ (entry) => entry[1] !== void 0
13125
+ )
13126
+ );
13127
+ }
13128
+ function finalizeAnthropicSessionTurn(state, error) {
13129
+ const turn = state.activeTurn;
13130
+ if (!turn) {
13131
+ return;
13132
+ }
13133
+ state.activeTurn = void 0;
13134
+ finalizeAnthropicSessionModelState(state, turn);
13135
+ for (const tool of turn.activeTools.values()) {
13136
+ finalizeAnthropicSessionToolState(tool);
13137
+ }
13138
+ turn.activeTools.clear();
13139
+ safeAnthropicSessionLog(turn.span, {
13140
+ ...error !== void 0 ? { error: error instanceof Error ? error : toLoggedError(error) } : {},
13141
+ ...turn.input.length > 0 ? { input: turn.input } : {},
13142
+ ...turn.lastOutput ? { output: turn.lastOutput } : {},
13143
+ ...Object.keys(turn.metrics).length > 0 ? { metrics: turn.metrics } : {}
13144
+ });
13145
+ turn.span.end();
13146
+ }
13147
+ function safeAnthropicSessionLog(span, event) {
13148
+ try {
13149
+ span.log(event);
13150
+ } catch (error) {
13151
+ debugLogger.debug("Error logging Anthropic Sessions span:", error);
13152
+ }
13153
+ }
12387
13154
  function parseMetricsFromUsage2(usage) {
12388
13155
  if (!usage) {
12389
13156
  return {};
@@ -12399,6 +13166,18 @@ function parseMetricsFromUsage2(usage) {
12399
13166
  saveIfExistsTo("output_tokens", "completion_tokens");
12400
13167
  saveIfExistsTo("cache_read_input_tokens", "prompt_cached_tokens");
12401
13168
  saveIfExistsTo("cache_creation_input_tokens", "prompt_cache_creation_tokens");
13169
+ if (isObject(usage.cache_creation)) {
13170
+ const cacheCreation = usage.cache_creation;
13171
+ for (const [source, target] of [
13172
+ ["ephemeral_5m_input_tokens", "prompt_cache_creation_5m_tokens"],
13173
+ ["ephemeral_1h_input_tokens", "prompt_cache_creation_1h_tokens"]
13174
+ ]) {
13175
+ const value = cacheCreation[source];
13176
+ if (typeof value === "number") {
13177
+ metrics[target] = value;
13178
+ }
13179
+ }
13180
+ }
12402
13181
  if (isObject(usage.server_tool_use)) {
12403
13182
  for (const [name, value] of Object.entries(usage.server_tool_use)) {
12404
13183
  if (typeof value === "number") {
@@ -14257,6 +15036,29 @@ var harnessAgentChannels = defineChannels(
14257
15036
  { instrumentationName: INSTRUMENTATION_NAMES.AI_SDK }
14258
15037
  );
14259
15038
 
15039
+ // src/instrumentation/plugins/cloudflare-think-context.ts
15040
+ var cloudflareThinkSpans = /* @__PURE__ */ new Map();
15041
+ function registerCloudflareThinkSpan(span) {
15042
+ if (span.spanId) {
15043
+ cloudflareThinkSpans.set(span.spanId, span);
15044
+ }
15045
+ }
15046
+ function unregisterCloudflareThinkSpan(span) {
15047
+ if (span.spanId) {
15048
+ cloudflareThinkSpans.delete(span.spanId);
15049
+ }
15050
+ }
15051
+ function currentCloudflareThinkSpan() {
15052
+ const parentSpanIds = _internalGetGlobalState()?.contextManager.getParentSpanIds()?.spanParents ?? [];
15053
+ for (const parentSpanId of parentSpanIds) {
15054
+ const span = cloudflareThinkSpans.get(parentSpanId);
15055
+ if (span) {
15056
+ return span;
15057
+ }
15058
+ }
15059
+ return void 0;
15060
+ }
15061
+
14260
15062
  // src/instrumentation/plugins/ai-sdk-plugin.ts
14261
15063
  var DEFAULT_DENY_OUTPUT_PATHS = [
14262
15064
  // v3
@@ -14363,6 +15165,7 @@ var AISDKPlugin = class extends BasePlugin {
14363
15165
  traceStreamingChannel(aiSDKChannels.streamText, {
14364
15166
  name: "streamText",
14365
15167
  type: "function" /* FUNCTION */,
15168
+ shouldTrace: () => currentCloudflareThinkSpan() === void 0,
14366
15169
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
14367
15170
  extractOutput: (result, endEvent) => processAISDKOutput(
14368
15171
  result,
@@ -14383,6 +15186,7 @@ var AISDKPlugin = class extends BasePlugin {
14383
15186
  traceSyncStreamChannel(aiSDKChannels.streamTextSync, {
14384
15187
  name: "streamText",
14385
15188
  type: "function" /* FUNCTION */,
15189
+ shouldTrace: () => currentCloudflareThinkSpan() === void 0,
14386
15190
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
14387
15191
  patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
14388
15192
  defaultDenyOutputPaths: denyOutputPaths,
@@ -15368,6 +16172,23 @@ function prepareAISDKWorkflowAgentStreamInput(params, event, span, defaultDenyOu
15368
16172
  metadata
15369
16173
  };
15370
16174
  }
16175
+ function prepareAISDKAgentCallInput(params, event, span, defaultDenyOutputPaths = DEFAULT_DENY_OUTPUT_PATHS) {
16176
+ const { input } = processAISDKWorkflowAgentCallInput(params);
16177
+ const metadata = extractMetadataFromCallParams(params, event.self);
16178
+ const childTracing = prepareAISDKChildTracing(
16179
+ params,
16180
+ event.self,
16181
+ span,
16182
+ defaultDenyOutputPaths,
16183
+ event.aiSDK,
16184
+ { agentOwner: true }
16185
+ );
16186
+ event.modelWrapped = childTracing.modelWrapped;
16187
+ if (childTracing.cleanup) {
16188
+ event.__braintrust_ai_sdk_cleanup = childTracing.cleanup;
16189
+ }
16190
+ return { input, metadata };
16191
+ }
15371
16192
  function prepareAISDKEmbedInput(params, self) {
15372
16193
  return {
15373
16194
  input: { ...params },
@@ -15391,6 +16212,18 @@ function extractTopLevelAISDKMetrics(result, event, startTime) {
15391
16212
  }
15392
16213
  return metrics;
15393
16214
  }
16215
+ async function extractResolvedAISDKTokenMetrics(result) {
16216
+ for (const field of ["totalUsage", "usage"]) {
16217
+ try {
16218
+ const usage = await Promise.resolve(result[field]);
16219
+ if (usage !== void 0) {
16220
+ return extractTokenMetrics({ [field]: usage });
16221
+ }
16222
+ } catch {
16223
+ }
16224
+ }
16225
+ return extractTokenMetrics(result);
16226
+ }
15394
16227
  function hasModelChildTracing(event) {
15395
16228
  return event?.modelWrapped === true || event?.__braintrust_ai_sdk_model_wrapped === true;
15396
16229
  }
@@ -16208,13 +17041,15 @@ function patchAISDKStreamingResult(args) {
16208
17041
  const {
16209
17042
  defaultDenyOutputPaths,
16210
17043
  endEvent,
17044
+ forceTopLevelMetrics,
16211
17045
  onComplete,
16212
17046
  onCancel,
16213
17047
  onError,
16214
17048
  result,
16215
17049
  resolvePromiseUsage,
16216
17050
  span,
16217
- startTime
17051
+ startTime,
17052
+ transformOutput
16218
17053
  } = args;
16219
17054
  if (!result || typeof result !== "object") {
16220
17055
  return false;
@@ -16267,8 +17102,8 @@ function patchAISDKStreamingResult(args) {
16267
17102
  }
16268
17103
  outputLogged = true;
16269
17104
  try {
16270
- const metrics = extractTopLevelAISDKMetrics(result, endEvent);
16271
- if (resolvePromiseUsage) {
17105
+ const metrics = forceTopLevelMetrics ? await extractResolvedAISDKTokenMetrics(result) : extractTopLevelAISDKMetrics(result, endEvent);
17106
+ if (resolvePromiseUsage && !forceTopLevelMetrics) {
16272
17107
  try {
16273
17108
  const resultRecord2 = result;
16274
17109
  const pendingUsage = resultRecord2.totalUsage ?? resultRecord2.usage;
@@ -16287,10 +17122,11 @@ function patchAISDKStreamingResult(args) {
16287
17122
  if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
16288
17123
  metrics.time_to_first_token = firstChunkTime - startTime;
16289
17124
  }
16290
- const output = await processAISDKStreamingOutput(
17125
+ const processedOutput = await processAISDKStreamingOutput(
16291
17126
  result,
16292
17127
  resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
16293
17128
  );
17129
+ const output = transformOutput ? transformOutput(processedOutput) : processedOutput;
16294
17130
  const metadata = buildResolvedMetadataPayload(result).metadata;
16295
17131
  try {
16296
17132
  span.log({
@@ -17640,37 +18476,97 @@ function seedTaskToolUseIdMapping(taskIdToToolUseId, message) {
17640
18476
  taskIdToToolUseId.set(message.task_id, message.tool_use_id);
17641
18477
  }
17642
18478
  }
17643
- function extractUsageFromMessage(message) {
17644
- const metrics = {};
17645
- let usage;
17646
- if (message.type === "assistant") {
17647
- usage = message.message?.usage;
17648
- } else if (message.type === "result") {
17649
- usage = message.usage;
17650
- }
18479
+ function tokenCount(value) {
18480
+ return typeof value === "number" && Number.isFinite(value) && Number.isInteger(value) && value >= 0 ? value : void 0;
18481
+ }
18482
+ function copyUsage(usage) {
17651
18483
  if (!usage || typeof usage !== "object") {
17652
- return metrics;
18484
+ return void 0;
18485
+ }
18486
+ const copy = {};
18487
+ for (const key of [
18488
+ "input_tokens",
18489
+ "output_tokens",
18490
+ "cache_read_input_tokens",
18491
+ "cache_creation_input_tokens"
18492
+ ]) {
18493
+ const value = tokenCount(Reflect.get(usage, key));
18494
+ if (value !== void 0) {
18495
+ copy[key] = value;
18496
+ }
18497
+ }
18498
+ const cacheCreation = Reflect.get(usage, "cache_creation");
18499
+ if (cacheCreation && typeof cacheCreation === "object") {
18500
+ const cacheCreationCopy = {};
18501
+ for (const key of [
18502
+ "ephemeral_5m_input_tokens",
18503
+ "ephemeral_1h_input_tokens"
18504
+ ]) {
18505
+ const value = tokenCount(Reflect.get(cacheCreation, key));
18506
+ if (value !== void 0) {
18507
+ cacheCreationCopy[key] = value;
18508
+ }
18509
+ }
18510
+ if (Object.keys(cacheCreationCopy).length > 0) {
18511
+ copy.cache_creation = cacheCreationCopy;
18512
+ }
18513
+ }
18514
+ return Object.keys(copy).length > 0 ? copy : void 0;
18515
+ }
18516
+ function mergeUsage(base, override) {
18517
+ if (!base || !override) {
18518
+ return override ?? base;
18519
+ }
18520
+ const cacheCreation = base.cache_creation || override.cache_creation ? { ...base.cache_creation, ...override.cache_creation } : void 0;
18521
+ return {
18522
+ ...base,
18523
+ ...override,
18524
+ ...cacheCreation && { cache_creation: cacheCreation }
18525
+ };
18526
+ }
18527
+ function extractUsage(usage, includeOutput) {
18528
+ const metrics = {};
18529
+ if (!usage) {
18530
+ return {};
17653
18531
  }
17654
18532
  const inputTokens = getNumberProperty(usage, "input_tokens");
17655
18533
  if (inputTokens !== void 0) {
17656
18534
  metrics.prompt_tokens = inputTokens;
17657
18535
  }
17658
- const outputTokens = getNumberProperty(usage, "output_tokens");
17659
- if (outputTokens !== void 0) {
17660
- metrics.completion_tokens = outputTokens;
18536
+ if (includeOutput) {
18537
+ const outputTokens = getNumberProperty(usage, "output_tokens");
18538
+ if (outputTokens !== void 0) {
18539
+ metrics.completion_tokens = outputTokens;
18540
+ }
17661
18541
  }
17662
18542
  const cacheReadTokens = getNumberProperty(usage, "cache_read_input_tokens") || 0;
17663
18543
  const cacheCreationTokens = getNumberProperty(usage, "cache_creation_input_tokens") || 0;
17664
- if (cacheReadTokens > 0 || cacheCreationTokens > 0) {
17665
- Object.assign(
17666
- metrics,
17667
- extractAnthropicCacheTokens(cacheReadTokens, cacheCreationTokens)
17668
- );
18544
+ Object.assign(
18545
+ metrics,
18546
+ extractAnthropicCacheTokens(cacheReadTokens, cacheCreationTokens)
18547
+ );
18548
+ const cacheCreation5mTokens = getNumberProperty(
18549
+ usage.cache_creation,
18550
+ "ephemeral_5m_input_tokens"
18551
+ );
18552
+ const cacheCreation1hTokens = getNumberProperty(
18553
+ usage.cache_creation,
18554
+ "ephemeral_1h_input_tokens"
18555
+ );
18556
+ if (cacheCreation5mTokens !== void 0) {
18557
+ metrics.prompt_cache_creation_5m_tokens = cacheCreation5mTokens;
17669
18558
  }
17670
- if (Object.keys(metrics).length > 0) {
17671
- Object.assign(metrics, finalizeAnthropicTokens(metrics));
18559
+ if (cacheCreation1hTokens !== void 0) {
18560
+ metrics.prompt_cache_creation_1h_tokens = cacheCreation1hTokens;
17672
18561
  }
17673
- return metrics;
18562
+ if (Object.keys(metrics).length === 0) {
18563
+ return {};
18564
+ }
18565
+ const finalized = finalizeAnthropicTokens(metrics);
18566
+ if (metrics.completion_tokens === void 0) {
18567
+ delete finalized.tokens;
18568
+ }
18569
+ return toNumericMetrics(finalized);
17674
18570
  }
17675
18571
  function buildLLMInput(promptMessages, conversationHistory) {
17676
18572
  const inputParts = [...promptMessages, ...conversationHistory];
@@ -17704,16 +18600,16 @@ function buildRootPromptMessages(prompt, capturedPromptMessages) {
17704
18600
  function formatCapturedMessages(messages) {
17705
18601
  return messages.length > 0 ? messages : [];
17706
18602
  }
17707
- async function createLLMSpanForMessages(messages, promptMessages, conversationHistory, options, startTime, parentSpan, existingSpan) {
18603
+ async function createLLMSpanForMessages(messages, promptMessages, conversationHistory, options, startTime, parentSpan, usage, hasFinalOutputUsage, existingSpan) {
17708
18604
  if (messages.length === 0) {
17709
18605
  return void 0;
17710
18606
  }
17711
18607
  const lastMessage = messages[messages.length - 1];
17712
- if (lastMessage.type !== "assistant" || !lastMessage.message?.usage) {
18608
+ if (lastMessage.type !== "assistant") {
17713
18609
  return void 0;
17714
18610
  }
17715
- const model = lastMessage.message.model || options.model;
17716
- const usage = extractUsageFromMessage(lastMessage);
18611
+ const model = lastMessage.message?.model || options.model;
18612
+ const metrics = options.includePartialMessages ? extractUsage(usage, hasFinalOutputUsage) : {};
17717
18613
  const input = buildLLMInput(promptMessages, conversationHistory);
17718
18614
  const outputs = messages.map(
17719
18615
  (m) => m.message?.content && m.message?.role ? { content: m.message.content, role: m.message.role } : void 0
@@ -17735,8 +18631,8 @@ async function createLLMSpanForMessages(messages, promptMessages, conversationHi
17735
18631
  );
17736
18632
  span.log({
17737
18633
  input,
17738
- metadata: model ? { model } : void 0,
17739
- metrics: usage,
18634
+ metadata: { ...model && { model }, provider: "anthropic" },
18635
+ ...Object.keys(metrics).length > 0 ? { metrics } : {},
17740
18636
  output: outputs
17741
18637
  });
17742
18638
  const spanExport = await span.export();
@@ -17826,11 +18722,17 @@ function prepareLocalToolHandlersInMcpServers(mcpServers) {
17826
18722
  }
17827
18723
  return { hasLocalToolHandlers, localToolHookNames };
17828
18724
  }
17829
- function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers, localToolHookNames, skipLocalToolHooks, subAgentDetailsByToolUseId, subAgentSpans, endedSubAgentSpans) {
18725
+ function createToolTracingHooks(resolveParentSpan, taskIdToToolUseId, toolUseToParent, activeToolSpans, mcpServers, localToolHookNames, skipLocalToolHooks, subAgentDetailsByToolUseId, subAgentSpans, endedSubAgentSpans) {
17830
18726
  const preToolUse = async (input, toolUseID) => {
17831
18727
  if (input.hook_event_name !== "PreToolUse" || !toolUseID) {
17832
18728
  return {};
17833
18729
  }
18730
+ if (!toolUseToParent.has(toolUseID) && input.agent_id) {
18731
+ const parentToolUseId = taskIdToToolUseId.get(input.agent_id);
18732
+ if (parentToolUseId) {
18733
+ toolUseToParent.set(toolUseID, parentToolUseId);
18734
+ }
18735
+ }
17834
18736
  if (skipLocalToolHooks && (isLocalToolUse(input.tool_name, mcpServers) || localToolHookNames.has(input.tool_name))) {
17835
18737
  return {};
17836
18738
  }
@@ -18026,9 +18928,6 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
18026
18928
  }
18027
18929
  const metadata = {
18028
18930
  ...subAgentDetailsToMetadata(details),
18029
- ...input.agent_transcript_path && {
18030
- "claude_agent_sdk.agent_transcript_path": input.agent_transcript_path
18031
- },
18032
18931
  "claude_agent_sdk.stop_hook_active": input.stop_hook_active
18033
18932
  };
18034
18933
  try {
@@ -18050,7 +18949,7 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
18050
18949
  subagentStop
18051
18950
  };
18052
18951
  }
18053
- function injectTracingHooks(options, resolveParentSpan, activeToolSpans, localToolHookNames, skipLocalToolHooks, subAgentDetailsByToolUseId, subAgentSpans, endedSubAgentSpans) {
18952
+ function injectTracingHooks(options, resolveParentSpan, taskIdToToolUseId, toolUseToParent, activeToolSpans, localToolHookNames, skipLocalToolHooks, subAgentDetailsByToolUseId, subAgentSpans, endedSubAgentSpans) {
18054
18953
  const {
18055
18954
  preToolUse,
18056
18955
  postToolUse,
@@ -18059,6 +18958,8 @@ function injectTracingHooks(options, resolveParentSpan, activeToolSpans, localTo
18059
18958
  subagentStop
18060
18959
  } = createToolTracingHooks(
18061
18960
  resolveParentSpan,
18961
+ taskIdToToolUseId,
18962
+ toolUseToParent,
18062
18963
  activeToolSpans,
18063
18964
  options.mcpServers,
18064
18965
  localToolHookNames,
@@ -18140,6 +19041,13 @@ async function finalizeCurrentMessageGroup(state) {
18140
19041
  }
18141
19042
  }
18142
19043
  const existingLlmSpan = state.activeLlmSpansByParentToolUse.get(parentKey);
19044
+ const lastMessage = state.currentMessages[state.currentMessages.length - 1];
19045
+ const messageId = lastMessage?.message?.id;
19046
+ const usage = state.options.includePartialMessages ? mergeUsage(
19047
+ copyUsage(lastMessage?.message?.usage),
19048
+ messageId ? state.usageByMessageId.get(messageId) : void 0
19049
+ ) : void 0;
19050
+ const hasFinalOutputUsage = messageId !== void 0 && state.finalOutputUsageMessageIds.has(messageId);
18143
19051
  const llmSpanResult = await createLLMSpanForMessages(
18144
19052
  state.currentMessages,
18145
19053
  promptMessages,
@@ -18147,6 +19055,8 @@ async function finalizeCurrentMessageGroup(state) {
18147
19055
  state.options,
18148
19056
  state.currentMessageStartTime,
18149
19057
  parentSpan,
19058
+ usage,
19059
+ hasFinalOutputUsage,
18150
19060
  existingLlmSpan
18151
19061
  );
18152
19062
  if (llmSpanResult) {
@@ -18164,9 +19074,17 @@ async function finalizeCurrentMessageGroup(state) {
18164
19074
  }
18165
19075
  }
18166
19076
  state.activeLlmSpansByParentToolUse.delete(parentKey);
18167
- const lastMessage = state.currentMessages[state.currentMessages.length - 1];
18168
- if (lastMessage?.message?.usage) {
18169
- state.accumulatedOutputTokens += getNumberProperty(lastMessage.message.usage, "output_tokens") || 0;
19077
+ if (messageId) {
19078
+ state.usageByMessageId.delete(messageId);
19079
+ state.finalOutputUsageMessageIds.delete(messageId);
19080
+ for (const [
19081
+ parent,
19082
+ activeMessageId
19083
+ ] of state.activePartialMessageIdByParentKey) {
19084
+ if (activeMessageId === messageId) {
19085
+ state.activePartialMessageIdByParentKey.delete(parent);
19086
+ }
19087
+ }
18170
19088
  }
18171
19089
  state.currentMessages.length = 0;
18172
19090
  }
@@ -18257,6 +19175,10 @@ async function ensureActiveLlmSpanForParentToolUse(rootSpan, activeLlmSpansByPar
18257
19175
  );
18258
19176
  llmParentSpan = await subAgentSpan.export();
18259
19177
  }
19178
+ const racedLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
19179
+ if (racedLlmSpan) {
19180
+ return racedLlmSpan;
19181
+ }
18260
19182
  const llmSpan = startSpan(
18261
19183
  withSpanInstrumentationName(
18262
19184
  {
@@ -18376,7 +19298,49 @@ async function maybeHandleTaskLifecycleMessage(state, message) {
18376
19298
  }
18377
19299
  return true;
18378
19300
  }
19301
+ function handlePartialUsageMessage(state, message) {
19302
+ if (message.type !== "stream_event") {
19303
+ return false;
19304
+ }
19305
+ const event = message.event;
19306
+ if (!event || typeof event !== "object") {
19307
+ return true;
19308
+ }
19309
+ const parentKey = llmParentKey(message.parent_tool_use_id ?? null);
19310
+ if (event.type === "message_start") {
19311
+ const messageId2 = event.message?.id;
19312
+ const usage = copyUsage(event.message?.usage);
19313
+ if (messageId2) {
19314
+ state.activePartialMessageIdByParentKey.set(parentKey, messageId2);
19315
+ if (usage) {
19316
+ state.usageByMessageId.set(messageId2, usage);
19317
+ }
19318
+ }
19319
+ return true;
19320
+ }
19321
+ const messageId = state.activePartialMessageIdByParentKey.get(parentKey);
19322
+ if (!messageId) {
19323
+ return true;
19324
+ }
19325
+ if (event.type === "message_delta") {
19326
+ const update = copyUsage(event.usage);
19327
+ if (update) {
19328
+ const usage = state.usageByMessageId.get(messageId) ?? {};
19329
+ Object.assign(usage, update);
19330
+ state.usageByMessageId.set(messageId, usage);
19331
+ if (update.output_tokens !== void 0) {
19332
+ state.finalOutputUsageMessageIds.add(messageId);
19333
+ }
19334
+ }
19335
+ } else if (event.type === "message_stop") {
19336
+ state.activePartialMessageIdByParentKey.delete(parentKey);
19337
+ }
19338
+ return true;
19339
+ }
18379
19340
  async function handleStreamMessage(state, message) {
19341
+ if (handlePartialUsageMessage(state, message)) {
19342
+ return;
19343
+ }
18380
19344
  maybeTrackToolUseContext(state, message);
18381
19345
  if (await maybeHandleTaskLifecycleMessage(state, message)) {
18382
19346
  return;
@@ -18423,36 +19387,9 @@ async function handleStreamMessage(state, message) {
18423
19387
  );
18424
19388
  state.currentMessages.push(message);
18425
19389
  }
18426
- if (message.type !== "result" || !message.usage) {
19390
+ if (message.type !== "result") {
18427
19391
  return;
18428
19392
  }
18429
- const finalUsageMetrics = extractUsageFromMessage(message);
18430
- if (state.currentMessages.length > 0 && finalUsageMetrics.completion_tokens !== void 0) {
18431
- const lastMessage = state.currentMessages[state.currentMessages.length - 1];
18432
- if (lastMessage?.message?.usage) {
18433
- const adjustedTokens = finalUsageMetrics.completion_tokens - state.accumulatedOutputTokens;
18434
- if (adjustedTokens >= 0) {
18435
- lastMessage.message.usage.output_tokens = adjustedTokens;
18436
- }
18437
- const resultUsage = message.usage;
18438
- if (resultUsage && typeof resultUsage === "object") {
18439
- const cacheReadTokens = getNumberProperty(
18440
- resultUsage,
18441
- "cache_read_input_tokens"
18442
- );
18443
- if (cacheReadTokens !== void 0) {
18444
- lastMessage.message.usage.cache_read_input_tokens = cacheReadTokens;
18445
- }
18446
- const cacheCreationTokens = getNumberProperty(
18447
- resultUsage,
18448
- "cache_creation_input_tokens"
18449
- );
18450
- if (cacheCreationTokens !== void 0) {
18451
- lastMessage.message.usage.cache_creation_input_tokens = cacheCreationTokens;
18452
- }
18453
- }
18454
- }
18455
- }
18456
19393
  const metadata = {};
18457
19394
  if (message.num_turns !== void 0) {
18458
19395
  metadata.num_turns = message.num_turns;
@@ -18460,8 +19397,12 @@ async function handleStreamMessage(state, message) {
18460
19397
  if (message.session_id !== void 0) {
18461
19398
  metadata.session_id = message.session_id;
18462
19399
  }
18463
- if (Object.keys(metadata).length > 0) {
18464
- state.span.log({ metadata });
19400
+ const metrics = state.options.includePartialMessages ? {} : extractUsage(copyUsage(message.usage), true);
19401
+ if (Object.keys(metadata).length > 0 || Object.keys(metrics).length > 0) {
19402
+ state.span.log({
19403
+ ...Object.keys(metadata).length > 0 ? { metadata } : {},
19404
+ ...Object.keys(metrics).length > 0 ? { metrics } : {}
19405
+ });
18465
19406
  }
18466
19407
  }
18467
19408
  async function finalizeQuerySpan(state) {
@@ -18485,6 +19426,9 @@ async function finalizeQuerySpan(state) {
18485
19426
  llmSpan.end();
18486
19427
  }
18487
19428
  state.activeLlmSpansByParentToolUse.clear();
19429
+ state.activePartialMessageIdByParentKey.clear();
19430
+ state.finalOutputUsageMessageIds.clear();
19431
+ state.usageByMessageId.clear();
18488
19432
  for (const toolSpan of state.activeToolSpans.values()) {
18489
19433
  toolSpan.end();
18490
19434
  }
@@ -18609,6 +19553,8 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
18609
19553
  const optionsWithHooks = injectTracingHooks(
18610
19554
  options,
18611
19555
  resolveToolUseParentSpan,
19556
+ taskIdToToolUseId,
19557
+ toolUseToParent,
18612
19558
  activeToolSpans,
18613
19559
  localToolHookNames,
18614
19560
  skipLocalToolHooks,
@@ -18619,8 +19565,8 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
18619
19565
  params.options = optionsWithHooks;
18620
19566
  event.arguments[0] = params;
18621
19567
  spans.set(event, {
18622
- accumulatedOutputTokens: 0,
18623
19568
  activeLlmSpansByParentToolUse,
19569
+ activePartialMessageIdByParentKey: /* @__PURE__ */ new Map(),
18624
19570
  activeToolSpans,
18625
19571
  conversationHistoryByParentKey,
18626
19572
  capturedPromptMessages,
@@ -18628,6 +19574,7 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
18628
19574
  currentMessageStartTime: startTime,
18629
19575
  currentMessages: [],
18630
19576
  endedSubAgentSpans,
19577
+ finalOutputUsageMessageIds: /* @__PURE__ */ new Set(),
18631
19578
  finalResults: [],
18632
19579
  options: optionsWithHooks,
18633
19580
  originalPrompt,
@@ -18643,6 +19590,7 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
18643
19590
  latestLlmParentBySubAgentToolUse,
18644
19591
  latestRootLlmParentRef,
18645
19592
  toolUseToParent,
19593
+ usageByMessageId: /* @__PURE__ */ new Map(),
18646
19594
  localToolContext
18647
19595
  });
18648
19596
  },
@@ -18712,6 +19660,295 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
18712
19660
  }
18713
19661
  };
18714
19662
 
19663
+ // src/instrumentation/plugins/cloudflare-think-channels.ts
19664
+ var cloudflareThinkChannels = defineChannels(
19665
+ "@cloudflare/think",
19666
+ {
19667
+ runInferenceLoop: channel({
19668
+ channelName: "Think.runInferenceLoop",
19669
+ kind: "async"
19670
+ })
19671
+ },
19672
+ { instrumentationName: INSTRUMENTATION_NAMES.CLOUDFLARE_THINK }
19673
+ );
19674
+
19675
+ // src/instrumentation/plugins/cloudflare-think-plugin.ts
19676
+ var THINK_STATE_ID = /* @__PURE__ */ Symbol.for("braintrust.cloudflare-think.state-id");
19677
+ var CloudflareThinkPlugin = class extends BasePlugin {
19678
+ statesBySpanId = /* @__PURE__ */ new Map();
19679
+ onEnable() {
19680
+ this.subscribeToThinkRuns();
19681
+ this.subscribeToAISDKStreamTextSync();
19682
+ this.subscribeToAISDKStreamTextAsync();
19683
+ }
19684
+ onDisable() {
19685
+ for (const unsubscribe of this.unsubscribers) {
19686
+ unsubscribe();
19687
+ }
19688
+ this.unsubscribers = [];
19689
+ for (const state of this.statesBySpanId.values()) {
19690
+ this.finishState(state);
19691
+ }
19692
+ this.statesBySpanId.clear();
19693
+ }
19694
+ subscribeToThinkRuns() {
19695
+ const channel2 = cloudflareThinkChannels.runInferenceLoop.tracingChannel();
19696
+ const states = /* @__PURE__ */ new WeakMap();
19697
+ const state = _internalGetGlobalState();
19698
+ const contextManager = state?.contextManager;
19699
+ const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
19700
+ const ensureState2 = (event) => {
19701
+ if (isAutoInstrumentationSuppressed()) {
19702
+ return void 0;
19703
+ }
19704
+ const existing = states.get(event);
19705
+ if (existing) {
19706
+ return existing;
19707
+ }
19708
+ const span = startSpan(
19709
+ withSpanInstrumentationName(
19710
+ {
19711
+ name: "Think.runTurn",
19712
+ spanAttributes: { type: "task" /* TASK */ }
19713
+ },
19714
+ INSTRUMENTATION_NAMES.CLOUDFLARE_THINK
19715
+ )
19716
+ );
19717
+ const runState = {
19718
+ aiResultPatched: false,
19719
+ fallbackInput: extractFallbackInput(event.self?.messages),
19720
+ finalized: false,
19721
+ inputLogged: false,
19722
+ span,
19723
+ startTime: getCurrentUnixTimestamp()
19724
+ };
19725
+ const metadata = {
19726
+ braintrust: {
19727
+ integration_name: "cloudflare-think",
19728
+ sdk_language: "typescript"
19729
+ }
19730
+ };
19731
+ if (typeof event.moduleVersion === "string") {
19732
+ metadata["cloudflare_think.version"] = event.moduleVersion;
19733
+ }
19734
+ span.log({ metadata });
19735
+ states.set(event, runState);
19736
+ if (span.spanId) {
19737
+ this.statesBySpanId.set(span.spanId, runState);
19738
+ }
19739
+ registerCloudflareThinkSpan(span);
19740
+ return runState;
19741
+ };
19742
+ if (contextManager && currentSpanStore && channel2.start) {
19743
+ channel2.start.bindStore(currentSpanStore, (event) => {
19744
+ const runState = ensureState2(event);
19745
+ return runState ? contextManager.wrapSpanForStore(runState.span) : currentSpanStore.getStore();
19746
+ });
19747
+ this.unsubscribers.push(
19748
+ () => channel2.start?.unbindStore(currentSpanStore)
19749
+ );
19750
+ }
19751
+ const handlers = {
19752
+ start: (event) => {
19753
+ ensureState2(event);
19754
+ },
19755
+ asyncEnd: (event) => {
19756
+ const runState = states.get(event);
19757
+ states.delete(event);
19758
+ if (!runState || runState.finalized || runState.aiResultPatched) {
19759
+ return;
19760
+ }
19761
+ this.finishState(runState, void 0, event.result);
19762
+ },
19763
+ error: (event) => {
19764
+ const runState = states.get(event);
19765
+ states.delete(event);
19766
+ if (runState) {
19767
+ this.finishState(runState, event.error);
19768
+ }
19769
+ }
19770
+ };
19771
+ channel2.subscribe(handlers);
19772
+ this.unsubscribers.push(() => channel2.unsubscribe(handlers));
19773
+ }
19774
+ subscribeToAISDKStreamTextSync() {
19775
+ const channel2 = aiSDKChannels.streamTextSync.tracingChannel();
19776
+ const handlers = {
19777
+ start: (event) => {
19778
+ this.startAISDKStream(event);
19779
+ },
19780
+ end: (event) => {
19781
+ this.endAISDKStream(event);
19782
+ },
19783
+ error: (event) => {
19784
+ this.errorAISDKStream(event);
19785
+ }
19786
+ };
19787
+ channel2.subscribe(handlers);
19788
+ this.unsubscribers.push(() => channel2.unsubscribe(handlers));
19789
+ }
19790
+ subscribeToAISDKStreamTextAsync() {
19791
+ const channel2 = aiSDKChannels.streamText.tracingChannel();
19792
+ const handlers = {
19793
+ start: (event) => {
19794
+ this.startAISDKStream(event);
19795
+ },
19796
+ asyncEnd: (event) => {
19797
+ this.endAISDKStream(event);
19798
+ },
19799
+ error: (event) => {
19800
+ this.errorAISDKStream(event);
19801
+ }
19802
+ };
19803
+ channel2.subscribe(handlers);
19804
+ this.unsubscribers.push(() => channel2.unsubscribe(handlers));
19805
+ }
19806
+ startAISDKStream(event) {
19807
+ const runState = this.currentState();
19808
+ if (!runState || runState.finalized) {
19809
+ return;
19810
+ }
19811
+ try {
19812
+ const prepared = prepareAISDKAgentCallInput(
19813
+ event.arguments[0],
19814
+ event,
19815
+ runState.span
19816
+ );
19817
+ runState.span.log({
19818
+ input: extractThinkTaskInput(prepared.input),
19819
+ metadata: {
19820
+ ...prepared.metadata,
19821
+ braintrust: {
19822
+ integration_name: "cloudflare-think",
19823
+ sdk_language: "typescript"
19824
+ }
19825
+ }
19826
+ });
19827
+ runState.inputLogged = true;
19828
+ runState.aiEvent = event;
19829
+ Reflect.set(event, THINK_STATE_ID, runState.span.spanId);
19830
+ } catch (error) {
19831
+ debugLogger.error(
19832
+ "Error preparing @cloudflare/think AI SDK tracing:",
19833
+ error
19834
+ );
19835
+ }
19836
+ }
19837
+ endAISDKStream(event) {
19838
+ const runState = this.stateForAISDKEvent(event);
19839
+ if (!runState || runState.finalized) {
19840
+ return;
19841
+ }
19842
+ const patched = patchAISDKStreamingResult({
19843
+ defaultDenyOutputPaths: DEFAULT_DENY_OUTPUT_PATHS,
19844
+ endEvent: event,
19845
+ forceTopLevelMetrics: true,
19846
+ onComplete: () => this.releaseState(runState),
19847
+ result: event.result,
19848
+ span: runState.span,
19849
+ startTime: runState.startTime,
19850
+ transformOutput: extractThinkTaskOutput
19851
+ });
19852
+ runState.aiResultPatched = patched;
19853
+ if (!patched) {
19854
+ this.finishState(runState, void 0, event.result);
19855
+ }
19856
+ }
19857
+ errorAISDKStream(event) {
19858
+ const runState = this.stateForAISDKEvent(event);
19859
+ if (runState) {
19860
+ this.finishState(runState, event.error);
19861
+ }
19862
+ }
19863
+ currentState() {
19864
+ const parentIds = _internalGetGlobalState()?.contextManager.getParentSpanIds()?.spanParents ?? [];
19865
+ for (const parentId of parentIds) {
19866
+ const state = this.statesBySpanId.get(parentId);
19867
+ if (state) {
19868
+ return state;
19869
+ }
19870
+ }
19871
+ return void 0;
19872
+ }
19873
+ stateForAISDKEvent(event) {
19874
+ const spanId = Reflect.get(event, THINK_STATE_ID);
19875
+ return typeof spanId === "string" ? this.statesBySpanId.get(spanId) : void 0;
19876
+ }
19877
+ finishState(state, error, output) {
19878
+ if (state.finalized) {
19879
+ return;
19880
+ }
19881
+ state.finalized = true;
19882
+ try {
19883
+ if (!state.inputLogged && state.fallbackInput !== void 0) {
19884
+ state.span.log({ input: state.fallbackInput });
19885
+ }
19886
+ if (error !== void 0) {
19887
+ state.span.log({ error });
19888
+ } else if (output !== void 0) {
19889
+ state.span.log({ output: extractThinkTaskOutput(output) });
19890
+ }
19891
+ finalizeAISDKChildTracing(state.aiEvent);
19892
+ state.span.end();
19893
+ } finally {
19894
+ this.releaseState(state);
19895
+ }
19896
+ }
19897
+ releaseState(state) {
19898
+ state.finalized = true;
19899
+ unregisterCloudflareThinkSpan(state.span);
19900
+ if (state.span.spanId) {
19901
+ this.statesBySpanId.delete(state.span.spanId);
19902
+ }
19903
+ }
19904
+ };
19905
+ function extractFallbackInput(messages) {
19906
+ if (!Array.isArray(messages) || messages.length === 0) {
19907
+ return void 0;
19908
+ }
19909
+ let latestUserIndex = -1;
19910
+ for (let index = messages.length - 1; index >= 0; index--) {
19911
+ if (messages[index]?.role === "user") {
19912
+ latestUserIndex = index;
19913
+ break;
19914
+ }
19915
+ }
19916
+ const selected = latestUserIndex >= 0 ? messages.slice(latestUserIndex) : [];
19917
+ return selected.map((message) => ({
19918
+ role: message.role,
19919
+ content: message.content ?? message.parts
19920
+ }));
19921
+ }
19922
+ function extractThinkTaskOutput(output) {
19923
+ if (!isObject(output)) {
19924
+ return output;
19925
+ }
19926
+ if (typeof output.text === "string") {
19927
+ return { role: "assistant", content: output.text };
19928
+ }
19929
+ if (output.object !== void 0) {
19930
+ return output.object;
19931
+ }
19932
+ return output;
19933
+ }
19934
+ function extractThinkTaskInput(input) {
19935
+ if (!isObject(input)) {
19936
+ return input;
19937
+ }
19938
+ const system = input.instructions ?? input.system;
19939
+ if (Array.isArray(input.messages)) {
19940
+ return system === void 0 ? input.messages : [{ role: "system", content: system }, ...input.messages];
19941
+ }
19942
+ if (Array.isArray(input.prompt)) {
19943
+ return system === void 0 ? input.prompt : [{ role: "system", content: system }, ...input.prompt];
19944
+ }
19945
+ if (typeof input.prompt === "string") {
19946
+ const messages = [{ role: "user", content: input.prompt }];
19947
+ return system === void 0 ? messages : [{ role: "system", content: system }, ...messages];
19948
+ }
19949
+ return input;
19950
+ }
19951
+
18715
19952
  // src/instrumentation/plugins/cursor-sdk-channels.ts
18716
19953
  var cursorSDKChannels = defineChannels(
18717
19954
  "@cursor/sdk",
@@ -20828,9 +22065,9 @@ function extractEmbedPromptTokenCount(response) {
20828
22065
  let sawAny = false;
20829
22066
  for (const embedding of embeddings) {
20830
22067
  const embeddingStats = tryToDict(tryToDict(embedding)?.statistics);
20831
- const tokenCount = embeddingStats?.tokenCount;
20832
- if (typeof tokenCount === "number" && Number.isFinite(tokenCount)) {
20833
- total += tokenCount;
22068
+ const tokenCount2 = embeddingStats?.tokenCount;
22069
+ if (typeof tokenCount2 === "number" && Number.isFinite(tokenCount2)) {
22070
+ total += tokenCount2;
20834
22071
  sawAny = true;
20835
22072
  }
20836
22073
  }
@@ -24477,6 +25714,470 @@ function aggregateMistralStreamChunks(chunks) {
24477
25714
  };
24478
25715
  }
24479
25716
 
25717
+ // src/instrumentation/plugins/ollama-channels.ts
25718
+ var ollamaChannels = defineChannels(
25719
+ "ollama",
25720
+ {
25721
+ chat: channel({
25722
+ channelName: "chat",
25723
+ kind: "async"
25724
+ }),
25725
+ generate: channel({
25726
+ channelName: "generate",
25727
+ kind: "async"
25728
+ }),
25729
+ embed: channel({
25730
+ channelName: "embed",
25731
+ kind: "async"
25732
+ })
25733
+ },
25734
+ { instrumentationName: INSTRUMENTATION_NAMES.OLLAMA }
25735
+ );
25736
+
25737
+ // src/instrumentation/plugins/ollama-plugin.ts
25738
+ var OllamaPlugin = class extends BasePlugin {
25739
+ onEnable() {
25740
+ this.unsubscribers.push(
25741
+ traceStreamingChannel(ollamaChannels.chat, {
25742
+ name: "ollama.chat",
25743
+ type: "llm" /* LLM */,
25744
+ extractInput: extractOllamaChatInput,
25745
+ extractOutput: (result, event) => extractOllamaChatOutput(
25746
+ result,
25747
+ countOllamaToolCalls(event?.arguments?.[0]?.messages)
25748
+ ),
25749
+ extractMetadata: extractOllamaResponseMetadata,
25750
+ extractMetrics: extractOllamaMetrics,
25751
+ aggregateChunks: aggregateOllamaChatChunks
25752
+ }),
25753
+ traceStreamingChannel(ollamaChannels.generate, {
25754
+ name: "ollama.generate",
25755
+ type: "llm" /* LLM */,
25756
+ extractInput: extractOllamaGenerateInput,
25757
+ extractOutput: extractOllamaGenerateOutput,
25758
+ extractMetadata: extractOllamaResponseMetadata,
25759
+ extractMetrics: extractOllamaMetrics,
25760
+ aggregateChunks: aggregateOllamaGenerateChunks
25761
+ }),
25762
+ traceAsyncChannel(ollamaChannels.embed, {
25763
+ name: "ollama.embed",
25764
+ type: "llm" /* LLM */,
25765
+ extractInput: extractOllamaEmbedInput,
25766
+ extractOutput: extractOllamaEmbedOutput,
25767
+ extractMetadata: extractOllamaResponseMetadata,
25768
+ extractMetrics: extractOllamaMetrics
25769
+ })
25770
+ );
25771
+ }
25772
+ onDisable() {
25773
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
25774
+ }
25775
+ };
25776
+ function isNonNegativeNumber(value) {
25777
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
25778
+ }
25779
+ function normalizeFinishReason(response, hasToolCalls = false) {
25780
+ if (hasToolCalls) {
25781
+ return "tool_calls";
25782
+ }
25783
+ return response?.done_reason || "stop";
25784
+ }
25785
+ function stringifyArguments(value) {
25786
+ if (typeof value === "string") {
25787
+ return value;
25788
+ }
25789
+ try {
25790
+ return JSON.stringify(value ?? {});
25791
+ } catch {
25792
+ return String(value);
25793
+ }
25794
+ }
25795
+ function syntheticToolCallId(name, index) {
25796
+ const normalizedName = name.replace(/[^a-zA-Z0-9_-]/g, "_") || "tool";
25797
+ return `ollama_call_${normalizedName}_${index}`;
25798
+ }
25799
+ function normalizeToolCall(toolCall, index) {
25800
+ const name = toolCall.function?.name;
25801
+ if (typeof name !== "string" || name.length === 0) {
25802
+ return void 0;
25803
+ }
25804
+ return {
25805
+ id: typeof toolCall.id === "string" && toolCall.id.length > 0 ? toolCall.id : syntheticToolCallId(name, index),
25806
+ type: "function",
25807
+ function: {
25808
+ name,
25809
+ arguments: stringifyArguments(toolCall.function?.arguments)
25810
+ }
25811
+ };
25812
+ }
25813
+ function normalizeToolCalls(toolCalls, syntheticIdOffset = 0) {
25814
+ if (!Array.isArray(toolCalls)) {
25815
+ return [];
25816
+ }
25817
+ return toolCalls.flatMap((toolCall, index) => {
25818
+ const normalized = normalizeToolCall(toolCall, syntheticIdOffset + index);
25819
+ return normalized ? [normalized] : [];
25820
+ });
25821
+ }
25822
+ function countOllamaToolCalls(messages) {
25823
+ if (!Array.isArray(messages)) {
25824
+ return 0;
25825
+ }
25826
+ return messages.reduce(
25827
+ (count, message) => count + (isObject(message) && Array.isArray(message.tool_calls) ? message.tool_calls.length : 0),
25828
+ 0
25829
+ );
25830
+ }
25831
+ function imageBytes(value) {
25832
+ if (value instanceof Uint8Array) {
25833
+ return value;
25834
+ }
25835
+ if (value instanceof ArrayBuffer) {
25836
+ return new Uint8Array(value);
25837
+ }
25838
+ if (typeof value !== "string" || value.startsWith("data:")) {
25839
+ return void 0;
25840
+ }
25841
+ try {
25842
+ const decoded = atob(value.slice(0, 24));
25843
+ return Uint8Array.from(decoded, (character) => character.charCodeAt(0));
25844
+ } catch {
25845
+ return void 0;
25846
+ }
25847
+ }
25848
+ function inferImageMediaType(value) {
25849
+ if (typeof value === "string") {
25850
+ const dataUrlType = value.match(/^data:(image\/[^;]+);base64,/i)?.[1];
25851
+ if (dataUrlType) {
25852
+ return dataUrlType;
25853
+ }
25854
+ }
25855
+ const bytes = imageBytes(value);
25856
+ if (!bytes) {
25857
+ return void 0;
25858
+ }
25859
+ if (bytes[0] === 137 && bytes[1] === 80 && bytes[2] === 78 && bytes[3] === 71) {
25860
+ return "image/png";
25861
+ }
25862
+ if (bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255) {
25863
+ return "image/jpeg";
25864
+ }
25865
+ const signature = String.fromCharCode(...bytes.slice(0, 12));
25866
+ if (signature.startsWith("GIF87a") || signature.startsWith("GIF89a")) {
25867
+ return "image/gif";
25868
+ }
25869
+ if (signature.startsWith("RIFF") && signature.slice(8, 12) === "WEBP") {
25870
+ return "image/webp";
25871
+ }
25872
+ return void 0;
25873
+ }
25874
+ function normalizeTextAndImages(content, images) {
25875
+ if (!images || images.length === 0) {
25876
+ return { content };
25877
+ }
25878
+ const imageParts = [];
25879
+ const unrecognizedImages = [];
25880
+ for (const image of images) {
25881
+ let localImagePath;
25882
+ let localPathMediaType;
25883
+ if (typeof image === "string" && !/^data:/i.test(image) && !/^https?:\/\//i.test(image)) {
25884
+ const extension = image.match(/\.([a-z0-9]+)$/i)?.[1]?.toLowerCase();
25885
+ const extensionMediaType = {
25886
+ png: "image/png",
25887
+ jpg: "image/jpeg",
25888
+ jpeg: "image/jpeg",
25889
+ gif: "image/gif",
25890
+ webp: "image/webp"
25891
+ }[extension ?? ""];
25892
+ if (extensionMediaType && isomorph_default.statSync) {
25893
+ try {
25894
+ if (isomorph_default.statSync(image).isFile()) {
25895
+ localImagePath = image;
25896
+ localPathMediaType = extensionMediaType;
25897
+ }
25898
+ } catch {
25899
+ }
25900
+ }
25901
+ }
25902
+ const mediaType = localPathMediaType ?? inferImageMediaType(image);
25903
+ if (!mediaType) {
25904
+ unrecognizedImages.push(image);
25905
+ continue;
25906
+ }
25907
+ const processedImage = localImagePath ? new Attachment({
25908
+ data: localImagePath,
25909
+ filename: localImagePath.split(/[\\/]/).at(-1) ?? "image",
25910
+ contentType: mediaType
25911
+ }) : processInputAttachments({
25912
+ type: "image",
25913
+ image,
25914
+ mediaType
25915
+ }).image;
25916
+ imageParts.push({
25917
+ type: "image_url",
25918
+ image_url: { url: processedImage }
25919
+ });
25920
+ }
25921
+ return {
25922
+ content: imageParts.length > 0 ? [...content ? [{ type: "text", text: content }] : [], ...imageParts] : content,
25923
+ ...unrecognizedImages.length > 0 ? { unrecognizedImages } : {}
25924
+ };
25925
+ }
25926
+ function normalizeMessage(message, toolCallId, syntheticToolCallIdOffset = 0) {
25927
+ if (typeof message.role !== "string") {
25928
+ return void 0;
25929
+ }
25930
+ const toolCalls = normalizeToolCalls(
25931
+ message.tool_calls,
25932
+ syntheticToolCallIdOffset
25933
+ );
25934
+ if (message.role === "tool") {
25935
+ const toolName = typeof message.tool_name === "string" && message.tool_name.length > 0 ? message.tool_name : "tool";
25936
+ return {
25937
+ role: "tool",
25938
+ tool_call_id: toolCallId ?? syntheticToolCallId(toolName, 0),
25939
+ content: typeof message.content === "string" ? message.content : ""
25940
+ };
25941
+ }
25942
+ const normalizedContent = normalizeTextAndImages(
25943
+ typeof message.content === "string" ? message.content || (toolCalls.length > 0 ? null : "") : toolCalls.length > 0 ? null : "",
25944
+ message.images
25945
+ );
25946
+ return {
25947
+ role: message.role,
25948
+ content: normalizedContent.content,
25949
+ ...typeof message.thinking === "string" && message.thinking.length > 0 ? { reasoning: message.thinking } : {},
25950
+ ...toolCalls.length > 0 ? { tool_calls: toolCalls } : {},
25951
+ ...normalizedContent.unrecognizedImages ? { images: normalizedContent.unrecognizedImages } : {}
25952
+ };
25953
+ }
25954
+ function normalizeMessages(messages) {
25955
+ if (!Array.isArray(messages)) {
25956
+ return [];
25957
+ }
25958
+ const pendingToolCallIds = /* @__PURE__ */ new Map();
25959
+ let syntheticToolCallIdOffset = 0;
25960
+ return messages.flatMap((message) => {
25961
+ if (!isObject(message)) {
25962
+ return [];
25963
+ }
25964
+ const ollamaMessage = message;
25965
+ let toolCallId;
25966
+ if (ollamaMessage.role === "tool") {
25967
+ const toolName = ollamaMessage.tool_name;
25968
+ if (typeof toolName === "string") {
25969
+ toolCallId = pendingToolCallIds.get(toolName)?.shift();
25970
+ }
25971
+ }
25972
+ const normalized = normalizeMessage(
25973
+ ollamaMessage,
25974
+ toolCallId,
25975
+ syntheticToolCallIdOffset
25976
+ );
25977
+ if (Array.isArray(ollamaMessage.tool_calls)) {
25978
+ syntheticToolCallIdOffset += ollamaMessage.tool_calls.length;
25979
+ }
25980
+ if (ollamaMessage.role === "assistant" && normalized) {
25981
+ const toolCalls = Array.isArray(normalized.tool_calls) ? normalized.tool_calls : [];
25982
+ for (const toolCall of toolCalls) {
25983
+ if (!isObject(toolCall) || !isObject(toolCall.function)) {
25984
+ continue;
25985
+ }
25986
+ const name = toolCall.function.name;
25987
+ const id = toolCall.id;
25988
+ if (typeof name === "string" && typeof id === "string") {
25989
+ const ids = pendingToolCallIds.get(name) ?? [];
25990
+ ids.push(id);
25991
+ pendingToolCallIds.set(name, ids);
25992
+ }
25993
+ }
25994
+ }
25995
+ return normalized ? [normalized] : [];
25996
+ });
25997
+ }
25998
+ function normalizeToolDefinition(tool) {
25999
+ const fn = tool.function;
26000
+ if (!fn || typeof fn.name !== "string" || fn.name.length === 0) {
26001
+ return void 0;
26002
+ }
26003
+ return {
26004
+ type: "function",
26005
+ function: {
26006
+ name: fn.name,
26007
+ ...typeof fn.description === "string" ? { description: fn.description } : {},
26008
+ ...isObject(fn.parameters) ? { parameters: fn.parameters } : {}
26009
+ }
26010
+ };
26011
+ }
26012
+ function extractToolsMetadata(tools) {
26013
+ if (!Array.isArray(tools)) {
26014
+ return {};
26015
+ }
26016
+ const normalized = tools.flatMap((tool) => {
26017
+ if (!isObject(tool)) {
26018
+ return [];
26019
+ }
26020
+ const definition = normalizeToolDefinition(tool);
26021
+ return definition ? [definition] : [];
26022
+ });
26023
+ return normalized.length > 0 ? { tools: normalized } : {};
26024
+ }
26025
+ function extractOptionsMetadata(options) {
26026
+ if (!isObject(options)) {
26027
+ return {};
26028
+ }
26029
+ const metadata = {};
26030
+ const mappings = [
26031
+ ["temperature", "temperature"],
26032
+ ["top_p", "top_p"],
26033
+ ["num_predict", "max_tokens"],
26034
+ ["frequency_penalty", "frequency_penalty"],
26035
+ ["presence_penalty", "presence_penalty"],
26036
+ ["stop", "stop"]
26037
+ ];
26038
+ for (const [source, target] of mappings) {
26039
+ if (options[source] !== void 0) {
26040
+ metadata[target] = options[source];
26041
+ }
26042
+ }
26043
+ return metadata;
26044
+ }
26045
+ function extractRequestMetadata(request) {
26046
+ return {
26047
+ provider: "ollama",
26048
+ ...typeof request?.model === "string" ? { model: request.model } : {},
26049
+ ...extractOptionsMetadata(request?.options),
26050
+ ...request?.format !== void 0 ? { response_format: request.format } : {}
26051
+ };
26052
+ }
26053
+ function extractOllamaChatInput([request]) {
26054
+ return {
26055
+ input: normalizeMessages(request.messages),
26056
+ metadata: {
26057
+ ...extractRequestMetadata(request),
26058
+ ...extractToolsMetadata(request.tools)
26059
+ }
26060
+ };
26061
+ }
26062
+ function extractOllamaGenerateInput([request]) {
26063
+ const normalizedPrompt = normalizeTextAndImages(
26064
+ typeof request.prompt === "string" ? request.prompt : "",
26065
+ Array.isArray(request.images) ? request.images : void 0
26066
+ );
26067
+ const input = [
26068
+ ...typeof request.system === "string" ? [{ role: "system", content: request.system }] : [],
26069
+ {
26070
+ role: "user",
26071
+ content: normalizedPrompt.content,
26072
+ ...typeof request.suffix === "string" ? { suffix: request.suffix } : {},
26073
+ ...normalizedPrompt.unrecognizedImages ? { images: normalizedPrompt.unrecognizedImages } : {}
26074
+ }
26075
+ ];
26076
+ return {
26077
+ input,
26078
+ metadata: extractRequestMetadata(request)
26079
+ };
26080
+ }
26081
+ function extractOllamaEmbedInput([request]) {
26082
+ return {
26083
+ input: request.input,
26084
+ metadata: extractRequestMetadata(request)
26085
+ };
26086
+ }
26087
+ function extractOllamaChatOutput(result, syntheticToolCallIdOffset = 0) {
26088
+ if (!isObject(result) || !isObject(result.message)) {
26089
+ return void 0;
26090
+ }
26091
+ const message = normalizeMessage(
26092
+ result.message,
26093
+ void 0,
26094
+ syntheticToolCallIdOffset
26095
+ );
26096
+ if (!message) {
26097
+ return void 0;
26098
+ }
26099
+ const toolCalls = Array.isArray(message.tool_calls) ? message.tool_calls : [];
26100
+ return [
26101
+ {
26102
+ index: 0,
26103
+ finish_reason: normalizeFinishReason(result, toolCalls.length > 0),
26104
+ message
26105
+ }
26106
+ ];
26107
+ }
26108
+ function extractOllamaGenerateOutput(result) {
26109
+ if (!isObject(result) || typeof result.response !== "string") {
26110
+ return void 0;
26111
+ }
26112
+ return [
26113
+ {
26114
+ index: 0,
26115
+ finish_reason: normalizeFinishReason(result),
26116
+ message: {
26117
+ role: "assistant",
26118
+ content: result.response,
26119
+ ...typeof result.thinking === "string" && result.thinking.length > 0 ? { reasoning: result.thinking } : {}
26120
+ }
26121
+ }
26122
+ ];
26123
+ }
26124
+ function extractOllamaEmbedOutput(result) {
26125
+ const embedding = Array.isArray(result?.embeddings) ? result.embeddings[0] : void 0;
26126
+ return Array.isArray(embedding) ? { embedding_length: embedding.length } : void 0;
26127
+ }
26128
+ function extractOllamaResponseMetadata(result) {
26129
+ return typeof result?.model === "string" ? { model: result.model } : void 0;
26130
+ }
26131
+ function extractOllamaMetrics(result) {
26132
+ const metrics = {};
26133
+ const promptTokens = result?.prompt_eval_count;
26134
+ const completionTokens = result?.eval_count;
26135
+ if (isNonNegativeNumber(promptTokens)) {
26136
+ metrics.prompt_tokens = promptTokens;
26137
+ }
26138
+ if (isNonNegativeNumber(completionTokens)) {
26139
+ metrics.completion_tokens = completionTokens;
26140
+ }
26141
+ if (isNonNegativeNumber(promptTokens) || isNonNegativeNumber(completionTokens)) {
26142
+ metrics.tokens = (isNonNegativeNumber(promptTokens) ? promptTokens : 0) + (isNonNegativeNumber(completionTokens) ? completionTokens : 0);
26143
+ }
26144
+ return metrics;
26145
+ }
26146
+ function aggregateOllamaChatChunks(chunks, _result, event, _startTime) {
26147
+ const last = chunks.at(-1);
26148
+ const message = {
26149
+ role: "assistant",
26150
+ content: chunks.map((chunk) => chunk.message?.content ?? "").join(""),
26151
+ thinking: chunks.map((chunk) => chunk.message?.thinking ?? "").join(""),
26152
+ tool_calls: chunks.flatMap((chunk) => chunk.message?.tool_calls ?? [])
26153
+ };
26154
+ const response = {
26155
+ ...last,
26156
+ message
26157
+ };
26158
+ return {
26159
+ output: extractOllamaChatOutput(
26160
+ response,
26161
+ countOllamaToolCalls(event?.arguments?.[0]?.messages)
26162
+ ),
26163
+ metrics: extractOllamaMetrics(last ?? {}),
26164
+ metadata: extractOllamaResponseMetadata(last ?? {})
26165
+ };
26166
+ }
26167
+ function aggregateOllamaGenerateChunks(chunks, _result, _event, _startTime) {
26168
+ const last = chunks.at(-1);
26169
+ const response = {
26170
+ ...last,
26171
+ response: chunks.map((chunk) => chunk.response ?? "").join(""),
26172
+ thinking: chunks.map((chunk) => chunk.thinking ?? "").join("")
26173
+ };
26174
+ return {
26175
+ output: extractOllamaGenerateOutput(response),
26176
+ metrics: extractOllamaMetrics(last ?? {}),
26177
+ metadata: extractOllamaResponseMetadata(last ?? {})
26178
+ };
26179
+ }
26180
+
24480
26181
  // src/instrumentation/plugins/google-adk-channels.ts
24481
26182
  var googleADKChannels = defineChannels(
24482
26183
  "@google/adk",
@@ -27261,7 +28962,7 @@ function getStringProperty2(obj, key) {
27261
28962
  return typeof value === "string" ? value : void 0;
27262
28963
  }
27263
28964
  function extractMetricsFromUsage(usage) {
27264
- const metrics = {
28965
+ const rawMetrics = {
27265
28966
  prompt_tokens: usage.inputTokens,
27266
28967
  completion_tokens: usage.outputTokens,
27267
28968
  ...extractAnthropicCacheTokens(
@@ -27270,10 +28971,10 @@ function extractMetricsFromUsage(usage) {
27270
28971
  )
27271
28972
  };
27272
28973
  if (usage.reasoningTokens !== void 0) {
27273
- metrics.completion_reasoning_tokens = usage.reasoningTokens;
27274
- metrics.reasoning_tokens = usage.reasoningTokens;
28974
+ rawMetrics.completion_reasoning_tokens = usage.reasoningTokens;
28975
+ rawMetrics.reasoning_tokens = usage.reasoningTokens;
27275
28976
  }
27276
- Object.assign(metrics, finalizeAnthropicTokens(metrics));
28977
+ const metrics = finalizeAnthropicTokens(rawMetrics);
27277
28978
  const metadata = {
27278
28979
  model: usage.model
27279
28980
  };
@@ -28212,17 +29913,20 @@ var FlueObserveBridge = class {
28212
29913
  return;
28213
29914
  }
28214
29915
  const metadata = {
29916
+ ...event.runId ? this.runsById.get(event.runId)?.metadata : {},
28215
29917
  ...extractEventMetadata(event),
28216
29918
  "flue.operation": event.operationKind,
28217
29919
  provider: "flue"
28218
29920
  };
28219
29921
  const parent = this.parentSpanForEvent(event);
28220
- const span = startFlueSpan(parent, {
29922
+ const args = {
28221
29923
  name: `flue.${event.operationKind}`,
28222
29924
  spanAttributes: { type: "task" /* TASK */ },
28223
29925
  startTime: eventTime(event.timestamp),
28224
29926
  event: { metadata }
28225
- });
29927
+ };
29928
+ const runSpan = event.runId ? this.runsById.get(event.runId)?.span : void 0;
29929
+ const span = event.operationKind === "prompt" && (!parent || parent === runSpan) ? startFlueRootSpan(args) : startFlueSpan(parent, args);
28226
29930
  this.operationsById.set(event.operationId, { metadata, span });
28227
29931
  }
28228
29932
  handleOperation(event) {
@@ -28230,16 +29934,21 @@ var FlueObserveBridge = class {
28230
29934
  return;
28231
29935
  }
28232
29936
  const state = this.operationsById.get(event.operationId) ?? this.startSyntheticOperation(event);
28233
- const output = operationOutput(event);
29937
+ const output = operationOutput(event) ?? outputFromAgentTurn(state.latestAgentOutput);
28234
29938
  const metadata = {
28235
29939
  ...state.metadata,
28236
29940
  ...extractEventMetadata(event),
28237
29941
  ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {},
28238
29942
  ...event.usage ? { "flue.usage": event.usage } : {}
28239
29943
  };
29944
+ const input = flueOperationInput(event);
29945
+ if (!state.loggedInput && input !== void 0) {
29946
+ safeLog3(state.span, { input });
29947
+ state.loggedInput = true;
29948
+ }
28240
29949
  this.finishPendingChildrenForOperation(event, output);
28241
29950
  safeLog3(state.span, {
28242
- ...event.isError ? { error: toLoggedError(event.error) } : {},
29951
+ ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.error) } : {},
28243
29952
  metadata,
28244
29953
  metrics: durationMetrics2(event.durationMs),
28245
29954
  output
@@ -28253,6 +29962,8 @@ var FlueObserveBridge = class {
28253
29962
  return;
28254
29963
  }
28255
29964
  const input = flueTurnRequestInput(event);
29965
+ const operation = event.operationId ? this.operationsById.get(event.operationId) : void 0;
29966
+ const turnInput = prepareFlueTurnInput(event, input, operation);
28256
29967
  const model = flueTurnRequestModel(event);
28257
29968
  const provider = flueTurnRequestProvider(event);
28258
29969
  const api = flueTurnRequestApi(event);
@@ -28265,20 +29976,22 @@ var FlueObserveBridge = class {
28265
29976
  ...provider ? { "flue.provider": provider } : {},
28266
29977
  ...event.purpose ? { "flue.turn_purpose": event.purpose } : {},
28267
29978
  ...reasoning ? { reasoning } : {},
28268
- ...input?.systemPrompt ? { "flue.system_prompt": input.systemPrompt } : {},
28269
- ...input?.tools ? { tools: input.tools } : {}
29979
+ ...turnInput.metadata
28270
29980
  };
28271
29981
  const parent = this.parentSpanForTurn(event);
28272
29982
  const span = startFlueSpan(parent, {
28273
- name: `llm:${model ?? event.purpose ?? "unknown"}`,
29983
+ name: "flue.turn",
28274
29984
  spanAttributes: { type: "llm" /* LLM */ },
28275
29985
  startTime: eventTime(event.timestamp),
28276
29986
  event: {
28277
- input: input?.messages,
29987
+ input: turnInput.messages,
28278
29988
  metadata
28279
29989
  }
28280
29990
  });
28281
- this.logOperationInput(event.operationId, input?.messages ?? input);
29991
+ this.logOperationInput(
29992
+ event.operationId,
29993
+ latestUserMessageInput(input?.messages)
29994
+ );
28282
29995
  this.turnsByKey.set(key, { metadata, span });
28283
29996
  }
28284
29997
  handleTurn(event) {
@@ -28314,6 +30027,12 @@ var FlueObserveBridge = class {
28314
30027
  },
28315
30028
  output
28316
30029
  });
30030
+ if (event.purpose === "agent" && event.operationId) {
30031
+ const operation = this.operationsById.get(event.operationId);
30032
+ if (operation) {
30033
+ operation.latestAgentOutput = output;
30034
+ }
30035
+ }
28317
30036
  safeEnd(state.span, eventTime(event.timestamp));
28318
30037
  this.turnsByKey.delete(key);
28319
30038
  }
@@ -28393,7 +30112,7 @@ var FlueObserveBridge = class {
28393
30112
  return;
28394
30113
  }
28395
30114
  safeLog3(state.span, {
28396
- ...event.isError ? { error: toLoggedError(event.result) } : {},
30115
+ ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.result) } : {},
28397
30116
  metadata: {
28398
30117
  ...state.metadata,
28399
30118
  ...extractEventMetadata(event),
@@ -28439,6 +30158,7 @@ var FlueObserveBridge = class {
28439
30158
  ...event.usage ? { "flue.usage": event.usage } : {}
28440
30159
  };
28441
30160
  safeLog3(state.span, {
30161
+ ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.error) } : {},
28442
30162
  metadata,
28443
30163
  metrics: {
28444
30164
  ...durationMetrics2(event.durationMs),
@@ -28518,16 +30238,20 @@ var FlueObserveBridge = class {
28518
30238
  }
28519
30239
  startSyntheticOperation(event) {
28520
30240
  const metadata = {
30241
+ ...event.runId ? this.runsById.get(event.runId)?.metadata : {},
28521
30242
  ...extractEventMetadata(event),
28522
30243
  "flue.operation": event.operationKind,
28523
30244
  provider: "flue"
28524
30245
  };
28525
- const span = startFlueSpan(this.parentSpanForEvent(event), {
30246
+ const args = {
28526
30247
  name: `flue.${event.operationKind}`,
28527
30248
  spanAttributes: { type: "task" /* TASK */ },
28528
30249
  startTime: eventTime(event.timestamp),
28529
30250
  event: { metadata }
28530
- });
30251
+ };
30252
+ const parent = this.parentSpanForEvent(event);
30253
+ const runSpan = event.runId ? this.runsById.get(event.runId)?.span : void 0;
30254
+ const span = event.operationKind === "prompt" && (!parent || parent === runSpan) ? startFlueRootSpan(args) : startFlueSpan(parent, args);
28531
30255
  return { metadata, span };
28532
30256
  }
28533
30257
  startSyntheticTurn(event) {
@@ -28543,7 +30267,7 @@ var FlueObserveBridge = class {
28543
30267
  ...event.purpose ? { "flue.turn_purpose": event.purpose } : {}
28544
30268
  };
28545
30269
  const span = startFlueSpan(this.parentSpanForEvent(event), {
28546
- name: `llm:${model ?? event.purpose ?? "unknown"}`,
30270
+ name: "flue.turn",
28547
30271
  spanAttributes: { type: "llm" /* LLM */ },
28548
30272
  startTime: eventTime(event.timestamp),
28549
30273
  event: { metadata }
@@ -28675,7 +30399,10 @@ function extractEventMetadata(event, ctx) {
28675
30399
  return {
28676
30400
  ...event.runId ? { "flue.run_id": event.runId } : {},
28677
30401
  ...event.instanceId ? { "flue.instance_id": event.instanceId } : {},
30402
+ ...event.submissionId ? { "flue.submission_id": event.submissionId } : {},
28678
30403
  ...event.dispatchId ? { "flue.dispatch_id": event.dispatchId } : {},
30404
+ ...event.agentName ? { "flue.agent_name": event.agentName } : {},
30405
+ ...event.conversationId ? { "flue.conversation_id": event.conversationId } : {},
28679
30406
  ...typeof event.eventIndex === "number" ? { "flue.event_index": event.eventIndex } : {},
28680
30407
  ...event.session ? { "flue.session": event.session } : {},
28681
30408
  ...event.parentSession ? { "flue.parent_session": event.parentSession } : {},
@@ -28703,8 +30430,73 @@ function flueRunInput(event) {
28703
30430
  function flueTurnRequestInput(event) {
28704
30431
  return event.request?.input ?? event.input;
28705
30432
  }
30433
+ function prepareFlueTurnInput(event, input, operation) {
30434
+ const messages = input?.messages;
30435
+ const tracksUserTurn = event.purpose === "agent" && operation?.metadata["flue.operation"] === "prompt" && Array.isArray(messages);
30436
+ if (!tracksUserTurn) {
30437
+ return {
30438
+ messages,
30439
+ metadata: {
30440
+ ...input?.systemPrompt ? { "flue.system_prompt": input.systemPrompt } : {},
30441
+ ...input?.tools ? { tools: input.tools } : {}
30442
+ }
30443
+ };
30444
+ }
30445
+ const previous = operation.turnInputState;
30446
+ const previousMessageCount = previous?.messageCount ?? 0;
30447
+ const boundaryFingerprint = messages.length > 0 ? fingerprintJsonValue(messages[messages.length - 1]) : void 0;
30448
+ const continuesPreviousInput = previous !== void 0 && messages.length >= previousMessageCount && (previousMessageCount === 0 || previous.boundaryFingerprint !== void 0 && previous.boundaryFingerprint === fingerprintJsonValue(messages[previousMessageCount - 1]));
30449
+ const inputMode = previous === void 0 ? "full" : continuesPreviousInput ? "delta" : "reset";
30450
+ const systemPromptFingerprint = fingerprintJsonValue(input?.systemPrompt);
30451
+ const toolsFingerprint = fingerprintJsonValue(input?.tools);
30452
+ operation.turnInputState = {
30453
+ ...boundaryFingerprint !== void 0 ? { boundaryFingerprint } : {},
30454
+ messageCount: messages.length,
30455
+ ...systemPromptFingerprint !== void 0 ? { systemPromptFingerprint } : {},
30456
+ ...toolsFingerprint !== void 0 ? { toolsFingerprint } : {}
30457
+ };
30458
+ return {
30459
+ messages: continuesPreviousInput ? messages.slice(previousMessageCount) : messages,
30460
+ metadata: {
30461
+ "flue.input_mode": inputMode,
30462
+ ...continuesPreviousInput ? { "flue.input_message_offset": previousMessageCount } : {},
30463
+ ...input?.systemPrompt && (!continuesPreviousInput || systemPromptFingerprint !== previous?.systemPromptFingerprint) ? { "flue.system_prompt": input.systemPrompt } : {},
30464
+ ...input?.tools && (!continuesPreviousInput || toolsFingerprint !== previous?.toolsFingerprint) ? { tools: input.tools } : {}
30465
+ }
30466
+ };
30467
+ }
30468
+ function fingerprintJsonValue(value) {
30469
+ try {
30470
+ const serialized = JSON.stringify(value);
30471
+ if (serialized === void 0) {
30472
+ return void 0;
30473
+ }
30474
+ let hash = 2166136261;
30475
+ for (let i = 0; i < serialized.length; i++) {
30476
+ hash = Math.imul(hash ^ serialized.charCodeAt(i), 16777619);
30477
+ }
30478
+ return `${serialized.length}:${hash >>> 0}`;
30479
+ } catch {
30480
+ return void 0;
30481
+ }
30482
+ }
30483
+ function latestUserMessageInput(messages) {
30484
+ if (!messages) {
30485
+ return void 0;
30486
+ }
30487
+ for (let i = messages.length - 1; i >= 0; i--) {
30488
+ const message = messages[i];
30489
+ if (isObjectLike(message) && Reflect.get(message, "role") === "user") {
30490
+ return [message];
30491
+ }
30492
+ }
30493
+ return void 0;
30494
+ }
30495
+ function flueOperationInput(event) {
30496
+ return typeof event.agentInput?.text === "string" ? [{ content: event.agentInput.text, role: "user" }] : void 0;
30497
+ }
28706
30498
  function flueTurnRequestModel(event) {
28707
- return event.request?.model ?? event.model;
30499
+ return event.request?.requestedModel ?? event.request?.model ?? event.model;
28708
30500
  }
28709
30501
  function flueTurnRequestProvider(event) {
28710
30502
  return event.request?.providerName ?? event.provider ?? event.request?.providerId;
@@ -28713,10 +30505,10 @@ function flueTurnRequestApi(event) {
28713
30505
  return event.request?.api ?? event.api;
28714
30506
  }
28715
30507
  function flueTurnRequestReasoning(event) {
28716
- return event.request?.reasoning ?? event.reasoning;
30508
+ return event.request?.reasoningLevel ?? event.request?.reasoning ?? event.reasoning;
28717
30509
  }
28718
30510
  function flueTurnModel(event) {
28719
- return event.request?.model ?? event.model;
30511
+ return event.response?.responseModel ?? event.request?.requestedModel ?? event.request?.model ?? event.model;
28720
30512
  }
28721
30513
  function flueTurnProvider(event) {
28722
30514
  return event.request?.providerName ?? event.provider ?? event.request?.providerId;
@@ -28731,7 +30523,7 @@ function flueTurnOutput(event) {
28731
30523
  return event.response?.output ?? event.output;
28732
30524
  }
28733
30525
  function flueTurnStopReason(event) {
28734
- return event.response?.stopReason ?? event.stopReason;
30526
+ return event.response?.finishReason ?? event.response?.stopReason ?? event.stopReason;
28735
30527
  }
28736
30528
  function flueTurnError(event) {
28737
30529
  return event.response?.error ?? event.response?.errorInfo?.message ?? event.error;
@@ -28746,6 +30538,9 @@ function flueToolInput(event) {
28746
30538
  return event.input;
28747
30539
  }
28748
30540
  function flueToolOutput(event) {
30541
+ if (Object.hasOwn(event, "effectiveResult")) {
30542
+ return event.effectiveResult;
30543
+ }
28749
30544
  return event.output !== void 0 ? event.output : event.result;
28750
30545
  }
28751
30546
  function flueToolError(event) {
@@ -28753,10 +30548,36 @@ function flueToolError(event) {
28753
30548
  }
28754
30549
  function operationOutput(event) {
28755
30550
  if (event.operationKind === "prompt" || event.operationKind === "skill") {
28756
- return llmResultFromOperationResult(event.result);
30551
+ return outputFromAgentInvocation(event.agentOutput) ?? llmResultFromOperationResult(event.result);
28757
30552
  }
28758
30553
  return event.result ?? (event.operationKind === "compact" ? { completed: true } : void 0);
28759
30554
  }
30555
+ function outputFromAgentInvocation(output) {
30556
+ if (output?.type === "text") {
30557
+ return output.text;
30558
+ }
30559
+ if (output?.type === "data") {
30560
+ return output.data;
30561
+ }
30562
+ return void 0;
30563
+ }
30564
+ function outputFromAgentTurn(output) {
30565
+ if (!isObjectLike(output)) {
30566
+ return output;
30567
+ }
30568
+ const content = Reflect.get(output, "content");
30569
+ if (!Array.isArray(content)) {
30570
+ return output;
30571
+ }
30572
+ const text = content.flatMap((part) => {
30573
+ if (!isObjectLike(part) || Reflect.get(part, "type") !== "text") {
30574
+ return [];
30575
+ }
30576
+ const value = Reflect.get(part, "text");
30577
+ return typeof value === "string" ? [value] : [];
30578
+ });
30579
+ return text.length > 0 ? text.join("") : output;
30580
+ }
28760
30581
  function llmResultFromOperationResult(result) {
28761
30582
  if (!isObjectLike(result)) {
28762
30583
  return result;
@@ -28831,6 +30652,21 @@ function startFlueSpan(parent, args) {
28831
30652
  withSpanInstrumentationName(args, INSTRUMENTATION_NAMES.FLUE)
28832
30653
  );
28833
30654
  }
30655
+ function startFlueRootSpan(args) {
30656
+ const state = _internalGetGlobalState();
30657
+ const spanId = state.idGenerator.getSpanId();
30658
+ const rootSpanId = state.idGenerator.shareRootSpanId() ? spanId : state.idGenerator.getTraceId();
30659
+ return withCurrent(
30660
+ NOOP_SPAN,
30661
+ () => startSpan({
30662
+ ...withSpanInstrumentationName(args, INSTRUMENTATION_NAMES.FLUE),
30663
+ parentSpanIds: { parentSpanIds: [], rootSpanId },
30664
+ spanId,
30665
+ state
30666
+ }),
30667
+ state
30668
+ );
30669
+ }
28834
30670
  function runWithCurrentSpanStore(span, next) {
28835
30671
  const state = _internalGetGlobalState();
28836
30672
  const contextManager = state?.contextManager;
@@ -28855,7 +30691,7 @@ function safeEnd(span, endTime) {
28855
30691
  }
28856
30692
  }
28857
30693
  function logInstrumentationError3(label, error) {
28858
- console.error(`Error in ${label} instrumentation:`, error);
30694
+ debugLogger.debug(`Error in ${label} instrumentation:`, error);
28859
30695
  }
28860
30696
 
28861
30697
  // src/wrappers/langchain/callback-handler.ts
@@ -29784,12 +31620,13 @@ var piCodingAgentChannels = defineChannels(
29784
31620
  );
29785
31621
 
29786
31622
  // src/instrumentation/plugins/pi-coding-agent-plugin.ts
29787
- var piStreamPatchStates = /* @__PURE__ */ new WeakMap();
31623
+ var piAgentPatchStates = /* @__PURE__ */ new WeakMap();
31624
+ var piAgentEventSubscriptions = /* @__PURE__ */ new WeakSet();
29788
31625
  var piPromptContextStore;
29789
31626
  var PiCodingAgentPlugin = class extends BasePlugin {
29790
31627
  activePromptStates = /* @__PURE__ */ new Set();
29791
31628
  onEnable() {
29792
- this.subscribeToPrompt();
31629
+ this.interceptPrompt();
29793
31630
  }
29794
31631
  onDisable() {
29795
31632
  for (const unsubscribe of this.unsubscribers) {
@@ -29797,65 +31634,74 @@ var PiCodingAgentPlugin = class extends BasePlugin {
29797
31634
  }
29798
31635
  this.unsubscribers = [];
29799
31636
  for (const state of [...this.activePromptStates]) {
29800
- void finalizePiPromptRun(state).catch((error) => {
29801
- logInstrumentationError4("Pi Coding Agent disable cleanup", error);
29802
- });
31637
+ finishPiPromptRun(state);
29803
31638
  }
29804
31639
  }
29805
- subscribeToPrompt() {
29806
- const channel2 = piCodingAgentChannels.prompt.tracingChannel();
29807
- const states = /* @__PURE__ */ new WeakMap();
29808
- const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(channel2);
29809
- const handlers = {
29810
- start: (event) => {
29811
- const state = startPiPromptRun(event, (state2) => {
29812
- this.activePromptStates.delete(state2);
29813
- });
29814
- if (state) {
29815
- this.activePromptStates.add(state);
29816
- states.set(event, state);
29817
- }
29818
- },
29819
- asyncEnd: async (event) => {
29820
- const state = states.get(event);
29821
- if (!state) {
29822
- return;
29823
- }
29824
- states.delete(event);
29825
- state.promptCallEnded = true;
29826
- if (!state.finalized && state.deferCompletionUntilTurnEnd && !state.turnEnded) {
29827
- if (!state.sawStreamFn) {
29828
- state.queued = true;
29829
- if (!state.streamPatchState.queuedPromptStates.includes(state)) {
29830
- state.streamPatchState.queuedPromptStates.push(state);
29831
- }
31640
+ interceptPrompt() {
31641
+ this.unsubscribers.push(
31642
+ piCodingAgentChannels.prompt.intercept(
31643
+ (target, thisArg, args, additional) => {
31644
+ const invokeTarget = () => Reflect.apply(target, thisArg, args);
31645
+ let state;
31646
+ try {
31647
+ state = startPiPromptRun(
31648
+ {
31649
+ ...additional,
31650
+ arguments: args,
31651
+ self: thisArg
31652
+ },
31653
+ (finalizedState) => {
31654
+ this.activePromptStates.delete(finalizedState);
31655
+ }
31656
+ );
31657
+ } catch (error) {
31658
+ logInstrumentationError4("Pi Coding Agent prompt start", error);
29832
31659
  }
29833
- return;
29834
- }
29835
- await finalizePiPromptRun(state);
29836
- },
29837
- error: async (event) => {
29838
- const state = states.get(event);
29839
- if (!state) {
29840
- return;
31660
+ if (!state) {
31661
+ return runWithAutoInstrumentationSuppressed(invokeTarget);
31662
+ }
31663
+ this.activePromptStates.add(state);
31664
+ return promptContextStore().run(
31665
+ state,
31666
+ () => runWithAutoInstrumentationSuppressed(() => {
31667
+ let result;
31668
+ try {
31669
+ result = invokeTarget();
31670
+ } catch (error) {
31671
+ finishPiPromptRun(state, error);
31672
+ throw error;
31673
+ }
31674
+ return Promise.resolve(result).then(
31675
+ (value) => {
31676
+ finishPiPromptCall(state);
31677
+ return value;
31678
+ },
31679
+ (error) => {
31680
+ finishPiPromptRun(state, error);
31681
+ throw error;
31682
+ }
31683
+ );
31684
+ })
31685
+ );
29841
31686
  }
29842
- states.delete(event);
29843
- await finalizePiPromptRun(state, event.error);
29844
- }
29845
- };
29846
- channel2.subscribe(handlers);
29847
- this.unsubscribers.push(() => {
29848
- unbindAutoInstrumentationSuppression?.();
29849
- channel2.unsubscribe(handlers);
29850
- });
31687
+ )
31688
+ );
29851
31689
  }
29852
31690
  };
31691
+ function finishPiPromptCall(state) {
31692
+ state.promptCallEnded = true;
31693
+ if (state.deferCompletionUntilTurnEnd && !state.turnEnded) {
31694
+ return;
31695
+ }
31696
+ finishPiPromptRun(state);
31697
+ }
29853
31698
  function startPiPromptRun(event, onFinalize) {
29854
31699
  const session = extractSession(event);
29855
31700
  const agent = session?.agent;
29856
31701
  if (!session || !isPiAgent(agent)) {
29857
31702
  return void 0;
29858
31703
  }
31704
+ installPiAgentInstrumentation(agent);
29859
31705
  const metadata = {
29860
31706
  ...extractSessionMetadata(session),
29861
31707
  ...extractPromptOptionsMetadata(event.arguments[1]),
@@ -29877,9 +31723,7 @@ function startPiPromptRun(event, onFinalize) {
29877
31723
  INSTRUMENTATION_NAMES.PI_CODING_AGENT
29878
31724
  )
29879
31725
  );
29880
- const streamPatchState = installPiStreamPatch(agent);
29881
31726
  const options = event.arguments[1];
29882
- const promptText = event.arguments[0];
29883
31727
  const state = {
29884
31728
  activeLlmSpans: /* @__PURE__ */ new Set(),
29885
31729
  activeToolSpans: /* @__PURE__ */ new Map(),
@@ -29891,29 +31735,10 @@ function startPiPromptRun(event, onFinalize) {
29891
31735
  metrics: {},
29892
31736
  onFinalize,
29893
31737
  promptCallEnded: false,
29894
- ...typeof promptText === "string" ? { promptText } : {},
29895
- queued: false,
29896
31738
  span,
29897
- sawStreamFn: false,
29898
31739
  startTime: getCurrentUnixTimestamp(),
29899
- streamPatchState,
29900
31740
  turnEnded: false
29901
31741
  };
29902
- state.restorePromptContext = enterPiPromptContext(state);
29903
- streamPatchState.activePromptStates.add(state);
29904
- try {
29905
- state.unsubscribeAgent = agent.subscribe(async (agentEvent) => {
29906
- try {
29907
- await runWithAutoInstrumentationSuppressed(
29908
- () => handlePiAgentEvent(state, agentEvent)
29909
- );
29910
- } catch (error) {
29911
- logInstrumentationError4("Pi Coding Agent event", error);
29912
- }
29913
- });
29914
- } catch (error) {
29915
- logInstrumentationError4("Pi Coding Agent event subscription", error);
29916
- }
29917
31742
  return state;
29918
31743
  }
29919
31744
  function extractSession(event) {
@@ -29927,111 +31752,55 @@ function promptContextStore() {
29927
31752
  piPromptContextStore ??= isomorph_default.newAsyncLocalStorage();
29928
31753
  return piPromptContextStore;
29929
31754
  }
29930
- function currentPromptContextFrames() {
29931
- return promptContextStore().getStore()?.frames ?? [];
29932
- }
29933
31755
  function currentPiPromptState() {
29934
- const frames = currentPromptContextFrames();
29935
- return frames[frames.length - 1]?.state;
29936
- }
29937
- function enterPiPromptContext(state) {
29938
- const frame = {
29939
- id: /* @__PURE__ */ Symbol("braintrust.pi-coding-agent.prompt"),
29940
- state
29941
- };
29942
- promptContextStore().enterWith({
29943
- frames: [...currentPromptContextFrames(), frame]
29944
- });
29945
- return () => {
29946
- const frames = currentPromptContextFrames().filter(
29947
- (candidate) => candidate.id !== frame.id
29948
- );
29949
- promptContextStore().enterWith(frames.length > 0 ? { frames } : void 0);
29950
- };
29951
- }
29952
- function installPiStreamPatch(agent) {
29953
- const existing = piStreamPatchStates.get(agent);
29954
- if (existing) {
29955
- if (agent.streamFn !== existing.wrappedStreamFn) {
29956
- debugLogger.debug(
29957
- "Pi Coding Agent streamFn changed while Braintrust instrumentation was active; preserving existing patch state."
29958
- );
29959
- }
29960
- return existing;
29961
- }
29962
- const patchState = {
29963
- activePromptStates: /* @__PURE__ */ new Set(),
29964
- agent,
29965
- originalStreamFn: agent.streamFn,
29966
- queuedPromptStates: [],
29967
- wrappedStreamFn: agent.streamFn
29968
- };
29969
- patchState.wrappedStreamFn = makeSharedInstrumentedStreamFn(patchState);
29970
- agent.streamFn = patchState.wrappedStreamFn;
29971
- piStreamPatchStates.set(agent, patchState);
29972
- return patchState;
29973
- }
29974
- function resolveStreamPromptState(patchState, context) {
29975
- let lastUserText;
29976
- if (Array.isArray(context.messages)) {
29977
- for (let i = context.messages.length - 1; i >= 0; i--) {
29978
- const message = context.messages[i];
29979
- if (isPiUserMessage(message)) {
29980
- if (typeof message.content === "string") {
29981
- lastUserText = message.content;
29982
- } else {
29983
- lastUserText = message.content.flatMap((part) => part.type === "text" ? [part.text] : []).join("");
29984
- }
29985
- break;
29986
- }
29987
- }
29988
- }
29989
- if (lastUserText !== void 0) {
29990
- const queuedMatch = patchState.queuedPromptStates.find(
29991
- (state) => state.promptText === lastUserText
29992
- );
29993
- if (queuedMatch) {
29994
- return queuedMatch;
29995
- }
29996
- const matches = [...patchState.activePromptStates].filter(
29997
- (state) => state.promptText === lastUserText
31756
+ return promptContextStore().getStore();
31757
+ }
31758
+ function installPiAgentInstrumentation(agent) {
31759
+ const existing = piAgentPatchStates.get(agent);
31760
+ if (!existing || agent.streamFn !== existing.wrappedStreamFn) {
31761
+ const patchState = {
31762
+ originalStreamFn: agent.streamFn,
31763
+ wrappedStreamFn: agent.streamFn
31764
+ };
31765
+ patchState.wrappedStreamFn = makeInstrumentedStreamFn(
31766
+ agent,
31767
+ patchState.originalStreamFn
29998
31768
  );
29999
- if (matches.length === 1) {
30000
- return matches[0];
30001
- }
31769
+ agent.streamFn = patchState.wrappedStreamFn;
31770
+ piAgentPatchStates.set(agent, patchState);
30002
31771
  }
30003
- const contextState = currentPiPromptState();
30004
- if (contextState && patchState.activePromptStates.has(contextState) && (!contextState.queued || lastUserText !== void 0 && contextState.promptText === lastUserText)) {
30005
- return contextState;
31772
+ if (piAgentEventSubscriptions.has(agent)) {
31773
+ return;
30006
31774
  }
30007
- if (patchState.activePromptStates.size === 1) {
30008
- return [...patchState.activePromptStates][0];
31775
+ try {
31776
+ agent.subscribe(async (event) => {
31777
+ const state = currentPiPromptState();
31778
+ if (!state || state.agent !== agent || state.finalized) {
31779
+ return;
31780
+ }
31781
+ try {
31782
+ await runWithAutoInstrumentationSuppressed(
31783
+ () => handlePiAgentEvent(state, event)
31784
+ );
31785
+ } catch (error) {
31786
+ logInstrumentationError4("Pi Coding Agent event", error);
31787
+ }
31788
+ });
31789
+ piAgentEventSubscriptions.add(agent);
31790
+ } catch (error) {
31791
+ logInstrumentationError4("Pi Coding Agent event subscription", error);
30009
31792
  }
30010
- return void 0;
30011
31793
  }
30012
- function makeSharedInstrumentedStreamFn(patchState) {
31794
+ function makeInstrumentedStreamFn(agent, originalStreamFn) {
30013
31795
  return async function instrumentedPiStreamFn(model, context, options) {
30014
- const state = resolveStreamPromptState(patchState, context);
30015
- if (!state) {
30016
- const invokeOriginal = () => Reflect.apply(patchState.originalStreamFn, this, [
30017
- model,
30018
- context,
30019
- options
30020
- ]);
30021
- return patchState.activePromptStates.size > 0 ? runWithAutoInstrumentationSuppressed(invokeOriginal) : invokeOriginal();
31796
+ const invokeOriginal = () => Reflect.apply(originalStreamFn, this, [model, context, options]);
31797
+ const state = currentPiPromptState();
31798
+ if (!state || state.agent !== agent || state.finalized) {
31799
+ return invokeOriginal();
30022
31800
  }
30023
- state.sawStreamFn = true;
30024
- removeQueuedPromptState(state);
30025
- state.streamPatchState.eventPromptState = state;
30026
31801
  const llmState = await startPiLlmSpan(state, model, context, options);
30027
31802
  try {
30028
- const stream = await runWithAutoInstrumentationSuppressed(
30029
- () => Reflect.apply(patchState.originalStreamFn, this, [
30030
- model,
30031
- context,
30032
- options
30033
- ])
30034
- );
31803
+ const stream = await runWithAutoInstrumentationSuppressed(invokeOriginal);
30035
31804
  return patchAssistantMessageStream(stream, state, llmState);
30036
31805
  } catch (error) {
30037
31806
  finishPiLlmSpan(state, llmState, void 0, error);
@@ -30178,13 +31947,6 @@ async function handlePiAgentEvent(state, event) {
30178
31947
  if (state.finalized) {
30179
31948
  return;
30180
31949
  }
30181
- const eventPromptState = state.streamPatchState.eventPromptState;
30182
- if (eventPromptState && eventPromptState !== state) {
30183
- return;
30184
- }
30185
- if (!eventPromptState && (state.queued || state.streamPatchState.activePromptStates.size > 1 && currentPiPromptState() !== state)) {
30186
- return;
30187
- }
30188
31950
  switch (event.type) {
30189
31951
  case "message_end":
30190
31952
  if (isPiAssistantMessage(event.message)) {
@@ -30199,11 +31961,8 @@ async function handlePiAgentEvent(state, event) {
30199
31961
  addMetrics(state.metrics, extractUsageMetrics2(event.message.usage));
30200
31962
  }
30201
31963
  }
30202
- if (state.streamPatchState.eventPromptState === state) {
30203
- state.streamPatchState.eventPromptState = void 0;
30204
- }
30205
31964
  if (state.promptCallEnded && state.deferCompletionUntilTurnEnd) {
30206
- await finalizePiPromptRun(state);
31965
+ finishPiPromptRun(state);
30207
31966
  }
30208
31967
  return;
30209
31968
  case "tool_execution_start":
@@ -30276,19 +32035,13 @@ function finishPiToolSpan(state, event) {
30276
32035
  }
30277
32036
  }
30278
32037
  }
30279
- async function finalizePiPromptRun(state, error) {
32038
+ function finishPiPromptRun(state, error) {
30280
32039
  if (state.finalized) {
30281
32040
  return;
30282
32041
  }
30283
32042
  state.finalized = true;
30284
32043
  state.onFinalize?.(state);
30285
- restorePiStreamFn(state);
30286
- try {
30287
- state.unsubscribeAgent?.();
30288
- } catch (unsubscribeError) {
30289
- logInstrumentationError4("Pi Coding Agent unsubscribe", unsubscribeError);
30290
- }
30291
- await finishOpenLlmSpans(state, error);
32044
+ finishOpenLlmSpans(state, error);
30292
32045
  finishOpenToolSpans(state, error);
30293
32046
  const metadata = {
30294
32047
  ...state.metadata,
@@ -30305,34 +32058,14 @@ async function finalizePiPromptRun(state, error) {
30305
32058
  output: state.output
30306
32059
  });
30307
32060
  } finally {
30308
- state.span.end();
30309
- }
30310
- }
30311
- function restorePiStreamFn(state) {
30312
- const patchState = state.streamPatchState;
30313
- patchState.activePromptStates.delete(state);
30314
- removeQueuedPromptState(state);
30315
- if (patchState.eventPromptState === state) {
30316
- patchState.eventPromptState = void 0;
30317
- }
30318
- state.restorePromptContext?.();
30319
- if (patchState.activePromptStates.size > 0) {
30320
- return;
30321
- }
30322
- if (patchState.agent.streamFn === patchState.wrappedStreamFn) {
30323
- patchState.agent.streamFn = patchState.originalStreamFn;
30324
- }
30325
- piStreamPatchStates.delete(patchState.agent);
30326
- }
30327
- function removeQueuedPromptState(state) {
30328
- state.queued = false;
30329
- const queuedPromptStates = state.streamPatchState.queuedPromptStates;
30330
- const index = queuedPromptStates.indexOf(state);
30331
- if (index >= 0) {
30332
- queuedPromptStates.splice(index, 1);
32061
+ try {
32062
+ state.span.end();
32063
+ } catch (endError) {
32064
+ logInstrumentationError4("Pi Coding Agent prompt end", endError);
32065
+ }
30333
32066
  }
30334
32067
  }
30335
- async function finishOpenLlmSpans(state, error) {
32068
+ function finishOpenLlmSpans(state, error) {
30336
32069
  for (const llmState of [...state.activeLlmSpans]) {
30337
32070
  finishPiLlmSpan(state, llmState, void 0, error);
30338
32071
  }
@@ -30413,7 +32146,7 @@ function normalizeAssistantMessage(message) {
30413
32146
  (part) => part.type === "thinking" && !part.redacted ? [part.thinking] : []
30414
32147
  ).join("");
30415
32148
  const toolCalls = message.content.flatMap(
30416
- (part) => part.type === "toolCall" ? [normalizeToolCall(part)] : []
32149
+ (part) => part.type === "toolCall" ? [normalizeToolCall2(part)] : []
30417
32150
  );
30418
32151
  return {
30419
32152
  role: "assistant",
@@ -30448,13 +32181,13 @@ function normalizeUserContent(content) {
30448
32181
  return part;
30449
32182
  });
30450
32183
  }
30451
- function normalizeToolCall(toolCall) {
32184
+ function normalizeToolCall2(toolCall) {
30452
32185
  return {
30453
32186
  id: toolCall.id,
30454
32187
  type: "function",
30455
32188
  function: {
30456
32189
  name: toolCall.name,
30457
- arguments: stringifyArguments(toolCall.arguments)
32190
+ arguments: stringifyArguments2(toolCall.arguments)
30458
32191
  }
30459
32192
  };
30460
32193
  }
@@ -30637,7 +32370,7 @@ function cleanMetrics5(metrics) {
30637
32370
  }
30638
32371
  return cleaned;
30639
32372
  }
30640
- function stringifyArguments(value) {
32373
+ function stringifyArguments2(value) {
30641
32374
  if (typeof value === "string") {
30642
32375
  return value;
30643
32376
  }
@@ -30833,8 +32566,7 @@ function startAgentStream(event, activeChildParents) {
30833
32566
  ...extractAgentMetadata2(agent),
30834
32567
  ...extractModelMetadata3(model),
30835
32568
  "strands.operation": "Agent.stream",
30836
- provider: extractProvider(model),
30837
- ...event.moduleVersion ? { "strands_agent_sdk.version": event.moduleVersion } : {}
32569
+ provider: extractProvider(model)
30838
32570
  };
30839
32571
  const parentSpan = agent ? getOnlyChildParent(activeChildParents, agent) : void 0;
30840
32572
  const attachmentCache = createStrandsAttachmentCache();
@@ -30884,8 +32616,7 @@ function startMultiAgentStream(event, operation, activeChildParents) {
30884
32616
  const metadata = {
30885
32617
  "strands.operation": operation,
30886
32618
  provider: "strands",
30887
- ...orchestrator?.id ? { "strands.orchestrator.id": orchestrator.id } : {},
30888
- ...event.moduleVersion ? { "strands_agent_sdk.version": event.moduleVersion } : {}
32619
+ ...orchestrator?.id ? { "strands.orchestrator.id": orchestrator.id } : {}
30889
32620
  };
30890
32621
  const parentSpan = orchestrator ? getOnlyChildParent(activeChildParents, orchestrator) : void 0;
30891
32622
  const input = processStrandsInputAttachments(event.arguments[0]);
@@ -31671,6 +33402,320 @@ function logInstrumentationError5(context, error) {
31671
33402
  debugLogger.debug(`${context}:`, error);
31672
33403
  }
31673
33404
 
33405
+ // src/instrumentation/plugins/voyageai-channels.ts
33406
+ var voyageAIChannels = defineChannels(
33407
+ "voyageai",
33408
+ {
33409
+ embed: channel({
33410
+ channelName: "embed",
33411
+ kind: "async"
33412
+ }),
33413
+ multimodalEmbed: channel({
33414
+ channelName: "multimodalEmbed",
33415
+ kind: "async"
33416
+ }),
33417
+ rerank: channel({
33418
+ channelName: "rerank",
33419
+ kind: "async"
33420
+ }),
33421
+ contextualizedEmbed: channel({
33422
+ channelName: "contextualizedEmbed",
33423
+ kind: "async"
33424
+ })
33425
+ },
33426
+ { instrumentationName: INSTRUMENTATION_NAMES.VOYAGEAI }
33427
+ );
33428
+
33429
+ // src/instrumentation/plugins/voyageai-plugin.ts
33430
+ var RERANK_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
33431
+ "model",
33432
+ "returnDocuments",
33433
+ "topK",
33434
+ "truncation"
33435
+ ]);
33436
+ var VoyageAIPlugin = class extends BasePlugin {
33437
+ onEnable() {
33438
+ this.unsubscribers.push(
33439
+ interceptVoyageAICall(
33440
+ voyageAIChannels.embed,
33441
+ "voyageai.embed",
33442
+ extractTextEmbeddingInput,
33443
+ summarizeEmbeddingOutput,
33444
+ extractEmbeddingUsageMetrics
33445
+ ),
33446
+ interceptVoyageAICall(
33447
+ voyageAIChannels.multimodalEmbed,
33448
+ "voyageai.multimodalEmbed",
33449
+ extractMultimodalEmbeddingInput,
33450
+ summarizeEmbeddingOutput,
33451
+ extractEmbeddingUsageMetrics
33452
+ ),
33453
+ interceptVoyageAICall(
33454
+ voyageAIChannels.rerank,
33455
+ "voyageai.rerank",
33456
+ extractRerankInput,
33457
+ summarizeRerankOutput
33458
+ ),
33459
+ interceptVoyageAICall(
33460
+ voyageAIChannels.contextualizedEmbed,
33461
+ "voyageai.contextualizedEmbed",
33462
+ extractContextualizedEmbeddingInput,
33463
+ summarizeContextualizedEmbeddingOutput,
33464
+ extractEmbeddingUsageMetrics
33465
+ )
33466
+ );
33467
+ }
33468
+ onDisable() {
33469
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
33470
+ }
33471
+ };
33472
+ function interceptVoyageAICall(channel2, name, extractInput2, extractOutput2, extractMetrics2 = extractUsageMetrics3) {
33473
+ return channel2.intercept((target, thisArg, args) => {
33474
+ const invokeTarget = () => Reflect.apply(target, thisArg, args);
33475
+ if (isAutoInstrumentationSuppressed()) {
33476
+ return invokeTarget();
33477
+ }
33478
+ let span;
33479
+ try {
33480
+ const { input, metadata } = extractInput2(args);
33481
+ span = startSpan(
33482
+ withSpanInstrumentationName(
33483
+ {
33484
+ event: { input, metadata },
33485
+ name,
33486
+ spanAttributes: { type: "llm" /* LLM */ }
33487
+ },
33488
+ INSTRUMENTATION_NAMES.VOYAGEAI
33489
+ )
33490
+ );
33491
+ } catch (error) {
33492
+ debugLogger.error(`Error starting span for ${name}:`, error);
33493
+ return invokeTarget();
33494
+ }
33495
+ let result;
33496
+ try {
33497
+ result = withCurrent(
33498
+ span,
33499
+ () => runWithAutoInstrumentationSuppressed(invokeTarget)
33500
+ );
33501
+ } catch (error) {
33502
+ finishVoyageAISpan(span, name, () => span.log({ error }));
33503
+ throw error;
33504
+ }
33505
+ void Promise.resolve(result).then(
33506
+ (value) => finishVoyageAISpan(span, name, () => {
33507
+ const metadata = extractResponseMetadata3(value);
33508
+ span.log({
33509
+ output: extractOutput2(value),
33510
+ ...metadata ? { metadata } : {},
33511
+ metrics: extractMetrics2(value)
33512
+ });
33513
+ }),
33514
+ (error) => finishVoyageAISpan(span, name, () => span.log({ error }))
33515
+ );
33516
+ return result;
33517
+ });
33518
+ }
33519
+ function finishVoyageAISpan(span, name, log) {
33520
+ try {
33521
+ log();
33522
+ } catch (error) {
33523
+ debugLogger.error(`Error logging span for ${name}:`, error);
33524
+ }
33525
+ try {
33526
+ span.end();
33527
+ } catch (error) {
33528
+ debugLogger.error(`Error ending span for ${name}:`, error);
33529
+ }
33530
+ }
33531
+ function getRequestArg2(args) {
33532
+ if (Array.isArray(args)) {
33533
+ return isObject(args[0]) ? args[0] : void 0;
33534
+ }
33535
+ if (!isObject(args)) {
33536
+ return void 0;
33537
+ }
33538
+ const firstArg = Reflect.get(args, "0");
33539
+ return isObject(firstArg) ? firstArg : void 0;
33540
+ }
33541
+ function pickMetadata(request, allowlist) {
33542
+ const metadata = {};
33543
+ if (request) {
33544
+ for (const key of allowlist) {
33545
+ if (!Object.hasOwn(request, key)) {
33546
+ continue;
33547
+ }
33548
+ const value = request[key];
33549
+ if (value !== void 0) {
33550
+ metadata[key] = value;
33551
+ }
33552
+ }
33553
+ }
33554
+ return {
33555
+ ...metadata,
33556
+ provider: "voyage"
33557
+ };
33558
+ }
33559
+ function buildEmbeddingInput(inputs, request) {
33560
+ const outputDimensions = request?.outputDimension;
33561
+ return {
33562
+ inputs,
33563
+ ...typeof outputDimensions === "number" && Number.isFinite(outputDimensions) ? { output_dimensions: outputDimensions } : {}
33564
+ };
33565
+ }
33566
+ function embeddingMetadata(request) {
33567
+ return {
33568
+ ...typeof request?.model === "string" ? { model: request.model } : {},
33569
+ provider: "voyage"
33570
+ };
33571
+ }
33572
+ function extractTextEmbeddingInput(args) {
33573
+ const request = getRequestArg2(args);
33574
+ const rawInput = request?.input;
33575
+ const values = Array.isArray(rawInput) ? rawInput : [rawInput];
33576
+ return {
33577
+ input: buildEmbeddingInput(
33578
+ values.flatMap(
33579
+ (value) => typeof value === "string" ? [{ content: value }] : []
33580
+ ),
33581
+ request
33582
+ ),
33583
+ metadata: embeddingMetadata(request)
33584
+ };
33585
+ }
33586
+ function extractContextualizedEmbeddingInput(args) {
33587
+ const request = getRequestArg2(args);
33588
+ const rawInputs = request?.inputs;
33589
+ const values = Array.isArray(rawInputs) ? rawInputs.flatMap((value) => Array.isArray(value) ? value : [value]) : [];
33590
+ return {
33591
+ input: buildEmbeddingInput(
33592
+ values.flatMap(
33593
+ (value) => typeof value === "string" ? [{ content: value }] : []
33594
+ ),
33595
+ request
33596
+ ),
33597
+ metadata: embeddingMetadata(request)
33598
+ };
33599
+ }
33600
+ function extractMultimodalEmbeddingInput(args) {
33601
+ const request = getRequestArg2(args);
33602
+ const rawInputs = request?.inputs;
33603
+ const inputs = Array.isArray(rawInputs) ? rawInputs.map((rawInput) => {
33604
+ const rawContent = isObject(rawInput) ? rawInput.content : void 0;
33605
+ return {
33606
+ content: Array.isArray(rawContent) ? rawContent.flatMap(normalizeMultimodalContentPart) : []
33607
+ };
33608
+ }) : [];
33609
+ const input = buildEmbeddingInput(inputs, request);
33610
+ const processedInput = processInputAttachments(input);
33611
+ return {
33612
+ input: hasInlineEmbeddingMedia(processedInput) ? input : processedInput,
33613
+ metadata: embeddingMetadata(request)
33614
+ };
33615
+ }
33616
+ function normalizeMultimodalContentPart(part) {
33617
+ if (!isObject(part) || typeof part.type !== "string") {
33618
+ return [];
33619
+ }
33620
+ if (part.type === "text") {
33621
+ return typeof part.text === "string" ? [{ type: "text", text: part.text }] : [];
33622
+ }
33623
+ const camelCaseField = {
33624
+ image_base64: "imageBase64",
33625
+ image_url: "imageUrl",
33626
+ video_base64: "videoBase64",
33627
+ video_url: "videoUrl"
33628
+ };
33629
+ const field = camelCaseField[part.type];
33630
+ if (!field) {
33631
+ return [];
33632
+ }
33633
+ const data = typeof part[field] === "string" ? part[field] : part[part.type];
33634
+ if (typeof data !== "string") {
33635
+ return [];
33636
+ }
33637
+ return part.type.startsWith("image_") ? [{ type: "image_url", image_url: { url: data } }] : [{ type: "file", file: { file_data: data } }];
33638
+ }
33639
+ function hasInlineEmbeddingMedia(input) {
33640
+ return input.inputs.some(
33641
+ ({ content }) => Array.isArray(content) ? content.some((part) => {
33642
+ const value = part.type === "image_url" ? part.image_url.url : part.type === "file" ? part.file.file_data : void 0;
33643
+ return typeof value === "string" && value.startsWith("data:");
33644
+ }) : false
33645
+ );
33646
+ }
33647
+ function extractRerankInput(args) {
33648
+ const request = getRequestArg2(args);
33649
+ const documents = request?.documents;
33650
+ return {
33651
+ input: {
33652
+ documents,
33653
+ query: request?.query
33654
+ },
33655
+ metadata: {
33656
+ ...pickMetadata(request, RERANK_METADATA_ALLOWLIST),
33657
+ ...Array.isArray(documents) ? { document_count: documents.length } : {}
33658
+ }
33659
+ };
33660
+ }
33661
+ function extractResponseMetadata3(result) {
33662
+ if (!isObject(result)) {
33663
+ return void 0;
33664
+ }
33665
+ const rawResponse = isObject(result.rawResponse) ? result.rawResponse : void 0;
33666
+ const model = typeof result.model === "string" ? result.model : typeof rawResponse?.model === "string" ? rawResponse.model : void 0;
33667
+ return model ? { model } : void 0;
33668
+ }
33669
+ function summarizeEmbeddingOutput(result) {
33670
+ return {
33671
+ count: isObject(result) && Array.isArray(result.data) ? result.data.length : 0
33672
+ };
33673
+ }
33674
+ function summarizeRerankOutput(result) {
33675
+ if (!isObject(result) || !Array.isArray(result.data)) {
33676
+ return void 0;
33677
+ }
33678
+ return result.data.slice(0, 100).map((item) => ({
33679
+ index: isObject(item) ? item.index : void 0,
33680
+ relevance_score: isObject(item) ? (typeof item.relevanceScore === "number" ? item.relevanceScore : item.relevance_score) ?? null : null
33681
+ }));
33682
+ }
33683
+ function summarizeContextualizedEmbeddingOutput(result) {
33684
+ if (!isObject(result)) {
33685
+ return { count: 0 };
33686
+ }
33687
+ if (Array.isArray(result.results)) {
33688
+ return {
33689
+ count: result.results.reduce(
33690
+ (count, item) => count + (isObject(item) && Array.isArray(item.embeddings) ? item.embeddings.length : 0),
33691
+ 0
33692
+ )
33693
+ };
33694
+ }
33695
+ if (!Array.isArray(result.data)) {
33696
+ return { count: 0 };
33697
+ }
33698
+ return {
33699
+ count: result.data.reduce(
33700
+ (count, item) => count + (isObject(item) && Array.isArray(item.data) ? item.data.length : 0),
33701
+ 0
33702
+ )
33703
+ };
33704
+ }
33705
+ function extractEmbeddingUsageMetrics(result) {
33706
+ const metrics = extractUsageMetrics3(result);
33707
+ return typeof metrics.tokens === "number" ? { prompt_tokens: metrics.tokens, tokens: metrics.tokens } : {};
33708
+ }
33709
+ function extractUsageMetrics3(result) {
33710
+ if (!isObject(result)) {
33711
+ return {};
33712
+ }
33713
+ const rawResponse = isObject(result.rawResponse) ? result.rawResponse : void 0;
33714
+ const usage = isObject(result.usage) ? result.usage : isObject(rawResponse?.usage) ? rawResponse.usage : void 0;
33715
+ const tokens = typeof result.totalTokens === "number" ? result.totalTokens : usage?.totalTokens ?? usage?.total_tokens;
33716
+ return typeof tokens === "number" && Number.isFinite(tokens) && tokens >= 0 ? { tokens } : {};
33717
+ }
33718
+
31674
33719
  // src/instrumentation/plugins/cloudflare-ai-chat-channels.ts
31675
33720
  var cloudflareAIChatChannels = defineChannels(
31676
33721
  "@cloudflare/ai-chat",
@@ -32205,6 +34250,7 @@ var BraintrustPlugin = class extends BasePlugin {
32205
34250
  anthropicPlugin = null;
32206
34251
  aiSDKPlugin = null;
32207
34252
  claudeAgentSDKPlugin = null;
34253
+ cloudflareThinkPlugin = null;
32208
34254
  cursorSDKPlugin = null;
32209
34255
  openAIAgentsPlugin = null;
32210
34256
  googleGenAIPlugin = null;
@@ -32213,6 +34259,7 @@ var BraintrustPlugin = class extends BasePlugin {
32213
34259
  openRouterPlugin = null;
32214
34260
  openRouterAgentPlugin = null;
32215
34261
  mistralPlugin = null;
34262
+ ollamaPlugin = null;
32216
34263
  googleADKPlugin = null;
32217
34264
  coherePlugin = null;
32218
34265
  groqPlugin = null;
@@ -32224,6 +34271,7 @@ var BraintrustPlugin = class extends BasePlugin {
32224
34271
  langSmithPlugin = null;
32225
34272
  piCodingAgentPlugin = null;
32226
34273
  strandsAgentSDKPlugin = null;
34274
+ voyageAIPlugin = null;
32227
34275
  cloudflareAIChatPlugin = null;
32228
34276
  cloudflareAgentsPlugin = null;
32229
34277
  constructor(config = {}) {
@@ -32252,6 +34300,10 @@ var BraintrustPlugin = class extends BasePlugin {
32252
34300
  this.claudeAgentSDKPlugin = new ClaudeAgentSDKPlugin();
32253
34301
  this.claudeAgentSDKPlugin.enable();
32254
34302
  }
34303
+ if (integrations.cloudflareThink !== false) {
34304
+ this.cloudflareThinkPlugin = new CloudflareThinkPlugin();
34305
+ this.cloudflareThinkPlugin.enable();
34306
+ }
32255
34307
  if (integrations.cursorSDK !== false && integrations.cursor !== false) {
32256
34308
  this.cursorSDKPlugin = new CursorSDKPlugin();
32257
34309
  this.cursorSDKPlugin.enable();
@@ -32282,6 +34334,10 @@ var BraintrustPlugin = class extends BasePlugin {
32282
34334
  this.mistralPlugin = new MistralPlugin();
32283
34335
  this.mistralPlugin.enable();
32284
34336
  }
34337
+ if (integrations.ollama !== false) {
34338
+ this.ollamaPlugin = new OllamaPlugin();
34339
+ this.ollamaPlugin.enable();
34340
+ }
32285
34341
  if (integrations.googleADK !== false) {
32286
34342
  this.googleADKPlugin = new GoogleADKPlugin();
32287
34343
  this.googleADKPlugin.enable();
@@ -32290,6 +34346,10 @@ var BraintrustPlugin = class extends BasePlugin {
32290
34346
  this.coherePlugin = new CoherePlugin();
32291
34347
  this.coherePlugin.enable();
32292
34348
  }
34349
+ if (integrations.voyageai !== false) {
34350
+ this.voyageAIPlugin = new VoyageAIPlugin();
34351
+ this.voyageAIPlugin.enable();
34352
+ }
32293
34353
  if (integrations.groq !== false) {
32294
34354
  this.groqPlugin = new GroqPlugin();
32295
34355
  this.groqPlugin.enable();
@@ -32358,6 +34418,10 @@ var BraintrustPlugin = class extends BasePlugin {
32358
34418
  this.claudeAgentSDKPlugin.disable();
32359
34419
  this.claudeAgentSDKPlugin = null;
32360
34420
  }
34421
+ if (this.cloudflareThinkPlugin) {
34422
+ this.cloudflareThinkPlugin.disable();
34423
+ this.cloudflareThinkPlugin = null;
34424
+ }
32361
34425
  if (this.cursorSDKPlugin) {
32362
34426
  this.cursorSDKPlugin.disable();
32363
34427
  this.cursorSDKPlugin = null;
@@ -32390,6 +34454,10 @@ var BraintrustPlugin = class extends BasePlugin {
32390
34454
  this.mistralPlugin.disable();
32391
34455
  this.mistralPlugin = null;
32392
34456
  }
34457
+ if (this.ollamaPlugin) {
34458
+ this.ollamaPlugin.disable();
34459
+ this.ollamaPlugin = null;
34460
+ }
32393
34461
  if (this.googleADKPlugin) {
32394
34462
  this.googleADKPlugin.disable();
32395
34463
  this.googleADKPlugin = null;
@@ -32398,6 +34466,10 @@ var BraintrustPlugin = class extends BasePlugin {
32398
34466
  this.coherePlugin.disable();
32399
34467
  this.coherePlugin = null;
32400
34468
  }
34469
+ if (this.voyageAIPlugin) {
34470
+ this.voyageAIPlugin.disable();
34471
+ this.voyageAIPlugin = null;
34472
+ }
32401
34473
  if (this.groqPlugin) {
32402
34474
  this.groqPlugin.disable();
32403
34475
  this.groqPlugin = null;
@@ -34126,6 +36198,7 @@ var envIntegrationAliases = {
34126
36198
  cloudflareaichat: "cloudflareAIChat",
34127
36199
  "cloudflare-ai-chat": "cloudflareAIChat",
34128
36200
  "@cloudflare/ai-chat": "cloudflareAIChat",
36201
+ cloudflarethink: "cloudflareThink",
34129
36202
  cursor: "cursor",
34130
36203
  "cursor-sdk": "cursorSDK",
34131
36204
  cursorsdk: "cursorSDK",
@@ -34146,6 +36219,7 @@ var envIntegrationAliases = {
34146
36219
  openrouteragent: "openrouterAgent",
34147
36220
  "openrouter-agent": "openrouterAgent",
34148
36221
  mistral: "mistral",
36222
+ ollama: "ollama",
34149
36223
  googleadk: "googleADK",
34150
36224
  "google-adk": "googleADK",
34151
36225
  cohere: "cohere",
@@ -34166,7 +36240,10 @@ var envIntegrationAliases = {
34166
36240
  "langchain-js": "langchain",
34167
36241
  "@langchain": "langchain",
34168
36242
  langgraph: "langgraph",
34169
- langsmith: "langsmith"
36243
+ langsmith: "langsmith",
36244
+ voyage: "voyageai",
36245
+ "voyage-ai": "voyageai",
36246
+ voyageai: "voyageai"
34170
36247
  };
34171
36248
  function getDefaultInstrumentationIntegrations() {
34172
36249
  return {
@@ -34181,6 +36258,7 @@ function getDefaultInstrumentationIntegrations() {
34181
36258
  huggingface: true,
34182
36259
  claudeAgentSDK: true,
34183
36260
  cloudflareAIChat: true,
36261
+ cloudflareThink: true,
34184
36262
  cursor: true,
34185
36263
  cursorSDK: true,
34186
36264
  flue: true,
@@ -34189,6 +36267,7 @@ function getDefaultInstrumentationIntegrations() {
34189
36267
  openrouter: true,
34190
36268
  openrouterAgent: true,
34191
36269
  mistral: true,
36270
+ ollama: true,
34192
36271
  cohere: true,
34193
36272
  groq: true,
34194
36273
  bedrock: true,
@@ -34199,6 +36278,7 @@ function getDefaultInstrumentationIntegrations() {
34199
36278
  langchain: true,
34200
36279
  langgraph: true,
34201
36280
  langsmith: true,
36281
+ voyageai: true,
34202
36282
  piCodingAgent: true,
34203
36283
  strandsAgentSDK: true,
34204
36284
  cloudflareAgents: true