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
@@ -3,8 +3,10 @@ var GLOBAL_INSTRUMENTATION_HOOKS_KEY = "__braintrust_instrumentation_hooks";
3
3
  var GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION = 1;
4
4
  var GLOBAL_INSTRUMENTATION_HOOKS_REGISTRY_BRAND = "braintrust.global-instrumentation-hooks.registry";
5
5
  var GLOBAL_INSTRUMENTATION_HOOK_BRAND = "braintrust.global-instrumentation-hooks.hook";
6
+ var GLOBAL_INVOCATION_HOOK_BRAND = "braintrust.global-instrumentation-hooks.invocation-hook";
6
7
  var registryBrand = Symbol.for(GLOBAL_INSTRUMENTATION_HOOKS_REGISTRY_BRAND);
7
8
  var hookBrand = Symbol.for(GLOBAL_INSTRUMENTATION_HOOK_BRAND);
9
+ var invocationHookBrand = Symbol.for(GLOBAL_INVOCATION_HOOK_BRAND);
8
10
  var errorReporter;
9
11
  function setGlobalHookErrorReporter(reporter) {
10
12
  const previousReporter = errorReporter;
@@ -149,12 +151,69 @@ var traceEvents = [
149
151
  "asyncEnd",
150
152
  "error"
151
153
  ];
154
+ function traceInvocation(hook, operator, target, thisArg, args, additional, callbackIndex = -1) {
155
+ const context = {
156
+ ...additional,
157
+ arguments: args,
158
+ self: thisArg
159
+ };
160
+ const invoke = () => hook.invoke(target, thisArg, args, additional);
161
+ if (operator === "traceCallback") {
162
+ return hook.traceCallback(invoke, callbackIndex, context);
163
+ }
164
+ if (operator === "tracePromise") {
165
+ return hook.tracePromise(invoke, context);
166
+ }
167
+ return hook.traceSync(invoke, context);
168
+ }
169
+ var InvocationHook = class {
170
+ interceptors = [];
171
+ get hasInterceptors() {
172
+ return this.interceptors.length > 0;
173
+ }
174
+ intercept(interceptor) {
175
+ if (typeof interceptor !== "function") {
176
+ throw new TypeError("interceptor must be a function");
177
+ }
178
+ this.interceptors = [...this.interceptors, interceptor];
179
+ let active = true;
180
+ return () => {
181
+ if (!active) {
182
+ return;
183
+ }
184
+ active = false;
185
+ const index = this.interceptors.indexOf(interceptor);
186
+ if (index !== -1) {
187
+ this.interceptors = [
188
+ ...this.interceptors.slice(0, index),
189
+ ...this.interceptors.slice(index + 1)
190
+ ];
191
+ }
192
+ };
193
+ }
194
+ invoke(target, thisArg, args, additional) {
195
+ const interceptors = this.interceptors;
196
+ if (interceptors.length === 0) {
197
+ return Reflect.apply(target, thisArg, args);
198
+ }
199
+ let next = target;
200
+ for (let index = interceptors.length - 1; index >= 0; index -= 1) {
201
+ const interceptor = interceptors[index];
202
+ const downstream = next;
203
+ next = function(...nextArgs) {
204
+ return interceptor(downstream, this, nextArgs, additional);
205
+ };
206
+ }
207
+ return Reflect.apply(next, thisArg, args);
208
+ }
209
+ };
152
210
  var TracingHook = class {
153
211
  start;
154
212
  end;
155
213
  asyncStart;
156
214
  asyncEnd;
157
215
  error;
216
+ invocationHook = new InvocationHook();
158
217
  constructor(nameOrChannels) {
159
218
  Object.defineProperty(this, hookBrand, {
160
219
  configurable: false,
@@ -162,6 +221,12 @@ var TracingHook = class {
162
221
  value: GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION,
163
222
  writable: false
164
223
  });
224
+ Object.defineProperty(this, invocationHookBrand, {
225
+ configurable: false,
226
+ enumerable: false,
227
+ value: GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION,
228
+ writable: false
229
+ });
165
230
  if (typeof nameOrChannels === "string") {
166
231
  this.start = new HookChannel(`tracing:${nameOrChannels}:start`);
167
232
  this.end = new HookChannel(`tracing:${nameOrChannels}:end`);
@@ -179,6 +244,26 @@ var TracingHook = class {
179
244
  get hasSubscribers() {
180
245
  return this.start.hasSubscribers || this.end.hasSubscribers || this.asyncStart.hasSubscribers || this.asyncEnd.hasSubscribers || this.error.hasSubscribers;
181
246
  }
247
+ get hasInterceptors() {
248
+ return this.invocationHook.hasInterceptors;
249
+ }
250
+ intercept(interceptor) {
251
+ return this.invocationHook.intercept(interceptor);
252
+ }
253
+ invoke(target, thisArg, args, additional) {
254
+ return this.invocationHook.invoke(target, thisArg, args, additional);
255
+ }
256
+ traceInvocation(operator, target, thisArg, args, additional, callbackIndex = -1) {
257
+ return traceInvocation(
258
+ this,
259
+ operator,
260
+ target,
261
+ thisArg,
262
+ args,
263
+ additional,
264
+ callbackIndex
265
+ );
266
+ }
182
267
  subscribe(handlers) {
183
268
  for (const eventName of traceEvents) {
184
269
  const handler = handlers[eventName];
@@ -400,6 +485,60 @@ function hasTracingHookShape(value) {
400
485
  return false;
401
486
  }
402
487
  }
488
+ function hasInvocationHookShape(value) {
489
+ if (typeof value !== "object" && typeof value !== "function" || value === null) {
490
+ return false;
491
+ }
492
+ try {
493
+ const hook = value;
494
+ return value[invocationHookBrand] === GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION && typeof hook.hasInterceptors === "boolean" && typeof hook.intercept === "function" && typeof hook.invoke === "function";
495
+ } catch {
496
+ return false;
497
+ }
498
+ }
499
+ function installInvocationHook(value) {
500
+ const hasInvocationHook = hasInvocationHookShape(value);
501
+ const invocationHook = new InvocationHook();
502
+ try {
503
+ if (!hasInvocationHook) {
504
+ Object.defineProperties(value, {
505
+ [invocationHookBrand]: {
506
+ configurable: false,
507
+ enumerable: false,
508
+ value: GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION,
509
+ writable: false
510
+ },
511
+ hasInterceptors: {
512
+ configurable: false,
513
+ enumerable: false,
514
+ get: () => invocationHook.hasInterceptors
515
+ },
516
+ intercept: {
517
+ configurable: false,
518
+ enumerable: false,
519
+ value: invocationHook.intercept.bind(invocationHook),
520
+ writable: false
521
+ },
522
+ invoke: {
523
+ configurable: false,
524
+ enumerable: false,
525
+ value: invocationHook.invoke.bind(invocationHook),
526
+ writable: false
527
+ }
528
+ });
529
+ }
530
+ if (typeof value.traceInvocation !== "function") {
531
+ Object.defineProperty(value, "traceInvocation", {
532
+ configurable: false,
533
+ enumerable: false,
534
+ value: traceInvocation.bind(void 0, value),
535
+ writable: false
536
+ });
537
+ }
538
+ } catch (error) {
539
+ reportError(error);
540
+ }
541
+ }
403
542
  function isCompatibleTracingHook(value) {
404
543
  try {
405
544
  return value[hookBrand] === GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION && hasTracingHookShape(value);
@@ -486,6 +625,7 @@ function newGlobalTracingChannel(nameOrChannels) {
486
625
  return inertTracingHook;
487
626
  }
488
627
  if (isCompatibleTracingHook(existing)) {
628
+ installInvocationHook(existing);
489
629
  return existing;
490
630
  }
491
631
  if (existing !== void 0) {
@@ -541,6 +681,114 @@ var iso = {
541
681
  };
542
682
  var isomorph_default = iso;
543
683
 
684
+ // src/debug-logger.ts
685
+ var PREFIX = "[braintrust]";
686
+ var DEBUG_LOG_LEVEL_SYMBOL = /* @__PURE__ */ Symbol.for("braintrust-debug-log-level");
687
+ var LOG_LEVEL_PRIORITY = {
688
+ error: 0,
689
+ warn: 1,
690
+ info: 2,
691
+ debug: 3
692
+ };
693
+ var hasWarnedAboutInvalidEnvValue = false;
694
+ var debugLogStateResolver = void 0;
695
+ function warnInvalidEnvValue(value) {
696
+ if (hasWarnedAboutInvalidEnvValue) {
697
+ return;
698
+ }
699
+ hasWarnedAboutInvalidEnvValue = true;
700
+ console.warn(
701
+ PREFIX,
702
+ `Invalid BRAINTRUST_DEBUG_LOG_LEVEL value "${value}". Expected "error", "warn", "info", or "debug".`
703
+ );
704
+ }
705
+ function normalizeDebugLogLevelOption(option) {
706
+ if (option === false) {
707
+ return void 0;
708
+ }
709
+ if (option === "error" || option === "warn" || option === "info" || option === "debug") {
710
+ return option;
711
+ }
712
+ throw new Error(
713
+ `Invalid debugLogLevel value "${option}". Expected false, "error", "warn", "info", or "debug".`
714
+ );
715
+ }
716
+ function parseDebugLogLevelEnv(value) {
717
+ if (!value) {
718
+ return void 0;
719
+ }
720
+ if (value === "error" || value === "warn" || value === "info" || value === "debug") {
721
+ return value;
722
+ }
723
+ warnInvalidEnvValue(value);
724
+ return void 0;
725
+ }
726
+ function getEnvDebugLogLevel() {
727
+ return parseDebugLogLevelEnv(isomorph_default.getEnv("BRAINTRUST_DEBUG_LOG_LEVEL"));
728
+ }
729
+ function setGlobalDebugLogLevel(level) {
730
+ globalThis[DEBUG_LOG_LEVEL_SYMBOL] = level;
731
+ }
732
+ function setDebugLogStateResolver(resolver) {
733
+ debugLogStateResolver = resolver;
734
+ }
735
+ function resolveDebugLogLevel(state) {
736
+ const stateLevel = state?.getDebugLogLevel?.();
737
+ const hasStateOverride = state?.hasDebugLogLevelOverride?.() ?? false;
738
+ if (hasStateOverride) {
739
+ return stateLevel;
740
+ }
741
+ const globalLevel = (
742
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
743
+ globalThis[DEBUG_LOG_LEVEL_SYMBOL]
744
+ );
745
+ if (globalLevel !== void 0) {
746
+ return globalLevel === false ? void 0 : globalLevel;
747
+ }
748
+ return getEnvDebugLogLevel();
749
+ }
750
+ function emit(method, state, args) {
751
+ const level = resolveDebugLogLevel(state);
752
+ if (!level || LOG_LEVEL_PRIORITY[method] > LOG_LEVEL_PRIORITY[level]) {
753
+ return;
754
+ }
755
+ if (method === "info") {
756
+ console.log(PREFIX, ...args);
757
+ } else if (method === "debug") {
758
+ console.debug(PREFIX, ...args);
759
+ } else if (method === "warn") {
760
+ console.warn(PREFIX, ...args);
761
+ } else {
762
+ console.error(PREFIX, ...args);
763
+ }
764
+ }
765
+ function createDebugLogger(state) {
766
+ const resolveState = () => state ?? debugLogStateResolver?.();
767
+ return {
768
+ info(...args) {
769
+ emit("info", resolveState(), args);
770
+ },
771
+ debug(...args) {
772
+ emit("debug", resolveState(), args);
773
+ },
774
+ warn(...args) {
775
+ emit("warn", resolveState(), args);
776
+ },
777
+ error(...args) {
778
+ emit("error", resolveState(), args);
779
+ }
780
+ };
781
+ }
782
+ var debugLogger = {
783
+ ...createDebugLogger(),
784
+ forState(state) {
785
+ return createDebugLogger(state);
786
+ }
787
+ };
788
+ setGlobalHookErrorReporter((error) => {
789
+ debugLogger.error("Global instrumentation hook error:", error);
790
+ });
791
+
544
792
  // src/instrumentation/core/stream-patcher.ts
545
793
  function isAsyncIterable(value) {
546
794
  return value !== null && typeof value === "object" && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
@@ -565,112 +813,133 @@ function patchStreamIfNeeded(stream, options) {
565
813
  );
566
814
  return stream;
567
815
  }
568
- if (hasAsyncIteratorMethods(stream) && isSelfAsyncIterator(stream)) {
569
- if ("__braintrust_patched_iterator_methods" in stream) {
570
- return stream;
816
+ const chunks = [];
817
+ let completed = false;
818
+ const notifyCancellation = async () => {
819
+ try {
820
+ await (options.onCancel ?? options.onComplete)(chunks);
821
+ } catch (error) {
822
+ debugLogger.error("Error in stream cancellation handler:", error);
571
823
  }
824
+ };
825
+ const patchAbortIfPresent = () => {
572
826
  try {
573
- const originalNext = stream.next.bind(stream);
574
- const originalReturn = typeof stream.return === "function" ? stream.return.bind(stream) : null;
575
- const originalThrow = typeof stream.throw === "function" ? stream.throw.bind(stream) : null;
576
- const chunks = [];
577
- let completed = false;
578
- stream.next = async (...args) => {
579
- try {
580
- const result = await runNextWithWrapper(
581
- options,
582
- () => originalNext(...args)
583
- );
584
- if (result.done) {
827
+ if ("abort" in stream && typeof stream.abort === "function") {
828
+ const originalAbort = stream.abort.bind(stream);
829
+ stream.abort = (...args) => {
830
+ try {
831
+ return originalAbort(...args);
832
+ } finally {
585
833
  if (!completed) {
586
834
  completed = true;
587
- try {
588
- await options.onComplete(chunks);
589
- } catch (error) {
590
- console.error("Error in stream onComplete handler:", error);
591
- }
592
- }
593
- } else {
594
- const chunk = result.value;
595
- const shouldCollect = options.shouldCollect ? options.shouldCollect(chunk) : true;
596
- if (shouldCollect) {
597
- chunks.push(chunk);
598
- if (options.onChunk) {
599
- try {
600
- await options.onChunk(chunk);
601
- } catch (error) {
602
- console.error("Error in stream onChunk handler:", error);
603
- }
604
- }
835
+ void notifyCancellation();
605
836
  }
606
837
  }
607
- return result;
608
- } catch (error) {
609
- if (!completed) {
610
- completed = true;
611
- if (options.onError) {
612
- try {
613
- await options.onError(
614
- error instanceof Error ? error : new Error(String(error)),
615
- chunks
616
- );
617
- } catch (handlerError) {
618
- console.error("Error in stream onError handler:", handlerError);
619
- }
620
- }
621
- }
622
- throw error;
623
- }
624
- };
625
- if (originalReturn) {
626
- stream.return = async (...args) => {
627
- if (!completed) {
628
- completed = true;
629
- try {
630
- await options.onComplete(chunks);
631
- } catch (error) {
632
- console.error("Error in stream onComplete handler:", error);
633
- }
634
- }
635
- return originalReturn(...args);
636
- };
637
- }
638
- if (originalThrow) {
639
- stream.throw = async (...args) => {
640
- if (!completed) {
641
- completed = true;
642
- const rawError = args[0];
643
- const error = rawError instanceof Error ? rawError : new Error(String(rawError));
644
- if (options.onError) {
645
- try {
646
- await options.onError(error, chunks);
647
- } catch (handlerError) {
648
- console.error("Error in stream onError handler:", handlerError);
649
- }
650
- }
651
- }
652
- return originalThrow(...args);
653
838
  };
654
839
  }
655
- Object.defineProperty(stream, "__braintrust_patched_iterator_methods", {
656
- value: true
657
- });
658
- return stream;
659
840
  } catch (error) {
660
- console.warn("Failed to patch stream iterator methods:", error);
841
+ debugLogger.warn("Failed to patch stream abort method:", error);
661
842
  }
662
- }
663
- const originalIteratorFn = stream[Symbol.asyncIterator];
664
- if ("__braintrust_patched" in originalIteratorFn && originalIteratorFn["__braintrust_patched"]) {
665
- return stream;
666
- }
667
- try {
668
- const patchedIteratorFn = function() {
669
- const iterator = originalIteratorFn.call(this);
670
- const originalNext = iterator.next.bind(iterator);
671
- const chunks = [];
672
- let completed = false;
673
- iterator.next = async function(...args) {
843
+ };
844
+ if (hasAsyncIteratorMethods(stream) && isSelfAsyncIterator(stream)) {
845
+ if ("__braintrust_patched_iterator_methods" in stream) {
846
+ return stream;
847
+ }
848
+ try {
849
+ const originalNext = stream.next.bind(stream);
850
+ const originalReturn = typeof stream.return === "function" ? stream.return.bind(stream) : null;
851
+ const originalThrow = typeof stream.throw === "function" ? stream.throw.bind(stream) : null;
852
+ stream.next = async (...args) => {
853
+ try {
854
+ const result = await runNextWithWrapper(
855
+ options,
856
+ () => originalNext(...args)
857
+ );
858
+ if (result.done) {
859
+ if (!completed) {
860
+ completed = true;
861
+ try {
862
+ await options.onComplete(chunks);
863
+ } catch (error) {
864
+ console.error("Error in stream onComplete handler:", error);
865
+ }
866
+ }
867
+ } else {
868
+ const chunk = result.value;
869
+ const shouldCollect = options.shouldCollect ? options.shouldCollect(chunk) : true;
870
+ if (shouldCollect) {
871
+ chunks.push(chunk);
872
+ if (options.onChunk) {
873
+ try {
874
+ await options.onChunk(chunk);
875
+ } catch (error) {
876
+ console.error("Error in stream onChunk handler:", error);
877
+ }
878
+ }
879
+ }
880
+ }
881
+ return result;
882
+ } catch (error) {
883
+ if (!completed) {
884
+ completed = true;
885
+ if (options.onError) {
886
+ try {
887
+ await options.onError(
888
+ error instanceof Error ? error : new Error(String(error)),
889
+ chunks
890
+ );
891
+ } catch (handlerError) {
892
+ console.error("Error in stream onError handler:", handlerError);
893
+ }
894
+ }
895
+ }
896
+ throw error;
897
+ }
898
+ };
899
+ if (originalReturn) {
900
+ stream.return = async (...args) => {
901
+ if (!completed) {
902
+ completed = true;
903
+ await notifyCancellation();
904
+ }
905
+ return originalReturn(...args);
906
+ };
907
+ }
908
+ if (originalThrow) {
909
+ stream.throw = async (...args) => {
910
+ if (!completed) {
911
+ completed = true;
912
+ const rawError = args[0];
913
+ const error = rawError instanceof Error ? rawError : new Error(String(rawError));
914
+ if (options.onError) {
915
+ try {
916
+ await options.onError(error, chunks);
917
+ } catch (handlerError) {
918
+ console.error("Error in stream onError handler:", handlerError);
919
+ }
920
+ }
921
+ }
922
+ return originalThrow(...args);
923
+ };
924
+ }
925
+ Object.defineProperty(stream, "__braintrust_patched_iterator_methods", {
926
+ value: true
927
+ });
928
+ patchAbortIfPresent();
929
+ return stream;
930
+ } catch (error) {
931
+ console.warn("Failed to patch stream iterator methods:", error);
932
+ }
933
+ }
934
+ const originalIteratorFn = stream[Symbol.asyncIterator];
935
+ if ("__braintrust_patched" in originalIteratorFn && originalIteratorFn["__braintrust_patched"]) {
936
+ return stream;
937
+ }
938
+ try {
939
+ const patchedIteratorFn = function() {
940
+ const iterator = originalIteratorFn.call(this);
941
+ const originalNext = iterator.next.bind(iterator);
942
+ iterator.next = async function(...args) {
674
943
  try {
675
944
  const result = await runNextWithWrapper(
676
945
  options,
@@ -722,11 +991,7 @@ function patchStreamIfNeeded(stream, options) {
722
991
  iterator.return = async function(...args) {
723
992
  if (!completed) {
724
993
  completed = true;
725
- try {
726
- await options.onComplete(chunks);
727
- } catch (error) {
728
- console.error("Error in stream onComplete handler:", error);
729
- }
994
+ await notifyCancellation();
730
995
  }
731
996
  return originalReturn(...args);
732
997
  };
@@ -755,6 +1020,7 @@ function patchStreamIfNeeded(stream, options) {
755
1020
  value: true
756
1021
  });
757
1022
  stream[Symbol.asyncIterator] = patchedIteratorFn;
1023
+ patchAbortIfPresent();
758
1024
  return stream;
759
1025
  } catch (error) {
760
1026
  console.warn("Failed to patch stream:", error);
@@ -768,114 +1034,6 @@ function runNextWithWrapper(options, callback) {
768
1034
  // src/logger.ts
769
1035
  import { v4 as uuidv42 } from "uuid";
770
1036
 
771
- // src/debug-logger.ts
772
- var PREFIX = "[braintrust]";
773
- var DEBUG_LOG_LEVEL_SYMBOL = /* @__PURE__ */ Symbol.for("braintrust-debug-log-level");
774
- var LOG_LEVEL_PRIORITY = {
775
- error: 0,
776
- warn: 1,
777
- info: 2,
778
- debug: 3
779
- };
780
- var hasWarnedAboutInvalidEnvValue = false;
781
- var debugLogStateResolver = void 0;
782
- function warnInvalidEnvValue(value) {
783
- if (hasWarnedAboutInvalidEnvValue) {
784
- return;
785
- }
786
- hasWarnedAboutInvalidEnvValue = true;
787
- console.warn(
788
- PREFIX,
789
- `Invalid BRAINTRUST_DEBUG_LOG_LEVEL value "${value}". Expected "error", "warn", "info", or "debug".`
790
- );
791
- }
792
- function normalizeDebugLogLevelOption(option) {
793
- if (option === false) {
794
- return void 0;
795
- }
796
- if (option === "error" || option === "warn" || option === "info" || option === "debug") {
797
- return option;
798
- }
799
- throw new Error(
800
- `Invalid debugLogLevel value "${option}". Expected false, "error", "warn", "info", or "debug".`
801
- );
802
- }
803
- function parseDebugLogLevelEnv(value) {
804
- if (!value) {
805
- return void 0;
806
- }
807
- if (value === "error" || value === "warn" || value === "info" || value === "debug") {
808
- return value;
809
- }
810
- warnInvalidEnvValue(value);
811
- return void 0;
812
- }
813
- function getEnvDebugLogLevel() {
814
- return parseDebugLogLevelEnv(isomorph_default.getEnv("BRAINTRUST_DEBUG_LOG_LEVEL"));
815
- }
816
- function setGlobalDebugLogLevel(level) {
817
- globalThis[DEBUG_LOG_LEVEL_SYMBOL] = level;
818
- }
819
- function setDebugLogStateResolver(resolver) {
820
- debugLogStateResolver = resolver;
821
- }
822
- function resolveDebugLogLevel(state) {
823
- const stateLevel = state?.getDebugLogLevel?.();
824
- const hasStateOverride = state?.hasDebugLogLevelOverride?.() ?? false;
825
- if (hasStateOverride) {
826
- return stateLevel;
827
- }
828
- const globalLevel = (
829
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
830
- globalThis[DEBUG_LOG_LEVEL_SYMBOL]
831
- );
832
- if (globalLevel !== void 0) {
833
- return globalLevel === false ? void 0 : globalLevel;
834
- }
835
- return getEnvDebugLogLevel();
836
- }
837
- function emit(method, state, args) {
838
- const level = resolveDebugLogLevel(state);
839
- if (!level || LOG_LEVEL_PRIORITY[method] > LOG_LEVEL_PRIORITY[level]) {
840
- return;
841
- }
842
- if (method === "info") {
843
- console.log(PREFIX, ...args);
844
- } else if (method === "debug") {
845
- console.debug(PREFIX, ...args);
846
- } else if (method === "warn") {
847
- console.warn(PREFIX, ...args);
848
- } else {
849
- console.error(PREFIX, ...args);
850
- }
851
- }
852
- function createDebugLogger(state) {
853
- const resolveState = () => state ?? debugLogStateResolver?.();
854
- return {
855
- info(...args) {
856
- emit("info", resolveState(), args);
857
- },
858
- debug(...args) {
859
- emit("debug", resolveState(), args);
860
- },
861
- warn(...args) {
862
- emit("warn", resolveState(), args);
863
- },
864
- error(...args) {
865
- emit("error", resolveState(), args);
866
- }
867
- };
868
- }
869
- var debugLogger = {
870
- ...createDebugLogger(),
871
- forState(state) {
872
- return createDebugLogger(state);
873
- }
874
- };
875
- setGlobalHookErrorReporter((error) => {
876
- debugLogger.error("Global instrumentation hook error:", error);
877
- });
878
-
879
1037
  // src/queue.ts
880
1038
  var DEFAULT_QUEUE_SIZE = 15e3;
881
1039
  var Queue = class {
@@ -5382,6 +5540,7 @@ var INSTRUMENTATION_NAMES = {
5382
5540
  CLAUDE_AGENT_SDK: "claude-agent-sdk",
5383
5541
  CLOUDFLARE_AI_CHAT: "cloudflare-ai-chat",
5384
5542
  CLOUDFLARE_AGENTS: "cloudflare-agents",
5543
+ CLOUDFLARE_THINK: "cloudflare-think",
5385
5544
  COHERE: "cohere",
5386
5545
  CURSOR_SDK: "cursor-sdk",
5387
5546
  EVE: "eve",
@@ -5396,6 +5555,7 @@ var INSTRUMENTATION_NAMES = {
5396
5555
  LANGSMITH: "langsmith",
5397
5556
  MASTRA: "mastra",
5398
5557
  MISTRAL: "mistral",
5558
+ OLLAMA: "ollama",
5399
5559
  OPENAI: "openai",
5400
5560
  OPENAI_AGENTS: "openai-agents",
5401
5561
  OPENAI_CODEX: "openai-codex",
@@ -5407,7 +5567,7 @@ var INSTRUMENTATION_NAMES = {
5407
5567
  var INTERNAL_SPAN_INSTRUMENTATION_NAME = /* @__PURE__ */ Symbol.for(
5408
5568
  "braintrust.spanInstrumentationName"
5409
5569
  );
5410
- var SDK_VERSION = true ? "3.26.0" : "0.0.0";
5570
+ var SDK_VERSION = true ? "3.27.0" : "0.0.0";
5411
5571
  function withSpanInstrumentationName(args, instrumentationName) {
5412
5572
  return {
5413
5573
  ...args,
@@ -10428,6 +10588,33 @@ function traceStreamingChannel(channel2, config) {
10428
10588
  const { span, startTime } = spanData;
10429
10589
  if (isAsyncIterable(asyncEndEvent.result)) {
10430
10590
  let firstChunkTime;
10591
+ const handleStreamError = (error) => {
10592
+ try {
10593
+ span.log({ error });
10594
+ } catch (loggingError) {
10595
+ debugLogger.error(
10596
+ `Error logging failure for ${channelName}:`,
10597
+ loggingError
10598
+ );
10599
+ }
10600
+ try {
10601
+ span.end();
10602
+ } catch (endingError) {
10603
+ debugLogger.error(
10604
+ `Error ending span for ${channelName}:`,
10605
+ endingError
10606
+ );
10607
+ }
10608
+ states.delete(event);
10609
+ runStreamingErrorHook({
10610
+ channelName,
10611
+ config,
10612
+ error,
10613
+ event: asyncEndEvent,
10614
+ span,
10615
+ startTime
10616
+ });
10617
+ };
10431
10618
  patchStreamIfNeeded(asyncEndEvent.result, {
10432
10619
  onChunk: () => {
10433
10620
  if (firstChunkTime === void 0) {
@@ -10507,33 +10694,12 @@ function traceStreamingChannel(channel2, config) {
10507
10694
  });
10508
10695
  }
10509
10696
  },
10510
- onError: (error) => {
10511
- try {
10512
- span.log({ error });
10513
- } catch (loggingError) {
10514
- debugLogger.error(
10515
- `Error logging failure for ${channelName}:`,
10516
- loggingError
10517
- );
10518
- }
10519
- try {
10520
- span.end();
10521
- } catch (endingError) {
10522
- debugLogger.error(
10523
- `Error ending span for ${channelName}:`,
10524
- endingError
10525
- );
10526
- }
10527
- states.delete(event);
10528
- runStreamingErrorHook({
10529
- channelName,
10530
- config,
10531
- error,
10532
- event: asyncEndEvent,
10533
- span,
10534
- startTime
10535
- });
10536
- }
10697
+ onCancel: () => {
10698
+ const error = new Error("Stream cancelled before completion");
10699
+ error.name = "AbortError";
10700
+ handleStreamError(error);
10701
+ },
10702
+ onError: handleStreamError
10537
10703
  });
10538
10704
  return;
10539
10705
  }
@@ -10921,11 +11087,21 @@ function defineChannels(pkg, channels, options) {
10921
11087
  const tracingChannel2 = () => isomorph_default.newTracingChannel(
10922
11088
  fullChannelName
10923
11089
  );
11090
+ const intercept2 = (interceptor) => {
11091
+ const hook = tracingChannel2();
11092
+ return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
11093
+ };
11094
+ };
10924
11095
  return [
10925
11096
  key,
10926
11097
  {
10927
11098
  ...asyncSpec,
10928
11099
  instrumentationName,
11100
+ intercept: intercept2,
11101
+ invoke: (target, thisArg, args, additional) => {
11102
+ const hook = tracingChannel2();
11103
+ return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
11104
+ },
10929
11105
  tracingChannel: tracingChannel2,
10930
11106
  tracePromise: (fn, context) => tracingChannel2().tracePromise(
10931
11107
  fn,
@@ -10939,11 +11115,21 @@ function defineChannels(pkg, channels, options) {
10939
11115
  const tracingChannel = () => isomorph_default.newTracingChannel(
10940
11116
  fullChannelName
10941
11117
  );
11118
+ const intercept = (interceptor) => {
11119
+ const hook = tracingChannel();
11120
+ return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
11121
+ };
11122
+ };
10942
11123
  return [
10943
11124
  key,
10944
11125
  {
10945
11126
  ...syncSpec,
10946
11127
  instrumentationName,
11128
+ intercept,
11129
+ invoke: (target, thisArg, args, additional) => {
11130
+ const hook = tracingChannel();
11131
+ return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
11132
+ },
10947
11133
  tracingChannel,
10948
11134
  traceSync: (fn, context) => tracingChannel().traceSync(
10949
11135
  fn,
@@ -12194,6 +12380,12 @@ function extractAnthropicCacheTokens(cacheReadTokens = 0, cacheCreationTokens =
12194
12380
  return cacheTokens;
12195
12381
  }
12196
12382
 
12383
+ // src/wrappers/anthropic-session-collector.ts
12384
+ var sessionStreamCollectors = /* @__PURE__ */ new WeakMap();
12385
+ function registerAnthropicSessionStreamCollector(stream, collector) {
12386
+ sessionStreamCollectors.set(stream, collector);
12387
+ }
12388
+
12197
12389
  // src/instrumentation/plugins/anthropic-channels.ts
12198
12390
  var anthropicChannels = defineChannels(
12199
12391
  "@anthropic-ai/sdk",
@@ -12209,6 +12401,14 @@ var anthropicChannels = defineChannels(
12209
12401
  betaMessagesToolRunner: channel({
12210
12402
  channelName: "beta.messages.toolRunner",
12211
12403
  kind: "sync-stream"
12404
+ }),
12405
+ betaSessionsEventsStream: channel({
12406
+ channelName: "beta.sessions.events.stream",
12407
+ kind: "async"
12408
+ }),
12409
+ betaSessionsThreadsEventsStream: channel({
12410
+ channelName: "beta.sessions.threads.events.stream",
12411
+ kind: "async"
12212
12412
  })
12213
12413
  },
12214
12414
  { instrumentationName: INSTRUMENTATION_NAMES.ANTHROPIC }
@@ -12222,6 +12422,7 @@ var AnthropicPlugin = class extends BasePlugin {
12222
12422
  onEnable() {
12223
12423
  this.subscribeToAnthropicChannels();
12224
12424
  this.subscribeToAnthropicToolRunner();
12425
+ this.subscribeToAnthropicSessionStreams();
12225
12426
  }
12226
12427
  onDisable() {
12227
12428
  this.unsubscribers = unsubscribeAll(this.unsubscribers);
@@ -12339,7 +12540,411 @@ var AnthropicPlugin = class extends BasePlugin {
12339
12540
  tracingChannel.unsubscribe(handlers);
12340
12541
  });
12341
12542
  }
12543
+ subscribeToAnthropicSessionStreams() {
12544
+ this.subscribeToAnthropicSessionStream(
12545
+ anthropicChannels.betaSessionsEventsStream,
12546
+ false
12547
+ );
12548
+ this.subscribeToAnthropicSessionStream(
12549
+ anthropicChannels.betaSessionsThreadsEventsStream,
12550
+ true
12551
+ );
12552
+ }
12553
+ subscribeToAnthropicSessionStream(channel2, isThread) {
12554
+ const tracingChannel = channel2.tracingChannel();
12555
+ const pending = /* @__PURE__ */ new WeakSet();
12556
+ const handlers = {
12557
+ start: (event) => {
12558
+ if (isAutoInstrumentationSuppressed()) {
12559
+ return;
12560
+ }
12561
+ pending.add(event);
12562
+ },
12563
+ asyncEnd: (event) => {
12564
+ if (!pending.delete(event)) {
12565
+ return;
12566
+ }
12567
+ const stream = event.result;
12568
+ if (!isAsyncIterable(stream)) {
12569
+ return;
12570
+ }
12571
+ registerAnthropicSessionStreamCollector(stream, () => {
12572
+ wrapAnthropicSessionEventStream(stream, isThread);
12573
+ });
12574
+ },
12575
+ error: (event) => {
12576
+ pending.delete(event);
12577
+ }
12578
+ };
12579
+ tracingChannel.subscribe(handlers);
12580
+ this.unsubscribers.push(() => tracingChannel.unsubscribe(handlers));
12581
+ }
12342
12582
  };
12583
+ function wrapAnthropicSessionEventStream(stream, isThread) {
12584
+ const state = {
12585
+ history: [],
12586
+ isThread,
12587
+ pendingInput: [],
12588
+ seenEventIds: /* @__PURE__ */ new Set()
12589
+ };
12590
+ patchStreamIfNeeded(stream, {
12591
+ onChunk: (event) => handleAnthropicSessionEvent(state, event),
12592
+ onComplete: () => finalizeAnthropicSessionTurn(state),
12593
+ onError: (error) => finalizeAnthropicSessionTurn(state, error)
12594
+ });
12595
+ return stream;
12596
+ }
12597
+ function handleAnthropicSessionEvent(state, event) {
12598
+ try {
12599
+ if (typeof event.id === "string" && event.type !== "event_delta" && state.seenEventIds.has(event.id)) {
12600
+ return;
12601
+ }
12602
+ if (typeof event.id === "string" && event.type !== "event_delta") {
12603
+ state.seenEventIds.add(event.id);
12604
+ }
12605
+ switch (event.type) {
12606
+ case "user.message":
12607
+ case "system.message":
12608
+ recordAnthropicSessionInput(
12609
+ state,
12610
+ event
12611
+ );
12612
+ break;
12613
+ case "session.status_running":
12614
+ if (!state.isThread) {
12615
+ ensureAnthropicSessionTurn(state);
12616
+ }
12617
+ break;
12618
+ case "session.thread_status_running":
12619
+ if (state.isThread) {
12620
+ ensureAnthropicSessionTurn(state);
12621
+ }
12622
+ break;
12623
+ case "span.model_request_start":
12624
+ if (typeof event.id === "string") {
12625
+ startAnthropicSessionModel(state, event.id);
12626
+ }
12627
+ break;
12628
+ case "event_delta":
12629
+ recordAnthropicSessionFirstToken(state, event);
12630
+ break;
12631
+ case "agent.message":
12632
+ recordAnthropicSessionMessage(
12633
+ state,
12634
+ event
12635
+ );
12636
+ break;
12637
+ case "agent.custom_tool_use":
12638
+ case "agent.mcp_tool_use":
12639
+ case "agent.tool_use":
12640
+ startAnthropicSessionTool(state, event);
12641
+ break;
12642
+ case "user.tool_confirmation":
12643
+ recordAnthropicSessionToolConfirmation(state, event);
12644
+ break;
12645
+ case "agent.mcp_tool_result":
12646
+ case "agent.tool_result":
12647
+ case "user.custom_tool_result":
12648
+ case "user.tool_result":
12649
+ finalizeAnthropicSessionTool(
12650
+ state,
12651
+ event
12652
+ );
12653
+ break;
12654
+ case "span.model_request_end":
12655
+ finalizeAnthropicSessionModel(
12656
+ state,
12657
+ event
12658
+ );
12659
+ break;
12660
+ case "session.status_idle":
12661
+ case "session.thread_status_idle": {
12662
+ if (event.type === "session.status_idle" && state.isThread || event.type === "session.thread_status_idle" && !state.isThread) {
12663
+ break;
12664
+ }
12665
+ const stopReason = isObject(event.stop_reason) ? event.stop_reason.type : void 0;
12666
+ if (stopReason === "end_turn") {
12667
+ finalizeAnthropicSessionTurn(state);
12668
+ } else if (stopReason === "retries_exhausted") {
12669
+ finalizeAnthropicSessionTurn(
12670
+ state,
12671
+ "Anthropic session retries exhausted"
12672
+ );
12673
+ }
12674
+ break;
12675
+ }
12676
+ case "session.error":
12677
+ finalizeAnthropicSessionTurn(state, event.error);
12678
+ break;
12679
+ case "session.deleted":
12680
+ case "session.status_terminated":
12681
+ case "session.thread_status_terminated":
12682
+ if (event.type === "session.deleted" || event.type === "session.status_terminated" && !state.isThread || event.type === "session.thread_status_terminated" && state.isThread) {
12683
+ finalizeAnthropicSessionTurn(state);
12684
+ }
12685
+ break;
12686
+ default:
12687
+ break;
12688
+ }
12689
+ } catch (error) {
12690
+ debugLogger.debug("Error processing Anthropic Sessions event:", error);
12691
+ }
12692
+ }
12693
+ function ensureAnthropicSessionTurn(state) {
12694
+ if (state.activeTurn) {
12695
+ return state.activeTurn;
12696
+ }
12697
+ const input = state.pendingInput;
12698
+ state.pendingInput = [];
12699
+ const span = startSpan(
12700
+ withSpanInstrumentationName(
12701
+ {
12702
+ event: {
12703
+ ...input.length > 0 ? { input } : {},
12704
+ metadata: { provider: "anthropic" }
12705
+ },
12706
+ name: state.isThread ? "anthropic.beta.sessions.thread.turn" : "anthropic.beta.sessions.turn",
12707
+ spanAttributes: { type: "task" /* TASK */ }
12708
+ },
12709
+ INSTRUMENTATION_NAMES.ANTHROPIC
12710
+ )
12711
+ );
12712
+ state.activeTurn = {
12713
+ activeTools: /* @__PURE__ */ new Map(),
12714
+ input: input.slice(),
12715
+ metrics: {},
12716
+ span
12717
+ };
12718
+ return state.activeTurn;
12719
+ }
12720
+ function recordAnthropicSessionInput(state, event) {
12721
+ const content = processAttachmentsInInput(event.content);
12722
+ const message = {
12723
+ role: event.type === "system.message" ? "system" : "user",
12724
+ content
12725
+ };
12726
+ state.history.push(message);
12727
+ if (state.activeTurn) {
12728
+ state.activeTurn.input.push(message);
12729
+ } else {
12730
+ state.pendingInput.push(message);
12731
+ }
12732
+ }
12733
+ function startAnthropicSessionModel(state, startEventId) {
12734
+ const turn = ensureAnthropicSessionTurn(state);
12735
+ if (turn.activeModel) {
12736
+ finalizeAnthropicSessionModelState(state, turn);
12737
+ }
12738
+ const span = withCurrent(
12739
+ turn.span,
12740
+ () => startSpan(
12741
+ withSpanInstrumentationName(
12742
+ {
12743
+ event: {
12744
+ ...state.history.length > 0 ? { input: state.history.slice() } : {},
12745
+ metadata: { provider: "anthropic" }
12746
+ },
12747
+ name: "anthropic.messages.create",
12748
+ spanAttributes: { type: "llm" /* LLM */ }
12749
+ },
12750
+ INSTRUMENTATION_NAMES.ANTHROPIC
12751
+ )
12752
+ )
12753
+ );
12754
+ turn.activeModel = {
12755
+ output: [],
12756
+ span,
12757
+ startEventId,
12758
+ startTime: getCurrentUnixTimestamp()
12759
+ };
12760
+ }
12761
+ function recordAnthropicSessionFirstToken(state, event) {
12762
+ const model = state.activeTurn?.activeModel;
12763
+ if (!model || model.firstTokenTime !== void 0 || !isObject(event.delta) || !isObject(event.delta.content) || typeof event.delta.content.text !== "string") {
12764
+ return;
12765
+ }
12766
+ model.firstTokenTime = getCurrentUnixTimestamp();
12767
+ }
12768
+ function recordAnthropicSessionMessage(state, event) {
12769
+ const turn = ensureAnthropicSessionTurn(state);
12770
+ const content = processAttachmentsInInput(
12771
+ event.content
12772
+ );
12773
+ if (turn.activeModel) {
12774
+ turn.activeModel.output.push(...content);
12775
+ } else {
12776
+ const output = { role: "assistant", content };
12777
+ turn.lastOutput = output;
12778
+ state.history.push(output);
12779
+ }
12780
+ }
12781
+ function startAnthropicSessionTool(state, event) {
12782
+ const turn = ensureAnthropicSessionTurn(state);
12783
+ if (turn.activeModel) {
12784
+ turn.activeModel.output.push({
12785
+ type: "tool_use",
12786
+ id: event.id,
12787
+ name: event.name,
12788
+ input: event.input
12789
+ });
12790
+ }
12791
+ const existing = turn.activeTools.get(event.id);
12792
+ if (existing) {
12793
+ existing.span.end();
12794
+ turn.activeTools.delete(event.id);
12795
+ }
12796
+ const span = withCurrent(
12797
+ turn.span,
12798
+ () => startSpan(
12799
+ withSpanInstrumentationName(
12800
+ {
12801
+ event: { input: event.input },
12802
+ name: event.name,
12803
+ spanAttributes: { type: "tool" /* TOOL */ }
12804
+ },
12805
+ INSTRUMENTATION_NAMES.ANTHROPIC
12806
+ )
12807
+ )
12808
+ );
12809
+ const toolState = {
12810
+ approval: event.evaluated_permission === "allow" ? "approved" : event.evaluated_permission === "deny" ? "denied" : void 0,
12811
+ span
12812
+ };
12813
+ turn.activeTools.set(event.id, toolState);
12814
+ if (toolState.approval === "denied") {
12815
+ finalizeAnthropicSessionToolState(toolState);
12816
+ turn.activeTools.delete(event.id);
12817
+ }
12818
+ }
12819
+ function recordAnthropicSessionToolConfirmation(state, event) {
12820
+ if (typeof event.tool_use_id !== "string" || event.result !== "allow" && event.result !== "deny") {
12821
+ return;
12822
+ }
12823
+ const turn = state.activeTurn;
12824
+ const tool = turn?.activeTools.get(event.tool_use_id);
12825
+ if (!turn || !tool) {
12826
+ return;
12827
+ }
12828
+ tool.approval = event.result === "allow" ? "approved" : "denied";
12829
+ if (tool.approval === "denied") {
12830
+ finalizeAnthropicSessionToolState(tool);
12831
+ turn.activeTools.delete(event.tool_use_id);
12832
+ }
12833
+ }
12834
+ function finalizeAnthropicSessionTool(state, event) {
12835
+ const toolUseId = event.tool_use_id ?? event.mcp_tool_use_id ?? event.custom_tool_use_id;
12836
+ if (!toolUseId) {
12837
+ return;
12838
+ }
12839
+ const content = processAttachmentsInInput(event.content);
12840
+ const turn = state.activeTurn;
12841
+ const tool = turn?.activeTools.get(toolUseId);
12842
+ if (turn && tool) {
12843
+ finalizeAnthropicSessionToolState(tool, event, content);
12844
+ turn.activeTools.delete(toolUseId);
12845
+ }
12846
+ const toolResult = {
12847
+ type: "tool_result",
12848
+ tool_use_id: toolUseId,
12849
+ ...content !== void 0 ? { content } : {},
12850
+ ...event.is_error === true ? { is_error: true } : {}
12851
+ };
12852
+ state.history.push({
12853
+ role: "user",
12854
+ content: [toolResult]
12855
+ });
12856
+ }
12857
+ function finalizeAnthropicSessionToolState(state, event, content = event?.content) {
12858
+ safeAnthropicSessionLog(state.span, {
12859
+ ...event?.is_error === true ? {
12860
+ error: content ?? "Anthropic session tool execution failed"
12861
+ } : {},
12862
+ ...state.approval ? { metadata: { tool_approval: state.approval } } : {},
12863
+ ...content !== void 0 ? { output: content } : {}
12864
+ });
12865
+ state.span.end();
12866
+ }
12867
+ function finalizeAnthropicSessionModel(state, event) {
12868
+ const turn = state.activeTurn;
12869
+ const model = turn?.activeModel;
12870
+ if (!turn || !model || model.startEventId !== event.model_request_start_id) {
12871
+ return;
12872
+ }
12873
+ finalizeAnthropicSessionModelState(state, turn, event);
12874
+ }
12875
+ function finalizeAnthropicSessionModelState(state, turn, event) {
12876
+ const model = turn.activeModel;
12877
+ if (!model) {
12878
+ return;
12879
+ }
12880
+ turn.activeModel = void 0;
12881
+ const metrics = event ? parseAnthropicSessionModelUsage(event.model_usage) : {};
12882
+ if (model.firstTokenTime !== void 0) {
12883
+ metrics.time_to_first_token = model.firstTokenTime - model.startTime;
12884
+ }
12885
+ const output = model.output.length > 0 ? { role: "assistant", content: model.output } : void 0;
12886
+ safeAnthropicSessionLog(model.span, {
12887
+ ...event?.is_error ? { error: "Anthropic session model request failed" } : {},
12888
+ ...Object.keys(metrics).length > 0 ? { metrics } : {},
12889
+ ...output ? { output } : {}
12890
+ });
12891
+ model.span.end();
12892
+ if (output) {
12893
+ turn.lastOutput = output;
12894
+ state.history.push(output);
12895
+ }
12896
+ for (const key of [
12897
+ "prompt_tokens",
12898
+ "completion_tokens",
12899
+ "tokens",
12900
+ "prompt_cached_tokens",
12901
+ "prompt_cache_creation_tokens"
12902
+ ]) {
12903
+ const value = metrics[key];
12904
+ if (typeof value === "number") {
12905
+ turn.metrics[key] = (turn.metrics[key] ?? 0) + value;
12906
+ }
12907
+ }
12908
+ }
12909
+ function parseAnthropicSessionModelUsage(usage) {
12910
+ const finalized = finalizeAnthropicTokens({
12911
+ completion_tokens: usage.output_tokens,
12912
+ prompt_cache_creation_tokens: usage.cache_creation_input_tokens,
12913
+ prompt_cached_tokens: usage.cache_read_input_tokens,
12914
+ prompt_tokens: usage.input_tokens
12915
+ });
12916
+ return Object.fromEntries(
12917
+ Object.entries(finalized).filter(
12918
+ (entry) => entry[1] !== void 0
12919
+ )
12920
+ );
12921
+ }
12922
+ function finalizeAnthropicSessionTurn(state, error) {
12923
+ const turn = state.activeTurn;
12924
+ if (!turn) {
12925
+ return;
12926
+ }
12927
+ state.activeTurn = void 0;
12928
+ finalizeAnthropicSessionModelState(state, turn);
12929
+ for (const tool of turn.activeTools.values()) {
12930
+ finalizeAnthropicSessionToolState(tool);
12931
+ }
12932
+ turn.activeTools.clear();
12933
+ safeAnthropicSessionLog(turn.span, {
12934
+ ...error !== void 0 ? { error: error instanceof Error ? error : toLoggedError(error) } : {},
12935
+ ...turn.input.length > 0 ? { input: turn.input } : {},
12936
+ ...turn.lastOutput ? { output: turn.lastOutput } : {},
12937
+ ...Object.keys(turn.metrics).length > 0 ? { metrics: turn.metrics } : {}
12938
+ });
12939
+ turn.span.end();
12940
+ }
12941
+ function safeAnthropicSessionLog(span, event) {
12942
+ try {
12943
+ span.log(event);
12944
+ } catch (error) {
12945
+ debugLogger.debug("Error logging Anthropic Sessions span:", error);
12946
+ }
12947
+ }
12343
12948
  function parseMetricsFromUsage2(usage) {
12344
12949
  if (!usage) {
12345
12950
  return {};
@@ -14213,6 +14818,29 @@ var harnessAgentChannels = defineChannels(
14213
14818
  { instrumentationName: INSTRUMENTATION_NAMES.AI_SDK }
14214
14819
  );
14215
14820
 
14821
+ // src/instrumentation/plugins/cloudflare-think-context.ts
14822
+ var cloudflareThinkSpans = /* @__PURE__ */ new Map();
14823
+ function registerCloudflareThinkSpan(span) {
14824
+ if (span.spanId) {
14825
+ cloudflareThinkSpans.set(span.spanId, span);
14826
+ }
14827
+ }
14828
+ function unregisterCloudflareThinkSpan(span) {
14829
+ if (span.spanId) {
14830
+ cloudflareThinkSpans.delete(span.spanId);
14831
+ }
14832
+ }
14833
+ function currentCloudflareThinkSpan() {
14834
+ const parentSpanIds = _internalGetGlobalState()?.contextManager.getParentSpanIds()?.spanParents ?? [];
14835
+ for (const parentSpanId of parentSpanIds) {
14836
+ const span = cloudflareThinkSpans.get(parentSpanId);
14837
+ if (span) {
14838
+ return span;
14839
+ }
14840
+ }
14841
+ return void 0;
14842
+ }
14843
+
14216
14844
  // src/instrumentation/plugins/ai-sdk-plugin.ts
14217
14845
  var DEFAULT_DENY_OUTPUT_PATHS = [
14218
14846
  // v3
@@ -14319,6 +14947,7 @@ var AISDKPlugin = class extends BasePlugin {
14319
14947
  traceStreamingChannel(aiSDKChannels.streamText, {
14320
14948
  name: "streamText",
14321
14949
  type: "function" /* FUNCTION */,
14950
+ shouldTrace: () => currentCloudflareThinkSpan() === void 0,
14322
14951
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
14323
14952
  extractOutput: (result, endEvent) => processAISDKOutput(
14324
14953
  result,
@@ -14339,6 +14968,7 @@ var AISDKPlugin = class extends BasePlugin {
14339
14968
  traceSyncStreamChannel(aiSDKChannels.streamTextSync, {
14340
14969
  name: "streamText",
14341
14970
  type: "function" /* FUNCTION */,
14971
+ shouldTrace: () => currentCloudflareThinkSpan() === void 0,
14342
14972
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
14343
14973
  patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
14344
14974
  defaultDenyOutputPaths: denyOutputPaths,
@@ -15324,6 +15954,23 @@ function prepareAISDKWorkflowAgentStreamInput(params, event, span, defaultDenyOu
15324
15954
  metadata
15325
15955
  };
15326
15956
  }
15957
+ function prepareAISDKAgentCallInput(params, event, span, defaultDenyOutputPaths = DEFAULT_DENY_OUTPUT_PATHS) {
15958
+ const { input } = processAISDKWorkflowAgentCallInput(params);
15959
+ const metadata = extractMetadataFromCallParams(params, event.self);
15960
+ const childTracing = prepareAISDKChildTracing(
15961
+ params,
15962
+ event.self,
15963
+ span,
15964
+ defaultDenyOutputPaths,
15965
+ event.aiSDK,
15966
+ { agentOwner: true }
15967
+ );
15968
+ event.modelWrapped = childTracing.modelWrapped;
15969
+ if (childTracing.cleanup) {
15970
+ event.__braintrust_ai_sdk_cleanup = childTracing.cleanup;
15971
+ }
15972
+ return { input, metadata };
15973
+ }
15327
15974
  function prepareAISDKEmbedInput(params, self) {
15328
15975
  return {
15329
15976
  input: { ...params },
@@ -15347,6 +15994,18 @@ function extractTopLevelAISDKMetrics(result, event, startTime) {
15347
15994
  }
15348
15995
  return metrics;
15349
15996
  }
15997
+ async function extractResolvedAISDKTokenMetrics(result) {
15998
+ for (const field of ["totalUsage", "usage"]) {
15999
+ try {
16000
+ const usage = await Promise.resolve(result[field]);
16001
+ if (usage !== void 0) {
16002
+ return extractTokenMetrics({ [field]: usage });
16003
+ }
16004
+ } catch {
16005
+ }
16006
+ }
16007
+ return extractTokenMetrics(result);
16008
+ }
15350
16009
  function hasModelChildTracing(event) {
15351
16010
  return event?.modelWrapped === true || event?.__braintrust_ai_sdk_model_wrapped === true;
15352
16011
  }
@@ -16164,13 +16823,15 @@ function patchAISDKStreamingResult(args) {
16164
16823
  const {
16165
16824
  defaultDenyOutputPaths,
16166
16825
  endEvent,
16826
+ forceTopLevelMetrics,
16167
16827
  onComplete,
16168
16828
  onCancel,
16169
16829
  onError,
16170
16830
  result,
16171
16831
  resolvePromiseUsage,
16172
16832
  span,
16173
- startTime
16833
+ startTime,
16834
+ transformOutput
16174
16835
  } = args;
16175
16836
  if (!result || typeof result !== "object") {
16176
16837
  return false;
@@ -16223,8 +16884,8 @@ function patchAISDKStreamingResult(args) {
16223
16884
  }
16224
16885
  outputLogged = true;
16225
16886
  try {
16226
- const metrics = extractTopLevelAISDKMetrics(result, endEvent);
16227
- if (resolvePromiseUsage) {
16887
+ const metrics = forceTopLevelMetrics ? await extractResolvedAISDKTokenMetrics(result) : extractTopLevelAISDKMetrics(result, endEvent);
16888
+ if (resolvePromiseUsage && !forceTopLevelMetrics) {
16228
16889
  try {
16229
16890
  const resultRecord2 = result;
16230
16891
  const pendingUsage = resultRecord2.totalUsage ?? resultRecord2.usage;
@@ -16243,10 +16904,11 @@ function patchAISDKStreamingResult(args) {
16243
16904
  if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
16244
16905
  metrics.time_to_first_token = firstChunkTime - startTime;
16245
16906
  }
16246
- const output = await processAISDKStreamingOutput(
16907
+ const processedOutput = await processAISDKStreamingOutput(
16247
16908
  result,
16248
16909
  resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
16249
16910
  );
16911
+ const output = transformOutput ? transformOutput(processedOutput) : processedOutput;
16250
16912
  const metadata = buildResolvedMetadataPayload(result).metadata;
16251
16913
  try {
16252
16914
  span.log({
@@ -18668,6 +19330,295 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
18668
19330
  }
18669
19331
  };
18670
19332
 
19333
+ // src/instrumentation/plugins/cloudflare-think-channels.ts
19334
+ var cloudflareThinkChannels = defineChannels(
19335
+ "@cloudflare/think",
19336
+ {
19337
+ runInferenceLoop: channel({
19338
+ channelName: "Think.runInferenceLoop",
19339
+ kind: "async"
19340
+ })
19341
+ },
19342
+ { instrumentationName: INSTRUMENTATION_NAMES.CLOUDFLARE_THINK }
19343
+ );
19344
+
19345
+ // src/instrumentation/plugins/cloudflare-think-plugin.ts
19346
+ var THINK_STATE_ID = /* @__PURE__ */ Symbol.for("braintrust.cloudflare-think.state-id");
19347
+ var CloudflareThinkPlugin = class extends BasePlugin {
19348
+ statesBySpanId = /* @__PURE__ */ new Map();
19349
+ onEnable() {
19350
+ this.subscribeToThinkRuns();
19351
+ this.subscribeToAISDKStreamTextSync();
19352
+ this.subscribeToAISDKStreamTextAsync();
19353
+ }
19354
+ onDisable() {
19355
+ for (const unsubscribe of this.unsubscribers) {
19356
+ unsubscribe();
19357
+ }
19358
+ this.unsubscribers = [];
19359
+ for (const state of this.statesBySpanId.values()) {
19360
+ this.finishState(state);
19361
+ }
19362
+ this.statesBySpanId.clear();
19363
+ }
19364
+ subscribeToThinkRuns() {
19365
+ const channel2 = cloudflareThinkChannels.runInferenceLoop.tracingChannel();
19366
+ const states = /* @__PURE__ */ new WeakMap();
19367
+ const state = _internalGetGlobalState();
19368
+ const contextManager = state?.contextManager;
19369
+ const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
19370
+ const ensureState2 = (event) => {
19371
+ if (isAutoInstrumentationSuppressed()) {
19372
+ return void 0;
19373
+ }
19374
+ const existing = states.get(event);
19375
+ if (existing) {
19376
+ return existing;
19377
+ }
19378
+ const span = startSpan(
19379
+ withSpanInstrumentationName(
19380
+ {
19381
+ name: "Think.runTurn",
19382
+ spanAttributes: { type: "task" /* TASK */ }
19383
+ },
19384
+ INSTRUMENTATION_NAMES.CLOUDFLARE_THINK
19385
+ )
19386
+ );
19387
+ const runState = {
19388
+ aiResultPatched: false,
19389
+ fallbackInput: extractFallbackInput(event.self?.messages),
19390
+ finalized: false,
19391
+ inputLogged: false,
19392
+ span,
19393
+ startTime: getCurrentUnixTimestamp()
19394
+ };
19395
+ const metadata = {
19396
+ braintrust: {
19397
+ integration_name: "cloudflare-think",
19398
+ sdk_language: "typescript"
19399
+ }
19400
+ };
19401
+ if (typeof event.moduleVersion === "string") {
19402
+ metadata["cloudflare_think.version"] = event.moduleVersion;
19403
+ }
19404
+ span.log({ metadata });
19405
+ states.set(event, runState);
19406
+ if (span.spanId) {
19407
+ this.statesBySpanId.set(span.spanId, runState);
19408
+ }
19409
+ registerCloudflareThinkSpan(span);
19410
+ return runState;
19411
+ };
19412
+ if (contextManager && currentSpanStore && channel2.start) {
19413
+ channel2.start.bindStore(currentSpanStore, (event) => {
19414
+ const runState = ensureState2(event);
19415
+ return runState ? contextManager.wrapSpanForStore(runState.span) : currentSpanStore.getStore();
19416
+ });
19417
+ this.unsubscribers.push(
19418
+ () => channel2.start?.unbindStore(currentSpanStore)
19419
+ );
19420
+ }
19421
+ const handlers = {
19422
+ start: (event) => {
19423
+ ensureState2(event);
19424
+ },
19425
+ asyncEnd: (event) => {
19426
+ const runState = states.get(event);
19427
+ states.delete(event);
19428
+ if (!runState || runState.finalized || runState.aiResultPatched) {
19429
+ return;
19430
+ }
19431
+ this.finishState(runState, void 0, event.result);
19432
+ },
19433
+ error: (event) => {
19434
+ const runState = states.get(event);
19435
+ states.delete(event);
19436
+ if (runState) {
19437
+ this.finishState(runState, event.error);
19438
+ }
19439
+ }
19440
+ };
19441
+ channel2.subscribe(handlers);
19442
+ this.unsubscribers.push(() => channel2.unsubscribe(handlers));
19443
+ }
19444
+ subscribeToAISDKStreamTextSync() {
19445
+ const channel2 = aiSDKChannels.streamTextSync.tracingChannel();
19446
+ const handlers = {
19447
+ start: (event) => {
19448
+ this.startAISDKStream(event);
19449
+ },
19450
+ end: (event) => {
19451
+ this.endAISDKStream(event);
19452
+ },
19453
+ error: (event) => {
19454
+ this.errorAISDKStream(event);
19455
+ }
19456
+ };
19457
+ channel2.subscribe(handlers);
19458
+ this.unsubscribers.push(() => channel2.unsubscribe(handlers));
19459
+ }
19460
+ subscribeToAISDKStreamTextAsync() {
19461
+ const channel2 = aiSDKChannels.streamText.tracingChannel();
19462
+ const handlers = {
19463
+ start: (event) => {
19464
+ this.startAISDKStream(event);
19465
+ },
19466
+ asyncEnd: (event) => {
19467
+ this.endAISDKStream(event);
19468
+ },
19469
+ error: (event) => {
19470
+ this.errorAISDKStream(event);
19471
+ }
19472
+ };
19473
+ channel2.subscribe(handlers);
19474
+ this.unsubscribers.push(() => channel2.unsubscribe(handlers));
19475
+ }
19476
+ startAISDKStream(event) {
19477
+ const runState = this.currentState();
19478
+ if (!runState || runState.finalized) {
19479
+ return;
19480
+ }
19481
+ try {
19482
+ const prepared = prepareAISDKAgentCallInput(
19483
+ event.arguments[0],
19484
+ event,
19485
+ runState.span
19486
+ );
19487
+ runState.span.log({
19488
+ input: extractThinkTaskInput(prepared.input),
19489
+ metadata: {
19490
+ ...prepared.metadata,
19491
+ braintrust: {
19492
+ integration_name: "cloudflare-think",
19493
+ sdk_language: "typescript"
19494
+ }
19495
+ }
19496
+ });
19497
+ runState.inputLogged = true;
19498
+ runState.aiEvent = event;
19499
+ Reflect.set(event, THINK_STATE_ID, runState.span.spanId);
19500
+ } catch (error) {
19501
+ debugLogger.error(
19502
+ "Error preparing @cloudflare/think AI SDK tracing:",
19503
+ error
19504
+ );
19505
+ }
19506
+ }
19507
+ endAISDKStream(event) {
19508
+ const runState = this.stateForAISDKEvent(event);
19509
+ if (!runState || runState.finalized) {
19510
+ return;
19511
+ }
19512
+ const patched = patchAISDKStreamingResult({
19513
+ defaultDenyOutputPaths: DEFAULT_DENY_OUTPUT_PATHS,
19514
+ endEvent: event,
19515
+ forceTopLevelMetrics: true,
19516
+ onComplete: () => this.releaseState(runState),
19517
+ result: event.result,
19518
+ span: runState.span,
19519
+ startTime: runState.startTime,
19520
+ transformOutput: extractThinkTaskOutput
19521
+ });
19522
+ runState.aiResultPatched = patched;
19523
+ if (!patched) {
19524
+ this.finishState(runState, void 0, event.result);
19525
+ }
19526
+ }
19527
+ errorAISDKStream(event) {
19528
+ const runState = this.stateForAISDKEvent(event);
19529
+ if (runState) {
19530
+ this.finishState(runState, event.error);
19531
+ }
19532
+ }
19533
+ currentState() {
19534
+ const parentIds = _internalGetGlobalState()?.contextManager.getParentSpanIds()?.spanParents ?? [];
19535
+ for (const parentId of parentIds) {
19536
+ const state = this.statesBySpanId.get(parentId);
19537
+ if (state) {
19538
+ return state;
19539
+ }
19540
+ }
19541
+ return void 0;
19542
+ }
19543
+ stateForAISDKEvent(event) {
19544
+ const spanId = Reflect.get(event, THINK_STATE_ID);
19545
+ return typeof spanId === "string" ? this.statesBySpanId.get(spanId) : void 0;
19546
+ }
19547
+ finishState(state, error, output) {
19548
+ if (state.finalized) {
19549
+ return;
19550
+ }
19551
+ state.finalized = true;
19552
+ try {
19553
+ if (!state.inputLogged && state.fallbackInput !== void 0) {
19554
+ state.span.log({ input: state.fallbackInput });
19555
+ }
19556
+ if (error !== void 0) {
19557
+ state.span.log({ error });
19558
+ } else if (output !== void 0) {
19559
+ state.span.log({ output: extractThinkTaskOutput(output) });
19560
+ }
19561
+ finalizeAISDKChildTracing(state.aiEvent);
19562
+ state.span.end();
19563
+ } finally {
19564
+ this.releaseState(state);
19565
+ }
19566
+ }
19567
+ releaseState(state) {
19568
+ state.finalized = true;
19569
+ unregisterCloudflareThinkSpan(state.span);
19570
+ if (state.span.spanId) {
19571
+ this.statesBySpanId.delete(state.span.spanId);
19572
+ }
19573
+ }
19574
+ };
19575
+ function extractFallbackInput(messages) {
19576
+ if (!Array.isArray(messages) || messages.length === 0) {
19577
+ return void 0;
19578
+ }
19579
+ let latestUserIndex = -1;
19580
+ for (let index = messages.length - 1; index >= 0; index--) {
19581
+ if (messages[index]?.role === "user") {
19582
+ latestUserIndex = index;
19583
+ break;
19584
+ }
19585
+ }
19586
+ const selected = latestUserIndex >= 0 ? messages.slice(latestUserIndex) : [];
19587
+ return selected.map((message) => ({
19588
+ role: message.role,
19589
+ content: message.content ?? message.parts
19590
+ }));
19591
+ }
19592
+ function extractThinkTaskOutput(output) {
19593
+ if (!isObject(output)) {
19594
+ return output;
19595
+ }
19596
+ if (typeof output.text === "string") {
19597
+ return { role: "assistant", content: output.text };
19598
+ }
19599
+ if (output.object !== void 0) {
19600
+ return output.object;
19601
+ }
19602
+ return output;
19603
+ }
19604
+ function extractThinkTaskInput(input) {
19605
+ if (!isObject(input)) {
19606
+ return input;
19607
+ }
19608
+ const system = input.instructions ?? input.system;
19609
+ if (Array.isArray(input.messages)) {
19610
+ return system === void 0 ? input.messages : [{ role: "system", content: system }, ...input.messages];
19611
+ }
19612
+ if (Array.isArray(input.prompt)) {
19613
+ return system === void 0 ? input.prompt : [{ role: "system", content: system }, ...input.prompt];
19614
+ }
19615
+ if (typeof input.prompt === "string") {
19616
+ const messages = [{ role: "user", content: input.prompt }];
19617
+ return system === void 0 ? messages : [{ role: "system", content: system }, ...messages];
19618
+ }
19619
+ return input;
19620
+ }
19621
+
18671
19622
  // src/instrumentation/plugins/cursor-sdk-channels.ts
18672
19623
  var cursorSDKChannels = defineChannels(
18673
19624
  "@cursor/sdk",
@@ -24433,6 +25384,470 @@ function aggregateMistralStreamChunks(chunks) {
24433
25384
  };
24434
25385
  }
24435
25386
 
25387
+ // src/instrumentation/plugins/ollama-channels.ts
25388
+ var ollamaChannels = defineChannels(
25389
+ "ollama",
25390
+ {
25391
+ chat: channel({
25392
+ channelName: "chat",
25393
+ kind: "async"
25394
+ }),
25395
+ generate: channel({
25396
+ channelName: "generate",
25397
+ kind: "async"
25398
+ }),
25399
+ embed: channel({
25400
+ channelName: "embed",
25401
+ kind: "async"
25402
+ })
25403
+ },
25404
+ { instrumentationName: INSTRUMENTATION_NAMES.OLLAMA }
25405
+ );
25406
+
25407
+ // src/instrumentation/plugins/ollama-plugin.ts
25408
+ var OllamaPlugin = class extends BasePlugin {
25409
+ onEnable() {
25410
+ this.unsubscribers.push(
25411
+ traceStreamingChannel(ollamaChannels.chat, {
25412
+ name: "ollama.chat",
25413
+ type: "llm" /* LLM */,
25414
+ extractInput: extractOllamaChatInput,
25415
+ extractOutput: (result, event) => extractOllamaChatOutput(
25416
+ result,
25417
+ countOllamaToolCalls(event?.arguments?.[0]?.messages)
25418
+ ),
25419
+ extractMetadata: extractOllamaResponseMetadata,
25420
+ extractMetrics: extractOllamaMetrics,
25421
+ aggregateChunks: aggregateOllamaChatChunks
25422
+ }),
25423
+ traceStreamingChannel(ollamaChannels.generate, {
25424
+ name: "ollama.generate",
25425
+ type: "llm" /* LLM */,
25426
+ extractInput: extractOllamaGenerateInput,
25427
+ extractOutput: extractOllamaGenerateOutput,
25428
+ extractMetadata: extractOllamaResponseMetadata,
25429
+ extractMetrics: extractOllamaMetrics,
25430
+ aggregateChunks: aggregateOllamaGenerateChunks
25431
+ }),
25432
+ traceAsyncChannel(ollamaChannels.embed, {
25433
+ name: "ollama.embed",
25434
+ type: "llm" /* LLM */,
25435
+ extractInput: extractOllamaEmbedInput,
25436
+ extractOutput: extractOllamaEmbedOutput,
25437
+ extractMetadata: extractOllamaResponseMetadata,
25438
+ extractMetrics: extractOllamaMetrics
25439
+ })
25440
+ );
25441
+ }
25442
+ onDisable() {
25443
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
25444
+ }
25445
+ };
25446
+ function isNonNegativeNumber(value) {
25447
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
25448
+ }
25449
+ function normalizeFinishReason(response, hasToolCalls = false) {
25450
+ if (hasToolCalls) {
25451
+ return "tool_calls";
25452
+ }
25453
+ return response?.done_reason || "stop";
25454
+ }
25455
+ function stringifyArguments(value) {
25456
+ if (typeof value === "string") {
25457
+ return value;
25458
+ }
25459
+ try {
25460
+ return JSON.stringify(value ?? {});
25461
+ } catch {
25462
+ return String(value);
25463
+ }
25464
+ }
25465
+ function syntheticToolCallId(name, index) {
25466
+ const normalizedName = name.replace(/[^a-zA-Z0-9_-]/g, "_") || "tool";
25467
+ return `ollama_call_${normalizedName}_${index}`;
25468
+ }
25469
+ function normalizeToolCall(toolCall, index) {
25470
+ const name = toolCall.function?.name;
25471
+ if (typeof name !== "string" || name.length === 0) {
25472
+ return void 0;
25473
+ }
25474
+ return {
25475
+ id: typeof toolCall.id === "string" && toolCall.id.length > 0 ? toolCall.id : syntheticToolCallId(name, index),
25476
+ type: "function",
25477
+ function: {
25478
+ name,
25479
+ arguments: stringifyArguments(toolCall.function?.arguments)
25480
+ }
25481
+ };
25482
+ }
25483
+ function normalizeToolCalls(toolCalls, syntheticIdOffset = 0) {
25484
+ if (!Array.isArray(toolCalls)) {
25485
+ return [];
25486
+ }
25487
+ return toolCalls.flatMap((toolCall, index) => {
25488
+ const normalized = normalizeToolCall(toolCall, syntheticIdOffset + index);
25489
+ return normalized ? [normalized] : [];
25490
+ });
25491
+ }
25492
+ function countOllamaToolCalls(messages) {
25493
+ if (!Array.isArray(messages)) {
25494
+ return 0;
25495
+ }
25496
+ return messages.reduce(
25497
+ (count, message) => count + (isObject(message) && Array.isArray(message.tool_calls) ? message.tool_calls.length : 0),
25498
+ 0
25499
+ );
25500
+ }
25501
+ function imageBytes(value) {
25502
+ if (value instanceof Uint8Array) {
25503
+ return value;
25504
+ }
25505
+ if (value instanceof ArrayBuffer) {
25506
+ return new Uint8Array(value);
25507
+ }
25508
+ if (typeof value !== "string" || value.startsWith("data:")) {
25509
+ return void 0;
25510
+ }
25511
+ try {
25512
+ const decoded = atob(value.slice(0, 24));
25513
+ return Uint8Array.from(decoded, (character) => character.charCodeAt(0));
25514
+ } catch {
25515
+ return void 0;
25516
+ }
25517
+ }
25518
+ function inferImageMediaType(value) {
25519
+ if (typeof value === "string") {
25520
+ const dataUrlType = value.match(/^data:(image\/[^;]+);base64,/i)?.[1];
25521
+ if (dataUrlType) {
25522
+ return dataUrlType;
25523
+ }
25524
+ }
25525
+ const bytes = imageBytes(value);
25526
+ if (!bytes) {
25527
+ return void 0;
25528
+ }
25529
+ if (bytes[0] === 137 && bytes[1] === 80 && bytes[2] === 78 && bytes[3] === 71) {
25530
+ return "image/png";
25531
+ }
25532
+ if (bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255) {
25533
+ return "image/jpeg";
25534
+ }
25535
+ const signature = String.fromCharCode(...bytes.slice(0, 12));
25536
+ if (signature.startsWith("GIF87a") || signature.startsWith("GIF89a")) {
25537
+ return "image/gif";
25538
+ }
25539
+ if (signature.startsWith("RIFF") && signature.slice(8, 12) === "WEBP") {
25540
+ return "image/webp";
25541
+ }
25542
+ return void 0;
25543
+ }
25544
+ function normalizeTextAndImages(content, images) {
25545
+ if (!images || images.length === 0) {
25546
+ return { content };
25547
+ }
25548
+ const imageParts = [];
25549
+ const unrecognizedImages = [];
25550
+ for (const image of images) {
25551
+ let localImagePath;
25552
+ let localPathMediaType;
25553
+ if (typeof image === "string" && !/^data:/i.test(image) && !/^https?:\/\//i.test(image)) {
25554
+ const extension = image.match(/\.([a-z0-9]+)$/i)?.[1]?.toLowerCase();
25555
+ const extensionMediaType = {
25556
+ png: "image/png",
25557
+ jpg: "image/jpeg",
25558
+ jpeg: "image/jpeg",
25559
+ gif: "image/gif",
25560
+ webp: "image/webp"
25561
+ }[extension ?? ""];
25562
+ if (extensionMediaType && isomorph_default.statSync) {
25563
+ try {
25564
+ if (isomorph_default.statSync(image).isFile()) {
25565
+ localImagePath = image;
25566
+ localPathMediaType = extensionMediaType;
25567
+ }
25568
+ } catch {
25569
+ }
25570
+ }
25571
+ }
25572
+ const mediaType = localPathMediaType ?? inferImageMediaType(image);
25573
+ if (!mediaType) {
25574
+ unrecognizedImages.push(image);
25575
+ continue;
25576
+ }
25577
+ const processedImage = localImagePath ? new Attachment({
25578
+ data: localImagePath,
25579
+ filename: localImagePath.split(/[\\/]/).at(-1) ?? "image",
25580
+ contentType: mediaType
25581
+ }) : processInputAttachments({
25582
+ type: "image",
25583
+ image,
25584
+ mediaType
25585
+ }).image;
25586
+ imageParts.push({
25587
+ type: "image_url",
25588
+ image_url: { url: processedImage }
25589
+ });
25590
+ }
25591
+ return {
25592
+ content: imageParts.length > 0 ? [...content ? [{ type: "text", text: content }] : [], ...imageParts] : content,
25593
+ ...unrecognizedImages.length > 0 ? { unrecognizedImages } : {}
25594
+ };
25595
+ }
25596
+ function normalizeMessage(message, toolCallId, syntheticToolCallIdOffset = 0) {
25597
+ if (typeof message.role !== "string") {
25598
+ return void 0;
25599
+ }
25600
+ const toolCalls = normalizeToolCalls(
25601
+ message.tool_calls,
25602
+ syntheticToolCallIdOffset
25603
+ );
25604
+ if (message.role === "tool") {
25605
+ const toolName = typeof message.tool_name === "string" && message.tool_name.length > 0 ? message.tool_name : "tool";
25606
+ return {
25607
+ role: "tool",
25608
+ tool_call_id: toolCallId ?? syntheticToolCallId(toolName, 0),
25609
+ content: typeof message.content === "string" ? message.content : ""
25610
+ };
25611
+ }
25612
+ const normalizedContent = normalizeTextAndImages(
25613
+ typeof message.content === "string" ? message.content || (toolCalls.length > 0 ? null : "") : toolCalls.length > 0 ? null : "",
25614
+ message.images
25615
+ );
25616
+ return {
25617
+ role: message.role,
25618
+ content: normalizedContent.content,
25619
+ ...typeof message.thinking === "string" && message.thinking.length > 0 ? { reasoning: message.thinking } : {},
25620
+ ...toolCalls.length > 0 ? { tool_calls: toolCalls } : {},
25621
+ ...normalizedContent.unrecognizedImages ? { images: normalizedContent.unrecognizedImages } : {}
25622
+ };
25623
+ }
25624
+ function normalizeMessages(messages) {
25625
+ if (!Array.isArray(messages)) {
25626
+ return [];
25627
+ }
25628
+ const pendingToolCallIds = /* @__PURE__ */ new Map();
25629
+ let syntheticToolCallIdOffset = 0;
25630
+ return messages.flatMap((message) => {
25631
+ if (!isObject(message)) {
25632
+ return [];
25633
+ }
25634
+ const ollamaMessage = message;
25635
+ let toolCallId;
25636
+ if (ollamaMessage.role === "tool") {
25637
+ const toolName = ollamaMessage.tool_name;
25638
+ if (typeof toolName === "string") {
25639
+ toolCallId = pendingToolCallIds.get(toolName)?.shift();
25640
+ }
25641
+ }
25642
+ const normalized = normalizeMessage(
25643
+ ollamaMessage,
25644
+ toolCallId,
25645
+ syntheticToolCallIdOffset
25646
+ );
25647
+ if (Array.isArray(ollamaMessage.tool_calls)) {
25648
+ syntheticToolCallIdOffset += ollamaMessage.tool_calls.length;
25649
+ }
25650
+ if (ollamaMessage.role === "assistant" && normalized) {
25651
+ const toolCalls = Array.isArray(normalized.tool_calls) ? normalized.tool_calls : [];
25652
+ for (const toolCall of toolCalls) {
25653
+ if (!isObject(toolCall) || !isObject(toolCall.function)) {
25654
+ continue;
25655
+ }
25656
+ const name = toolCall.function.name;
25657
+ const id = toolCall.id;
25658
+ if (typeof name === "string" && typeof id === "string") {
25659
+ const ids = pendingToolCallIds.get(name) ?? [];
25660
+ ids.push(id);
25661
+ pendingToolCallIds.set(name, ids);
25662
+ }
25663
+ }
25664
+ }
25665
+ return normalized ? [normalized] : [];
25666
+ });
25667
+ }
25668
+ function normalizeToolDefinition(tool) {
25669
+ const fn = tool.function;
25670
+ if (!fn || typeof fn.name !== "string" || fn.name.length === 0) {
25671
+ return void 0;
25672
+ }
25673
+ return {
25674
+ type: "function",
25675
+ function: {
25676
+ name: fn.name,
25677
+ ...typeof fn.description === "string" ? { description: fn.description } : {},
25678
+ ...isObject(fn.parameters) ? { parameters: fn.parameters } : {}
25679
+ }
25680
+ };
25681
+ }
25682
+ function extractToolsMetadata(tools) {
25683
+ if (!Array.isArray(tools)) {
25684
+ return {};
25685
+ }
25686
+ const normalized = tools.flatMap((tool) => {
25687
+ if (!isObject(tool)) {
25688
+ return [];
25689
+ }
25690
+ const definition = normalizeToolDefinition(tool);
25691
+ return definition ? [definition] : [];
25692
+ });
25693
+ return normalized.length > 0 ? { tools: normalized } : {};
25694
+ }
25695
+ function extractOptionsMetadata(options) {
25696
+ if (!isObject(options)) {
25697
+ return {};
25698
+ }
25699
+ const metadata = {};
25700
+ const mappings = [
25701
+ ["temperature", "temperature"],
25702
+ ["top_p", "top_p"],
25703
+ ["num_predict", "max_tokens"],
25704
+ ["frequency_penalty", "frequency_penalty"],
25705
+ ["presence_penalty", "presence_penalty"],
25706
+ ["stop", "stop"]
25707
+ ];
25708
+ for (const [source, target] of mappings) {
25709
+ if (options[source] !== void 0) {
25710
+ metadata[target] = options[source];
25711
+ }
25712
+ }
25713
+ return metadata;
25714
+ }
25715
+ function extractRequestMetadata(request) {
25716
+ return {
25717
+ provider: "ollama",
25718
+ ...typeof request?.model === "string" ? { model: request.model } : {},
25719
+ ...extractOptionsMetadata(request?.options),
25720
+ ...request?.format !== void 0 ? { response_format: request.format } : {}
25721
+ };
25722
+ }
25723
+ function extractOllamaChatInput([request]) {
25724
+ return {
25725
+ input: normalizeMessages(request.messages),
25726
+ metadata: {
25727
+ ...extractRequestMetadata(request),
25728
+ ...extractToolsMetadata(request.tools)
25729
+ }
25730
+ };
25731
+ }
25732
+ function extractOllamaGenerateInput([request]) {
25733
+ const normalizedPrompt = normalizeTextAndImages(
25734
+ typeof request.prompt === "string" ? request.prompt : "",
25735
+ Array.isArray(request.images) ? request.images : void 0
25736
+ );
25737
+ const input = [
25738
+ ...typeof request.system === "string" ? [{ role: "system", content: request.system }] : [],
25739
+ {
25740
+ role: "user",
25741
+ content: normalizedPrompt.content,
25742
+ ...typeof request.suffix === "string" ? { suffix: request.suffix } : {},
25743
+ ...normalizedPrompt.unrecognizedImages ? { images: normalizedPrompt.unrecognizedImages } : {}
25744
+ }
25745
+ ];
25746
+ return {
25747
+ input,
25748
+ metadata: extractRequestMetadata(request)
25749
+ };
25750
+ }
25751
+ function extractOllamaEmbedInput([request]) {
25752
+ return {
25753
+ input: request.input,
25754
+ metadata: extractRequestMetadata(request)
25755
+ };
25756
+ }
25757
+ function extractOllamaChatOutput(result, syntheticToolCallIdOffset = 0) {
25758
+ if (!isObject(result) || !isObject(result.message)) {
25759
+ return void 0;
25760
+ }
25761
+ const message = normalizeMessage(
25762
+ result.message,
25763
+ void 0,
25764
+ syntheticToolCallIdOffset
25765
+ );
25766
+ if (!message) {
25767
+ return void 0;
25768
+ }
25769
+ const toolCalls = Array.isArray(message.tool_calls) ? message.tool_calls : [];
25770
+ return [
25771
+ {
25772
+ index: 0,
25773
+ finish_reason: normalizeFinishReason(result, toolCalls.length > 0),
25774
+ message
25775
+ }
25776
+ ];
25777
+ }
25778
+ function extractOllamaGenerateOutput(result) {
25779
+ if (!isObject(result) || typeof result.response !== "string") {
25780
+ return void 0;
25781
+ }
25782
+ return [
25783
+ {
25784
+ index: 0,
25785
+ finish_reason: normalizeFinishReason(result),
25786
+ message: {
25787
+ role: "assistant",
25788
+ content: result.response,
25789
+ ...typeof result.thinking === "string" && result.thinking.length > 0 ? { reasoning: result.thinking } : {}
25790
+ }
25791
+ }
25792
+ ];
25793
+ }
25794
+ function extractOllamaEmbedOutput(result) {
25795
+ const embedding = Array.isArray(result?.embeddings) ? result.embeddings[0] : void 0;
25796
+ return Array.isArray(embedding) ? { embedding_length: embedding.length } : void 0;
25797
+ }
25798
+ function extractOllamaResponseMetadata(result) {
25799
+ return typeof result?.model === "string" ? { model: result.model } : void 0;
25800
+ }
25801
+ function extractOllamaMetrics(result) {
25802
+ const metrics = {};
25803
+ const promptTokens = result?.prompt_eval_count;
25804
+ const completionTokens = result?.eval_count;
25805
+ if (isNonNegativeNumber(promptTokens)) {
25806
+ metrics.prompt_tokens = promptTokens;
25807
+ }
25808
+ if (isNonNegativeNumber(completionTokens)) {
25809
+ metrics.completion_tokens = completionTokens;
25810
+ }
25811
+ if (isNonNegativeNumber(promptTokens) || isNonNegativeNumber(completionTokens)) {
25812
+ metrics.tokens = (isNonNegativeNumber(promptTokens) ? promptTokens : 0) + (isNonNegativeNumber(completionTokens) ? completionTokens : 0);
25813
+ }
25814
+ return metrics;
25815
+ }
25816
+ function aggregateOllamaChatChunks(chunks, _result, event, _startTime) {
25817
+ const last = chunks.at(-1);
25818
+ const message = {
25819
+ role: "assistant",
25820
+ content: chunks.map((chunk) => chunk.message?.content ?? "").join(""),
25821
+ thinking: chunks.map((chunk) => chunk.message?.thinking ?? "").join(""),
25822
+ tool_calls: chunks.flatMap((chunk) => chunk.message?.tool_calls ?? [])
25823
+ };
25824
+ const response = {
25825
+ ...last,
25826
+ message
25827
+ };
25828
+ return {
25829
+ output: extractOllamaChatOutput(
25830
+ response,
25831
+ countOllamaToolCalls(event?.arguments?.[0]?.messages)
25832
+ ),
25833
+ metrics: extractOllamaMetrics(last ?? {}),
25834
+ metadata: extractOllamaResponseMetadata(last ?? {})
25835
+ };
25836
+ }
25837
+ function aggregateOllamaGenerateChunks(chunks, _result, _event, _startTime) {
25838
+ const last = chunks.at(-1);
25839
+ const response = {
25840
+ ...last,
25841
+ response: chunks.map((chunk) => chunk.response ?? "").join(""),
25842
+ thinking: chunks.map((chunk) => chunk.thinking ?? "").join("")
25843
+ };
25844
+ return {
25845
+ output: extractOllamaGenerateOutput(response),
25846
+ metrics: extractOllamaMetrics(last ?? {}),
25847
+ metadata: extractOllamaResponseMetadata(last ?? {})
25848
+ };
25849
+ }
25850
+
24436
25851
  // src/instrumentation/plugins/google-adk-channels.ts
24437
25852
  var googleADKChannels = defineChannels(
24438
25853
  "@google/adk",
@@ -28186,7 +29601,7 @@ var FlueObserveBridge = class {
28186
29601
  return;
28187
29602
  }
28188
29603
  const state = this.operationsById.get(event.operationId) ?? this.startSyntheticOperation(event);
28189
- const output = operationOutput(event);
29604
+ const output = operationOutput(event) ?? outputFromAgentTurn(state.latestAgentOutput);
28190
29605
  const metadata = {
28191
29606
  ...state.metadata,
28192
29607
  ...extractEventMetadata(event),
@@ -28195,7 +29610,7 @@ var FlueObserveBridge = class {
28195
29610
  };
28196
29611
  this.finishPendingChildrenForOperation(event, output);
28197
29612
  safeLog3(state.span, {
28198
- ...event.isError ? { error: toLoggedError(event.error) } : {},
29613
+ ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.error) } : {},
28199
29614
  metadata,
28200
29615
  metrics: durationMetrics2(event.durationMs),
28201
29616
  output
@@ -28226,7 +29641,7 @@ var FlueObserveBridge = class {
28226
29641
  };
28227
29642
  const parent = this.parentSpanForTurn(event);
28228
29643
  const span = startFlueSpan(parent, {
28229
- name: `llm:${model ?? event.purpose ?? "unknown"}`,
29644
+ name: "flue.turn",
28230
29645
  spanAttributes: { type: "llm" /* LLM */ },
28231
29646
  startTime: eventTime(event.timestamp),
28232
29647
  event: {
@@ -28270,6 +29685,12 @@ var FlueObserveBridge = class {
28270
29685
  },
28271
29686
  output
28272
29687
  });
29688
+ if (event.purpose === "agent" && event.operationId) {
29689
+ const operation = this.operationsById.get(event.operationId);
29690
+ if (operation) {
29691
+ operation.latestAgentOutput = output;
29692
+ }
29693
+ }
28273
29694
  safeEnd(state.span, eventTime(event.timestamp));
28274
29695
  this.turnsByKey.delete(key);
28275
29696
  }
@@ -28349,7 +29770,7 @@ var FlueObserveBridge = class {
28349
29770
  return;
28350
29771
  }
28351
29772
  safeLog3(state.span, {
28352
- ...event.isError ? { error: toLoggedError(event.result) } : {},
29773
+ ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.result) } : {},
28353
29774
  metadata: {
28354
29775
  ...state.metadata,
28355
29776
  ...extractEventMetadata(event),
@@ -28395,6 +29816,7 @@ var FlueObserveBridge = class {
28395
29816
  ...event.usage ? { "flue.usage": event.usage } : {}
28396
29817
  };
28397
29818
  safeLog3(state.span, {
29819
+ ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.error) } : {},
28398
29820
  metadata,
28399
29821
  metrics: {
28400
29822
  ...durationMetrics2(event.durationMs),
@@ -28499,7 +29921,7 @@ var FlueObserveBridge = class {
28499
29921
  ...event.purpose ? { "flue.turn_purpose": event.purpose } : {}
28500
29922
  };
28501
29923
  const span = startFlueSpan(this.parentSpanForEvent(event), {
28502
- name: `llm:${model ?? event.purpose ?? "unknown"}`,
29924
+ name: "flue.turn",
28503
29925
  spanAttributes: { type: "llm" /* LLM */ },
28504
29926
  startTime: eventTime(event.timestamp),
28505
29927
  event: { metadata }
@@ -28631,7 +30053,10 @@ function extractEventMetadata(event, ctx) {
28631
30053
  return {
28632
30054
  ...event.runId ? { "flue.run_id": event.runId } : {},
28633
30055
  ...event.instanceId ? { "flue.instance_id": event.instanceId } : {},
30056
+ ...event.submissionId ? { "flue.submission_id": event.submissionId } : {},
28634
30057
  ...event.dispatchId ? { "flue.dispatch_id": event.dispatchId } : {},
30058
+ ...event.agentName ? { "flue.agent_name": event.agentName } : {},
30059
+ ...event.conversationId ? { "flue.conversation_id": event.conversationId } : {},
28635
30060
  ...typeof event.eventIndex === "number" ? { "flue.event_index": event.eventIndex } : {},
28636
30061
  ...event.session ? { "flue.session": event.session } : {},
28637
30062
  ...event.parentSession ? { "flue.parent_session": event.parentSession } : {},
@@ -28660,7 +30085,7 @@ function flueTurnRequestInput(event) {
28660
30085
  return event.request?.input ?? event.input;
28661
30086
  }
28662
30087
  function flueTurnRequestModel(event) {
28663
- return event.request?.model ?? event.model;
30088
+ return event.request?.requestedModel ?? event.request?.model ?? event.model;
28664
30089
  }
28665
30090
  function flueTurnRequestProvider(event) {
28666
30091
  return event.request?.providerName ?? event.provider ?? event.request?.providerId;
@@ -28669,10 +30094,10 @@ function flueTurnRequestApi(event) {
28669
30094
  return event.request?.api ?? event.api;
28670
30095
  }
28671
30096
  function flueTurnRequestReasoning(event) {
28672
- return event.request?.reasoning ?? event.reasoning;
30097
+ return event.request?.reasoningLevel ?? event.request?.reasoning ?? event.reasoning;
28673
30098
  }
28674
30099
  function flueTurnModel(event) {
28675
- return event.request?.model ?? event.model;
30100
+ return event.response?.responseModel ?? event.request?.requestedModel ?? event.request?.model ?? event.model;
28676
30101
  }
28677
30102
  function flueTurnProvider(event) {
28678
30103
  return event.request?.providerName ?? event.provider ?? event.request?.providerId;
@@ -28687,7 +30112,7 @@ function flueTurnOutput(event) {
28687
30112
  return event.response?.output ?? event.output;
28688
30113
  }
28689
30114
  function flueTurnStopReason(event) {
28690
- return event.response?.stopReason ?? event.stopReason;
30115
+ return event.response?.finishReason ?? event.response?.stopReason ?? event.stopReason;
28691
30116
  }
28692
30117
  function flueTurnError(event) {
28693
30118
  return event.response?.error ?? event.response?.errorInfo?.message ?? event.error;
@@ -28702,6 +30127,9 @@ function flueToolInput(event) {
28702
30127
  return event.input;
28703
30128
  }
28704
30129
  function flueToolOutput(event) {
30130
+ if (Object.hasOwn(event, "effectiveResult")) {
30131
+ return event.effectiveResult;
30132
+ }
28705
30133
  return event.output !== void 0 ? event.output : event.result;
28706
30134
  }
28707
30135
  function flueToolError(event) {
@@ -28709,10 +30137,36 @@ function flueToolError(event) {
28709
30137
  }
28710
30138
  function operationOutput(event) {
28711
30139
  if (event.operationKind === "prompt" || event.operationKind === "skill") {
28712
- return llmResultFromOperationResult(event.result);
30140
+ return outputFromAgentInvocation(event.agentOutput) ?? llmResultFromOperationResult(event.result);
28713
30141
  }
28714
30142
  return event.result ?? (event.operationKind === "compact" ? { completed: true } : void 0);
28715
30143
  }
30144
+ function outputFromAgentInvocation(output) {
30145
+ if (output?.type === "text") {
30146
+ return output.text;
30147
+ }
30148
+ if (output?.type === "data") {
30149
+ return output.data;
30150
+ }
30151
+ return void 0;
30152
+ }
30153
+ function outputFromAgentTurn(output) {
30154
+ if (!isObjectLike(output)) {
30155
+ return output;
30156
+ }
30157
+ const content = Reflect.get(output, "content");
30158
+ if (!Array.isArray(content)) {
30159
+ return output;
30160
+ }
30161
+ const text = content.flatMap((part) => {
30162
+ if (!isObjectLike(part) || Reflect.get(part, "type") !== "text") {
30163
+ return [];
30164
+ }
30165
+ const value = Reflect.get(part, "text");
30166
+ return typeof value === "string" ? [value] : [];
30167
+ });
30168
+ return text.length > 0 ? text.join("") : output;
30169
+ }
28716
30170
  function llmResultFromOperationResult(result) {
28717
30171
  if (!isObjectLike(result)) {
28718
30172
  return result;
@@ -28811,7 +30265,7 @@ function safeEnd(span, endTime) {
28811
30265
  }
28812
30266
  }
28813
30267
  function logInstrumentationError3(label, error) {
28814
- console.error(`Error in ${label} instrumentation:`, error);
30268
+ debugLogger.debug(`Error in ${label} instrumentation:`, error);
28815
30269
  }
28816
30270
 
28817
30271
  // src/wrappers/langchain/callback-handler.ts
@@ -29740,12 +31194,13 @@ var piCodingAgentChannels = defineChannels(
29740
31194
  );
29741
31195
 
29742
31196
  // src/instrumentation/plugins/pi-coding-agent-plugin.ts
29743
- var piStreamPatchStates = /* @__PURE__ */ new WeakMap();
31197
+ var piAgentPatchStates = /* @__PURE__ */ new WeakMap();
31198
+ var piAgentEventSubscriptions = /* @__PURE__ */ new WeakSet();
29744
31199
  var piPromptContextStore;
29745
31200
  var PiCodingAgentPlugin = class extends BasePlugin {
29746
31201
  activePromptStates = /* @__PURE__ */ new Set();
29747
31202
  onEnable() {
29748
- this.subscribeToPrompt();
31203
+ this.interceptPrompt();
29749
31204
  }
29750
31205
  onDisable() {
29751
31206
  for (const unsubscribe of this.unsubscribers) {
@@ -29753,65 +31208,74 @@ var PiCodingAgentPlugin = class extends BasePlugin {
29753
31208
  }
29754
31209
  this.unsubscribers = [];
29755
31210
  for (const state of [...this.activePromptStates]) {
29756
- void finalizePiPromptRun(state).catch((error) => {
29757
- logInstrumentationError4("Pi Coding Agent disable cleanup", error);
29758
- });
31211
+ finishPiPromptRun(state);
29759
31212
  }
29760
31213
  }
29761
- subscribeToPrompt() {
29762
- const channel2 = piCodingAgentChannels.prompt.tracingChannel();
29763
- const states = /* @__PURE__ */ new WeakMap();
29764
- const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(channel2);
29765
- const handlers = {
29766
- start: (event) => {
29767
- const state = startPiPromptRun(event, (state2) => {
29768
- this.activePromptStates.delete(state2);
29769
- });
29770
- if (state) {
29771
- this.activePromptStates.add(state);
29772
- states.set(event, state);
29773
- }
29774
- },
29775
- asyncEnd: async (event) => {
29776
- const state = states.get(event);
29777
- if (!state) {
29778
- return;
29779
- }
29780
- states.delete(event);
29781
- state.promptCallEnded = true;
29782
- if (!state.finalized && state.deferCompletionUntilTurnEnd && !state.turnEnded) {
29783
- if (!state.sawStreamFn) {
29784
- state.queued = true;
29785
- if (!state.streamPatchState.queuedPromptStates.includes(state)) {
29786
- state.streamPatchState.queuedPromptStates.push(state);
29787
- }
31214
+ interceptPrompt() {
31215
+ this.unsubscribers.push(
31216
+ piCodingAgentChannels.prompt.intercept(
31217
+ (target, thisArg, args, additional) => {
31218
+ const invokeTarget = () => Reflect.apply(target, thisArg, args);
31219
+ let state;
31220
+ try {
31221
+ state = startPiPromptRun(
31222
+ {
31223
+ ...additional,
31224
+ arguments: args,
31225
+ self: thisArg
31226
+ },
31227
+ (finalizedState) => {
31228
+ this.activePromptStates.delete(finalizedState);
31229
+ }
31230
+ );
31231
+ } catch (error) {
31232
+ logInstrumentationError4("Pi Coding Agent prompt start", error);
29788
31233
  }
29789
- return;
29790
- }
29791
- await finalizePiPromptRun(state);
29792
- },
29793
- error: async (event) => {
29794
- const state = states.get(event);
29795
- if (!state) {
29796
- return;
31234
+ if (!state) {
31235
+ return runWithAutoInstrumentationSuppressed(invokeTarget);
31236
+ }
31237
+ this.activePromptStates.add(state);
31238
+ return promptContextStore().run(
31239
+ state,
31240
+ () => runWithAutoInstrumentationSuppressed(() => {
31241
+ let result;
31242
+ try {
31243
+ result = invokeTarget();
31244
+ } catch (error) {
31245
+ finishPiPromptRun(state, error);
31246
+ throw error;
31247
+ }
31248
+ return Promise.resolve(result).then(
31249
+ (value) => {
31250
+ finishPiPromptCall(state);
31251
+ return value;
31252
+ },
31253
+ (error) => {
31254
+ finishPiPromptRun(state, error);
31255
+ throw error;
31256
+ }
31257
+ );
31258
+ })
31259
+ );
29797
31260
  }
29798
- states.delete(event);
29799
- await finalizePiPromptRun(state, event.error);
29800
- }
29801
- };
29802
- channel2.subscribe(handlers);
29803
- this.unsubscribers.push(() => {
29804
- unbindAutoInstrumentationSuppression?.();
29805
- channel2.unsubscribe(handlers);
29806
- });
31261
+ )
31262
+ );
29807
31263
  }
29808
31264
  };
31265
+ function finishPiPromptCall(state) {
31266
+ state.promptCallEnded = true;
31267
+ if (state.deferCompletionUntilTurnEnd && !state.turnEnded) {
31268
+ return;
31269
+ }
31270
+ finishPiPromptRun(state);
31271
+ }
29809
31272
  function startPiPromptRun(event, onFinalize) {
29810
31273
  const session = extractSession(event);
29811
31274
  const agent = session?.agent;
29812
31275
  if (!session || !isPiAgent(agent)) {
29813
31276
  return void 0;
29814
31277
  }
31278
+ installPiAgentInstrumentation(agent);
29815
31279
  const metadata = {
29816
31280
  ...extractSessionMetadata(session),
29817
31281
  ...extractPromptOptionsMetadata(event.arguments[1]),
@@ -29833,9 +31297,7 @@ function startPiPromptRun(event, onFinalize) {
29833
31297
  INSTRUMENTATION_NAMES.PI_CODING_AGENT
29834
31298
  )
29835
31299
  );
29836
- const streamPatchState = installPiStreamPatch(agent);
29837
31300
  const options = event.arguments[1];
29838
- const promptText = event.arguments[0];
29839
31301
  const state = {
29840
31302
  activeLlmSpans: /* @__PURE__ */ new Set(),
29841
31303
  activeToolSpans: /* @__PURE__ */ new Map(),
@@ -29847,29 +31309,10 @@ function startPiPromptRun(event, onFinalize) {
29847
31309
  metrics: {},
29848
31310
  onFinalize,
29849
31311
  promptCallEnded: false,
29850
- ...typeof promptText === "string" ? { promptText } : {},
29851
- queued: false,
29852
31312
  span,
29853
- sawStreamFn: false,
29854
31313
  startTime: getCurrentUnixTimestamp(),
29855
- streamPatchState,
29856
31314
  turnEnded: false
29857
31315
  };
29858
- state.restorePromptContext = enterPiPromptContext(state);
29859
- streamPatchState.activePromptStates.add(state);
29860
- try {
29861
- state.unsubscribeAgent = agent.subscribe(async (agentEvent) => {
29862
- try {
29863
- await runWithAutoInstrumentationSuppressed(
29864
- () => handlePiAgentEvent(state, agentEvent)
29865
- );
29866
- } catch (error) {
29867
- logInstrumentationError4("Pi Coding Agent event", error);
29868
- }
29869
- });
29870
- } catch (error) {
29871
- logInstrumentationError4("Pi Coding Agent event subscription", error);
29872
- }
29873
31316
  return state;
29874
31317
  }
29875
31318
  function extractSession(event) {
@@ -29883,111 +31326,55 @@ function promptContextStore() {
29883
31326
  piPromptContextStore ??= isomorph_default.newAsyncLocalStorage();
29884
31327
  return piPromptContextStore;
29885
31328
  }
29886
- function currentPromptContextFrames() {
29887
- return promptContextStore().getStore()?.frames ?? [];
29888
- }
29889
31329
  function currentPiPromptState() {
29890
- const frames = currentPromptContextFrames();
29891
- return frames[frames.length - 1]?.state;
29892
- }
29893
- function enterPiPromptContext(state) {
29894
- const frame = {
29895
- id: /* @__PURE__ */ Symbol("braintrust.pi-coding-agent.prompt"),
29896
- state
29897
- };
29898
- promptContextStore().enterWith({
29899
- frames: [...currentPromptContextFrames(), frame]
29900
- });
29901
- return () => {
29902
- const frames = currentPromptContextFrames().filter(
29903
- (candidate) => candidate.id !== frame.id
29904
- );
29905
- promptContextStore().enterWith(frames.length > 0 ? { frames } : void 0);
29906
- };
29907
- }
29908
- function installPiStreamPatch(agent) {
29909
- const existing = piStreamPatchStates.get(agent);
29910
- if (existing) {
29911
- if (agent.streamFn !== existing.wrappedStreamFn) {
29912
- debugLogger.debug(
29913
- "Pi Coding Agent streamFn changed while Braintrust instrumentation was active; preserving existing patch state."
29914
- );
29915
- }
29916
- return existing;
29917
- }
29918
- const patchState = {
29919
- activePromptStates: /* @__PURE__ */ new Set(),
29920
- agent,
29921
- originalStreamFn: agent.streamFn,
29922
- queuedPromptStates: [],
29923
- wrappedStreamFn: agent.streamFn
29924
- };
29925
- patchState.wrappedStreamFn = makeSharedInstrumentedStreamFn(patchState);
29926
- agent.streamFn = patchState.wrappedStreamFn;
29927
- piStreamPatchStates.set(agent, patchState);
29928
- return patchState;
29929
- }
29930
- function resolveStreamPromptState(patchState, context) {
29931
- let lastUserText;
29932
- if (Array.isArray(context.messages)) {
29933
- for (let i = context.messages.length - 1; i >= 0; i--) {
29934
- const message = context.messages[i];
29935
- if (isPiUserMessage(message)) {
29936
- if (typeof message.content === "string") {
29937
- lastUserText = message.content;
29938
- } else {
29939
- lastUserText = message.content.flatMap((part) => part.type === "text" ? [part.text] : []).join("");
29940
- }
29941
- break;
29942
- }
29943
- }
29944
- }
29945
- if (lastUserText !== void 0) {
29946
- const queuedMatch = patchState.queuedPromptStates.find(
29947
- (state) => state.promptText === lastUserText
29948
- );
29949
- if (queuedMatch) {
29950
- return queuedMatch;
29951
- }
29952
- const matches = [...patchState.activePromptStates].filter(
29953
- (state) => state.promptText === lastUserText
31330
+ return promptContextStore().getStore();
31331
+ }
31332
+ function installPiAgentInstrumentation(agent) {
31333
+ const existing = piAgentPatchStates.get(agent);
31334
+ if (!existing || agent.streamFn !== existing.wrappedStreamFn) {
31335
+ const patchState = {
31336
+ originalStreamFn: agent.streamFn,
31337
+ wrappedStreamFn: agent.streamFn
31338
+ };
31339
+ patchState.wrappedStreamFn = makeInstrumentedStreamFn(
31340
+ agent,
31341
+ patchState.originalStreamFn
29954
31342
  );
29955
- if (matches.length === 1) {
29956
- return matches[0];
29957
- }
31343
+ agent.streamFn = patchState.wrappedStreamFn;
31344
+ piAgentPatchStates.set(agent, patchState);
29958
31345
  }
29959
- const contextState = currentPiPromptState();
29960
- if (contextState && patchState.activePromptStates.has(contextState) && (!contextState.queued || lastUserText !== void 0 && contextState.promptText === lastUserText)) {
29961
- return contextState;
31346
+ if (piAgentEventSubscriptions.has(agent)) {
31347
+ return;
29962
31348
  }
29963
- if (patchState.activePromptStates.size === 1) {
29964
- return [...patchState.activePromptStates][0];
31349
+ try {
31350
+ agent.subscribe(async (event) => {
31351
+ const state = currentPiPromptState();
31352
+ if (!state || state.agent !== agent || state.finalized) {
31353
+ return;
31354
+ }
31355
+ try {
31356
+ await runWithAutoInstrumentationSuppressed(
31357
+ () => handlePiAgentEvent(state, event)
31358
+ );
31359
+ } catch (error) {
31360
+ logInstrumentationError4("Pi Coding Agent event", error);
31361
+ }
31362
+ });
31363
+ piAgentEventSubscriptions.add(agent);
31364
+ } catch (error) {
31365
+ logInstrumentationError4("Pi Coding Agent event subscription", error);
29965
31366
  }
29966
- return void 0;
29967
31367
  }
29968
- function makeSharedInstrumentedStreamFn(patchState) {
31368
+ function makeInstrumentedStreamFn(agent, originalStreamFn) {
29969
31369
  return async function instrumentedPiStreamFn(model, context, options) {
29970
- const state = resolveStreamPromptState(patchState, context);
29971
- if (!state) {
29972
- const invokeOriginal = () => Reflect.apply(patchState.originalStreamFn, this, [
29973
- model,
29974
- context,
29975
- options
29976
- ]);
29977
- return patchState.activePromptStates.size > 0 ? runWithAutoInstrumentationSuppressed(invokeOriginal) : invokeOriginal();
31370
+ const invokeOriginal = () => Reflect.apply(originalStreamFn, this, [model, context, options]);
31371
+ const state = currentPiPromptState();
31372
+ if (!state || state.agent !== agent || state.finalized) {
31373
+ return invokeOriginal();
29978
31374
  }
29979
- state.sawStreamFn = true;
29980
- removeQueuedPromptState(state);
29981
- state.streamPatchState.eventPromptState = state;
29982
31375
  const llmState = await startPiLlmSpan(state, model, context, options);
29983
31376
  try {
29984
- const stream = await runWithAutoInstrumentationSuppressed(
29985
- () => Reflect.apply(patchState.originalStreamFn, this, [
29986
- model,
29987
- context,
29988
- options
29989
- ])
29990
- );
31377
+ const stream = await runWithAutoInstrumentationSuppressed(invokeOriginal);
29991
31378
  return patchAssistantMessageStream(stream, state, llmState);
29992
31379
  } catch (error) {
29993
31380
  finishPiLlmSpan(state, llmState, void 0, error);
@@ -30134,13 +31521,6 @@ async function handlePiAgentEvent(state, event) {
30134
31521
  if (state.finalized) {
30135
31522
  return;
30136
31523
  }
30137
- const eventPromptState = state.streamPatchState.eventPromptState;
30138
- if (eventPromptState && eventPromptState !== state) {
30139
- return;
30140
- }
30141
- if (!eventPromptState && (state.queued || state.streamPatchState.activePromptStates.size > 1 && currentPiPromptState() !== state)) {
30142
- return;
30143
- }
30144
31524
  switch (event.type) {
30145
31525
  case "message_end":
30146
31526
  if (isPiAssistantMessage(event.message)) {
@@ -30155,11 +31535,8 @@ async function handlePiAgentEvent(state, event) {
30155
31535
  addMetrics(state.metrics, extractUsageMetrics2(event.message.usage));
30156
31536
  }
30157
31537
  }
30158
- if (state.streamPatchState.eventPromptState === state) {
30159
- state.streamPatchState.eventPromptState = void 0;
30160
- }
30161
31538
  if (state.promptCallEnded && state.deferCompletionUntilTurnEnd) {
30162
- await finalizePiPromptRun(state);
31539
+ finishPiPromptRun(state);
30163
31540
  }
30164
31541
  return;
30165
31542
  case "tool_execution_start":
@@ -30232,19 +31609,13 @@ function finishPiToolSpan(state, event) {
30232
31609
  }
30233
31610
  }
30234
31611
  }
30235
- async function finalizePiPromptRun(state, error) {
31612
+ function finishPiPromptRun(state, error) {
30236
31613
  if (state.finalized) {
30237
31614
  return;
30238
31615
  }
30239
31616
  state.finalized = true;
30240
31617
  state.onFinalize?.(state);
30241
- restorePiStreamFn(state);
30242
- try {
30243
- state.unsubscribeAgent?.();
30244
- } catch (unsubscribeError) {
30245
- logInstrumentationError4("Pi Coding Agent unsubscribe", unsubscribeError);
30246
- }
30247
- await finishOpenLlmSpans(state, error);
31618
+ finishOpenLlmSpans(state, error);
30248
31619
  finishOpenToolSpans(state, error);
30249
31620
  const metadata = {
30250
31621
  ...state.metadata,
@@ -30261,34 +31632,14 @@ async function finalizePiPromptRun(state, error) {
30261
31632
  output: state.output
30262
31633
  });
30263
31634
  } finally {
30264
- state.span.end();
30265
- }
30266
- }
30267
- function restorePiStreamFn(state) {
30268
- const patchState = state.streamPatchState;
30269
- patchState.activePromptStates.delete(state);
30270
- removeQueuedPromptState(state);
30271
- if (patchState.eventPromptState === state) {
30272
- patchState.eventPromptState = void 0;
30273
- }
30274
- state.restorePromptContext?.();
30275
- if (patchState.activePromptStates.size > 0) {
30276
- return;
30277
- }
30278
- if (patchState.agent.streamFn === patchState.wrappedStreamFn) {
30279
- patchState.agent.streamFn = patchState.originalStreamFn;
30280
- }
30281
- piStreamPatchStates.delete(patchState.agent);
30282
- }
30283
- function removeQueuedPromptState(state) {
30284
- state.queued = false;
30285
- const queuedPromptStates = state.streamPatchState.queuedPromptStates;
30286
- const index = queuedPromptStates.indexOf(state);
30287
- if (index >= 0) {
30288
- queuedPromptStates.splice(index, 1);
31635
+ try {
31636
+ state.span.end();
31637
+ } catch (endError) {
31638
+ logInstrumentationError4("Pi Coding Agent prompt end", endError);
31639
+ }
30289
31640
  }
30290
31641
  }
30291
- async function finishOpenLlmSpans(state, error) {
31642
+ function finishOpenLlmSpans(state, error) {
30292
31643
  for (const llmState of [...state.activeLlmSpans]) {
30293
31644
  finishPiLlmSpan(state, llmState, void 0, error);
30294
31645
  }
@@ -30369,7 +31720,7 @@ function normalizeAssistantMessage(message) {
30369
31720
  (part) => part.type === "thinking" && !part.redacted ? [part.thinking] : []
30370
31721
  ).join("");
30371
31722
  const toolCalls = message.content.flatMap(
30372
- (part) => part.type === "toolCall" ? [normalizeToolCall(part)] : []
31723
+ (part) => part.type === "toolCall" ? [normalizeToolCall2(part)] : []
30373
31724
  );
30374
31725
  return {
30375
31726
  role: "assistant",
@@ -30404,13 +31755,13 @@ function normalizeUserContent(content) {
30404
31755
  return part;
30405
31756
  });
30406
31757
  }
30407
- function normalizeToolCall(toolCall) {
31758
+ function normalizeToolCall2(toolCall) {
30408
31759
  return {
30409
31760
  id: toolCall.id,
30410
31761
  type: "function",
30411
31762
  function: {
30412
31763
  name: toolCall.name,
30413
- arguments: stringifyArguments(toolCall.arguments)
31764
+ arguments: stringifyArguments2(toolCall.arguments)
30414
31765
  }
30415
31766
  };
30416
31767
  }
@@ -30593,7 +31944,7 @@ function cleanMetrics5(metrics) {
30593
31944
  }
30594
31945
  return cleaned;
30595
31946
  }
30596
- function stringifyArguments(value) {
31947
+ function stringifyArguments2(value) {
30597
31948
  if (typeof value === "string") {
30598
31949
  return value;
30599
31950
  }
@@ -32161,6 +33512,7 @@ var BraintrustPlugin = class extends BasePlugin {
32161
33512
  anthropicPlugin = null;
32162
33513
  aiSDKPlugin = null;
32163
33514
  claudeAgentSDKPlugin = null;
33515
+ cloudflareThinkPlugin = null;
32164
33516
  cursorSDKPlugin = null;
32165
33517
  openAIAgentsPlugin = null;
32166
33518
  googleGenAIPlugin = null;
@@ -32169,6 +33521,7 @@ var BraintrustPlugin = class extends BasePlugin {
32169
33521
  openRouterPlugin = null;
32170
33522
  openRouterAgentPlugin = null;
32171
33523
  mistralPlugin = null;
33524
+ ollamaPlugin = null;
32172
33525
  googleADKPlugin = null;
32173
33526
  coherePlugin = null;
32174
33527
  groqPlugin = null;
@@ -32208,6 +33561,10 @@ var BraintrustPlugin = class extends BasePlugin {
32208
33561
  this.claudeAgentSDKPlugin = new ClaudeAgentSDKPlugin();
32209
33562
  this.claudeAgentSDKPlugin.enable();
32210
33563
  }
33564
+ if (integrations.cloudflareThink !== false) {
33565
+ this.cloudflareThinkPlugin = new CloudflareThinkPlugin();
33566
+ this.cloudflareThinkPlugin.enable();
33567
+ }
32211
33568
  if (integrations.cursorSDK !== false && integrations.cursor !== false) {
32212
33569
  this.cursorSDKPlugin = new CursorSDKPlugin();
32213
33570
  this.cursorSDKPlugin.enable();
@@ -32238,6 +33595,10 @@ var BraintrustPlugin = class extends BasePlugin {
32238
33595
  this.mistralPlugin = new MistralPlugin();
32239
33596
  this.mistralPlugin.enable();
32240
33597
  }
33598
+ if (integrations.ollama !== false) {
33599
+ this.ollamaPlugin = new OllamaPlugin();
33600
+ this.ollamaPlugin.enable();
33601
+ }
32241
33602
  if (integrations.googleADK !== false) {
32242
33603
  this.googleADKPlugin = new GoogleADKPlugin();
32243
33604
  this.googleADKPlugin.enable();
@@ -32314,6 +33675,10 @@ var BraintrustPlugin = class extends BasePlugin {
32314
33675
  this.claudeAgentSDKPlugin.disable();
32315
33676
  this.claudeAgentSDKPlugin = null;
32316
33677
  }
33678
+ if (this.cloudflareThinkPlugin) {
33679
+ this.cloudflareThinkPlugin.disable();
33680
+ this.cloudflareThinkPlugin = null;
33681
+ }
32317
33682
  if (this.cursorSDKPlugin) {
32318
33683
  this.cursorSDKPlugin.disable();
32319
33684
  this.cursorSDKPlugin = null;
@@ -32346,6 +33711,10 @@ var BraintrustPlugin = class extends BasePlugin {
32346
33711
  this.mistralPlugin.disable();
32347
33712
  this.mistralPlugin = null;
32348
33713
  }
33714
+ if (this.ollamaPlugin) {
33715
+ this.ollamaPlugin.disable();
33716
+ this.ollamaPlugin = null;
33717
+ }
32349
33718
  if (this.googleADKPlugin) {
32350
33719
  this.googleADKPlugin.disable();
32351
33720
  this.googleADKPlugin = null;
@@ -34082,6 +35451,7 @@ var envIntegrationAliases = {
34082
35451
  cloudflareaichat: "cloudflareAIChat",
34083
35452
  "cloudflare-ai-chat": "cloudflareAIChat",
34084
35453
  "@cloudflare/ai-chat": "cloudflareAIChat",
35454
+ cloudflarethink: "cloudflareThink",
34085
35455
  cursor: "cursor",
34086
35456
  "cursor-sdk": "cursorSDK",
34087
35457
  cursorsdk: "cursorSDK",
@@ -34102,6 +35472,7 @@ var envIntegrationAliases = {
34102
35472
  openrouteragent: "openrouterAgent",
34103
35473
  "openrouter-agent": "openrouterAgent",
34104
35474
  mistral: "mistral",
35475
+ ollama: "ollama",
34105
35476
  googleadk: "googleADK",
34106
35477
  "google-adk": "googleADK",
34107
35478
  cohere: "cohere",
@@ -34137,6 +35508,7 @@ function getDefaultInstrumentationIntegrations() {
34137
35508
  huggingface: true,
34138
35509
  claudeAgentSDK: true,
34139
35510
  cloudflareAIChat: true,
35511
+ cloudflareThink: true,
34140
35512
  cursor: true,
34141
35513
  cursorSDK: true,
34142
35514
  flue: true,
@@ -34145,6 +35517,7 @@ function getDefaultInstrumentationIntegrations() {
34145
35517
  openrouter: true,
34146
35518
  openrouterAgent: true,
34147
35519
  mistral: true,
35520
+ ollama: true,
34148
35521
  cohere: true,
34149
35522
  groq: true,
34150
35523
  bedrock: true,