braintrust 3.26.0 → 3.27.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 (57) hide show
  1. package/dev/dist/index.js +2440 -1067
  2. package/dev/dist/index.mjs +1644 -271
  3. package/dist/apply-auto-instrumentation.js +320 -261
  4. package/dist/apply-auto-instrumentation.mjs +118 -59
  5. package/dist/auto-instrumentations/bundler/esbuild.cjs +377 -59
  6. package/dist/auto-instrumentations/bundler/esbuild.mjs +5 -4
  7. package/dist/auto-instrumentations/bundler/next.cjs +379 -61
  8. package/dist/auto-instrumentations/bundler/next.mjs +6 -5
  9. package/dist/auto-instrumentations/bundler/rollup.cjs +377 -59
  10. package/dist/auto-instrumentations/bundler/rollup.mjs +5 -4
  11. package/dist/auto-instrumentations/bundler/vite.cjs +406 -60
  12. package/dist/auto-instrumentations/bundler/vite.mjs +34 -5
  13. package/dist/auto-instrumentations/bundler/webpack-loader.cjs +363 -59
  14. package/dist/auto-instrumentations/bundler/webpack.cjs +377 -59
  15. package/dist/auto-instrumentations/bundler/webpack.mjs +6 -5
  16. package/dist/auto-instrumentations/{chunk-AKKPLXTP.mjs → chunk-2AMDGD65.mjs} +160 -57
  17. package/dist/auto-instrumentations/{chunk-V5LEODRX.mjs → chunk-BW33ULMW.mjs} +1 -1
  18. package/dist/auto-instrumentations/{chunk-XYN63IG5.mjs → chunk-I55G56ZL.mjs} +21 -58
  19. package/dist/auto-instrumentations/{chunk-NRE4QUQR.mjs → chunk-JPUFNW7X.mjs} +140 -0
  20. package/dist/auto-instrumentations/{chunk-6E22MYSW.mjs → chunk-XEYKUBLY.mjs} +30 -4
  21. package/dist/auto-instrumentations/{chunk-XZHHE4Y3.mjs → chunk-ZNHTSSGI.mjs} +155 -2
  22. package/dist/auto-instrumentations/hook.mjs +161 -3
  23. package/dist/auto-instrumentations/index.cjs +296 -1
  24. package/dist/auto-instrumentations/index.d.mts +5 -1
  25. package/dist/auto-instrumentations/index.d.ts +5 -1
  26. package/dist/auto-instrumentations/index.mjs +6 -2
  27. package/dist/auto-instrumentations/loader/cjs-patch.cjs +105 -57
  28. package/dist/auto-instrumentations/loader/cjs-patch.mjs +2 -2
  29. package/dist/auto-instrumentations/loader/esm-hook.mjs +1 -1
  30. package/dist/browser.d.mts +57 -5
  31. package/dist/browser.d.ts +57 -5
  32. package/dist/browser.js +1855 -285
  33. package/dist/browser.mjs +1855 -285
  34. package/dist/{chunk-PN7EWK66.mjs → chunk-CZM5JIQL.mjs} +209 -1
  35. package/dist/{chunk-VYNNEKSA.js → chunk-MF7NU6BT.js} +216 -8
  36. package/dist/{chunk-VRZZQPAA.js → chunk-QRHGVBKU.js} +2403 -1220
  37. package/dist/{chunk-XIZOM2HO.mjs → chunk-YKD22IMR.mjs} +1454 -271
  38. package/dist/cli.js +1645 -272
  39. package/dist/edge-light.d.mts +1 -1
  40. package/dist/edge-light.d.ts +1 -1
  41. package/dist/edge-light.js +1855 -285
  42. package/dist/edge-light.mjs +1855 -285
  43. package/dist/index.d.mts +57 -5
  44. package/dist/index.d.ts +57 -5
  45. package/dist/index.js +600 -413
  46. package/dist/index.mjs +201 -14
  47. package/dist/instrumentation/index.d.mts +8 -0
  48. package/dist/instrumentation/index.d.ts +8 -0
  49. package/dist/instrumentation/index.js +1839 -466
  50. package/dist/instrumentation/index.mjs +1839 -466
  51. package/dist/vitest-evals-reporter.js +45 -43
  52. package/dist/vitest-evals-reporter.mjs +5 -3
  53. package/dist/workerd.d.mts +1 -1
  54. package/dist/workerd.d.ts +1 -1
  55. package/dist/workerd.js +1855 -285
  56. package/dist/workerd.mjs +1855 -285
  57. package/package.json +1 -1
@@ -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 {
@@ -5426,6 +5584,7 @@ var INSTRUMENTATION_NAMES = {
5426
5584
  CLAUDE_AGENT_SDK: "claude-agent-sdk",
5427
5585
  CLOUDFLARE_AI_CHAT: "cloudflare-ai-chat",
5428
5586
  CLOUDFLARE_AGENTS: "cloudflare-agents",
5587
+ CLOUDFLARE_THINK: "cloudflare-think",
5429
5588
  COHERE: "cohere",
5430
5589
  CURSOR_SDK: "cursor-sdk",
5431
5590
  EVE: "eve",
@@ -5440,6 +5599,7 @@ var INSTRUMENTATION_NAMES = {
5440
5599
  LANGSMITH: "langsmith",
5441
5600
  MASTRA: "mastra",
5442
5601
  MISTRAL: "mistral",
5602
+ OLLAMA: "ollama",
5443
5603
  OPENAI: "openai",
5444
5604
  OPENAI_AGENTS: "openai-agents",
5445
5605
  OPENAI_CODEX: "openai-codex",
@@ -5451,7 +5611,7 @@ var INSTRUMENTATION_NAMES = {
5451
5611
  var INTERNAL_SPAN_INSTRUMENTATION_NAME = /* @__PURE__ */ Symbol.for(
5452
5612
  "braintrust.spanInstrumentationName"
5453
5613
  );
5454
- var SDK_VERSION = true ? "3.26.0" : "0.0.0";
5614
+ var SDK_VERSION = true ? "3.27.0" : "0.0.0";
5455
5615
  function withSpanInstrumentationName(args, instrumentationName) {
5456
5616
  return {
5457
5617
  ...args,
@@ -10472,6 +10632,33 @@ function traceStreamingChannel(channel2, config) {
10472
10632
  const { span, startTime } = spanData;
10473
10633
  if (isAsyncIterable(asyncEndEvent.result)) {
10474
10634
  let firstChunkTime;
10635
+ const handleStreamError = (error) => {
10636
+ try {
10637
+ span.log({ error });
10638
+ } catch (loggingError) {
10639
+ debugLogger.error(
10640
+ `Error logging failure for ${channelName}:`,
10641
+ loggingError
10642
+ );
10643
+ }
10644
+ try {
10645
+ span.end();
10646
+ } catch (endingError) {
10647
+ debugLogger.error(
10648
+ `Error ending span for ${channelName}:`,
10649
+ endingError
10650
+ );
10651
+ }
10652
+ states.delete(event);
10653
+ runStreamingErrorHook({
10654
+ channelName,
10655
+ config,
10656
+ error,
10657
+ event: asyncEndEvent,
10658
+ span,
10659
+ startTime
10660
+ });
10661
+ };
10475
10662
  patchStreamIfNeeded(asyncEndEvent.result, {
10476
10663
  onChunk: () => {
10477
10664
  if (firstChunkTime === void 0) {
@@ -10551,33 +10738,12 @@ function traceStreamingChannel(channel2, config) {
10551
10738
  });
10552
10739
  }
10553
10740
  },
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
- }
10741
+ onCancel: () => {
10742
+ const error = new Error("Stream cancelled before completion");
10743
+ error.name = "AbortError";
10744
+ handleStreamError(error);
10745
+ },
10746
+ onError: handleStreamError
10581
10747
  });
10582
10748
  return;
10583
10749
  }
@@ -10965,11 +11131,21 @@ function defineChannels(pkg, channels, options) {
10965
11131
  const tracingChannel2 = () => isomorph_default.newTracingChannel(
10966
11132
  fullChannelName
10967
11133
  );
11134
+ const intercept2 = (interceptor) => {
11135
+ const hook = tracingChannel2();
11136
+ return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
11137
+ };
11138
+ };
10968
11139
  return [
10969
11140
  key,
10970
11141
  {
10971
11142
  ...asyncSpec,
10972
11143
  instrumentationName,
11144
+ intercept: intercept2,
11145
+ invoke: (target, thisArg, args, additional) => {
11146
+ const hook = tracingChannel2();
11147
+ return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
11148
+ },
10973
11149
  tracingChannel: tracingChannel2,
10974
11150
  tracePromise: (fn, context) => tracingChannel2().tracePromise(
10975
11151
  fn,
@@ -10983,11 +11159,21 @@ function defineChannels(pkg, channels, options) {
10983
11159
  const tracingChannel = () => isomorph_default.newTracingChannel(
10984
11160
  fullChannelName
10985
11161
  );
11162
+ const intercept = (interceptor) => {
11163
+ const hook = tracingChannel();
11164
+ return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
11165
+ };
11166
+ };
10986
11167
  return [
10987
11168
  key,
10988
11169
  {
10989
11170
  ...syncSpec,
10990
11171
  instrumentationName,
11172
+ intercept,
11173
+ invoke: (target, thisArg, args, additional) => {
11174
+ const hook = tracingChannel();
11175
+ return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
11176
+ },
10991
11177
  tracingChannel,
10992
11178
  traceSync: (fn, context) => tracingChannel().traceSync(
10993
11179
  fn,
@@ -12238,6 +12424,12 @@ function extractAnthropicCacheTokens(cacheReadTokens = 0, cacheCreationTokens =
12238
12424
  return cacheTokens;
12239
12425
  }
12240
12426
 
12427
+ // src/wrappers/anthropic-session-collector.ts
12428
+ var sessionStreamCollectors = /* @__PURE__ */ new WeakMap();
12429
+ function registerAnthropicSessionStreamCollector(stream, collector) {
12430
+ sessionStreamCollectors.set(stream, collector);
12431
+ }
12432
+
12241
12433
  // src/instrumentation/plugins/anthropic-channels.ts
12242
12434
  var anthropicChannels = defineChannels(
12243
12435
  "@anthropic-ai/sdk",
@@ -12253,6 +12445,14 @@ var anthropicChannels = defineChannels(
12253
12445
  betaMessagesToolRunner: channel({
12254
12446
  channelName: "beta.messages.toolRunner",
12255
12447
  kind: "sync-stream"
12448
+ }),
12449
+ betaSessionsEventsStream: channel({
12450
+ channelName: "beta.sessions.events.stream",
12451
+ kind: "async"
12452
+ }),
12453
+ betaSessionsThreadsEventsStream: channel({
12454
+ channelName: "beta.sessions.threads.events.stream",
12455
+ kind: "async"
12256
12456
  })
12257
12457
  },
12258
12458
  { instrumentationName: INSTRUMENTATION_NAMES.ANTHROPIC }
@@ -12266,6 +12466,7 @@ var AnthropicPlugin = class extends BasePlugin {
12266
12466
  onEnable() {
12267
12467
  this.subscribeToAnthropicChannels();
12268
12468
  this.subscribeToAnthropicToolRunner();
12469
+ this.subscribeToAnthropicSessionStreams();
12269
12470
  }
12270
12471
  onDisable() {
12271
12472
  this.unsubscribers = unsubscribeAll(this.unsubscribers);
@@ -12383,7 +12584,411 @@ var AnthropicPlugin = class extends BasePlugin {
12383
12584
  tracingChannel.unsubscribe(handlers);
12384
12585
  });
12385
12586
  }
12587
+ subscribeToAnthropicSessionStreams() {
12588
+ this.subscribeToAnthropicSessionStream(
12589
+ anthropicChannels.betaSessionsEventsStream,
12590
+ false
12591
+ );
12592
+ this.subscribeToAnthropicSessionStream(
12593
+ anthropicChannels.betaSessionsThreadsEventsStream,
12594
+ true
12595
+ );
12596
+ }
12597
+ subscribeToAnthropicSessionStream(channel2, isThread) {
12598
+ const tracingChannel = channel2.tracingChannel();
12599
+ const pending = /* @__PURE__ */ new WeakSet();
12600
+ const handlers = {
12601
+ start: (event) => {
12602
+ if (isAutoInstrumentationSuppressed()) {
12603
+ return;
12604
+ }
12605
+ pending.add(event);
12606
+ },
12607
+ asyncEnd: (event) => {
12608
+ if (!pending.delete(event)) {
12609
+ return;
12610
+ }
12611
+ const stream = event.result;
12612
+ if (!isAsyncIterable(stream)) {
12613
+ return;
12614
+ }
12615
+ registerAnthropicSessionStreamCollector(stream, () => {
12616
+ wrapAnthropicSessionEventStream(stream, isThread);
12617
+ });
12618
+ },
12619
+ error: (event) => {
12620
+ pending.delete(event);
12621
+ }
12622
+ };
12623
+ tracingChannel.subscribe(handlers);
12624
+ this.unsubscribers.push(() => tracingChannel.unsubscribe(handlers));
12625
+ }
12386
12626
  };
12627
+ function wrapAnthropicSessionEventStream(stream, isThread) {
12628
+ const state = {
12629
+ history: [],
12630
+ isThread,
12631
+ pendingInput: [],
12632
+ seenEventIds: /* @__PURE__ */ new Set()
12633
+ };
12634
+ patchStreamIfNeeded(stream, {
12635
+ onChunk: (event) => handleAnthropicSessionEvent(state, event),
12636
+ onComplete: () => finalizeAnthropicSessionTurn(state),
12637
+ onError: (error) => finalizeAnthropicSessionTurn(state, error)
12638
+ });
12639
+ return stream;
12640
+ }
12641
+ function handleAnthropicSessionEvent(state, event) {
12642
+ try {
12643
+ if (typeof event.id === "string" && event.type !== "event_delta" && state.seenEventIds.has(event.id)) {
12644
+ return;
12645
+ }
12646
+ if (typeof event.id === "string" && event.type !== "event_delta") {
12647
+ state.seenEventIds.add(event.id);
12648
+ }
12649
+ switch (event.type) {
12650
+ case "user.message":
12651
+ case "system.message":
12652
+ recordAnthropicSessionInput(
12653
+ state,
12654
+ event
12655
+ );
12656
+ break;
12657
+ case "session.status_running":
12658
+ if (!state.isThread) {
12659
+ ensureAnthropicSessionTurn(state);
12660
+ }
12661
+ break;
12662
+ case "session.thread_status_running":
12663
+ if (state.isThread) {
12664
+ ensureAnthropicSessionTurn(state);
12665
+ }
12666
+ break;
12667
+ case "span.model_request_start":
12668
+ if (typeof event.id === "string") {
12669
+ startAnthropicSessionModel(state, event.id);
12670
+ }
12671
+ break;
12672
+ case "event_delta":
12673
+ recordAnthropicSessionFirstToken(state, event);
12674
+ break;
12675
+ case "agent.message":
12676
+ recordAnthropicSessionMessage(
12677
+ state,
12678
+ event
12679
+ );
12680
+ break;
12681
+ case "agent.custom_tool_use":
12682
+ case "agent.mcp_tool_use":
12683
+ case "agent.tool_use":
12684
+ startAnthropicSessionTool(state, event);
12685
+ break;
12686
+ case "user.tool_confirmation":
12687
+ recordAnthropicSessionToolConfirmation(state, event);
12688
+ break;
12689
+ case "agent.mcp_tool_result":
12690
+ case "agent.tool_result":
12691
+ case "user.custom_tool_result":
12692
+ case "user.tool_result":
12693
+ finalizeAnthropicSessionTool(
12694
+ state,
12695
+ event
12696
+ );
12697
+ break;
12698
+ case "span.model_request_end":
12699
+ finalizeAnthropicSessionModel(
12700
+ state,
12701
+ event
12702
+ );
12703
+ break;
12704
+ case "session.status_idle":
12705
+ case "session.thread_status_idle": {
12706
+ if (event.type === "session.status_idle" && state.isThread || event.type === "session.thread_status_idle" && !state.isThread) {
12707
+ break;
12708
+ }
12709
+ const stopReason = isObject(event.stop_reason) ? event.stop_reason.type : void 0;
12710
+ if (stopReason === "end_turn") {
12711
+ finalizeAnthropicSessionTurn(state);
12712
+ } else if (stopReason === "retries_exhausted") {
12713
+ finalizeAnthropicSessionTurn(
12714
+ state,
12715
+ "Anthropic session retries exhausted"
12716
+ );
12717
+ }
12718
+ break;
12719
+ }
12720
+ case "session.error":
12721
+ finalizeAnthropicSessionTurn(state, event.error);
12722
+ break;
12723
+ case "session.deleted":
12724
+ case "session.status_terminated":
12725
+ case "session.thread_status_terminated":
12726
+ if (event.type === "session.deleted" || event.type === "session.status_terminated" && !state.isThread || event.type === "session.thread_status_terminated" && state.isThread) {
12727
+ finalizeAnthropicSessionTurn(state);
12728
+ }
12729
+ break;
12730
+ default:
12731
+ break;
12732
+ }
12733
+ } catch (error) {
12734
+ debugLogger.debug("Error processing Anthropic Sessions event:", error);
12735
+ }
12736
+ }
12737
+ function ensureAnthropicSessionTurn(state) {
12738
+ if (state.activeTurn) {
12739
+ return state.activeTurn;
12740
+ }
12741
+ const input = state.pendingInput;
12742
+ state.pendingInput = [];
12743
+ const span = startSpan(
12744
+ withSpanInstrumentationName(
12745
+ {
12746
+ event: {
12747
+ ...input.length > 0 ? { input } : {},
12748
+ metadata: { provider: "anthropic" }
12749
+ },
12750
+ name: state.isThread ? "anthropic.beta.sessions.thread.turn" : "anthropic.beta.sessions.turn",
12751
+ spanAttributes: { type: "task" /* TASK */ }
12752
+ },
12753
+ INSTRUMENTATION_NAMES.ANTHROPIC
12754
+ )
12755
+ );
12756
+ state.activeTurn = {
12757
+ activeTools: /* @__PURE__ */ new Map(),
12758
+ input: input.slice(),
12759
+ metrics: {},
12760
+ span
12761
+ };
12762
+ return state.activeTurn;
12763
+ }
12764
+ function recordAnthropicSessionInput(state, event) {
12765
+ const content = processAttachmentsInInput(event.content);
12766
+ const message = {
12767
+ role: event.type === "system.message" ? "system" : "user",
12768
+ content
12769
+ };
12770
+ state.history.push(message);
12771
+ if (state.activeTurn) {
12772
+ state.activeTurn.input.push(message);
12773
+ } else {
12774
+ state.pendingInput.push(message);
12775
+ }
12776
+ }
12777
+ function startAnthropicSessionModel(state, startEventId) {
12778
+ const turn = ensureAnthropicSessionTurn(state);
12779
+ if (turn.activeModel) {
12780
+ finalizeAnthropicSessionModelState(state, turn);
12781
+ }
12782
+ const span = withCurrent(
12783
+ turn.span,
12784
+ () => startSpan(
12785
+ withSpanInstrumentationName(
12786
+ {
12787
+ event: {
12788
+ ...state.history.length > 0 ? { input: state.history.slice() } : {},
12789
+ metadata: { provider: "anthropic" }
12790
+ },
12791
+ name: "anthropic.messages.create",
12792
+ spanAttributes: { type: "llm" /* LLM */ }
12793
+ },
12794
+ INSTRUMENTATION_NAMES.ANTHROPIC
12795
+ )
12796
+ )
12797
+ );
12798
+ turn.activeModel = {
12799
+ output: [],
12800
+ span,
12801
+ startEventId,
12802
+ startTime: getCurrentUnixTimestamp()
12803
+ };
12804
+ }
12805
+ function recordAnthropicSessionFirstToken(state, event) {
12806
+ const model = state.activeTurn?.activeModel;
12807
+ if (!model || model.firstTokenTime !== void 0 || !isObject(event.delta) || !isObject(event.delta.content) || typeof event.delta.content.text !== "string") {
12808
+ return;
12809
+ }
12810
+ model.firstTokenTime = getCurrentUnixTimestamp();
12811
+ }
12812
+ function recordAnthropicSessionMessage(state, event) {
12813
+ const turn = ensureAnthropicSessionTurn(state);
12814
+ const content = processAttachmentsInInput(
12815
+ event.content
12816
+ );
12817
+ if (turn.activeModel) {
12818
+ turn.activeModel.output.push(...content);
12819
+ } else {
12820
+ const output = { role: "assistant", content };
12821
+ turn.lastOutput = output;
12822
+ state.history.push(output);
12823
+ }
12824
+ }
12825
+ function startAnthropicSessionTool(state, event) {
12826
+ const turn = ensureAnthropicSessionTurn(state);
12827
+ if (turn.activeModel) {
12828
+ turn.activeModel.output.push({
12829
+ type: "tool_use",
12830
+ id: event.id,
12831
+ name: event.name,
12832
+ input: event.input
12833
+ });
12834
+ }
12835
+ const existing = turn.activeTools.get(event.id);
12836
+ if (existing) {
12837
+ existing.span.end();
12838
+ turn.activeTools.delete(event.id);
12839
+ }
12840
+ const span = withCurrent(
12841
+ turn.span,
12842
+ () => startSpan(
12843
+ withSpanInstrumentationName(
12844
+ {
12845
+ event: { input: event.input },
12846
+ name: event.name,
12847
+ spanAttributes: { type: "tool" /* TOOL */ }
12848
+ },
12849
+ INSTRUMENTATION_NAMES.ANTHROPIC
12850
+ )
12851
+ )
12852
+ );
12853
+ const toolState = {
12854
+ approval: event.evaluated_permission === "allow" ? "approved" : event.evaluated_permission === "deny" ? "denied" : void 0,
12855
+ span
12856
+ };
12857
+ turn.activeTools.set(event.id, toolState);
12858
+ if (toolState.approval === "denied") {
12859
+ finalizeAnthropicSessionToolState(toolState);
12860
+ turn.activeTools.delete(event.id);
12861
+ }
12862
+ }
12863
+ function recordAnthropicSessionToolConfirmation(state, event) {
12864
+ if (typeof event.tool_use_id !== "string" || event.result !== "allow" && event.result !== "deny") {
12865
+ return;
12866
+ }
12867
+ const turn = state.activeTurn;
12868
+ const tool = turn?.activeTools.get(event.tool_use_id);
12869
+ if (!turn || !tool) {
12870
+ return;
12871
+ }
12872
+ tool.approval = event.result === "allow" ? "approved" : "denied";
12873
+ if (tool.approval === "denied") {
12874
+ finalizeAnthropicSessionToolState(tool);
12875
+ turn.activeTools.delete(event.tool_use_id);
12876
+ }
12877
+ }
12878
+ function finalizeAnthropicSessionTool(state, event) {
12879
+ const toolUseId = event.tool_use_id ?? event.mcp_tool_use_id ?? event.custom_tool_use_id;
12880
+ if (!toolUseId) {
12881
+ return;
12882
+ }
12883
+ const content = processAttachmentsInInput(event.content);
12884
+ const turn = state.activeTurn;
12885
+ const tool = turn?.activeTools.get(toolUseId);
12886
+ if (turn && tool) {
12887
+ finalizeAnthropicSessionToolState(tool, event, content);
12888
+ turn.activeTools.delete(toolUseId);
12889
+ }
12890
+ const toolResult = {
12891
+ type: "tool_result",
12892
+ tool_use_id: toolUseId,
12893
+ ...content !== void 0 ? { content } : {},
12894
+ ...event.is_error === true ? { is_error: true } : {}
12895
+ };
12896
+ state.history.push({
12897
+ role: "user",
12898
+ content: [toolResult]
12899
+ });
12900
+ }
12901
+ function finalizeAnthropicSessionToolState(state, event, content = event?.content) {
12902
+ safeAnthropicSessionLog(state.span, {
12903
+ ...event?.is_error === true ? {
12904
+ error: content ?? "Anthropic session tool execution failed"
12905
+ } : {},
12906
+ ...state.approval ? { metadata: { tool_approval: state.approval } } : {},
12907
+ ...content !== void 0 ? { output: content } : {}
12908
+ });
12909
+ state.span.end();
12910
+ }
12911
+ function finalizeAnthropicSessionModel(state, event) {
12912
+ const turn = state.activeTurn;
12913
+ const model = turn?.activeModel;
12914
+ if (!turn || !model || model.startEventId !== event.model_request_start_id) {
12915
+ return;
12916
+ }
12917
+ finalizeAnthropicSessionModelState(state, turn, event);
12918
+ }
12919
+ function finalizeAnthropicSessionModelState(state, turn, event) {
12920
+ const model = turn.activeModel;
12921
+ if (!model) {
12922
+ return;
12923
+ }
12924
+ turn.activeModel = void 0;
12925
+ const metrics = event ? parseAnthropicSessionModelUsage(event.model_usage) : {};
12926
+ if (model.firstTokenTime !== void 0) {
12927
+ metrics.time_to_first_token = model.firstTokenTime - model.startTime;
12928
+ }
12929
+ const output = model.output.length > 0 ? { role: "assistant", content: model.output } : void 0;
12930
+ safeAnthropicSessionLog(model.span, {
12931
+ ...event?.is_error ? { error: "Anthropic session model request failed" } : {},
12932
+ ...Object.keys(metrics).length > 0 ? { metrics } : {},
12933
+ ...output ? { output } : {}
12934
+ });
12935
+ model.span.end();
12936
+ if (output) {
12937
+ turn.lastOutput = output;
12938
+ state.history.push(output);
12939
+ }
12940
+ for (const key of [
12941
+ "prompt_tokens",
12942
+ "completion_tokens",
12943
+ "tokens",
12944
+ "prompt_cached_tokens",
12945
+ "prompt_cache_creation_tokens"
12946
+ ]) {
12947
+ const value = metrics[key];
12948
+ if (typeof value === "number") {
12949
+ turn.metrics[key] = (turn.metrics[key] ?? 0) + value;
12950
+ }
12951
+ }
12952
+ }
12953
+ function parseAnthropicSessionModelUsage(usage) {
12954
+ const finalized = finalizeAnthropicTokens({
12955
+ completion_tokens: usage.output_tokens,
12956
+ prompt_cache_creation_tokens: usage.cache_creation_input_tokens,
12957
+ prompt_cached_tokens: usage.cache_read_input_tokens,
12958
+ prompt_tokens: usage.input_tokens
12959
+ });
12960
+ return Object.fromEntries(
12961
+ Object.entries(finalized).filter(
12962
+ (entry) => entry[1] !== void 0
12963
+ )
12964
+ );
12965
+ }
12966
+ function finalizeAnthropicSessionTurn(state, error) {
12967
+ const turn = state.activeTurn;
12968
+ if (!turn) {
12969
+ return;
12970
+ }
12971
+ state.activeTurn = void 0;
12972
+ finalizeAnthropicSessionModelState(state, turn);
12973
+ for (const tool of turn.activeTools.values()) {
12974
+ finalizeAnthropicSessionToolState(tool);
12975
+ }
12976
+ turn.activeTools.clear();
12977
+ safeAnthropicSessionLog(turn.span, {
12978
+ ...error !== void 0 ? { error: error instanceof Error ? error : toLoggedError(error) } : {},
12979
+ ...turn.input.length > 0 ? { input: turn.input } : {},
12980
+ ...turn.lastOutput ? { output: turn.lastOutput } : {},
12981
+ ...Object.keys(turn.metrics).length > 0 ? { metrics: turn.metrics } : {}
12982
+ });
12983
+ turn.span.end();
12984
+ }
12985
+ function safeAnthropicSessionLog(span, event) {
12986
+ try {
12987
+ span.log(event);
12988
+ } catch (error) {
12989
+ debugLogger.debug("Error logging Anthropic Sessions span:", error);
12990
+ }
12991
+ }
12387
12992
  function parseMetricsFromUsage2(usage) {
12388
12993
  if (!usage) {
12389
12994
  return {};
@@ -14257,6 +14862,29 @@ var harnessAgentChannels = defineChannels(
14257
14862
  { instrumentationName: INSTRUMENTATION_NAMES.AI_SDK }
14258
14863
  );
14259
14864
 
14865
+ // src/instrumentation/plugins/cloudflare-think-context.ts
14866
+ var cloudflareThinkSpans = /* @__PURE__ */ new Map();
14867
+ function registerCloudflareThinkSpan(span) {
14868
+ if (span.spanId) {
14869
+ cloudflareThinkSpans.set(span.spanId, span);
14870
+ }
14871
+ }
14872
+ function unregisterCloudflareThinkSpan(span) {
14873
+ if (span.spanId) {
14874
+ cloudflareThinkSpans.delete(span.spanId);
14875
+ }
14876
+ }
14877
+ function currentCloudflareThinkSpan() {
14878
+ const parentSpanIds = _internalGetGlobalState()?.contextManager.getParentSpanIds()?.spanParents ?? [];
14879
+ for (const parentSpanId of parentSpanIds) {
14880
+ const span = cloudflareThinkSpans.get(parentSpanId);
14881
+ if (span) {
14882
+ return span;
14883
+ }
14884
+ }
14885
+ return void 0;
14886
+ }
14887
+
14260
14888
  // src/instrumentation/plugins/ai-sdk-plugin.ts
14261
14889
  var DEFAULT_DENY_OUTPUT_PATHS = [
14262
14890
  // v3
@@ -14363,6 +14991,7 @@ var AISDKPlugin = class extends BasePlugin {
14363
14991
  traceStreamingChannel(aiSDKChannels.streamText, {
14364
14992
  name: "streamText",
14365
14993
  type: "function" /* FUNCTION */,
14994
+ shouldTrace: () => currentCloudflareThinkSpan() === void 0,
14366
14995
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
14367
14996
  extractOutput: (result, endEvent) => processAISDKOutput(
14368
14997
  result,
@@ -14383,6 +15012,7 @@ var AISDKPlugin = class extends BasePlugin {
14383
15012
  traceSyncStreamChannel(aiSDKChannels.streamTextSync, {
14384
15013
  name: "streamText",
14385
15014
  type: "function" /* FUNCTION */,
15015
+ shouldTrace: () => currentCloudflareThinkSpan() === void 0,
14386
15016
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
14387
15017
  patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
14388
15018
  defaultDenyOutputPaths: denyOutputPaths,
@@ -15368,6 +15998,23 @@ function prepareAISDKWorkflowAgentStreamInput(params, event, span, defaultDenyOu
15368
15998
  metadata
15369
15999
  };
15370
16000
  }
16001
+ function prepareAISDKAgentCallInput(params, event, span, defaultDenyOutputPaths = DEFAULT_DENY_OUTPUT_PATHS) {
16002
+ const { input } = processAISDKWorkflowAgentCallInput(params);
16003
+ const metadata = extractMetadataFromCallParams(params, event.self);
16004
+ const childTracing = prepareAISDKChildTracing(
16005
+ params,
16006
+ event.self,
16007
+ span,
16008
+ defaultDenyOutputPaths,
16009
+ event.aiSDK,
16010
+ { agentOwner: true }
16011
+ );
16012
+ event.modelWrapped = childTracing.modelWrapped;
16013
+ if (childTracing.cleanup) {
16014
+ event.__braintrust_ai_sdk_cleanup = childTracing.cleanup;
16015
+ }
16016
+ return { input, metadata };
16017
+ }
15371
16018
  function prepareAISDKEmbedInput(params, self) {
15372
16019
  return {
15373
16020
  input: { ...params },
@@ -15391,6 +16038,18 @@ function extractTopLevelAISDKMetrics(result, event, startTime) {
15391
16038
  }
15392
16039
  return metrics;
15393
16040
  }
16041
+ async function extractResolvedAISDKTokenMetrics(result) {
16042
+ for (const field of ["totalUsage", "usage"]) {
16043
+ try {
16044
+ const usage = await Promise.resolve(result[field]);
16045
+ if (usage !== void 0) {
16046
+ return extractTokenMetrics({ [field]: usage });
16047
+ }
16048
+ } catch {
16049
+ }
16050
+ }
16051
+ return extractTokenMetrics(result);
16052
+ }
15394
16053
  function hasModelChildTracing(event) {
15395
16054
  return event?.modelWrapped === true || event?.__braintrust_ai_sdk_model_wrapped === true;
15396
16055
  }
@@ -16208,13 +16867,15 @@ function patchAISDKStreamingResult(args) {
16208
16867
  const {
16209
16868
  defaultDenyOutputPaths,
16210
16869
  endEvent,
16870
+ forceTopLevelMetrics,
16211
16871
  onComplete,
16212
16872
  onCancel,
16213
16873
  onError,
16214
16874
  result,
16215
16875
  resolvePromiseUsage,
16216
16876
  span,
16217
- startTime
16877
+ startTime,
16878
+ transformOutput
16218
16879
  } = args;
16219
16880
  if (!result || typeof result !== "object") {
16220
16881
  return false;
@@ -16267,8 +16928,8 @@ function patchAISDKStreamingResult(args) {
16267
16928
  }
16268
16929
  outputLogged = true;
16269
16930
  try {
16270
- const metrics = extractTopLevelAISDKMetrics(result, endEvent);
16271
- if (resolvePromiseUsage) {
16931
+ const metrics = forceTopLevelMetrics ? await extractResolvedAISDKTokenMetrics(result) : extractTopLevelAISDKMetrics(result, endEvent);
16932
+ if (resolvePromiseUsage && !forceTopLevelMetrics) {
16272
16933
  try {
16273
16934
  const resultRecord2 = result;
16274
16935
  const pendingUsage = resultRecord2.totalUsage ?? resultRecord2.usage;
@@ -16287,10 +16948,11 @@ function patchAISDKStreamingResult(args) {
16287
16948
  if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
16288
16949
  metrics.time_to_first_token = firstChunkTime - startTime;
16289
16950
  }
16290
- const output = await processAISDKStreamingOutput(
16951
+ const processedOutput = await processAISDKStreamingOutput(
16291
16952
  result,
16292
16953
  resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
16293
16954
  );
16955
+ const output = transformOutput ? transformOutput(processedOutput) : processedOutput;
16294
16956
  const metadata = buildResolvedMetadataPayload(result).metadata;
16295
16957
  try {
16296
16958
  span.log({
@@ -18712,6 +19374,295 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
18712
19374
  }
18713
19375
  };
18714
19376
 
19377
+ // src/instrumentation/plugins/cloudflare-think-channels.ts
19378
+ var cloudflareThinkChannels = defineChannels(
19379
+ "@cloudflare/think",
19380
+ {
19381
+ runInferenceLoop: channel({
19382
+ channelName: "Think.runInferenceLoop",
19383
+ kind: "async"
19384
+ })
19385
+ },
19386
+ { instrumentationName: INSTRUMENTATION_NAMES.CLOUDFLARE_THINK }
19387
+ );
19388
+
19389
+ // src/instrumentation/plugins/cloudflare-think-plugin.ts
19390
+ var THINK_STATE_ID = /* @__PURE__ */ Symbol.for("braintrust.cloudflare-think.state-id");
19391
+ var CloudflareThinkPlugin = class extends BasePlugin {
19392
+ statesBySpanId = /* @__PURE__ */ new Map();
19393
+ onEnable() {
19394
+ this.subscribeToThinkRuns();
19395
+ this.subscribeToAISDKStreamTextSync();
19396
+ this.subscribeToAISDKStreamTextAsync();
19397
+ }
19398
+ onDisable() {
19399
+ for (const unsubscribe of this.unsubscribers) {
19400
+ unsubscribe();
19401
+ }
19402
+ this.unsubscribers = [];
19403
+ for (const state of this.statesBySpanId.values()) {
19404
+ this.finishState(state);
19405
+ }
19406
+ this.statesBySpanId.clear();
19407
+ }
19408
+ subscribeToThinkRuns() {
19409
+ const channel2 = cloudflareThinkChannels.runInferenceLoop.tracingChannel();
19410
+ const states = /* @__PURE__ */ new WeakMap();
19411
+ const state = _internalGetGlobalState();
19412
+ const contextManager = state?.contextManager;
19413
+ const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
19414
+ const ensureState2 = (event) => {
19415
+ if (isAutoInstrumentationSuppressed()) {
19416
+ return void 0;
19417
+ }
19418
+ const existing = states.get(event);
19419
+ if (existing) {
19420
+ return existing;
19421
+ }
19422
+ const span = startSpan(
19423
+ withSpanInstrumentationName(
19424
+ {
19425
+ name: "Think.runTurn",
19426
+ spanAttributes: { type: "task" /* TASK */ }
19427
+ },
19428
+ INSTRUMENTATION_NAMES.CLOUDFLARE_THINK
19429
+ )
19430
+ );
19431
+ const runState = {
19432
+ aiResultPatched: false,
19433
+ fallbackInput: extractFallbackInput(event.self?.messages),
19434
+ finalized: false,
19435
+ inputLogged: false,
19436
+ span,
19437
+ startTime: getCurrentUnixTimestamp()
19438
+ };
19439
+ const metadata = {
19440
+ braintrust: {
19441
+ integration_name: "cloudflare-think",
19442
+ sdk_language: "typescript"
19443
+ }
19444
+ };
19445
+ if (typeof event.moduleVersion === "string") {
19446
+ metadata["cloudflare_think.version"] = event.moduleVersion;
19447
+ }
19448
+ span.log({ metadata });
19449
+ states.set(event, runState);
19450
+ if (span.spanId) {
19451
+ this.statesBySpanId.set(span.spanId, runState);
19452
+ }
19453
+ registerCloudflareThinkSpan(span);
19454
+ return runState;
19455
+ };
19456
+ if (contextManager && currentSpanStore && channel2.start) {
19457
+ channel2.start.bindStore(currentSpanStore, (event) => {
19458
+ const runState = ensureState2(event);
19459
+ return runState ? contextManager.wrapSpanForStore(runState.span) : currentSpanStore.getStore();
19460
+ });
19461
+ this.unsubscribers.push(
19462
+ () => channel2.start?.unbindStore(currentSpanStore)
19463
+ );
19464
+ }
19465
+ const handlers = {
19466
+ start: (event) => {
19467
+ ensureState2(event);
19468
+ },
19469
+ asyncEnd: (event) => {
19470
+ const runState = states.get(event);
19471
+ states.delete(event);
19472
+ if (!runState || runState.finalized || runState.aiResultPatched) {
19473
+ return;
19474
+ }
19475
+ this.finishState(runState, void 0, event.result);
19476
+ },
19477
+ error: (event) => {
19478
+ const runState = states.get(event);
19479
+ states.delete(event);
19480
+ if (runState) {
19481
+ this.finishState(runState, event.error);
19482
+ }
19483
+ }
19484
+ };
19485
+ channel2.subscribe(handlers);
19486
+ this.unsubscribers.push(() => channel2.unsubscribe(handlers));
19487
+ }
19488
+ subscribeToAISDKStreamTextSync() {
19489
+ const channel2 = aiSDKChannels.streamTextSync.tracingChannel();
19490
+ const handlers = {
19491
+ start: (event) => {
19492
+ this.startAISDKStream(event);
19493
+ },
19494
+ end: (event) => {
19495
+ this.endAISDKStream(event);
19496
+ },
19497
+ error: (event) => {
19498
+ this.errorAISDKStream(event);
19499
+ }
19500
+ };
19501
+ channel2.subscribe(handlers);
19502
+ this.unsubscribers.push(() => channel2.unsubscribe(handlers));
19503
+ }
19504
+ subscribeToAISDKStreamTextAsync() {
19505
+ const channel2 = aiSDKChannels.streamText.tracingChannel();
19506
+ const handlers = {
19507
+ start: (event) => {
19508
+ this.startAISDKStream(event);
19509
+ },
19510
+ asyncEnd: (event) => {
19511
+ this.endAISDKStream(event);
19512
+ },
19513
+ error: (event) => {
19514
+ this.errorAISDKStream(event);
19515
+ }
19516
+ };
19517
+ channel2.subscribe(handlers);
19518
+ this.unsubscribers.push(() => channel2.unsubscribe(handlers));
19519
+ }
19520
+ startAISDKStream(event) {
19521
+ const runState = this.currentState();
19522
+ if (!runState || runState.finalized) {
19523
+ return;
19524
+ }
19525
+ try {
19526
+ const prepared = prepareAISDKAgentCallInput(
19527
+ event.arguments[0],
19528
+ event,
19529
+ runState.span
19530
+ );
19531
+ runState.span.log({
19532
+ input: extractThinkTaskInput(prepared.input),
19533
+ metadata: {
19534
+ ...prepared.metadata,
19535
+ braintrust: {
19536
+ integration_name: "cloudflare-think",
19537
+ sdk_language: "typescript"
19538
+ }
19539
+ }
19540
+ });
19541
+ runState.inputLogged = true;
19542
+ runState.aiEvent = event;
19543
+ Reflect.set(event, THINK_STATE_ID, runState.span.spanId);
19544
+ } catch (error) {
19545
+ debugLogger.error(
19546
+ "Error preparing @cloudflare/think AI SDK tracing:",
19547
+ error
19548
+ );
19549
+ }
19550
+ }
19551
+ endAISDKStream(event) {
19552
+ const runState = this.stateForAISDKEvent(event);
19553
+ if (!runState || runState.finalized) {
19554
+ return;
19555
+ }
19556
+ const patched = patchAISDKStreamingResult({
19557
+ defaultDenyOutputPaths: DEFAULT_DENY_OUTPUT_PATHS,
19558
+ endEvent: event,
19559
+ forceTopLevelMetrics: true,
19560
+ onComplete: () => this.releaseState(runState),
19561
+ result: event.result,
19562
+ span: runState.span,
19563
+ startTime: runState.startTime,
19564
+ transformOutput: extractThinkTaskOutput
19565
+ });
19566
+ runState.aiResultPatched = patched;
19567
+ if (!patched) {
19568
+ this.finishState(runState, void 0, event.result);
19569
+ }
19570
+ }
19571
+ errorAISDKStream(event) {
19572
+ const runState = this.stateForAISDKEvent(event);
19573
+ if (runState) {
19574
+ this.finishState(runState, event.error);
19575
+ }
19576
+ }
19577
+ currentState() {
19578
+ const parentIds = _internalGetGlobalState()?.contextManager.getParentSpanIds()?.spanParents ?? [];
19579
+ for (const parentId of parentIds) {
19580
+ const state = this.statesBySpanId.get(parentId);
19581
+ if (state) {
19582
+ return state;
19583
+ }
19584
+ }
19585
+ return void 0;
19586
+ }
19587
+ stateForAISDKEvent(event) {
19588
+ const spanId = Reflect.get(event, THINK_STATE_ID);
19589
+ return typeof spanId === "string" ? this.statesBySpanId.get(spanId) : void 0;
19590
+ }
19591
+ finishState(state, error, output) {
19592
+ if (state.finalized) {
19593
+ return;
19594
+ }
19595
+ state.finalized = true;
19596
+ try {
19597
+ if (!state.inputLogged && state.fallbackInput !== void 0) {
19598
+ state.span.log({ input: state.fallbackInput });
19599
+ }
19600
+ if (error !== void 0) {
19601
+ state.span.log({ error });
19602
+ } else if (output !== void 0) {
19603
+ state.span.log({ output: extractThinkTaskOutput(output) });
19604
+ }
19605
+ finalizeAISDKChildTracing(state.aiEvent);
19606
+ state.span.end();
19607
+ } finally {
19608
+ this.releaseState(state);
19609
+ }
19610
+ }
19611
+ releaseState(state) {
19612
+ state.finalized = true;
19613
+ unregisterCloudflareThinkSpan(state.span);
19614
+ if (state.span.spanId) {
19615
+ this.statesBySpanId.delete(state.span.spanId);
19616
+ }
19617
+ }
19618
+ };
19619
+ function extractFallbackInput(messages) {
19620
+ if (!Array.isArray(messages) || messages.length === 0) {
19621
+ return void 0;
19622
+ }
19623
+ let latestUserIndex = -1;
19624
+ for (let index = messages.length - 1; index >= 0; index--) {
19625
+ if (messages[index]?.role === "user") {
19626
+ latestUserIndex = index;
19627
+ break;
19628
+ }
19629
+ }
19630
+ const selected = latestUserIndex >= 0 ? messages.slice(latestUserIndex) : [];
19631
+ return selected.map((message) => ({
19632
+ role: message.role,
19633
+ content: message.content ?? message.parts
19634
+ }));
19635
+ }
19636
+ function extractThinkTaskOutput(output) {
19637
+ if (!isObject(output)) {
19638
+ return output;
19639
+ }
19640
+ if (typeof output.text === "string") {
19641
+ return { role: "assistant", content: output.text };
19642
+ }
19643
+ if (output.object !== void 0) {
19644
+ return output.object;
19645
+ }
19646
+ return output;
19647
+ }
19648
+ function extractThinkTaskInput(input) {
19649
+ if (!isObject(input)) {
19650
+ return input;
19651
+ }
19652
+ const system = input.instructions ?? input.system;
19653
+ if (Array.isArray(input.messages)) {
19654
+ return system === void 0 ? input.messages : [{ role: "system", content: system }, ...input.messages];
19655
+ }
19656
+ if (Array.isArray(input.prompt)) {
19657
+ return system === void 0 ? input.prompt : [{ role: "system", content: system }, ...input.prompt];
19658
+ }
19659
+ if (typeof input.prompt === "string") {
19660
+ const messages = [{ role: "user", content: input.prompt }];
19661
+ return system === void 0 ? messages : [{ role: "system", content: system }, ...messages];
19662
+ }
19663
+ return input;
19664
+ }
19665
+
18715
19666
  // src/instrumentation/plugins/cursor-sdk-channels.ts
18716
19667
  var cursorSDKChannels = defineChannels(
18717
19668
  "@cursor/sdk",
@@ -24477,6 +25428,470 @@ function aggregateMistralStreamChunks(chunks) {
24477
25428
  };
24478
25429
  }
24479
25430
 
25431
+ // src/instrumentation/plugins/ollama-channels.ts
25432
+ var ollamaChannels = defineChannels(
25433
+ "ollama",
25434
+ {
25435
+ chat: channel({
25436
+ channelName: "chat",
25437
+ kind: "async"
25438
+ }),
25439
+ generate: channel({
25440
+ channelName: "generate",
25441
+ kind: "async"
25442
+ }),
25443
+ embed: channel({
25444
+ channelName: "embed",
25445
+ kind: "async"
25446
+ })
25447
+ },
25448
+ { instrumentationName: INSTRUMENTATION_NAMES.OLLAMA }
25449
+ );
25450
+
25451
+ // src/instrumentation/plugins/ollama-plugin.ts
25452
+ var OllamaPlugin = class extends BasePlugin {
25453
+ onEnable() {
25454
+ this.unsubscribers.push(
25455
+ traceStreamingChannel(ollamaChannels.chat, {
25456
+ name: "ollama.chat",
25457
+ type: "llm" /* LLM */,
25458
+ extractInput: extractOllamaChatInput,
25459
+ extractOutput: (result, event) => extractOllamaChatOutput(
25460
+ result,
25461
+ countOllamaToolCalls(event?.arguments?.[0]?.messages)
25462
+ ),
25463
+ extractMetadata: extractOllamaResponseMetadata,
25464
+ extractMetrics: extractOllamaMetrics,
25465
+ aggregateChunks: aggregateOllamaChatChunks
25466
+ }),
25467
+ traceStreamingChannel(ollamaChannels.generate, {
25468
+ name: "ollama.generate",
25469
+ type: "llm" /* LLM */,
25470
+ extractInput: extractOllamaGenerateInput,
25471
+ extractOutput: extractOllamaGenerateOutput,
25472
+ extractMetadata: extractOllamaResponseMetadata,
25473
+ extractMetrics: extractOllamaMetrics,
25474
+ aggregateChunks: aggregateOllamaGenerateChunks
25475
+ }),
25476
+ traceAsyncChannel(ollamaChannels.embed, {
25477
+ name: "ollama.embed",
25478
+ type: "llm" /* LLM */,
25479
+ extractInput: extractOllamaEmbedInput,
25480
+ extractOutput: extractOllamaEmbedOutput,
25481
+ extractMetadata: extractOllamaResponseMetadata,
25482
+ extractMetrics: extractOllamaMetrics
25483
+ })
25484
+ );
25485
+ }
25486
+ onDisable() {
25487
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
25488
+ }
25489
+ };
25490
+ function isNonNegativeNumber(value) {
25491
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
25492
+ }
25493
+ function normalizeFinishReason(response, hasToolCalls = false) {
25494
+ if (hasToolCalls) {
25495
+ return "tool_calls";
25496
+ }
25497
+ return response?.done_reason || "stop";
25498
+ }
25499
+ function stringifyArguments(value) {
25500
+ if (typeof value === "string") {
25501
+ return value;
25502
+ }
25503
+ try {
25504
+ return JSON.stringify(value ?? {});
25505
+ } catch {
25506
+ return String(value);
25507
+ }
25508
+ }
25509
+ function syntheticToolCallId(name, index) {
25510
+ const normalizedName = name.replace(/[^a-zA-Z0-9_-]/g, "_") || "tool";
25511
+ return `ollama_call_${normalizedName}_${index}`;
25512
+ }
25513
+ function normalizeToolCall(toolCall, index) {
25514
+ const name = toolCall.function?.name;
25515
+ if (typeof name !== "string" || name.length === 0) {
25516
+ return void 0;
25517
+ }
25518
+ return {
25519
+ id: typeof toolCall.id === "string" && toolCall.id.length > 0 ? toolCall.id : syntheticToolCallId(name, index),
25520
+ type: "function",
25521
+ function: {
25522
+ name,
25523
+ arguments: stringifyArguments(toolCall.function?.arguments)
25524
+ }
25525
+ };
25526
+ }
25527
+ function normalizeToolCalls(toolCalls, syntheticIdOffset = 0) {
25528
+ if (!Array.isArray(toolCalls)) {
25529
+ return [];
25530
+ }
25531
+ return toolCalls.flatMap((toolCall, index) => {
25532
+ const normalized = normalizeToolCall(toolCall, syntheticIdOffset + index);
25533
+ return normalized ? [normalized] : [];
25534
+ });
25535
+ }
25536
+ function countOllamaToolCalls(messages) {
25537
+ if (!Array.isArray(messages)) {
25538
+ return 0;
25539
+ }
25540
+ return messages.reduce(
25541
+ (count, message) => count + (isObject(message) && Array.isArray(message.tool_calls) ? message.tool_calls.length : 0),
25542
+ 0
25543
+ );
25544
+ }
25545
+ function imageBytes(value) {
25546
+ if (value instanceof Uint8Array) {
25547
+ return value;
25548
+ }
25549
+ if (value instanceof ArrayBuffer) {
25550
+ return new Uint8Array(value);
25551
+ }
25552
+ if (typeof value !== "string" || value.startsWith("data:")) {
25553
+ return void 0;
25554
+ }
25555
+ try {
25556
+ const decoded = atob(value.slice(0, 24));
25557
+ return Uint8Array.from(decoded, (character) => character.charCodeAt(0));
25558
+ } catch {
25559
+ return void 0;
25560
+ }
25561
+ }
25562
+ function inferImageMediaType(value) {
25563
+ if (typeof value === "string") {
25564
+ const dataUrlType = value.match(/^data:(image\/[^;]+);base64,/i)?.[1];
25565
+ if (dataUrlType) {
25566
+ return dataUrlType;
25567
+ }
25568
+ }
25569
+ const bytes = imageBytes(value);
25570
+ if (!bytes) {
25571
+ return void 0;
25572
+ }
25573
+ if (bytes[0] === 137 && bytes[1] === 80 && bytes[2] === 78 && bytes[3] === 71) {
25574
+ return "image/png";
25575
+ }
25576
+ if (bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255) {
25577
+ return "image/jpeg";
25578
+ }
25579
+ const signature = String.fromCharCode(...bytes.slice(0, 12));
25580
+ if (signature.startsWith("GIF87a") || signature.startsWith("GIF89a")) {
25581
+ return "image/gif";
25582
+ }
25583
+ if (signature.startsWith("RIFF") && signature.slice(8, 12) === "WEBP") {
25584
+ return "image/webp";
25585
+ }
25586
+ return void 0;
25587
+ }
25588
+ function normalizeTextAndImages(content, images) {
25589
+ if (!images || images.length === 0) {
25590
+ return { content };
25591
+ }
25592
+ const imageParts = [];
25593
+ const unrecognizedImages = [];
25594
+ for (const image of images) {
25595
+ let localImagePath;
25596
+ let localPathMediaType;
25597
+ if (typeof image === "string" && !/^data:/i.test(image) && !/^https?:\/\//i.test(image)) {
25598
+ const extension = image.match(/\.([a-z0-9]+)$/i)?.[1]?.toLowerCase();
25599
+ const extensionMediaType = {
25600
+ png: "image/png",
25601
+ jpg: "image/jpeg",
25602
+ jpeg: "image/jpeg",
25603
+ gif: "image/gif",
25604
+ webp: "image/webp"
25605
+ }[extension ?? ""];
25606
+ if (extensionMediaType && isomorph_default.statSync) {
25607
+ try {
25608
+ if (isomorph_default.statSync(image).isFile()) {
25609
+ localImagePath = image;
25610
+ localPathMediaType = extensionMediaType;
25611
+ }
25612
+ } catch {
25613
+ }
25614
+ }
25615
+ }
25616
+ const mediaType = localPathMediaType ?? inferImageMediaType(image);
25617
+ if (!mediaType) {
25618
+ unrecognizedImages.push(image);
25619
+ continue;
25620
+ }
25621
+ const processedImage = localImagePath ? new Attachment({
25622
+ data: localImagePath,
25623
+ filename: localImagePath.split(/[\\/]/).at(-1) ?? "image",
25624
+ contentType: mediaType
25625
+ }) : processInputAttachments({
25626
+ type: "image",
25627
+ image,
25628
+ mediaType
25629
+ }).image;
25630
+ imageParts.push({
25631
+ type: "image_url",
25632
+ image_url: { url: processedImage }
25633
+ });
25634
+ }
25635
+ return {
25636
+ content: imageParts.length > 0 ? [...content ? [{ type: "text", text: content }] : [], ...imageParts] : content,
25637
+ ...unrecognizedImages.length > 0 ? { unrecognizedImages } : {}
25638
+ };
25639
+ }
25640
+ function normalizeMessage(message, toolCallId, syntheticToolCallIdOffset = 0) {
25641
+ if (typeof message.role !== "string") {
25642
+ return void 0;
25643
+ }
25644
+ const toolCalls = normalizeToolCalls(
25645
+ message.tool_calls,
25646
+ syntheticToolCallIdOffset
25647
+ );
25648
+ if (message.role === "tool") {
25649
+ const toolName = typeof message.tool_name === "string" && message.tool_name.length > 0 ? message.tool_name : "tool";
25650
+ return {
25651
+ role: "tool",
25652
+ tool_call_id: toolCallId ?? syntheticToolCallId(toolName, 0),
25653
+ content: typeof message.content === "string" ? message.content : ""
25654
+ };
25655
+ }
25656
+ const normalizedContent = normalizeTextAndImages(
25657
+ typeof message.content === "string" ? message.content || (toolCalls.length > 0 ? null : "") : toolCalls.length > 0 ? null : "",
25658
+ message.images
25659
+ );
25660
+ return {
25661
+ role: message.role,
25662
+ content: normalizedContent.content,
25663
+ ...typeof message.thinking === "string" && message.thinking.length > 0 ? { reasoning: message.thinking } : {},
25664
+ ...toolCalls.length > 0 ? { tool_calls: toolCalls } : {},
25665
+ ...normalizedContent.unrecognizedImages ? { images: normalizedContent.unrecognizedImages } : {}
25666
+ };
25667
+ }
25668
+ function normalizeMessages(messages) {
25669
+ if (!Array.isArray(messages)) {
25670
+ return [];
25671
+ }
25672
+ const pendingToolCallIds = /* @__PURE__ */ new Map();
25673
+ let syntheticToolCallIdOffset = 0;
25674
+ return messages.flatMap((message) => {
25675
+ if (!isObject(message)) {
25676
+ return [];
25677
+ }
25678
+ const ollamaMessage = message;
25679
+ let toolCallId;
25680
+ if (ollamaMessage.role === "tool") {
25681
+ const toolName = ollamaMessage.tool_name;
25682
+ if (typeof toolName === "string") {
25683
+ toolCallId = pendingToolCallIds.get(toolName)?.shift();
25684
+ }
25685
+ }
25686
+ const normalized = normalizeMessage(
25687
+ ollamaMessage,
25688
+ toolCallId,
25689
+ syntheticToolCallIdOffset
25690
+ );
25691
+ if (Array.isArray(ollamaMessage.tool_calls)) {
25692
+ syntheticToolCallIdOffset += ollamaMessage.tool_calls.length;
25693
+ }
25694
+ if (ollamaMessage.role === "assistant" && normalized) {
25695
+ const toolCalls = Array.isArray(normalized.tool_calls) ? normalized.tool_calls : [];
25696
+ for (const toolCall of toolCalls) {
25697
+ if (!isObject(toolCall) || !isObject(toolCall.function)) {
25698
+ continue;
25699
+ }
25700
+ const name = toolCall.function.name;
25701
+ const id = toolCall.id;
25702
+ if (typeof name === "string" && typeof id === "string") {
25703
+ const ids = pendingToolCallIds.get(name) ?? [];
25704
+ ids.push(id);
25705
+ pendingToolCallIds.set(name, ids);
25706
+ }
25707
+ }
25708
+ }
25709
+ return normalized ? [normalized] : [];
25710
+ });
25711
+ }
25712
+ function normalizeToolDefinition(tool) {
25713
+ const fn = tool.function;
25714
+ if (!fn || typeof fn.name !== "string" || fn.name.length === 0) {
25715
+ return void 0;
25716
+ }
25717
+ return {
25718
+ type: "function",
25719
+ function: {
25720
+ name: fn.name,
25721
+ ...typeof fn.description === "string" ? { description: fn.description } : {},
25722
+ ...isObject(fn.parameters) ? { parameters: fn.parameters } : {}
25723
+ }
25724
+ };
25725
+ }
25726
+ function extractToolsMetadata(tools) {
25727
+ if (!Array.isArray(tools)) {
25728
+ return {};
25729
+ }
25730
+ const normalized = tools.flatMap((tool) => {
25731
+ if (!isObject(tool)) {
25732
+ return [];
25733
+ }
25734
+ const definition = normalizeToolDefinition(tool);
25735
+ return definition ? [definition] : [];
25736
+ });
25737
+ return normalized.length > 0 ? { tools: normalized } : {};
25738
+ }
25739
+ function extractOptionsMetadata(options) {
25740
+ if (!isObject(options)) {
25741
+ return {};
25742
+ }
25743
+ const metadata = {};
25744
+ const mappings = [
25745
+ ["temperature", "temperature"],
25746
+ ["top_p", "top_p"],
25747
+ ["num_predict", "max_tokens"],
25748
+ ["frequency_penalty", "frequency_penalty"],
25749
+ ["presence_penalty", "presence_penalty"],
25750
+ ["stop", "stop"]
25751
+ ];
25752
+ for (const [source, target] of mappings) {
25753
+ if (options[source] !== void 0) {
25754
+ metadata[target] = options[source];
25755
+ }
25756
+ }
25757
+ return metadata;
25758
+ }
25759
+ function extractRequestMetadata(request) {
25760
+ return {
25761
+ provider: "ollama",
25762
+ ...typeof request?.model === "string" ? { model: request.model } : {},
25763
+ ...extractOptionsMetadata(request?.options),
25764
+ ...request?.format !== void 0 ? { response_format: request.format } : {}
25765
+ };
25766
+ }
25767
+ function extractOllamaChatInput([request]) {
25768
+ return {
25769
+ input: normalizeMessages(request.messages),
25770
+ metadata: {
25771
+ ...extractRequestMetadata(request),
25772
+ ...extractToolsMetadata(request.tools)
25773
+ }
25774
+ };
25775
+ }
25776
+ function extractOllamaGenerateInput([request]) {
25777
+ const normalizedPrompt = normalizeTextAndImages(
25778
+ typeof request.prompt === "string" ? request.prompt : "",
25779
+ Array.isArray(request.images) ? request.images : void 0
25780
+ );
25781
+ const input = [
25782
+ ...typeof request.system === "string" ? [{ role: "system", content: request.system }] : [],
25783
+ {
25784
+ role: "user",
25785
+ content: normalizedPrompt.content,
25786
+ ...typeof request.suffix === "string" ? { suffix: request.suffix } : {},
25787
+ ...normalizedPrompt.unrecognizedImages ? { images: normalizedPrompt.unrecognizedImages } : {}
25788
+ }
25789
+ ];
25790
+ return {
25791
+ input,
25792
+ metadata: extractRequestMetadata(request)
25793
+ };
25794
+ }
25795
+ function extractOllamaEmbedInput([request]) {
25796
+ return {
25797
+ input: request.input,
25798
+ metadata: extractRequestMetadata(request)
25799
+ };
25800
+ }
25801
+ function extractOllamaChatOutput(result, syntheticToolCallIdOffset = 0) {
25802
+ if (!isObject(result) || !isObject(result.message)) {
25803
+ return void 0;
25804
+ }
25805
+ const message = normalizeMessage(
25806
+ result.message,
25807
+ void 0,
25808
+ syntheticToolCallIdOffset
25809
+ );
25810
+ if (!message) {
25811
+ return void 0;
25812
+ }
25813
+ const toolCalls = Array.isArray(message.tool_calls) ? message.tool_calls : [];
25814
+ return [
25815
+ {
25816
+ index: 0,
25817
+ finish_reason: normalizeFinishReason(result, toolCalls.length > 0),
25818
+ message
25819
+ }
25820
+ ];
25821
+ }
25822
+ function extractOllamaGenerateOutput(result) {
25823
+ if (!isObject(result) || typeof result.response !== "string") {
25824
+ return void 0;
25825
+ }
25826
+ return [
25827
+ {
25828
+ index: 0,
25829
+ finish_reason: normalizeFinishReason(result),
25830
+ message: {
25831
+ role: "assistant",
25832
+ content: result.response,
25833
+ ...typeof result.thinking === "string" && result.thinking.length > 0 ? { reasoning: result.thinking } : {}
25834
+ }
25835
+ }
25836
+ ];
25837
+ }
25838
+ function extractOllamaEmbedOutput(result) {
25839
+ const embedding = Array.isArray(result?.embeddings) ? result.embeddings[0] : void 0;
25840
+ return Array.isArray(embedding) ? { embedding_length: embedding.length } : void 0;
25841
+ }
25842
+ function extractOllamaResponseMetadata(result) {
25843
+ return typeof result?.model === "string" ? { model: result.model } : void 0;
25844
+ }
25845
+ function extractOllamaMetrics(result) {
25846
+ const metrics = {};
25847
+ const promptTokens = result?.prompt_eval_count;
25848
+ const completionTokens = result?.eval_count;
25849
+ if (isNonNegativeNumber(promptTokens)) {
25850
+ metrics.prompt_tokens = promptTokens;
25851
+ }
25852
+ if (isNonNegativeNumber(completionTokens)) {
25853
+ metrics.completion_tokens = completionTokens;
25854
+ }
25855
+ if (isNonNegativeNumber(promptTokens) || isNonNegativeNumber(completionTokens)) {
25856
+ metrics.tokens = (isNonNegativeNumber(promptTokens) ? promptTokens : 0) + (isNonNegativeNumber(completionTokens) ? completionTokens : 0);
25857
+ }
25858
+ return metrics;
25859
+ }
25860
+ function aggregateOllamaChatChunks(chunks, _result, event, _startTime) {
25861
+ const last = chunks.at(-1);
25862
+ const message = {
25863
+ role: "assistant",
25864
+ content: chunks.map((chunk) => chunk.message?.content ?? "").join(""),
25865
+ thinking: chunks.map((chunk) => chunk.message?.thinking ?? "").join(""),
25866
+ tool_calls: chunks.flatMap((chunk) => chunk.message?.tool_calls ?? [])
25867
+ };
25868
+ const response = {
25869
+ ...last,
25870
+ message
25871
+ };
25872
+ return {
25873
+ output: extractOllamaChatOutput(
25874
+ response,
25875
+ countOllamaToolCalls(event?.arguments?.[0]?.messages)
25876
+ ),
25877
+ metrics: extractOllamaMetrics(last ?? {}),
25878
+ metadata: extractOllamaResponseMetadata(last ?? {})
25879
+ };
25880
+ }
25881
+ function aggregateOllamaGenerateChunks(chunks, _result, _event, _startTime) {
25882
+ const last = chunks.at(-1);
25883
+ const response = {
25884
+ ...last,
25885
+ response: chunks.map((chunk) => chunk.response ?? "").join(""),
25886
+ thinking: chunks.map((chunk) => chunk.thinking ?? "").join("")
25887
+ };
25888
+ return {
25889
+ output: extractOllamaGenerateOutput(response),
25890
+ metrics: extractOllamaMetrics(last ?? {}),
25891
+ metadata: extractOllamaResponseMetadata(last ?? {})
25892
+ };
25893
+ }
25894
+
24480
25895
  // src/instrumentation/plugins/google-adk-channels.ts
24481
25896
  var googleADKChannels = defineChannels(
24482
25897
  "@google/adk",
@@ -28230,7 +29645,7 @@ var FlueObserveBridge = class {
28230
29645
  return;
28231
29646
  }
28232
29647
  const state = this.operationsById.get(event.operationId) ?? this.startSyntheticOperation(event);
28233
- const output = operationOutput(event);
29648
+ const output = operationOutput(event) ?? outputFromAgentTurn(state.latestAgentOutput);
28234
29649
  const metadata = {
28235
29650
  ...state.metadata,
28236
29651
  ...extractEventMetadata(event),
@@ -28239,7 +29654,7 @@ var FlueObserveBridge = class {
28239
29654
  };
28240
29655
  this.finishPendingChildrenForOperation(event, output);
28241
29656
  safeLog3(state.span, {
28242
- ...event.isError ? { error: toLoggedError(event.error) } : {},
29657
+ ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.error) } : {},
28243
29658
  metadata,
28244
29659
  metrics: durationMetrics2(event.durationMs),
28245
29660
  output
@@ -28270,7 +29685,7 @@ var FlueObserveBridge = class {
28270
29685
  };
28271
29686
  const parent = this.parentSpanForTurn(event);
28272
29687
  const span = startFlueSpan(parent, {
28273
- name: `llm:${model ?? event.purpose ?? "unknown"}`,
29688
+ name: "flue.turn",
28274
29689
  spanAttributes: { type: "llm" /* LLM */ },
28275
29690
  startTime: eventTime(event.timestamp),
28276
29691
  event: {
@@ -28314,6 +29729,12 @@ var FlueObserveBridge = class {
28314
29729
  },
28315
29730
  output
28316
29731
  });
29732
+ if (event.purpose === "agent" && event.operationId) {
29733
+ const operation = this.operationsById.get(event.operationId);
29734
+ if (operation) {
29735
+ operation.latestAgentOutput = output;
29736
+ }
29737
+ }
28317
29738
  safeEnd(state.span, eventTime(event.timestamp));
28318
29739
  this.turnsByKey.delete(key);
28319
29740
  }
@@ -28393,7 +29814,7 @@ var FlueObserveBridge = class {
28393
29814
  return;
28394
29815
  }
28395
29816
  safeLog3(state.span, {
28396
- ...event.isError ? { error: toLoggedError(event.result) } : {},
29817
+ ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.result) } : {},
28397
29818
  metadata: {
28398
29819
  ...state.metadata,
28399
29820
  ...extractEventMetadata(event),
@@ -28439,6 +29860,7 @@ var FlueObserveBridge = class {
28439
29860
  ...event.usage ? { "flue.usage": event.usage } : {}
28440
29861
  };
28441
29862
  safeLog3(state.span, {
29863
+ ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.error) } : {},
28442
29864
  metadata,
28443
29865
  metrics: {
28444
29866
  ...durationMetrics2(event.durationMs),
@@ -28543,7 +29965,7 @@ var FlueObserveBridge = class {
28543
29965
  ...event.purpose ? { "flue.turn_purpose": event.purpose } : {}
28544
29966
  };
28545
29967
  const span = startFlueSpan(this.parentSpanForEvent(event), {
28546
- name: `llm:${model ?? event.purpose ?? "unknown"}`,
29968
+ name: "flue.turn",
28547
29969
  spanAttributes: { type: "llm" /* LLM */ },
28548
29970
  startTime: eventTime(event.timestamp),
28549
29971
  event: { metadata }
@@ -28675,7 +30097,10 @@ function extractEventMetadata(event, ctx) {
28675
30097
  return {
28676
30098
  ...event.runId ? { "flue.run_id": event.runId } : {},
28677
30099
  ...event.instanceId ? { "flue.instance_id": event.instanceId } : {},
30100
+ ...event.submissionId ? { "flue.submission_id": event.submissionId } : {},
28678
30101
  ...event.dispatchId ? { "flue.dispatch_id": event.dispatchId } : {},
30102
+ ...event.agentName ? { "flue.agent_name": event.agentName } : {},
30103
+ ...event.conversationId ? { "flue.conversation_id": event.conversationId } : {},
28679
30104
  ...typeof event.eventIndex === "number" ? { "flue.event_index": event.eventIndex } : {},
28680
30105
  ...event.session ? { "flue.session": event.session } : {},
28681
30106
  ...event.parentSession ? { "flue.parent_session": event.parentSession } : {},
@@ -28704,7 +30129,7 @@ function flueTurnRequestInput(event) {
28704
30129
  return event.request?.input ?? event.input;
28705
30130
  }
28706
30131
  function flueTurnRequestModel(event) {
28707
- return event.request?.model ?? event.model;
30132
+ return event.request?.requestedModel ?? event.request?.model ?? event.model;
28708
30133
  }
28709
30134
  function flueTurnRequestProvider(event) {
28710
30135
  return event.request?.providerName ?? event.provider ?? event.request?.providerId;
@@ -28713,10 +30138,10 @@ function flueTurnRequestApi(event) {
28713
30138
  return event.request?.api ?? event.api;
28714
30139
  }
28715
30140
  function flueTurnRequestReasoning(event) {
28716
- return event.request?.reasoning ?? event.reasoning;
30141
+ return event.request?.reasoningLevel ?? event.request?.reasoning ?? event.reasoning;
28717
30142
  }
28718
30143
  function flueTurnModel(event) {
28719
- return event.request?.model ?? event.model;
30144
+ return event.response?.responseModel ?? event.request?.requestedModel ?? event.request?.model ?? event.model;
28720
30145
  }
28721
30146
  function flueTurnProvider(event) {
28722
30147
  return event.request?.providerName ?? event.provider ?? event.request?.providerId;
@@ -28731,7 +30156,7 @@ function flueTurnOutput(event) {
28731
30156
  return event.response?.output ?? event.output;
28732
30157
  }
28733
30158
  function flueTurnStopReason(event) {
28734
- return event.response?.stopReason ?? event.stopReason;
30159
+ return event.response?.finishReason ?? event.response?.stopReason ?? event.stopReason;
28735
30160
  }
28736
30161
  function flueTurnError(event) {
28737
30162
  return event.response?.error ?? event.response?.errorInfo?.message ?? event.error;
@@ -28746,6 +30171,9 @@ function flueToolInput(event) {
28746
30171
  return event.input;
28747
30172
  }
28748
30173
  function flueToolOutput(event) {
30174
+ if (Object.hasOwn(event, "effectiveResult")) {
30175
+ return event.effectiveResult;
30176
+ }
28749
30177
  return event.output !== void 0 ? event.output : event.result;
28750
30178
  }
28751
30179
  function flueToolError(event) {
@@ -28753,10 +30181,36 @@ function flueToolError(event) {
28753
30181
  }
28754
30182
  function operationOutput(event) {
28755
30183
  if (event.operationKind === "prompt" || event.operationKind === "skill") {
28756
- return llmResultFromOperationResult(event.result);
30184
+ return outputFromAgentInvocation(event.agentOutput) ?? llmResultFromOperationResult(event.result);
28757
30185
  }
28758
30186
  return event.result ?? (event.operationKind === "compact" ? { completed: true } : void 0);
28759
30187
  }
30188
+ function outputFromAgentInvocation(output) {
30189
+ if (output?.type === "text") {
30190
+ return output.text;
30191
+ }
30192
+ if (output?.type === "data") {
30193
+ return output.data;
30194
+ }
30195
+ return void 0;
30196
+ }
30197
+ function outputFromAgentTurn(output) {
30198
+ if (!isObjectLike(output)) {
30199
+ return output;
30200
+ }
30201
+ const content = Reflect.get(output, "content");
30202
+ if (!Array.isArray(content)) {
30203
+ return output;
30204
+ }
30205
+ const text = content.flatMap((part) => {
30206
+ if (!isObjectLike(part) || Reflect.get(part, "type") !== "text") {
30207
+ return [];
30208
+ }
30209
+ const value = Reflect.get(part, "text");
30210
+ return typeof value === "string" ? [value] : [];
30211
+ });
30212
+ return text.length > 0 ? text.join("") : output;
30213
+ }
28760
30214
  function llmResultFromOperationResult(result) {
28761
30215
  if (!isObjectLike(result)) {
28762
30216
  return result;
@@ -28855,7 +30309,7 @@ function safeEnd(span, endTime) {
28855
30309
  }
28856
30310
  }
28857
30311
  function logInstrumentationError3(label, error) {
28858
- console.error(`Error in ${label} instrumentation:`, error);
30312
+ debugLogger.debug(`Error in ${label} instrumentation:`, error);
28859
30313
  }
28860
30314
 
28861
30315
  // src/wrappers/langchain/callback-handler.ts
@@ -29784,12 +31238,13 @@ var piCodingAgentChannels = defineChannels(
29784
31238
  );
29785
31239
 
29786
31240
  // src/instrumentation/plugins/pi-coding-agent-plugin.ts
29787
- var piStreamPatchStates = /* @__PURE__ */ new WeakMap();
31241
+ var piAgentPatchStates = /* @__PURE__ */ new WeakMap();
31242
+ var piAgentEventSubscriptions = /* @__PURE__ */ new WeakSet();
29788
31243
  var piPromptContextStore;
29789
31244
  var PiCodingAgentPlugin = class extends BasePlugin {
29790
31245
  activePromptStates = /* @__PURE__ */ new Set();
29791
31246
  onEnable() {
29792
- this.subscribeToPrompt();
31247
+ this.interceptPrompt();
29793
31248
  }
29794
31249
  onDisable() {
29795
31250
  for (const unsubscribe of this.unsubscribers) {
@@ -29797,65 +31252,74 @@ var PiCodingAgentPlugin = class extends BasePlugin {
29797
31252
  }
29798
31253
  this.unsubscribers = [];
29799
31254
  for (const state of [...this.activePromptStates]) {
29800
- void finalizePiPromptRun(state).catch((error) => {
29801
- logInstrumentationError4("Pi Coding Agent disable cleanup", error);
29802
- });
31255
+ finishPiPromptRun(state);
29803
31256
  }
29804
31257
  }
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
- }
31258
+ interceptPrompt() {
31259
+ this.unsubscribers.push(
31260
+ piCodingAgentChannels.prompt.intercept(
31261
+ (target, thisArg, args, additional) => {
31262
+ const invokeTarget = () => Reflect.apply(target, thisArg, args);
31263
+ let state;
31264
+ try {
31265
+ state = startPiPromptRun(
31266
+ {
31267
+ ...additional,
31268
+ arguments: args,
31269
+ self: thisArg
31270
+ },
31271
+ (finalizedState) => {
31272
+ this.activePromptStates.delete(finalizedState);
31273
+ }
31274
+ );
31275
+ } catch (error) {
31276
+ logInstrumentationError4("Pi Coding Agent prompt start", error);
29832
31277
  }
29833
- return;
29834
- }
29835
- await finalizePiPromptRun(state);
29836
- },
29837
- error: async (event) => {
29838
- const state = states.get(event);
29839
- if (!state) {
29840
- return;
31278
+ if (!state) {
31279
+ return runWithAutoInstrumentationSuppressed(invokeTarget);
31280
+ }
31281
+ this.activePromptStates.add(state);
31282
+ return promptContextStore().run(
31283
+ state,
31284
+ () => runWithAutoInstrumentationSuppressed(() => {
31285
+ let result;
31286
+ try {
31287
+ result = invokeTarget();
31288
+ } catch (error) {
31289
+ finishPiPromptRun(state, error);
31290
+ throw error;
31291
+ }
31292
+ return Promise.resolve(result).then(
31293
+ (value) => {
31294
+ finishPiPromptCall(state);
31295
+ return value;
31296
+ },
31297
+ (error) => {
31298
+ finishPiPromptRun(state, error);
31299
+ throw error;
31300
+ }
31301
+ );
31302
+ })
31303
+ );
29841
31304
  }
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
- });
31305
+ )
31306
+ );
29851
31307
  }
29852
31308
  };
31309
+ function finishPiPromptCall(state) {
31310
+ state.promptCallEnded = true;
31311
+ if (state.deferCompletionUntilTurnEnd && !state.turnEnded) {
31312
+ return;
31313
+ }
31314
+ finishPiPromptRun(state);
31315
+ }
29853
31316
  function startPiPromptRun(event, onFinalize) {
29854
31317
  const session = extractSession(event);
29855
31318
  const agent = session?.agent;
29856
31319
  if (!session || !isPiAgent(agent)) {
29857
31320
  return void 0;
29858
31321
  }
31322
+ installPiAgentInstrumentation(agent);
29859
31323
  const metadata = {
29860
31324
  ...extractSessionMetadata(session),
29861
31325
  ...extractPromptOptionsMetadata(event.arguments[1]),
@@ -29877,9 +31341,7 @@ function startPiPromptRun(event, onFinalize) {
29877
31341
  INSTRUMENTATION_NAMES.PI_CODING_AGENT
29878
31342
  )
29879
31343
  );
29880
- const streamPatchState = installPiStreamPatch(agent);
29881
31344
  const options = event.arguments[1];
29882
- const promptText = event.arguments[0];
29883
31345
  const state = {
29884
31346
  activeLlmSpans: /* @__PURE__ */ new Set(),
29885
31347
  activeToolSpans: /* @__PURE__ */ new Map(),
@@ -29891,29 +31353,10 @@ function startPiPromptRun(event, onFinalize) {
29891
31353
  metrics: {},
29892
31354
  onFinalize,
29893
31355
  promptCallEnded: false,
29894
- ...typeof promptText === "string" ? { promptText } : {},
29895
- queued: false,
29896
31356
  span,
29897
- sawStreamFn: false,
29898
31357
  startTime: getCurrentUnixTimestamp(),
29899
- streamPatchState,
29900
31358
  turnEnded: false
29901
31359
  };
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
31360
  return state;
29918
31361
  }
29919
31362
  function extractSession(event) {
@@ -29927,111 +31370,55 @@ function promptContextStore() {
29927
31370
  piPromptContextStore ??= isomorph_default.newAsyncLocalStorage();
29928
31371
  return piPromptContextStore;
29929
31372
  }
29930
- function currentPromptContextFrames() {
29931
- return promptContextStore().getStore()?.frames ?? [];
29932
- }
29933
31373
  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
31374
+ return promptContextStore().getStore();
31375
+ }
31376
+ function installPiAgentInstrumentation(agent) {
31377
+ const existing = piAgentPatchStates.get(agent);
31378
+ if (!existing || agent.streamFn !== existing.wrappedStreamFn) {
31379
+ const patchState = {
31380
+ originalStreamFn: agent.streamFn,
31381
+ wrappedStreamFn: agent.streamFn
31382
+ };
31383
+ patchState.wrappedStreamFn = makeInstrumentedStreamFn(
31384
+ agent,
31385
+ patchState.originalStreamFn
29998
31386
  );
29999
- if (matches.length === 1) {
30000
- return matches[0];
30001
- }
31387
+ agent.streamFn = patchState.wrappedStreamFn;
31388
+ piAgentPatchStates.set(agent, patchState);
30002
31389
  }
30003
- const contextState = currentPiPromptState();
30004
- if (contextState && patchState.activePromptStates.has(contextState) && (!contextState.queued || lastUserText !== void 0 && contextState.promptText === lastUserText)) {
30005
- return contextState;
31390
+ if (piAgentEventSubscriptions.has(agent)) {
31391
+ return;
30006
31392
  }
30007
- if (patchState.activePromptStates.size === 1) {
30008
- return [...patchState.activePromptStates][0];
31393
+ try {
31394
+ agent.subscribe(async (event) => {
31395
+ const state = currentPiPromptState();
31396
+ if (!state || state.agent !== agent || state.finalized) {
31397
+ return;
31398
+ }
31399
+ try {
31400
+ await runWithAutoInstrumentationSuppressed(
31401
+ () => handlePiAgentEvent(state, event)
31402
+ );
31403
+ } catch (error) {
31404
+ logInstrumentationError4("Pi Coding Agent event", error);
31405
+ }
31406
+ });
31407
+ piAgentEventSubscriptions.add(agent);
31408
+ } catch (error) {
31409
+ logInstrumentationError4("Pi Coding Agent event subscription", error);
30009
31410
  }
30010
- return void 0;
30011
31411
  }
30012
- function makeSharedInstrumentedStreamFn(patchState) {
31412
+ function makeInstrumentedStreamFn(agent, originalStreamFn) {
30013
31413
  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();
31414
+ const invokeOriginal = () => Reflect.apply(originalStreamFn, this, [model, context, options]);
31415
+ const state = currentPiPromptState();
31416
+ if (!state || state.agent !== agent || state.finalized) {
31417
+ return invokeOriginal();
30022
31418
  }
30023
- state.sawStreamFn = true;
30024
- removeQueuedPromptState(state);
30025
- state.streamPatchState.eventPromptState = state;
30026
31419
  const llmState = await startPiLlmSpan(state, model, context, options);
30027
31420
  try {
30028
- const stream = await runWithAutoInstrumentationSuppressed(
30029
- () => Reflect.apply(patchState.originalStreamFn, this, [
30030
- model,
30031
- context,
30032
- options
30033
- ])
30034
- );
31421
+ const stream = await runWithAutoInstrumentationSuppressed(invokeOriginal);
30035
31422
  return patchAssistantMessageStream(stream, state, llmState);
30036
31423
  } catch (error) {
30037
31424
  finishPiLlmSpan(state, llmState, void 0, error);
@@ -30178,13 +31565,6 @@ async function handlePiAgentEvent(state, event) {
30178
31565
  if (state.finalized) {
30179
31566
  return;
30180
31567
  }
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
31568
  switch (event.type) {
30189
31569
  case "message_end":
30190
31570
  if (isPiAssistantMessage(event.message)) {
@@ -30199,11 +31579,8 @@ async function handlePiAgentEvent(state, event) {
30199
31579
  addMetrics(state.metrics, extractUsageMetrics2(event.message.usage));
30200
31580
  }
30201
31581
  }
30202
- if (state.streamPatchState.eventPromptState === state) {
30203
- state.streamPatchState.eventPromptState = void 0;
30204
- }
30205
31582
  if (state.promptCallEnded && state.deferCompletionUntilTurnEnd) {
30206
- await finalizePiPromptRun(state);
31583
+ finishPiPromptRun(state);
30207
31584
  }
30208
31585
  return;
30209
31586
  case "tool_execution_start":
@@ -30276,19 +31653,13 @@ function finishPiToolSpan(state, event) {
30276
31653
  }
30277
31654
  }
30278
31655
  }
30279
- async function finalizePiPromptRun(state, error) {
31656
+ function finishPiPromptRun(state, error) {
30280
31657
  if (state.finalized) {
30281
31658
  return;
30282
31659
  }
30283
31660
  state.finalized = true;
30284
31661
  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);
31662
+ finishOpenLlmSpans(state, error);
30292
31663
  finishOpenToolSpans(state, error);
30293
31664
  const metadata = {
30294
31665
  ...state.metadata,
@@ -30305,34 +31676,14 @@ async function finalizePiPromptRun(state, error) {
30305
31676
  output: state.output
30306
31677
  });
30307
31678
  } 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);
31679
+ try {
31680
+ state.span.end();
31681
+ } catch (endError) {
31682
+ logInstrumentationError4("Pi Coding Agent prompt end", endError);
31683
+ }
30333
31684
  }
30334
31685
  }
30335
- async function finishOpenLlmSpans(state, error) {
31686
+ function finishOpenLlmSpans(state, error) {
30336
31687
  for (const llmState of [...state.activeLlmSpans]) {
30337
31688
  finishPiLlmSpan(state, llmState, void 0, error);
30338
31689
  }
@@ -30413,7 +31764,7 @@ function normalizeAssistantMessage(message) {
30413
31764
  (part) => part.type === "thinking" && !part.redacted ? [part.thinking] : []
30414
31765
  ).join("");
30415
31766
  const toolCalls = message.content.flatMap(
30416
- (part) => part.type === "toolCall" ? [normalizeToolCall(part)] : []
31767
+ (part) => part.type === "toolCall" ? [normalizeToolCall2(part)] : []
30417
31768
  );
30418
31769
  return {
30419
31770
  role: "assistant",
@@ -30448,13 +31799,13 @@ function normalizeUserContent(content) {
30448
31799
  return part;
30449
31800
  });
30450
31801
  }
30451
- function normalizeToolCall(toolCall) {
31802
+ function normalizeToolCall2(toolCall) {
30452
31803
  return {
30453
31804
  id: toolCall.id,
30454
31805
  type: "function",
30455
31806
  function: {
30456
31807
  name: toolCall.name,
30457
- arguments: stringifyArguments(toolCall.arguments)
31808
+ arguments: stringifyArguments2(toolCall.arguments)
30458
31809
  }
30459
31810
  };
30460
31811
  }
@@ -30637,7 +31988,7 @@ function cleanMetrics5(metrics) {
30637
31988
  }
30638
31989
  return cleaned;
30639
31990
  }
30640
- function stringifyArguments(value) {
31991
+ function stringifyArguments2(value) {
30641
31992
  if (typeof value === "string") {
30642
31993
  return value;
30643
31994
  }
@@ -32205,6 +33556,7 @@ var BraintrustPlugin = class extends BasePlugin {
32205
33556
  anthropicPlugin = null;
32206
33557
  aiSDKPlugin = null;
32207
33558
  claudeAgentSDKPlugin = null;
33559
+ cloudflareThinkPlugin = null;
32208
33560
  cursorSDKPlugin = null;
32209
33561
  openAIAgentsPlugin = null;
32210
33562
  googleGenAIPlugin = null;
@@ -32213,6 +33565,7 @@ var BraintrustPlugin = class extends BasePlugin {
32213
33565
  openRouterPlugin = null;
32214
33566
  openRouterAgentPlugin = null;
32215
33567
  mistralPlugin = null;
33568
+ ollamaPlugin = null;
32216
33569
  googleADKPlugin = null;
32217
33570
  coherePlugin = null;
32218
33571
  groqPlugin = null;
@@ -32252,6 +33605,10 @@ var BraintrustPlugin = class extends BasePlugin {
32252
33605
  this.claudeAgentSDKPlugin = new ClaudeAgentSDKPlugin();
32253
33606
  this.claudeAgentSDKPlugin.enable();
32254
33607
  }
33608
+ if (integrations.cloudflareThink !== false) {
33609
+ this.cloudflareThinkPlugin = new CloudflareThinkPlugin();
33610
+ this.cloudflareThinkPlugin.enable();
33611
+ }
32255
33612
  if (integrations.cursorSDK !== false && integrations.cursor !== false) {
32256
33613
  this.cursorSDKPlugin = new CursorSDKPlugin();
32257
33614
  this.cursorSDKPlugin.enable();
@@ -32282,6 +33639,10 @@ var BraintrustPlugin = class extends BasePlugin {
32282
33639
  this.mistralPlugin = new MistralPlugin();
32283
33640
  this.mistralPlugin.enable();
32284
33641
  }
33642
+ if (integrations.ollama !== false) {
33643
+ this.ollamaPlugin = new OllamaPlugin();
33644
+ this.ollamaPlugin.enable();
33645
+ }
32285
33646
  if (integrations.googleADK !== false) {
32286
33647
  this.googleADKPlugin = new GoogleADKPlugin();
32287
33648
  this.googleADKPlugin.enable();
@@ -32358,6 +33719,10 @@ var BraintrustPlugin = class extends BasePlugin {
32358
33719
  this.claudeAgentSDKPlugin.disable();
32359
33720
  this.claudeAgentSDKPlugin = null;
32360
33721
  }
33722
+ if (this.cloudflareThinkPlugin) {
33723
+ this.cloudflareThinkPlugin.disable();
33724
+ this.cloudflareThinkPlugin = null;
33725
+ }
32361
33726
  if (this.cursorSDKPlugin) {
32362
33727
  this.cursorSDKPlugin.disable();
32363
33728
  this.cursorSDKPlugin = null;
@@ -32390,6 +33755,10 @@ var BraintrustPlugin = class extends BasePlugin {
32390
33755
  this.mistralPlugin.disable();
32391
33756
  this.mistralPlugin = null;
32392
33757
  }
33758
+ if (this.ollamaPlugin) {
33759
+ this.ollamaPlugin.disable();
33760
+ this.ollamaPlugin = null;
33761
+ }
32393
33762
  if (this.googleADKPlugin) {
32394
33763
  this.googleADKPlugin.disable();
32395
33764
  this.googleADKPlugin = null;
@@ -34126,6 +35495,7 @@ var envIntegrationAliases = {
34126
35495
  cloudflareaichat: "cloudflareAIChat",
34127
35496
  "cloudflare-ai-chat": "cloudflareAIChat",
34128
35497
  "@cloudflare/ai-chat": "cloudflareAIChat",
35498
+ cloudflarethink: "cloudflareThink",
34129
35499
  cursor: "cursor",
34130
35500
  "cursor-sdk": "cursorSDK",
34131
35501
  cursorsdk: "cursorSDK",
@@ -34146,6 +35516,7 @@ var envIntegrationAliases = {
34146
35516
  openrouteragent: "openrouterAgent",
34147
35517
  "openrouter-agent": "openrouterAgent",
34148
35518
  mistral: "mistral",
35519
+ ollama: "ollama",
34149
35520
  googleadk: "googleADK",
34150
35521
  "google-adk": "googleADK",
34151
35522
  cohere: "cohere",
@@ -34181,6 +35552,7 @@ function getDefaultInstrumentationIntegrations() {
34181
35552
  huggingface: true,
34182
35553
  claudeAgentSDK: true,
34183
35554
  cloudflareAIChat: true,
35555
+ cloudflareThink: true,
34184
35556
  cursor: true,
34185
35557
  cursorSDK: true,
34186
35558
  flue: true,
@@ -34189,6 +35561,7 @@ function getDefaultInstrumentationIntegrations() {
34189
35561
  openrouter: true,
34190
35562
  openrouterAgent: true,
34191
35563
  mistral: true,
35564
+ ollama: true,
34192
35565
  cohere: true,
34193
35566
  groq: true,
34194
35567
  bedrock: true,