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
package/dist/workerd.js CHANGED
@@ -99,6 +99,7 @@ __export(workerd_exports, {
99
99
  braintrustFlueObserver: () => braintrustFlueObserver,
100
100
  braintrustStreamChunkSchema: () => braintrustStreamChunkSchema,
101
101
  buildLocalSummary: () => buildLocalSummary,
102
+ collectAnthropicSession: () => collectAnthropicSession,
102
103
  configureInstrumentation: () => configureInstrumentation,
103
104
  constructLogs3OverflowRequest: () => constructLogs3OverflowRequest,
104
105
  createFinalValuePassThroughStream: () => createFinalValuePassThroughStream,
@@ -179,6 +180,7 @@ __export(workerd_exports, {
179
180
  wrapClaudeAgentSDK: () => wrapClaudeAgentSDK,
180
181
  wrapCloudflareAIChat: () => wrapCloudflareAIChat,
181
182
  wrapCloudflareAgent: () => wrapCloudflareAgent,
183
+ wrapCloudflareThink: () => wrapCloudflareThink,
182
184
  wrapCohere: () => wrapCohere,
183
185
  wrapCopilotClient: () => wrapCopilotClient,
184
186
  wrapCursorSDK: () => wrapCursorSDK,
@@ -193,6 +195,7 @@ __export(workerd_exports, {
193
195
  wrapLangSmithTraceable: () => wrapLangSmithTraceable,
194
196
  wrapMastraAgent: () => wrapMastraAgent,
195
197
  wrapMistral: () => wrapMistral,
198
+ wrapOllama: () => wrapOllama,
196
199
  wrapOpenAI: () => wrapOpenAI,
197
200
  wrapOpenAICodexSDK: () => wrapOpenAICodexSDK,
198
201
  wrapOpenAIv4: () => wrapOpenAIv4,
@@ -210,8 +213,10 @@ var GLOBAL_INSTRUMENTATION_HOOKS_KEY = "__braintrust_instrumentation_hooks";
210
213
  var GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION = 1;
211
214
  var GLOBAL_INSTRUMENTATION_HOOKS_REGISTRY_BRAND = "braintrust.global-instrumentation-hooks.registry";
212
215
  var GLOBAL_INSTRUMENTATION_HOOK_BRAND = "braintrust.global-instrumentation-hooks.hook";
216
+ var GLOBAL_INVOCATION_HOOK_BRAND = "braintrust.global-instrumentation-hooks.invocation-hook";
213
217
  var registryBrand = Symbol.for(GLOBAL_INSTRUMENTATION_HOOKS_REGISTRY_BRAND);
214
218
  var hookBrand = Symbol.for(GLOBAL_INSTRUMENTATION_HOOK_BRAND);
219
+ var invocationHookBrand = Symbol.for(GLOBAL_INVOCATION_HOOK_BRAND);
215
220
  var errorReporter;
216
221
  function setGlobalHookErrorReporter(reporter) {
217
222
  const previousReporter = errorReporter;
@@ -356,12 +361,69 @@ var traceEvents = [
356
361
  "asyncEnd",
357
362
  "error"
358
363
  ];
364
+ function traceInvocation(hook, operator, target, thisArg, args, additional, callbackIndex = -1) {
365
+ const context = {
366
+ ...additional,
367
+ arguments: args,
368
+ self: thisArg
369
+ };
370
+ const invoke2 = () => hook.invoke(target, thisArg, args, additional);
371
+ if (operator === "traceCallback") {
372
+ return hook.traceCallback(invoke2, callbackIndex, context);
373
+ }
374
+ if (operator === "tracePromise") {
375
+ return hook.tracePromise(invoke2, context);
376
+ }
377
+ return hook.traceSync(invoke2, context);
378
+ }
379
+ var InvocationHook = class {
380
+ interceptors = [];
381
+ get hasInterceptors() {
382
+ return this.interceptors.length > 0;
383
+ }
384
+ intercept(interceptor) {
385
+ if (typeof interceptor !== "function") {
386
+ throw new TypeError("interceptor must be a function");
387
+ }
388
+ this.interceptors = [...this.interceptors, interceptor];
389
+ let active = true;
390
+ return () => {
391
+ if (!active) {
392
+ return;
393
+ }
394
+ active = false;
395
+ const index = this.interceptors.indexOf(interceptor);
396
+ if (index !== -1) {
397
+ this.interceptors = [
398
+ ...this.interceptors.slice(0, index),
399
+ ...this.interceptors.slice(index + 1)
400
+ ];
401
+ }
402
+ };
403
+ }
404
+ invoke(target, thisArg, args, additional) {
405
+ const interceptors = this.interceptors;
406
+ if (interceptors.length === 0) {
407
+ return Reflect.apply(target, thisArg, args);
408
+ }
409
+ let next = target;
410
+ for (let index = interceptors.length - 1; index >= 0; index -= 1) {
411
+ const interceptor = interceptors[index];
412
+ const downstream = next;
413
+ next = function(...nextArgs) {
414
+ return interceptor(downstream, this, nextArgs, additional);
415
+ };
416
+ }
417
+ return Reflect.apply(next, thisArg, args);
418
+ }
419
+ };
359
420
  var TracingHook = class {
360
421
  start;
361
422
  end;
362
423
  asyncStart;
363
424
  asyncEnd;
364
425
  error;
426
+ invocationHook = new InvocationHook();
365
427
  constructor(nameOrChannels) {
366
428
  Object.defineProperty(this, hookBrand, {
367
429
  configurable: false,
@@ -369,6 +431,12 @@ var TracingHook = class {
369
431
  value: GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION,
370
432
  writable: false
371
433
  });
434
+ Object.defineProperty(this, invocationHookBrand, {
435
+ configurable: false,
436
+ enumerable: false,
437
+ value: GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION,
438
+ writable: false
439
+ });
372
440
  if (typeof nameOrChannels === "string") {
373
441
  this.start = new HookChannel(`tracing:${nameOrChannels}:start`);
374
442
  this.end = new HookChannel(`tracing:${nameOrChannels}:end`);
@@ -386,6 +454,26 @@ var TracingHook = class {
386
454
  get hasSubscribers() {
387
455
  return this.start.hasSubscribers || this.end.hasSubscribers || this.asyncStart.hasSubscribers || this.asyncEnd.hasSubscribers || this.error.hasSubscribers;
388
456
  }
457
+ get hasInterceptors() {
458
+ return this.invocationHook.hasInterceptors;
459
+ }
460
+ intercept(interceptor) {
461
+ return this.invocationHook.intercept(interceptor);
462
+ }
463
+ invoke(target, thisArg, args, additional) {
464
+ return this.invocationHook.invoke(target, thisArg, args, additional);
465
+ }
466
+ traceInvocation(operator, target, thisArg, args, additional, callbackIndex = -1) {
467
+ return traceInvocation(
468
+ this,
469
+ operator,
470
+ target,
471
+ thisArg,
472
+ args,
473
+ additional,
474
+ callbackIndex
475
+ );
476
+ }
389
477
  subscribe(handlers) {
390
478
  for (const eventName of traceEvents) {
391
479
  const handler = handlers[eventName];
@@ -607,6 +695,60 @@ function hasTracingHookShape(value) {
607
695
  return false;
608
696
  }
609
697
  }
698
+ function hasInvocationHookShape(value) {
699
+ if (typeof value !== "object" && typeof value !== "function" || value === null) {
700
+ return false;
701
+ }
702
+ try {
703
+ const hook = value;
704
+ return value[invocationHookBrand] === GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION && typeof hook.hasInterceptors === "boolean" && typeof hook.intercept === "function" && typeof hook.invoke === "function";
705
+ } catch {
706
+ return false;
707
+ }
708
+ }
709
+ function installInvocationHook(value) {
710
+ const hasInvocationHook = hasInvocationHookShape(value);
711
+ const invocationHook = new InvocationHook();
712
+ try {
713
+ if (!hasInvocationHook) {
714
+ Object.defineProperties(value, {
715
+ [invocationHookBrand]: {
716
+ configurable: false,
717
+ enumerable: false,
718
+ value: GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION,
719
+ writable: false
720
+ },
721
+ hasInterceptors: {
722
+ configurable: false,
723
+ enumerable: false,
724
+ get: () => invocationHook.hasInterceptors
725
+ },
726
+ intercept: {
727
+ configurable: false,
728
+ enumerable: false,
729
+ value: invocationHook.intercept.bind(invocationHook),
730
+ writable: false
731
+ },
732
+ invoke: {
733
+ configurable: false,
734
+ enumerable: false,
735
+ value: invocationHook.invoke.bind(invocationHook),
736
+ writable: false
737
+ }
738
+ });
739
+ }
740
+ if (typeof value.traceInvocation !== "function") {
741
+ Object.defineProperty(value, "traceInvocation", {
742
+ configurable: false,
743
+ enumerable: false,
744
+ value: traceInvocation.bind(void 0, value),
745
+ writable: false
746
+ });
747
+ }
748
+ } catch (error) {
749
+ reportError(error);
750
+ }
751
+ }
610
752
  function isCompatibleTracingHook(value) {
611
753
  try {
612
754
  return value[hookBrand] === GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION && hasTracingHookShape(value);
@@ -693,6 +835,7 @@ function newGlobalTracingChannel(nameOrChannels) {
693
835
  return inertTracingHook;
694
836
  }
695
837
  if (isCompatibleTracingHook(existing)) {
838
+ installInvocationHook(existing);
696
839
  return existing;
697
840
  }
698
841
  if (existing !== void 0) {
@@ -5528,6 +5671,7 @@ var INSTRUMENTATION_NAMES = {
5528
5671
  CLAUDE_AGENT_SDK: "claude-agent-sdk",
5529
5672
  CLOUDFLARE_AI_CHAT: "cloudflare-ai-chat",
5530
5673
  CLOUDFLARE_AGENTS: "cloudflare-agents",
5674
+ CLOUDFLARE_THINK: "cloudflare-think",
5531
5675
  COHERE: "cohere",
5532
5676
  CURSOR_SDK: "cursor-sdk",
5533
5677
  EVE: "eve",
@@ -5542,6 +5686,7 @@ var INSTRUMENTATION_NAMES = {
5542
5686
  LANGSMITH: "langsmith",
5543
5687
  MASTRA: "mastra",
5544
5688
  MISTRAL: "mistral",
5689
+ OLLAMA: "ollama",
5545
5690
  OPENAI: "openai",
5546
5691
  OPENAI_AGENTS: "openai-agents",
5547
5692
  OPENAI_CODEX: "openai-codex",
@@ -5553,7 +5698,7 @@ var INSTRUMENTATION_NAMES = {
5553
5698
  var INTERNAL_SPAN_INSTRUMENTATION_NAME = /* @__PURE__ */ Symbol.for(
5554
5699
  "braintrust.spanInstrumentationName"
5555
5700
  );
5556
- var SDK_VERSION = true ? "3.26.0" : "0.0.0";
5701
+ var SDK_VERSION = true ? "3.27.0" : "0.0.0";
5557
5702
  function withSpanInstrumentationName(args, instrumentationName) {
5558
5703
  return {
5559
5704
  ...args,
@@ -11726,6 +11871,34 @@ function patchStreamIfNeeded(stream, options) {
11726
11871
  );
11727
11872
  return stream;
11728
11873
  }
11874
+ const chunks = [];
11875
+ let completed = false;
11876
+ const notifyCancellation = async () => {
11877
+ try {
11878
+ await (options.onCancel ?? options.onComplete)(chunks);
11879
+ } catch (error) {
11880
+ debugLogger.error("Error in stream cancellation handler:", error);
11881
+ }
11882
+ };
11883
+ const patchAbortIfPresent = () => {
11884
+ try {
11885
+ if ("abort" in stream && typeof stream.abort === "function") {
11886
+ const originalAbort = stream.abort.bind(stream);
11887
+ stream.abort = (...args) => {
11888
+ try {
11889
+ return originalAbort(...args);
11890
+ } finally {
11891
+ if (!completed) {
11892
+ completed = true;
11893
+ void notifyCancellation();
11894
+ }
11895
+ }
11896
+ };
11897
+ }
11898
+ } catch (error) {
11899
+ debugLogger.warn("Failed to patch stream abort method:", error);
11900
+ }
11901
+ };
11729
11902
  if (hasAsyncIteratorMethods(stream) && isSelfAsyncIterator(stream)) {
11730
11903
  if ("__braintrust_patched_iterator_methods" in stream) {
11731
11904
  return stream;
@@ -11734,8 +11907,6 @@ function patchStreamIfNeeded(stream, options) {
11734
11907
  const originalNext = stream.next.bind(stream);
11735
11908
  const originalReturn = typeof stream.return === "function" ? stream.return.bind(stream) : null;
11736
11909
  const originalThrow = typeof stream.throw === "function" ? stream.throw.bind(stream) : null;
11737
- const chunks = [];
11738
- let completed = false;
11739
11910
  stream.next = async (...args) => {
11740
11911
  try {
11741
11912
  const result = await runNextWithWrapper(
@@ -11787,11 +11958,7 @@ function patchStreamIfNeeded(stream, options) {
11787
11958
  stream.return = async (...args) => {
11788
11959
  if (!completed) {
11789
11960
  completed = true;
11790
- try {
11791
- await options.onComplete(chunks);
11792
- } catch (error) {
11793
- console.error("Error in stream onComplete handler:", error);
11794
- }
11961
+ await notifyCancellation();
11795
11962
  }
11796
11963
  return originalReturn(...args);
11797
11964
  };
@@ -11816,6 +11983,7 @@ function patchStreamIfNeeded(stream, options) {
11816
11983
  Object.defineProperty(stream, "__braintrust_patched_iterator_methods", {
11817
11984
  value: true
11818
11985
  });
11986
+ patchAbortIfPresent();
11819
11987
  return stream;
11820
11988
  } catch (error) {
11821
11989
  console.warn("Failed to patch stream iterator methods:", error);
@@ -11829,8 +11997,6 @@ function patchStreamIfNeeded(stream, options) {
11829
11997
  const patchedIteratorFn = function() {
11830
11998
  const iterator = originalIteratorFn.call(this);
11831
11999
  const originalNext = iterator.next.bind(iterator);
11832
- const chunks = [];
11833
- let completed = false;
11834
12000
  iterator.next = async function(...args) {
11835
12001
  try {
11836
12002
  const result = await runNextWithWrapper(
@@ -11883,11 +12049,7 @@ function patchStreamIfNeeded(stream, options) {
11883
12049
  iterator.return = async function(...args) {
11884
12050
  if (!completed) {
11885
12051
  completed = true;
11886
- try {
11887
- await options.onComplete(chunks);
11888
- } catch (error) {
11889
- console.error("Error in stream onComplete handler:", error);
11890
- }
12052
+ await notifyCancellation();
11891
12053
  }
11892
12054
  return originalReturn(...args);
11893
12055
  };
@@ -11916,6 +12078,7 @@ function patchStreamIfNeeded(stream, options) {
11916
12078
  value: true
11917
12079
  });
11918
12080
  stream[Symbol.asyncIterator] = patchedIteratorFn;
12081
+ patchAbortIfPresent();
11919
12082
  return stream;
11920
12083
  } catch (error) {
11921
12084
  console.warn("Failed to patch stream:", error);
@@ -12664,6 +12827,33 @@ function traceStreamingChannel(channel2, config) {
12664
12827
  const { span, startTime } = spanData;
12665
12828
  if (isAsyncIterable(asyncEndEvent.result)) {
12666
12829
  let firstChunkTime;
12830
+ const handleStreamError = (error) => {
12831
+ try {
12832
+ span.log({ error });
12833
+ } catch (loggingError) {
12834
+ debugLogger.error(
12835
+ `Error logging failure for ${channelName}:`,
12836
+ loggingError
12837
+ );
12838
+ }
12839
+ try {
12840
+ span.end();
12841
+ } catch (endingError) {
12842
+ debugLogger.error(
12843
+ `Error ending span for ${channelName}:`,
12844
+ endingError
12845
+ );
12846
+ }
12847
+ states.delete(event);
12848
+ runStreamingErrorHook({
12849
+ channelName,
12850
+ config,
12851
+ error,
12852
+ event: asyncEndEvent,
12853
+ span,
12854
+ startTime
12855
+ });
12856
+ };
12667
12857
  patchStreamIfNeeded(asyncEndEvent.result, {
12668
12858
  onChunk: () => {
12669
12859
  if (firstChunkTime === void 0) {
@@ -12743,33 +12933,12 @@ function traceStreamingChannel(channel2, config) {
12743
12933
  });
12744
12934
  }
12745
12935
  },
12746
- onError: (error) => {
12747
- try {
12748
- span.log({ error });
12749
- } catch (loggingError) {
12750
- debugLogger.error(
12751
- `Error logging failure for ${channelName}:`,
12752
- loggingError
12753
- );
12754
- }
12755
- try {
12756
- span.end();
12757
- } catch (endingError) {
12758
- debugLogger.error(
12759
- `Error ending span for ${channelName}:`,
12760
- endingError
12761
- );
12762
- }
12763
- states.delete(event);
12764
- runStreamingErrorHook({
12765
- channelName,
12766
- config,
12767
- error,
12768
- event: asyncEndEvent,
12769
- span,
12770
- startTime
12771
- });
12772
- }
12936
+ onCancel: () => {
12937
+ const error = new Error("Stream cancelled before completion");
12938
+ error.name = "AbortError";
12939
+ handleStreamError(error);
12940
+ },
12941
+ onError: handleStreamError
12773
12942
  });
12774
12943
  return;
12775
12944
  }
@@ -13157,11 +13326,21 @@ function defineChannels(pkg, channels, options) {
13157
13326
  const tracingChannel2 = () => isomorph_default.newTracingChannel(
13158
13327
  fullChannelName
13159
13328
  );
13329
+ const intercept2 = (interceptor) => {
13330
+ const hook = tracingChannel2();
13331
+ return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
13332
+ };
13333
+ };
13160
13334
  return [
13161
13335
  key,
13162
13336
  {
13163
13337
  ...asyncSpec,
13164
13338
  instrumentationName,
13339
+ intercept: intercept2,
13340
+ invoke: (target, thisArg, args, additional) => {
13341
+ const hook = tracingChannel2();
13342
+ return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
13343
+ },
13165
13344
  tracingChannel: tracingChannel2,
13166
13345
  tracePromise: (fn, context) => tracingChannel2().tracePromise(
13167
13346
  fn,
@@ -13175,11 +13354,21 @@ function defineChannels(pkg, channels, options) {
13175
13354
  const tracingChannel = () => isomorph_default.newTracingChannel(
13176
13355
  fullChannelName
13177
13356
  );
13357
+ const intercept = (interceptor) => {
13358
+ const hook = tracingChannel();
13359
+ return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
13360
+ };
13361
+ };
13178
13362
  return [
13179
13363
  key,
13180
13364
  {
13181
13365
  ...syncSpec,
13182
13366
  instrumentationName,
13367
+ intercept,
13368
+ invoke: (target, thisArg, args, additional) => {
13369
+ const hook = tracingChannel();
13370
+ return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
13371
+ },
13183
13372
  tracingChannel,
13184
13373
  traceSync: (fn, context) => tracingChannel().traceSync(
13185
13374
  fn,
@@ -14430,6 +14619,25 @@ function extractAnthropicCacheTokens(cacheReadTokens = 0, cacheCreationTokens =
14430
14619
  return cacheTokens;
14431
14620
  }
14432
14621
 
14622
+ // src/wrappers/anthropic-session-collector.ts
14623
+ var sessionStreamCollectors = /* @__PURE__ */ new WeakMap();
14624
+ function registerAnthropicSessionStreamCollector(stream, collector) {
14625
+ sessionStreamCollectors.set(stream, collector);
14626
+ }
14627
+ function collectAnthropicSession(stream) {
14628
+ const collector = sessionStreamCollectors.get(stream);
14629
+ if (!collector) {
14630
+ return stream;
14631
+ }
14632
+ sessionStreamCollectors.delete(stream);
14633
+ try {
14634
+ collector();
14635
+ } catch (error) {
14636
+ debugLogger.error("Failed to collect Anthropic Sessions stream:", error);
14637
+ }
14638
+ return stream;
14639
+ }
14640
+
14433
14641
  // src/instrumentation/plugins/anthropic-channels.ts
14434
14642
  var anthropicChannels = defineChannels(
14435
14643
  "@anthropic-ai/sdk",
@@ -14445,6 +14653,14 @@ var anthropicChannels = defineChannels(
14445
14653
  betaMessagesToolRunner: channel({
14446
14654
  channelName: "beta.messages.toolRunner",
14447
14655
  kind: "sync-stream"
14656
+ }),
14657
+ betaSessionsEventsStream: channel({
14658
+ channelName: "beta.sessions.events.stream",
14659
+ kind: "async"
14660
+ }),
14661
+ betaSessionsThreadsEventsStream: channel({
14662
+ channelName: "beta.sessions.threads.events.stream",
14663
+ kind: "async"
14448
14664
  })
14449
14665
  },
14450
14666
  { instrumentationName: INSTRUMENTATION_NAMES.ANTHROPIC }
@@ -14458,6 +14674,7 @@ var AnthropicPlugin = class extends BasePlugin {
14458
14674
  onEnable() {
14459
14675
  this.subscribeToAnthropicChannels();
14460
14676
  this.subscribeToAnthropicToolRunner();
14677
+ this.subscribeToAnthropicSessionStreams();
14461
14678
  }
14462
14679
  onDisable() {
14463
14680
  this.unsubscribers = unsubscribeAll(this.unsubscribers);
@@ -14575,7 +14792,411 @@ var AnthropicPlugin = class extends BasePlugin {
14575
14792
  tracingChannel.unsubscribe(handlers);
14576
14793
  });
14577
14794
  }
14795
+ subscribeToAnthropicSessionStreams() {
14796
+ this.subscribeToAnthropicSessionStream(
14797
+ anthropicChannels.betaSessionsEventsStream,
14798
+ false
14799
+ );
14800
+ this.subscribeToAnthropicSessionStream(
14801
+ anthropicChannels.betaSessionsThreadsEventsStream,
14802
+ true
14803
+ );
14804
+ }
14805
+ subscribeToAnthropicSessionStream(channel2, isThread) {
14806
+ const tracingChannel = channel2.tracingChannel();
14807
+ const pending = /* @__PURE__ */ new WeakSet();
14808
+ const handlers = {
14809
+ start: (event) => {
14810
+ if (isAutoInstrumentationSuppressed()) {
14811
+ return;
14812
+ }
14813
+ pending.add(event);
14814
+ },
14815
+ asyncEnd: (event) => {
14816
+ if (!pending.delete(event)) {
14817
+ return;
14818
+ }
14819
+ const stream = event.result;
14820
+ if (!isAsyncIterable(stream)) {
14821
+ return;
14822
+ }
14823
+ registerAnthropicSessionStreamCollector(stream, () => {
14824
+ wrapAnthropicSessionEventStream(stream, isThread);
14825
+ });
14826
+ },
14827
+ error: (event) => {
14828
+ pending.delete(event);
14829
+ }
14830
+ };
14831
+ tracingChannel.subscribe(handlers);
14832
+ this.unsubscribers.push(() => tracingChannel.unsubscribe(handlers));
14833
+ }
14578
14834
  };
14835
+ function wrapAnthropicSessionEventStream(stream, isThread) {
14836
+ const state = {
14837
+ history: [],
14838
+ isThread,
14839
+ pendingInput: [],
14840
+ seenEventIds: /* @__PURE__ */ new Set()
14841
+ };
14842
+ patchStreamIfNeeded(stream, {
14843
+ onChunk: (event) => handleAnthropicSessionEvent(state, event),
14844
+ onComplete: () => finalizeAnthropicSessionTurn(state),
14845
+ onError: (error) => finalizeAnthropicSessionTurn(state, error)
14846
+ });
14847
+ return stream;
14848
+ }
14849
+ function handleAnthropicSessionEvent(state, event) {
14850
+ try {
14851
+ if (typeof event.id === "string" && event.type !== "event_delta" && state.seenEventIds.has(event.id)) {
14852
+ return;
14853
+ }
14854
+ if (typeof event.id === "string" && event.type !== "event_delta") {
14855
+ state.seenEventIds.add(event.id);
14856
+ }
14857
+ switch (event.type) {
14858
+ case "user.message":
14859
+ case "system.message":
14860
+ recordAnthropicSessionInput(
14861
+ state,
14862
+ event
14863
+ );
14864
+ break;
14865
+ case "session.status_running":
14866
+ if (!state.isThread) {
14867
+ ensureAnthropicSessionTurn(state);
14868
+ }
14869
+ break;
14870
+ case "session.thread_status_running":
14871
+ if (state.isThread) {
14872
+ ensureAnthropicSessionTurn(state);
14873
+ }
14874
+ break;
14875
+ case "span.model_request_start":
14876
+ if (typeof event.id === "string") {
14877
+ startAnthropicSessionModel(state, event.id);
14878
+ }
14879
+ break;
14880
+ case "event_delta":
14881
+ recordAnthropicSessionFirstToken(state, event);
14882
+ break;
14883
+ case "agent.message":
14884
+ recordAnthropicSessionMessage(
14885
+ state,
14886
+ event
14887
+ );
14888
+ break;
14889
+ case "agent.custom_tool_use":
14890
+ case "agent.mcp_tool_use":
14891
+ case "agent.tool_use":
14892
+ startAnthropicSessionTool(state, event);
14893
+ break;
14894
+ case "user.tool_confirmation":
14895
+ recordAnthropicSessionToolConfirmation(state, event);
14896
+ break;
14897
+ case "agent.mcp_tool_result":
14898
+ case "agent.tool_result":
14899
+ case "user.custom_tool_result":
14900
+ case "user.tool_result":
14901
+ finalizeAnthropicSessionTool(
14902
+ state,
14903
+ event
14904
+ );
14905
+ break;
14906
+ case "span.model_request_end":
14907
+ finalizeAnthropicSessionModel(
14908
+ state,
14909
+ event
14910
+ );
14911
+ break;
14912
+ case "session.status_idle":
14913
+ case "session.thread_status_idle": {
14914
+ if (event.type === "session.status_idle" && state.isThread || event.type === "session.thread_status_idle" && !state.isThread) {
14915
+ break;
14916
+ }
14917
+ const stopReason = isObject(event.stop_reason) ? event.stop_reason.type : void 0;
14918
+ if (stopReason === "end_turn") {
14919
+ finalizeAnthropicSessionTurn(state);
14920
+ } else if (stopReason === "retries_exhausted") {
14921
+ finalizeAnthropicSessionTurn(
14922
+ state,
14923
+ "Anthropic session retries exhausted"
14924
+ );
14925
+ }
14926
+ break;
14927
+ }
14928
+ case "session.error":
14929
+ finalizeAnthropicSessionTurn(state, event.error);
14930
+ break;
14931
+ case "session.deleted":
14932
+ case "session.status_terminated":
14933
+ case "session.thread_status_terminated":
14934
+ if (event.type === "session.deleted" || event.type === "session.status_terminated" && !state.isThread || event.type === "session.thread_status_terminated" && state.isThread) {
14935
+ finalizeAnthropicSessionTurn(state);
14936
+ }
14937
+ break;
14938
+ default:
14939
+ break;
14940
+ }
14941
+ } catch (error) {
14942
+ debugLogger.debug("Error processing Anthropic Sessions event:", error);
14943
+ }
14944
+ }
14945
+ function ensureAnthropicSessionTurn(state) {
14946
+ if (state.activeTurn) {
14947
+ return state.activeTurn;
14948
+ }
14949
+ const input = state.pendingInput;
14950
+ state.pendingInput = [];
14951
+ const span = startSpan(
14952
+ withSpanInstrumentationName(
14953
+ {
14954
+ event: {
14955
+ ...input.length > 0 ? { input } : {},
14956
+ metadata: { provider: "anthropic" }
14957
+ },
14958
+ name: state.isThread ? "anthropic.beta.sessions.thread.turn" : "anthropic.beta.sessions.turn",
14959
+ spanAttributes: { type: "task" /* TASK */ }
14960
+ },
14961
+ INSTRUMENTATION_NAMES.ANTHROPIC
14962
+ )
14963
+ );
14964
+ state.activeTurn = {
14965
+ activeTools: /* @__PURE__ */ new Map(),
14966
+ input: input.slice(),
14967
+ metrics: {},
14968
+ span
14969
+ };
14970
+ return state.activeTurn;
14971
+ }
14972
+ function recordAnthropicSessionInput(state, event) {
14973
+ const content = processAttachmentsInInput(event.content);
14974
+ const message = {
14975
+ role: event.type === "system.message" ? "system" : "user",
14976
+ content
14977
+ };
14978
+ state.history.push(message);
14979
+ if (state.activeTurn) {
14980
+ state.activeTurn.input.push(message);
14981
+ } else {
14982
+ state.pendingInput.push(message);
14983
+ }
14984
+ }
14985
+ function startAnthropicSessionModel(state, startEventId) {
14986
+ const turn = ensureAnthropicSessionTurn(state);
14987
+ if (turn.activeModel) {
14988
+ finalizeAnthropicSessionModelState(state, turn);
14989
+ }
14990
+ const span = withCurrent(
14991
+ turn.span,
14992
+ () => startSpan(
14993
+ withSpanInstrumentationName(
14994
+ {
14995
+ event: {
14996
+ ...state.history.length > 0 ? { input: state.history.slice() } : {},
14997
+ metadata: { provider: "anthropic" }
14998
+ },
14999
+ name: "anthropic.messages.create",
15000
+ spanAttributes: { type: "llm" /* LLM */ }
15001
+ },
15002
+ INSTRUMENTATION_NAMES.ANTHROPIC
15003
+ )
15004
+ )
15005
+ );
15006
+ turn.activeModel = {
15007
+ output: [],
15008
+ span,
15009
+ startEventId,
15010
+ startTime: getCurrentUnixTimestamp()
15011
+ };
15012
+ }
15013
+ function recordAnthropicSessionFirstToken(state, event) {
15014
+ const model = state.activeTurn?.activeModel;
15015
+ if (!model || model.firstTokenTime !== void 0 || !isObject(event.delta) || !isObject(event.delta.content) || typeof event.delta.content.text !== "string") {
15016
+ return;
15017
+ }
15018
+ model.firstTokenTime = getCurrentUnixTimestamp();
15019
+ }
15020
+ function recordAnthropicSessionMessage(state, event) {
15021
+ const turn = ensureAnthropicSessionTurn(state);
15022
+ const content = processAttachmentsInInput(
15023
+ event.content
15024
+ );
15025
+ if (turn.activeModel) {
15026
+ turn.activeModel.output.push(...content);
15027
+ } else {
15028
+ const output = { role: "assistant", content };
15029
+ turn.lastOutput = output;
15030
+ state.history.push(output);
15031
+ }
15032
+ }
15033
+ function startAnthropicSessionTool(state, event) {
15034
+ const turn = ensureAnthropicSessionTurn(state);
15035
+ if (turn.activeModel) {
15036
+ turn.activeModel.output.push({
15037
+ type: "tool_use",
15038
+ id: event.id,
15039
+ name: event.name,
15040
+ input: event.input
15041
+ });
15042
+ }
15043
+ const existing = turn.activeTools.get(event.id);
15044
+ if (existing) {
15045
+ existing.span.end();
15046
+ turn.activeTools.delete(event.id);
15047
+ }
15048
+ const span = withCurrent(
15049
+ turn.span,
15050
+ () => startSpan(
15051
+ withSpanInstrumentationName(
15052
+ {
15053
+ event: { input: event.input },
15054
+ name: event.name,
15055
+ spanAttributes: { type: "tool" /* TOOL */ }
15056
+ },
15057
+ INSTRUMENTATION_NAMES.ANTHROPIC
15058
+ )
15059
+ )
15060
+ );
15061
+ const toolState = {
15062
+ approval: event.evaluated_permission === "allow" ? "approved" : event.evaluated_permission === "deny" ? "denied" : void 0,
15063
+ span
15064
+ };
15065
+ turn.activeTools.set(event.id, toolState);
15066
+ if (toolState.approval === "denied") {
15067
+ finalizeAnthropicSessionToolState(toolState);
15068
+ turn.activeTools.delete(event.id);
15069
+ }
15070
+ }
15071
+ function recordAnthropicSessionToolConfirmation(state, event) {
15072
+ if (typeof event.tool_use_id !== "string" || event.result !== "allow" && event.result !== "deny") {
15073
+ return;
15074
+ }
15075
+ const turn = state.activeTurn;
15076
+ const tool = turn?.activeTools.get(event.tool_use_id);
15077
+ if (!turn || !tool) {
15078
+ return;
15079
+ }
15080
+ tool.approval = event.result === "allow" ? "approved" : "denied";
15081
+ if (tool.approval === "denied") {
15082
+ finalizeAnthropicSessionToolState(tool);
15083
+ turn.activeTools.delete(event.tool_use_id);
15084
+ }
15085
+ }
15086
+ function finalizeAnthropicSessionTool(state, event) {
15087
+ const toolUseId = event.tool_use_id ?? event.mcp_tool_use_id ?? event.custom_tool_use_id;
15088
+ if (!toolUseId) {
15089
+ return;
15090
+ }
15091
+ const content = processAttachmentsInInput(event.content);
15092
+ const turn = state.activeTurn;
15093
+ const tool = turn?.activeTools.get(toolUseId);
15094
+ if (turn && tool) {
15095
+ finalizeAnthropicSessionToolState(tool, event, content);
15096
+ turn.activeTools.delete(toolUseId);
15097
+ }
15098
+ const toolResult = {
15099
+ type: "tool_result",
15100
+ tool_use_id: toolUseId,
15101
+ ...content !== void 0 ? { content } : {},
15102
+ ...event.is_error === true ? { is_error: true } : {}
15103
+ };
15104
+ state.history.push({
15105
+ role: "user",
15106
+ content: [toolResult]
15107
+ });
15108
+ }
15109
+ function finalizeAnthropicSessionToolState(state, event, content = event?.content) {
15110
+ safeAnthropicSessionLog(state.span, {
15111
+ ...event?.is_error === true ? {
15112
+ error: content ?? "Anthropic session tool execution failed"
15113
+ } : {},
15114
+ ...state.approval ? { metadata: { tool_approval: state.approval } } : {},
15115
+ ...content !== void 0 ? { output: content } : {}
15116
+ });
15117
+ state.span.end();
15118
+ }
15119
+ function finalizeAnthropicSessionModel(state, event) {
15120
+ const turn = state.activeTurn;
15121
+ const model = turn?.activeModel;
15122
+ if (!turn || !model || model.startEventId !== event.model_request_start_id) {
15123
+ return;
15124
+ }
15125
+ finalizeAnthropicSessionModelState(state, turn, event);
15126
+ }
15127
+ function finalizeAnthropicSessionModelState(state, turn, event) {
15128
+ const model = turn.activeModel;
15129
+ if (!model) {
15130
+ return;
15131
+ }
15132
+ turn.activeModel = void 0;
15133
+ const metrics = event ? parseAnthropicSessionModelUsage(event.model_usage) : {};
15134
+ if (model.firstTokenTime !== void 0) {
15135
+ metrics.time_to_first_token = model.firstTokenTime - model.startTime;
15136
+ }
15137
+ const output = model.output.length > 0 ? { role: "assistant", content: model.output } : void 0;
15138
+ safeAnthropicSessionLog(model.span, {
15139
+ ...event?.is_error ? { error: "Anthropic session model request failed" } : {},
15140
+ ...Object.keys(metrics).length > 0 ? { metrics } : {},
15141
+ ...output ? { output } : {}
15142
+ });
15143
+ model.span.end();
15144
+ if (output) {
15145
+ turn.lastOutput = output;
15146
+ state.history.push(output);
15147
+ }
15148
+ for (const key of [
15149
+ "prompt_tokens",
15150
+ "completion_tokens",
15151
+ "tokens",
15152
+ "prompt_cached_tokens",
15153
+ "prompt_cache_creation_tokens"
15154
+ ]) {
15155
+ const value = metrics[key];
15156
+ if (typeof value === "number") {
15157
+ turn.metrics[key] = (turn.metrics[key] ?? 0) + value;
15158
+ }
15159
+ }
15160
+ }
15161
+ function parseAnthropicSessionModelUsage(usage) {
15162
+ const finalized = finalizeAnthropicTokens({
15163
+ completion_tokens: usage.output_tokens,
15164
+ prompt_cache_creation_tokens: usage.cache_creation_input_tokens,
15165
+ prompt_cached_tokens: usage.cache_read_input_tokens,
15166
+ prompt_tokens: usage.input_tokens
15167
+ });
15168
+ return Object.fromEntries(
15169
+ Object.entries(finalized).filter(
15170
+ (entry) => entry[1] !== void 0
15171
+ )
15172
+ );
15173
+ }
15174
+ function finalizeAnthropicSessionTurn(state, error) {
15175
+ const turn = state.activeTurn;
15176
+ if (!turn) {
15177
+ return;
15178
+ }
15179
+ state.activeTurn = void 0;
15180
+ finalizeAnthropicSessionModelState(state, turn);
15181
+ for (const tool of turn.activeTools.values()) {
15182
+ finalizeAnthropicSessionToolState(tool);
15183
+ }
15184
+ turn.activeTools.clear();
15185
+ safeAnthropicSessionLog(turn.span, {
15186
+ ...error !== void 0 ? { error: error instanceof Error ? error : toLoggedError(error) } : {},
15187
+ ...turn.input.length > 0 ? { input: turn.input } : {},
15188
+ ...turn.lastOutput ? { output: turn.lastOutput } : {},
15189
+ ...Object.keys(turn.metrics).length > 0 ? { metrics: turn.metrics } : {}
15190
+ });
15191
+ turn.span.end();
15192
+ }
15193
+ function safeAnthropicSessionLog(span, event) {
15194
+ try {
15195
+ span.log(event);
15196
+ } catch (error) {
15197
+ debugLogger.debug("Error logging Anthropic Sessions span:", error);
15198
+ }
15199
+ }
14579
15200
  function parseMetricsFromUsage2(usage) {
14580
15201
  if (!usage) {
14581
15202
  return {};
@@ -16449,6 +17070,29 @@ var harnessAgentChannels = defineChannels(
16449
17070
  { instrumentationName: INSTRUMENTATION_NAMES.AI_SDK }
16450
17071
  );
16451
17072
 
17073
+ // src/instrumentation/plugins/cloudflare-think-context.ts
17074
+ var cloudflareThinkSpans = /* @__PURE__ */ new Map();
17075
+ function registerCloudflareThinkSpan(span) {
17076
+ if (span.spanId) {
17077
+ cloudflareThinkSpans.set(span.spanId, span);
17078
+ }
17079
+ }
17080
+ function unregisterCloudflareThinkSpan(span) {
17081
+ if (span.spanId) {
17082
+ cloudflareThinkSpans.delete(span.spanId);
17083
+ }
17084
+ }
17085
+ function currentCloudflareThinkSpan() {
17086
+ const parentSpanIds = _internalGetGlobalState()?.contextManager.getParentSpanIds()?.spanParents ?? [];
17087
+ for (const parentSpanId of parentSpanIds) {
17088
+ const span = cloudflareThinkSpans.get(parentSpanId);
17089
+ if (span) {
17090
+ return span;
17091
+ }
17092
+ }
17093
+ return void 0;
17094
+ }
17095
+
16452
17096
  // src/instrumentation/plugins/ai-sdk-plugin.ts
16453
17097
  var DEFAULT_DENY_OUTPUT_PATHS = [
16454
17098
  // v3
@@ -16555,6 +17199,7 @@ var AISDKPlugin = class extends BasePlugin {
16555
17199
  traceStreamingChannel(aiSDKChannels.streamText, {
16556
17200
  name: "streamText",
16557
17201
  type: "function" /* FUNCTION */,
17202
+ shouldTrace: () => currentCloudflareThinkSpan() === void 0,
16558
17203
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
16559
17204
  extractOutput: (result, endEvent) => processAISDKOutput(
16560
17205
  result,
@@ -16575,6 +17220,7 @@ var AISDKPlugin = class extends BasePlugin {
16575
17220
  traceSyncStreamChannel(aiSDKChannels.streamTextSync, {
16576
17221
  name: "streamText",
16577
17222
  type: "function" /* FUNCTION */,
17223
+ shouldTrace: () => currentCloudflareThinkSpan() === void 0,
16578
17224
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
16579
17225
  patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
16580
17226
  defaultDenyOutputPaths: denyOutputPaths,
@@ -17560,6 +18206,23 @@ function prepareAISDKWorkflowAgentStreamInput(params, event, span, defaultDenyOu
17560
18206
  metadata
17561
18207
  };
17562
18208
  }
18209
+ function prepareAISDKAgentCallInput(params, event, span, defaultDenyOutputPaths = DEFAULT_DENY_OUTPUT_PATHS) {
18210
+ const { input } = processAISDKWorkflowAgentCallInput(params);
18211
+ const metadata = extractMetadataFromCallParams(params, event.self);
18212
+ const childTracing = prepareAISDKChildTracing(
18213
+ params,
18214
+ event.self,
18215
+ span,
18216
+ defaultDenyOutputPaths,
18217
+ event.aiSDK,
18218
+ { agentOwner: true }
18219
+ );
18220
+ event.modelWrapped = childTracing.modelWrapped;
18221
+ if (childTracing.cleanup) {
18222
+ event.__braintrust_ai_sdk_cleanup = childTracing.cleanup;
18223
+ }
18224
+ return { input, metadata };
18225
+ }
17563
18226
  function prepareAISDKEmbedInput(params, self) {
17564
18227
  return {
17565
18228
  input: { ...params },
@@ -17583,6 +18246,18 @@ function extractTopLevelAISDKMetrics(result, event, startTime) {
17583
18246
  }
17584
18247
  return metrics;
17585
18248
  }
18249
+ async function extractResolvedAISDKTokenMetrics(result) {
18250
+ for (const field of ["totalUsage", "usage"]) {
18251
+ try {
18252
+ const usage = await Promise.resolve(result[field]);
18253
+ if (usage !== void 0) {
18254
+ return extractTokenMetrics({ [field]: usage });
18255
+ }
18256
+ } catch {
18257
+ }
18258
+ }
18259
+ return extractTokenMetrics(result);
18260
+ }
17586
18261
  function hasModelChildTracing(event) {
17587
18262
  return event?.modelWrapped === true || event?.__braintrust_ai_sdk_model_wrapped === true;
17588
18263
  }
@@ -18400,13 +19075,15 @@ function patchAISDKStreamingResult(args) {
18400
19075
  const {
18401
19076
  defaultDenyOutputPaths,
18402
19077
  endEvent,
19078
+ forceTopLevelMetrics,
18403
19079
  onComplete,
18404
19080
  onCancel,
18405
19081
  onError,
18406
19082
  result,
18407
19083
  resolvePromiseUsage,
18408
19084
  span,
18409
- startTime
19085
+ startTime,
19086
+ transformOutput
18410
19087
  } = args;
18411
19088
  if (!result || typeof result !== "object") {
18412
19089
  return false;
@@ -18459,8 +19136,8 @@ function patchAISDKStreamingResult(args) {
18459
19136
  }
18460
19137
  outputLogged = true;
18461
19138
  try {
18462
- const metrics = extractTopLevelAISDKMetrics(result, endEvent);
18463
- if (resolvePromiseUsage) {
19139
+ const metrics = forceTopLevelMetrics ? await extractResolvedAISDKTokenMetrics(result) : extractTopLevelAISDKMetrics(result, endEvent);
19140
+ if (resolvePromiseUsage && !forceTopLevelMetrics) {
18464
19141
  try {
18465
19142
  const resultRecord2 = result;
18466
19143
  const pendingUsage = resultRecord2.totalUsage ?? resultRecord2.usage;
@@ -18479,10 +19156,11 @@ function patchAISDKStreamingResult(args) {
18479
19156
  if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
18480
19157
  metrics.time_to_first_token = firstChunkTime - startTime;
18481
19158
  }
18482
- const output = await processAISDKStreamingOutput(
19159
+ const processedOutput = await processAISDKStreamingOutput(
18483
19160
  result,
18484
19161
  resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
18485
19162
  );
19163
+ const output = transformOutput ? transformOutput(processedOutput) : processedOutput;
18486
19164
  const metadata = buildResolvedMetadataPayload(result).metadata;
18487
19165
  try {
18488
19166
  span.log({
@@ -20904,6 +21582,295 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
20904
21582
  }
20905
21583
  };
20906
21584
 
21585
+ // src/instrumentation/plugins/cloudflare-think-channels.ts
21586
+ var cloudflareThinkChannels = defineChannels(
21587
+ "@cloudflare/think",
21588
+ {
21589
+ runInferenceLoop: channel({
21590
+ channelName: "Think.runInferenceLoop",
21591
+ kind: "async"
21592
+ })
21593
+ },
21594
+ { instrumentationName: INSTRUMENTATION_NAMES.CLOUDFLARE_THINK }
21595
+ );
21596
+
21597
+ // src/instrumentation/plugins/cloudflare-think-plugin.ts
21598
+ var THINK_STATE_ID = /* @__PURE__ */ Symbol.for("braintrust.cloudflare-think.state-id");
21599
+ var CloudflareThinkPlugin = class extends BasePlugin {
21600
+ statesBySpanId = /* @__PURE__ */ new Map();
21601
+ onEnable() {
21602
+ this.subscribeToThinkRuns();
21603
+ this.subscribeToAISDKStreamTextSync();
21604
+ this.subscribeToAISDKStreamTextAsync();
21605
+ }
21606
+ onDisable() {
21607
+ for (const unsubscribe of this.unsubscribers) {
21608
+ unsubscribe();
21609
+ }
21610
+ this.unsubscribers = [];
21611
+ for (const state of this.statesBySpanId.values()) {
21612
+ this.finishState(state);
21613
+ }
21614
+ this.statesBySpanId.clear();
21615
+ }
21616
+ subscribeToThinkRuns() {
21617
+ const channel2 = cloudflareThinkChannels.runInferenceLoop.tracingChannel();
21618
+ const states = /* @__PURE__ */ new WeakMap();
21619
+ const state = _internalGetGlobalState();
21620
+ const contextManager = state?.contextManager;
21621
+ const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
21622
+ const ensureState2 = (event) => {
21623
+ if (isAutoInstrumentationSuppressed()) {
21624
+ return void 0;
21625
+ }
21626
+ const existing = states.get(event);
21627
+ if (existing) {
21628
+ return existing;
21629
+ }
21630
+ const span = startSpan(
21631
+ withSpanInstrumentationName(
21632
+ {
21633
+ name: "Think.runTurn",
21634
+ spanAttributes: { type: "task" /* TASK */ }
21635
+ },
21636
+ INSTRUMENTATION_NAMES.CLOUDFLARE_THINK
21637
+ )
21638
+ );
21639
+ const runState = {
21640
+ aiResultPatched: false,
21641
+ fallbackInput: extractFallbackInput(event.self?.messages),
21642
+ finalized: false,
21643
+ inputLogged: false,
21644
+ span,
21645
+ startTime: getCurrentUnixTimestamp()
21646
+ };
21647
+ const metadata = {
21648
+ braintrust: {
21649
+ integration_name: "cloudflare-think",
21650
+ sdk_language: "typescript"
21651
+ }
21652
+ };
21653
+ if (typeof event.moduleVersion === "string") {
21654
+ metadata["cloudflare_think.version"] = event.moduleVersion;
21655
+ }
21656
+ span.log({ metadata });
21657
+ states.set(event, runState);
21658
+ if (span.spanId) {
21659
+ this.statesBySpanId.set(span.spanId, runState);
21660
+ }
21661
+ registerCloudflareThinkSpan(span);
21662
+ return runState;
21663
+ };
21664
+ if (contextManager && currentSpanStore && channel2.start) {
21665
+ channel2.start.bindStore(currentSpanStore, (event) => {
21666
+ const runState = ensureState2(event);
21667
+ return runState ? contextManager.wrapSpanForStore(runState.span) : currentSpanStore.getStore();
21668
+ });
21669
+ this.unsubscribers.push(
21670
+ () => channel2.start?.unbindStore(currentSpanStore)
21671
+ );
21672
+ }
21673
+ const handlers = {
21674
+ start: (event) => {
21675
+ ensureState2(event);
21676
+ },
21677
+ asyncEnd: (event) => {
21678
+ const runState = states.get(event);
21679
+ states.delete(event);
21680
+ if (!runState || runState.finalized || runState.aiResultPatched) {
21681
+ return;
21682
+ }
21683
+ this.finishState(runState, void 0, event.result);
21684
+ },
21685
+ error: (event) => {
21686
+ const runState = states.get(event);
21687
+ states.delete(event);
21688
+ if (runState) {
21689
+ this.finishState(runState, event.error);
21690
+ }
21691
+ }
21692
+ };
21693
+ channel2.subscribe(handlers);
21694
+ this.unsubscribers.push(() => channel2.unsubscribe(handlers));
21695
+ }
21696
+ subscribeToAISDKStreamTextSync() {
21697
+ const channel2 = aiSDKChannels.streamTextSync.tracingChannel();
21698
+ const handlers = {
21699
+ start: (event) => {
21700
+ this.startAISDKStream(event);
21701
+ },
21702
+ end: (event) => {
21703
+ this.endAISDKStream(event);
21704
+ },
21705
+ error: (event) => {
21706
+ this.errorAISDKStream(event);
21707
+ }
21708
+ };
21709
+ channel2.subscribe(handlers);
21710
+ this.unsubscribers.push(() => channel2.unsubscribe(handlers));
21711
+ }
21712
+ subscribeToAISDKStreamTextAsync() {
21713
+ const channel2 = aiSDKChannels.streamText.tracingChannel();
21714
+ const handlers = {
21715
+ start: (event) => {
21716
+ this.startAISDKStream(event);
21717
+ },
21718
+ asyncEnd: (event) => {
21719
+ this.endAISDKStream(event);
21720
+ },
21721
+ error: (event) => {
21722
+ this.errorAISDKStream(event);
21723
+ }
21724
+ };
21725
+ channel2.subscribe(handlers);
21726
+ this.unsubscribers.push(() => channel2.unsubscribe(handlers));
21727
+ }
21728
+ startAISDKStream(event) {
21729
+ const runState = this.currentState();
21730
+ if (!runState || runState.finalized) {
21731
+ return;
21732
+ }
21733
+ try {
21734
+ const prepared = prepareAISDKAgentCallInput(
21735
+ event.arguments[0],
21736
+ event,
21737
+ runState.span
21738
+ );
21739
+ runState.span.log({
21740
+ input: extractThinkTaskInput(prepared.input),
21741
+ metadata: {
21742
+ ...prepared.metadata,
21743
+ braintrust: {
21744
+ integration_name: "cloudflare-think",
21745
+ sdk_language: "typescript"
21746
+ }
21747
+ }
21748
+ });
21749
+ runState.inputLogged = true;
21750
+ runState.aiEvent = event;
21751
+ Reflect.set(event, THINK_STATE_ID, runState.span.spanId);
21752
+ } catch (error) {
21753
+ debugLogger.error(
21754
+ "Error preparing @cloudflare/think AI SDK tracing:",
21755
+ error
21756
+ );
21757
+ }
21758
+ }
21759
+ endAISDKStream(event) {
21760
+ const runState = this.stateForAISDKEvent(event);
21761
+ if (!runState || runState.finalized) {
21762
+ return;
21763
+ }
21764
+ const patched = patchAISDKStreamingResult({
21765
+ defaultDenyOutputPaths: DEFAULT_DENY_OUTPUT_PATHS,
21766
+ endEvent: event,
21767
+ forceTopLevelMetrics: true,
21768
+ onComplete: () => this.releaseState(runState),
21769
+ result: event.result,
21770
+ span: runState.span,
21771
+ startTime: runState.startTime,
21772
+ transformOutput: extractThinkTaskOutput
21773
+ });
21774
+ runState.aiResultPatched = patched;
21775
+ if (!patched) {
21776
+ this.finishState(runState, void 0, event.result);
21777
+ }
21778
+ }
21779
+ errorAISDKStream(event) {
21780
+ const runState = this.stateForAISDKEvent(event);
21781
+ if (runState) {
21782
+ this.finishState(runState, event.error);
21783
+ }
21784
+ }
21785
+ currentState() {
21786
+ const parentIds = _internalGetGlobalState()?.contextManager.getParentSpanIds()?.spanParents ?? [];
21787
+ for (const parentId of parentIds) {
21788
+ const state = this.statesBySpanId.get(parentId);
21789
+ if (state) {
21790
+ return state;
21791
+ }
21792
+ }
21793
+ return void 0;
21794
+ }
21795
+ stateForAISDKEvent(event) {
21796
+ const spanId = Reflect.get(event, THINK_STATE_ID);
21797
+ return typeof spanId === "string" ? this.statesBySpanId.get(spanId) : void 0;
21798
+ }
21799
+ finishState(state, error, output) {
21800
+ if (state.finalized) {
21801
+ return;
21802
+ }
21803
+ state.finalized = true;
21804
+ try {
21805
+ if (!state.inputLogged && state.fallbackInput !== void 0) {
21806
+ state.span.log({ input: state.fallbackInput });
21807
+ }
21808
+ if (error !== void 0) {
21809
+ state.span.log({ error });
21810
+ } else if (output !== void 0) {
21811
+ state.span.log({ output: extractThinkTaskOutput(output) });
21812
+ }
21813
+ finalizeAISDKChildTracing(state.aiEvent);
21814
+ state.span.end();
21815
+ } finally {
21816
+ this.releaseState(state);
21817
+ }
21818
+ }
21819
+ releaseState(state) {
21820
+ state.finalized = true;
21821
+ unregisterCloudflareThinkSpan(state.span);
21822
+ if (state.span.spanId) {
21823
+ this.statesBySpanId.delete(state.span.spanId);
21824
+ }
21825
+ }
21826
+ };
21827
+ function extractFallbackInput(messages) {
21828
+ if (!Array.isArray(messages) || messages.length === 0) {
21829
+ return void 0;
21830
+ }
21831
+ let latestUserIndex = -1;
21832
+ for (let index = messages.length - 1; index >= 0; index--) {
21833
+ if (messages[index]?.role === "user") {
21834
+ latestUserIndex = index;
21835
+ break;
21836
+ }
21837
+ }
21838
+ const selected = latestUserIndex >= 0 ? messages.slice(latestUserIndex) : [];
21839
+ return selected.map((message) => ({
21840
+ role: message.role,
21841
+ content: message.content ?? message.parts
21842
+ }));
21843
+ }
21844
+ function extractThinkTaskOutput(output) {
21845
+ if (!isObject(output)) {
21846
+ return output;
21847
+ }
21848
+ if (typeof output.text === "string") {
21849
+ return { role: "assistant", content: output.text };
21850
+ }
21851
+ if (output.object !== void 0) {
21852
+ return output.object;
21853
+ }
21854
+ return output;
21855
+ }
21856
+ function extractThinkTaskInput(input) {
21857
+ if (!isObject(input)) {
21858
+ return input;
21859
+ }
21860
+ const system = input.instructions ?? input.system;
21861
+ if (Array.isArray(input.messages)) {
21862
+ return system === void 0 ? input.messages : [{ role: "system", content: system }, ...input.messages];
21863
+ }
21864
+ if (Array.isArray(input.prompt)) {
21865
+ return system === void 0 ? input.prompt : [{ role: "system", content: system }, ...input.prompt];
21866
+ }
21867
+ if (typeof input.prompt === "string") {
21868
+ const messages = [{ role: "user", content: input.prompt }];
21869
+ return system === void 0 ? messages : [{ role: "system", content: system }, ...messages];
21870
+ }
21871
+ return input;
21872
+ }
21873
+
20907
21874
  // src/instrumentation/plugins/cursor-sdk-channels.ts
20908
21875
  var cursorSDKChannels = defineChannels(
20909
21876
  "@cursor/sdk",
@@ -26669,6 +27636,470 @@ function aggregateMistralStreamChunks(chunks) {
26669
27636
  };
26670
27637
  }
26671
27638
 
27639
+ // src/instrumentation/plugins/ollama-channels.ts
27640
+ var ollamaChannels = defineChannels(
27641
+ "ollama",
27642
+ {
27643
+ chat: channel({
27644
+ channelName: "chat",
27645
+ kind: "async"
27646
+ }),
27647
+ generate: channel({
27648
+ channelName: "generate",
27649
+ kind: "async"
27650
+ }),
27651
+ embed: channel({
27652
+ channelName: "embed",
27653
+ kind: "async"
27654
+ })
27655
+ },
27656
+ { instrumentationName: INSTRUMENTATION_NAMES.OLLAMA }
27657
+ );
27658
+
27659
+ // src/instrumentation/plugins/ollama-plugin.ts
27660
+ var OllamaPlugin = class extends BasePlugin {
27661
+ onEnable() {
27662
+ this.unsubscribers.push(
27663
+ traceStreamingChannel(ollamaChannels.chat, {
27664
+ name: "ollama.chat",
27665
+ type: "llm" /* LLM */,
27666
+ extractInput: extractOllamaChatInput,
27667
+ extractOutput: (result, event) => extractOllamaChatOutput(
27668
+ result,
27669
+ countOllamaToolCalls(event?.arguments?.[0]?.messages)
27670
+ ),
27671
+ extractMetadata: extractOllamaResponseMetadata,
27672
+ extractMetrics: extractOllamaMetrics,
27673
+ aggregateChunks: aggregateOllamaChatChunks
27674
+ }),
27675
+ traceStreamingChannel(ollamaChannels.generate, {
27676
+ name: "ollama.generate",
27677
+ type: "llm" /* LLM */,
27678
+ extractInput: extractOllamaGenerateInput,
27679
+ extractOutput: extractOllamaGenerateOutput,
27680
+ extractMetadata: extractOllamaResponseMetadata,
27681
+ extractMetrics: extractOllamaMetrics,
27682
+ aggregateChunks: aggregateOllamaGenerateChunks
27683
+ }),
27684
+ traceAsyncChannel(ollamaChannels.embed, {
27685
+ name: "ollama.embed",
27686
+ type: "llm" /* LLM */,
27687
+ extractInput: extractOllamaEmbedInput,
27688
+ extractOutput: extractOllamaEmbedOutput,
27689
+ extractMetadata: extractOllamaResponseMetadata,
27690
+ extractMetrics: extractOllamaMetrics
27691
+ })
27692
+ );
27693
+ }
27694
+ onDisable() {
27695
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
27696
+ }
27697
+ };
27698
+ function isNonNegativeNumber(value) {
27699
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
27700
+ }
27701
+ function normalizeFinishReason(response, hasToolCalls = false) {
27702
+ if (hasToolCalls) {
27703
+ return "tool_calls";
27704
+ }
27705
+ return response?.done_reason || "stop";
27706
+ }
27707
+ function stringifyArguments(value) {
27708
+ if (typeof value === "string") {
27709
+ return value;
27710
+ }
27711
+ try {
27712
+ return JSON.stringify(value ?? {});
27713
+ } catch {
27714
+ return String(value);
27715
+ }
27716
+ }
27717
+ function syntheticToolCallId(name, index) {
27718
+ const normalizedName = name.replace(/[^a-zA-Z0-9_-]/g, "_") || "tool";
27719
+ return `ollama_call_${normalizedName}_${index}`;
27720
+ }
27721
+ function normalizeToolCall(toolCall, index) {
27722
+ const name = toolCall.function?.name;
27723
+ if (typeof name !== "string" || name.length === 0) {
27724
+ return void 0;
27725
+ }
27726
+ return {
27727
+ id: typeof toolCall.id === "string" && toolCall.id.length > 0 ? toolCall.id : syntheticToolCallId(name, index),
27728
+ type: "function",
27729
+ function: {
27730
+ name,
27731
+ arguments: stringifyArguments(toolCall.function?.arguments)
27732
+ }
27733
+ };
27734
+ }
27735
+ function normalizeToolCalls(toolCalls2, syntheticIdOffset = 0) {
27736
+ if (!Array.isArray(toolCalls2)) {
27737
+ return [];
27738
+ }
27739
+ return toolCalls2.flatMap((toolCall, index) => {
27740
+ const normalized = normalizeToolCall(toolCall, syntheticIdOffset + index);
27741
+ return normalized ? [normalized] : [];
27742
+ });
27743
+ }
27744
+ function countOllamaToolCalls(messages) {
27745
+ if (!Array.isArray(messages)) {
27746
+ return 0;
27747
+ }
27748
+ return messages.reduce(
27749
+ (count, message) => count + (isObject(message) && Array.isArray(message.tool_calls) ? message.tool_calls.length : 0),
27750
+ 0
27751
+ );
27752
+ }
27753
+ function imageBytes(value) {
27754
+ if (value instanceof Uint8Array) {
27755
+ return value;
27756
+ }
27757
+ if (value instanceof ArrayBuffer) {
27758
+ return new Uint8Array(value);
27759
+ }
27760
+ if (typeof value !== "string" || value.startsWith("data:")) {
27761
+ return void 0;
27762
+ }
27763
+ try {
27764
+ const decoded = atob(value.slice(0, 24));
27765
+ return Uint8Array.from(decoded, (character) => character.charCodeAt(0));
27766
+ } catch {
27767
+ return void 0;
27768
+ }
27769
+ }
27770
+ function inferImageMediaType(value) {
27771
+ if (typeof value === "string") {
27772
+ const dataUrlType = value.match(/^data:(image\/[^;]+);base64,/i)?.[1];
27773
+ if (dataUrlType) {
27774
+ return dataUrlType;
27775
+ }
27776
+ }
27777
+ const bytes = imageBytes(value);
27778
+ if (!bytes) {
27779
+ return void 0;
27780
+ }
27781
+ if (bytes[0] === 137 && bytes[1] === 80 && bytes[2] === 78 && bytes[3] === 71) {
27782
+ return "image/png";
27783
+ }
27784
+ if (bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255) {
27785
+ return "image/jpeg";
27786
+ }
27787
+ const signature = String.fromCharCode(...bytes.slice(0, 12));
27788
+ if (signature.startsWith("GIF87a") || signature.startsWith("GIF89a")) {
27789
+ return "image/gif";
27790
+ }
27791
+ if (signature.startsWith("RIFF") && signature.slice(8, 12) === "WEBP") {
27792
+ return "image/webp";
27793
+ }
27794
+ return void 0;
27795
+ }
27796
+ function normalizeTextAndImages(content, images) {
27797
+ if (!images || images.length === 0) {
27798
+ return { content };
27799
+ }
27800
+ const imageParts = [];
27801
+ const unrecognizedImages = [];
27802
+ for (const image of images) {
27803
+ let localImagePath;
27804
+ let localPathMediaType;
27805
+ if (typeof image === "string" && !/^data:/i.test(image) && !/^https?:\/\//i.test(image)) {
27806
+ const extension = image.match(/\.([a-z0-9]+)$/i)?.[1]?.toLowerCase();
27807
+ const extensionMediaType = {
27808
+ png: "image/png",
27809
+ jpg: "image/jpeg",
27810
+ jpeg: "image/jpeg",
27811
+ gif: "image/gif",
27812
+ webp: "image/webp"
27813
+ }[extension ?? ""];
27814
+ if (extensionMediaType && isomorph_default.statSync) {
27815
+ try {
27816
+ if (isomorph_default.statSync(image).isFile()) {
27817
+ localImagePath = image;
27818
+ localPathMediaType = extensionMediaType;
27819
+ }
27820
+ } catch {
27821
+ }
27822
+ }
27823
+ }
27824
+ const mediaType = localPathMediaType ?? inferImageMediaType(image);
27825
+ if (!mediaType) {
27826
+ unrecognizedImages.push(image);
27827
+ continue;
27828
+ }
27829
+ const processedImage = localImagePath ? new Attachment({
27830
+ data: localImagePath,
27831
+ filename: localImagePath.split(/[\\/]/).at(-1) ?? "image",
27832
+ contentType: mediaType
27833
+ }) : processInputAttachments({
27834
+ type: "image",
27835
+ image,
27836
+ mediaType
27837
+ }).image;
27838
+ imageParts.push({
27839
+ type: "image_url",
27840
+ image_url: { url: processedImage }
27841
+ });
27842
+ }
27843
+ return {
27844
+ content: imageParts.length > 0 ? [...content ? [{ type: "text", text: content }] : [], ...imageParts] : content,
27845
+ ...unrecognizedImages.length > 0 ? { unrecognizedImages } : {}
27846
+ };
27847
+ }
27848
+ function normalizeMessage(message, toolCallId, syntheticToolCallIdOffset = 0) {
27849
+ if (typeof message.role !== "string") {
27850
+ return void 0;
27851
+ }
27852
+ const toolCalls2 = normalizeToolCalls(
27853
+ message.tool_calls,
27854
+ syntheticToolCallIdOffset
27855
+ );
27856
+ if (message.role === "tool") {
27857
+ const toolName = typeof message.tool_name === "string" && message.tool_name.length > 0 ? message.tool_name : "tool";
27858
+ return {
27859
+ role: "tool",
27860
+ tool_call_id: toolCallId ?? syntheticToolCallId(toolName, 0),
27861
+ content: typeof message.content === "string" ? message.content : ""
27862
+ };
27863
+ }
27864
+ const normalizedContent = normalizeTextAndImages(
27865
+ typeof message.content === "string" ? message.content || (toolCalls2.length > 0 ? null : "") : toolCalls2.length > 0 ? null : "",
27866
+ message.images
27867
+ );
27868
+ return {
27869
+ role: message.role,
27870
+ content: normalizedContent.content,
27871
+ ...typeof message.thinking === "string" && message.thinking.length > 0 ? { reasoning: message.thinking } : {},
27872
+ ...toolCalls2.length > 0 ? { tool_calls: toolCalls2 } : {},
27873
+ ...normalizedContent.unrecognizedImages ? { images: normalizedContent.unrecognizedImages } : {}
27874
+ };
27875
+ }
27876
+ function normalizeMessages(messages) {
27877
+ if (!Array.isArray(messages)) {
27878
+ return [];
27879
+ }
27880
+ const pendingToolCallIds = /* @__PURE__ */ new Map();
27881
+ let syntheticToolCallIdOffset = 0;
27882
+ return messages.flatMap((message) => {
27883
+ if (!isObject(message)) {
27884
+ return [];
27885
+ }
27886
+ const ollamaMessage = message;
27887
+ let toolCallId;
27888
+ if (ollamaMessage.role === "tool") {
27889
+ const toolName = ollamaMessage.tool_name;
27890
+ if (typeof toolName === "string") {
27891
+ toolCallId = pendingToolCallIds.get(toolName)?.shift();
27892
+ }
27893
+ }
27894
+ const normalized = normalizeMessage(
27895
+ ollamaMessage,
27896
+ toolCallId,
27897
+ syntheticToolCallIdOffset
27898
+ );
27899
+ if (Array.isArray(ollamaMessage.tool_calls)) {
27900
+ syntheticToolCallIdOffset += ollamaMessage.tool_calls.length;
27901
+ }
27902
+ if (ollamaMessage.role === "assistant" && normalized) {
27903
+ const toolCalls2 = Array.isArray(normalized.tool_calls) ? normalized.tool_calls : [];
27904
+ for (const toolCall of toolCalls2) {
27905
+ if (!isObject(toolCall) || !isObject(toolCall.function)) {
27906
+ continue;
27907
+ }
27908
+ const name = toolCall.function.name;
27909
+ const id = toolCall.id;
27910
+ if (typeof name === "string" && typeof id === "string") {
27911
+ const ids = pendingToolCallIds.get(name) ?? [];
27912
+ ids.push(id);
27913
+ pendingToolCallIds.set(name, ids);
27914
+ }
27915
+ }
27916
+ }
27917
+ return normalized ? [normalized] : [];
27918
+ });
27919
+ }
27920
+ function normalizeToolDefinition(tool) {
27921
+ const fn = tool.function;
27922
+ if (!fn || typeof fn.name !== "string" || fn.name.length === 0) {
27923
+ return void 0;
27924
+ }
27925
+ return {
27926
+ type: "function",
27927
+ function: {
27928
+ name: fn.name,
27929
+ ...typeof fn.description === "string" ? { description: fn.description } : {},
27930
+ ...isObject(fn.parameters) ? { parameters: fn.parameters } : {}
27931
+ }
27932
+ };
27933
+ }
27934
+ function extractToolsMetadata(tools) {
27935
+ if (!Array.isArray(tools)) {
27936
+ return {};
27937
+ }
27938
+ const normalized = tools.flatMap((tool) => {
27939
+ if (!isObject(tool)) {
27940
+ return [];
27941
+ }
27942
+ const definition = normalizeToolDefinition(tool);
27943
+ return definition ? [definition] : [];
27944
+ });
27945
+ return normalized.length > 0 ? { tools: normalized } : {};
27946
+ }
27947
+ function extractOptionsMetadata(options) {
27948
+ if (!isObject(options)) {
27949
+ return {};
27950
+ }
27951
+ const metadata = {};
27952
+ const mappings = [
27953
+ ["temperature", "temperature"],
27954
+ ["top_p", "top_p"],
27955
+ ["num_predict", "max_tokens"],
27956
+ ["frequency_penalty", "frequency_penalty"],
27957
+ ["presence_penalty", "presence_penalty"],
27958
+ ["stop", "stop"]
27959
+ ];
27960
+ for (const [source, target] of mappings) {
27961
+ if (options[source] !== void 0) {
27962
+ metadata[target] = options[source];
27963
+ }
27964
+ }
27965
+ return metadata;
27966
+ }
27967
+ function extractRequestMetadata(request) {
27968
+ return {
27969
+ provider: "ollama",
27970
+ ...typeof request?.model === "string" ? { model: request.model } : {},
27971
+ ...extractOptionsMetadata(request?.options),
27972
+ ...request?.format !== void 0 ? { response_format: request.format } : {}
27973
+ };
27974
+ }
27975
+ function extractOllamaChatInput([request]) {
27976
+ return {
27977
+ input: normalizeMessages(request.messages),
27978
+ metadata: {
27979
+ ...extractRequestMetadata(request),
27980
+ ...extractToolsMetadata(request.tools)
27981
+ }
27982
+ };
27983
+ }
27984
+ function extractOllamaGenerateInput([request]) {
27985
+ const normalizedPrompt = normalizeTextAndImages(
27986
+ typeof request.prompt === "string" ? request.prompt : "",
27987
+ Array.isArray(request.images) ? request.images : void 0
27988
+ );
27989
+ const input = [
27990
+ ...typeof request.system === "string" ? [{ role: "system", content: request.system }] : [],
27991
+ {
27992
+ role: "user",
27993
+ content: normalizedPrompt.content,
27994
+ ...typeof request.suffix === "string" ? { suffix: request.suffix } : {},
27995
+ ...normalizedPrompt.unrecognizedImages ? { images: normalizedPrompt.unrecognizedImages } : {}
27996
+ }
27997
+ ];
27998
+ return {
27999
+ input,
28000
+ metadata: extractRequestMetadata(request)
28001
+ };
28002
+ }
28003
+ function extractOllamaEmbedInput([request]) {
28004
+ return {
28005
+ input: request.input,
28006
+ metadata: extractRequestMetadata(request)
28007
+ };
28008
+ }
28009
+ function extractOllamaChatOutput(result, syntheticToolCallIdOffset = 0) {
28010
+ if (!isObject(result) || !isObject(result.message)) {
28011
+ return void 0;
28012
+ }
28013
+ const message = normalizeMessage(
28014
+ result.message,
28015
+ void 0,
28016
+ syntheticToolCallIdOffset
28017
+ );
28018
+ if (!message) {
28019
+ return void 0;
28020
+ }
28021
+ const toolCalls2 = Array.isArray(message.tool_calls) ? message.tool_calls : [];
28022
+ return [
28023
+ {
28024
+ index: 0,
28025
+ finish_reason: normalizeFinishReason(result, toolCalls2.length > 0),
28026
+ message
28027
+ }
28028
+ ];
28029
+ }
28030
+ function extractOllamaGenerateOutput(result) {
28031
+ if (!isObject(result) || typeof result.response !== "string") {
28032
+ return void 0;
28033
+ }
28034
+ return [
28035
+ {
28036
+ index: 0,
28037
+ finish_reason: normalizeFinishReason(result),
28038
+ message: {
28039
+ role: "assistant",
28040
+ content: result.response,
28041
+ ...typeof result.thinking === "string" && result.thinking.length > 0 ? { reasoning: result.thinking } : {}
28042
+ }
28043
+ }
28044
+ ];
28045
+ }
28046
+ function extractOllamaEmbedOutput(result) {
28047
+ const embedding = Array.isArray(result?.embeddings) ? result.embeddings[0] : void 0;
28048
+ return Array.isArray(embedding) ? { embedding_length: embedding.length } : void 0;
28049
+ }
28050
+ function extractOllamaResponseMetadata(result) {
28051
+ return typeof result?.model === "string" ? { model: result.model } : void 0;
28052
+ }
28053
+ function extractOllamaMetrics(result) {
28054
+ const metrics = {};
28055
+ const promptTokens = result?.prompt_eval_count;
28056
+ const completionTokens = result?.eval_count;
28057
+ if (isNonNegativeNumber(promptTokens)) {
28058
+ metrics.prompt_tokens = promptTokens;
28059
+ }
28060
+ if (isNonNegativeNumber(completionTokens)) {
28061
+ metrics.completion_tokens = completionTokens;
28062
+ }
28063
+ if (isNonNegativeNumber(promptTokens) || isNonNegativeNumber(completionTokens)) {
28064
+ metrics.tokens = (isNonNegativeNumber(promptTokens) ? promptTokens : 0) + (isNonNegativeNumber(completionTokens) ? completionTokens : 0);
28065
+ }
28066
+ return metrics;
28067
+ }
28068
+ function aggregateOllamaChatChunks(chunks, _result, event, _startTime) {
28069
+ const last = chunks.at(-1);
28070
+ const message = {
28071
+ role: "assistant",
28072
+ content: chunks.map((chunk) => chunk.message?.content ?? "").join(""),
28073
+ thinking: chunks.map((chunk) => chunk.message?.thinking ?? "").join(""),
28074
+ tool_calls: chunks.flatMap((chunk) => chunk.message?.tool_calls ?? [])
28075
+ };
28076
+ const response = {
28077
+ ...last,
28078
+ message
28079
+ };
28080
+ return {
28081
+ output: extractOllamaChatOutput(
28082
+ response,
28083
+ countOllamaToolCalls(event?.arguments?.[0]?.messages)
28084
+ ),
28085
+ metrics: extractOllamaMetrics(last ?? {}),
28086
+ metadata: extractOllamaResponseMetadata(last ?? {})
28087
+ };
28088
+ }
28089
+ function aggregateOllamaGenerateChunks(chunks, _result, _event, _startTime) {
28090
+ const last = chunks.at(-1);
28091
+ const response = {
28092
+ ...last,
28093
+ response: chunks.map((chunk) => chunk.response ?? "").join(""),
28094
+ thinking: chunks.map((chunk) => chunk.thinking ?? "").join("")
28095
+ };
28096
+ return {
28097
+ output: extractOllamaGenerateOutput(response),
28098
+ metrics: extractOllamaMetrics(last ?? {}),
28099
+ metadata: extractOllamaResponseMetadata(last ?? {})
28100
+ };
28101
+ }
28102
+
26672
28103
  // src/instrumentation/plugins/google-adk-channels.ts
26673
28104
  var googleADKChannels = defineChannels(
26674
28105
  "@google/adk",
@@ -30422,7 +31853,7 @@ var FlueObserveBridge = class {
30422
31853
  return;
30423
31854
  }
30424
31855
  const state = this.operationsById.get(event.operationId) ?? this.startSyntheticOperation(event);
30425
- const output = operationOutput(event);
31856
+ const output = operationOutput(event) ?? outputFromAgentTurn(state.latestAgentOutput);
30426
31857
  const metadata = {
30427
31858
  ...state.metadata,
30428
31859
  ...extractEventMetadata(event),
@@ -30431,7 +31862,7 @@ var FlueObserveBridge = class {
30431
31862
  };
30432
31863
  this.finishPendingChildrenForOperation(event, output);
30433
31864
  safeLog3(state.span, {
30434
- ...event.isError ? { error: toLoggedError(event.error) } : {},
31865
+ ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.error) } : {},
30435
31866
  metadata,
30436
31867
  metrics: durationMetrics2(event.durationMs),
30437
31868
  output
@@ -30462,7 +31893,7 @@ var FlueObserveBridge = class {
30462
31893
  };
30463
31894
  const parent = this.parentSpanForTurn(event);
30464
31895
  const span = startFlueSpan(parent, {
30465
- name: `llm:${model ?? event.purpose ?? "unknown"}`,
31896
+ name: "flue.turn",
30466
31897
  spanAttributes: { type: "llm" /* LLM */ },
30467
31898
  startTime: eventTime(event.timestamp),
30468
31899
  event: {
@@ -30506,6 +31937,12 @@ var FlueObserveBridge = class {
30506
31937
  },
30507
31938
  output
30508
31939
  });
31940
+ if (event.purpose === "agent" && event.operationId) {
31941
+ const operation = this.operationsById.get(event.operationId);
31942
+ if (operation) {
31943
+ operation.latestAgentOutput = output;
31944
+ }
31945
+ }
30509
31946
  safeEnd(state.span, eventTime(event.timestamp));
30510
31947
  this.turnsByKey.delete(key);
30511
31948
  }
@@ -30585,7 +32022,7 @@ var FlueObserveBridge = class {
30585
32022
  return;
30586
32023
  }
30587
32024
  safeLog3(state.span, {
30588
- ...event.isError ? { error: toLoggedError(event.result) } : {},
32025
+ ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.result) } : {},
30589
32026
  metadata: {
30590
32027
  ...state.metadata,
30591
32028
  ...extractEventMetadata(event),
@@ -30631,6 +32068,7 @@ var FlueObserveBridge = class {
30631
32068
  ...event.usage ? { "flue.usage": event.usage } : {}
30632
32069
  };
30633
32070
  safeLog3(state.span, {
32071
+ ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.error) } : {},
30634
32072
  metadata,
30635
32073
  metrics: {
30636
32074
  ...durationMetrics2(event.durationMs),
@@ -30735,7 +32173,7 @@ var FlueObserveBridge = class {
30735
32173
  ...event.purpose ? { "flue.turn_purpose": event.purpose } : {}
30736
32174
  };
30737
32175
  const span = startFlueSpan(this.parentSpanForEvent(event), {
30738
- name: `llm:${model ?? event.purpose ?? "unknown"}`,
32176
+ name: "flue.turn",
30739
32177
  spanAttributes: { type: "llm" /* LLM */ },
30740
32178
  startTime: eventTime(event.timestamp),
30741
32179
  event: { metadata }
@@ -30867,7 +32305,10 @@ function extractEventMetadata(event, ctx) {
30867
32305
  return {
30868
32306
  ...event.runId ? { "flue.run_id": event.runId } : {},
30869
32307
  ...event.instanceId ? { "flue.instance_id": event.instanceId } : {},
32308
+ ...event.submissionId ? { "flue.submission_id": event.submissionId } : {},
30870
32309
  ...event.dispatchId ? { "flue.dispatch_id": event.dispatchId } : {},
32310
+ ...event.agentName ? { "flue.agent_name": event.agentName } : {},
32311
+ ...event.conversationId ? { "flue.conversation_id": event.conversationId } : {},
30871
32312
  ...typeof event.eventIndex === "number" ? { "flue.event_index": event.eventIndex } : {},
30872
32313
  ...event.session ? { "flue.session": event.session } : {},
30873
32314
  ...event.parentSession ? { "flue.parent_session": event.parentSession } : {},
@@ -30896,7 +32337,7 @@ function flueTurnRequestInput(event) {
30896
32337
  return event.request?.input ?? event.input;
30897
32338
  }
30898
32339
  function flueTurnRequestModel(event) {
30899
- return event.request?.model ?? event.model;
32340
+ return event.request?.requestedModel ?? event.request?.model ?? event.model;
30900
32341
  }
30901
32342
  function flueTurnRequestProvider(event) {
30902
32343
  return event.request?.providerName ?? event.provider ?? event.request?.providerId;
@@ -30905,10 +32346,10 @@ function flueTurnRequestApi(event) {
30905
32346
  return event.request?.api ?? event.api;
30906
32347
  }
30907
32348
  function flueTurnRequestReasoning(event) {
30908
- return event.request?.reasoning ?? event.reasoning;
32349
+ return event.request?.reasoningLevel ?? event.request?.reasoning ?? event.reasoning;
30909
32350
  }
30910
32351
  function flueTurnModel(event) {
30911
- return event.request?.model ?? event.model;
32352
+ return event.response?.responseModel ?? event.request?.requestedModel ?? event.request?.model ?? event.model;
30912
32353
  }
30913
32354
  function flueTurnProvider(event) {
30914
32355
  return event.request?.providerName ?? event.provider ?? event.request?.providerId;
@@ -30923,7 +32364,7 @@ function flueTurnOutput(event) {
30923
32364
  return event.response?.output ?? event.output;
30924
32365
  }
30925
32366
  function flueTurnStopReason(event) {
30926
- return event.response?.stopReason ?? event.stopReason;
32367
+ return event.response?.finishReason ?? event.response?.stopReason ?? event.stopReason;
30927
32368
  }
30928
32369
  function flueTurnError(event) {
30929
32370
  return event.response?.error ?? event.response?.errorInfo?.message ?? event.error;
@@ -30938,6 +32379,9 @@ function flueToolInput(event) {
30938
32379
  return event.input;
30939
32380
  }
30940
32381
  function flueToolOutput(event) {
32382
+ if (Object.hasOwn(event, "effectiveResult")) {
32383
+ return event.effectiveResult;
32384
+ }
30941
32385
  return event.output !== void 0 ? event.output : event.result;
30942
32386
  }
30943
32387
  function flueToolError(event) {
@@ -30945,10 +32389,36 @@ function flueToolError(event) {
30945
32389
  }
30946
32390
  function operationOutput(event) {
30947
32391
  if (event.operationKind === "prompt" || event.operationKind === "skill") {
30948
- return llmResultFromOperationResult(event.result);
32392
+ return outputFromAgentInvocation(event.agentOutput) ?? llmResultFromOperationResult(event.result);
30949
32393
  }
30950
32394
  return event.result ?? (event.operationKind === "compact" ? { completed: true } : void 0);
30951
32395
  }
32396
+ function outputFromAgentInvocation(output) {
32397
+ if (output?.type === "text") {
32398
+ return output.text;
32399
+ }
32400
+ if (output?.type === "data") {
32401
+ return output.data;
32402
+ }
32403
+ return void 0;
32404
+ }
32405
+ function outputFromAgentTurn(output) {
32406
+ if (!isObjectLike(output)) {
32407
+ return output;
32408
+ }
32409
+ const content = Reflect.get(output, "content");
32410
+ if (!Array.isArray(content)) {
32411
+ return output;
32412
+ }
32413
+ const text = content.flatMap((part) => {
32414
+ if (!isObjectLike(part) || Reflect.get(part, "type") !== "text") {
32415
+ return [];
32416
+ }
32417
+ const value = Reflect.get(part, "text");
32418
+ return typeof value === "string" ? [value] : [];
32419
+ });
32420
+ return text.length > 0 ? text.join("") : output;
32421
+ }
30952
32422
  function llmResultFromOperationResult(result) {
30953
32423
  if (!isObjectLike(result)) {
30954
32424
  return result;
@@ -31047,7 +32517,7 @@ function safeEnd(span, endTime) {
31047
32517
  }
31048
32518
  }
31049
32519
  function logInstrumentationError3(label, error) {
31050
- console.error(`Error in ${label} instrumentation:`, error);
32520
+ debugLogger.debug(`Error in ${label} instrumentation:`, error);
31051
32521
  }
31052
32522
 
31053
32523
  // src/wrappers/langchain/callback-handler.ts
@@ -31976,12 +33446,13 @@ var piCodingAgentChannels = defineChannels(
31976
33446
  );
31977
33447
 
31978
33448
  // src/instrumentation/plugins/pi-coding-agent-plugin.ts
31979
- var piStreamPatchStates = /* @__PURE__ */ new WeakMap();
33449
+ var piAgentPatchStates = /* @__PURE__ */ new WeakMap();
33450
+ var piAgentEventSubscriptions = /* @__PURE__ */ new WeakSet();
31980
33451
  var piPromptContextStore;
31981
33452
  var PiCodingAgentPlugin = class extends BasePlugin {
31982
33453
  activePromptStates = /* @__PURE__ */ new Set();
31983
33454
  onEnable() {
31984
- this.subscribeToPrompt();
33455
+ this.interceptPrompt();
31985
33456
  }
31986
33457
  onDisable() {
31987
33458
  for (const unsubscribe of this.unsubscribers) {
@@ -31989,65 +33460,74 @@ var PiCodingAgentPlugin = class extends BasePlugin {
31989
33460
  }
31990
33461
  this.unsubscribers = [];
31991
33462
  for (const state of [...this.activePromptStates]) {
31992
- void finalizePiPromptRun(state).catch((error) => {
31993
- logInstrumentationError4("Pi Coding Agent disable cleanup", error);
31994
- });
33463
+ finishPiPromptRun(state);
31995
33464
  }
31996
33465
  }
31997
- subscribeToPrompt() {
31998
- const channel2 = piCodingAgentChannels.prompt.tracingChannel();
31999
- const states = /* @__PURE__ */ new WeakMap();
32000
- const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(channel2);
32001
- const handlers = {
32002
- start: (event) => {
32003
- const state = startPiPromptRun(event, (state2) => {
32004
- this.activePromptStates.delete(state2);
32005
- });
32006
- if (state) {
32007
- this.activePromptStates.add(state);
32008
- states.set(event, state);
32009
- }
32010
- },
32011
- asyncEnd: async (event) => {
32012
- const state = states.get(event);
32013
- if (!state) {
32014
- return;
32015
- }
32016
- states.delete(event);
32017
- state.promptCallEnded = true;
32018
- if (!state.finalized && state.deferCompletionUntilTurnEnd && !state.turnEnded) {
32019
- if (!state.sawStreamFn) {
32020
- state.queued = true;
32021
- if (!state.streamPatchState.queuedPromptStates.includes(state)) {
32022
- state.streamPatchState.queuedPromptStates.push(state);
32023
- }
33466
+ interceptPrompt() {
33467
+ this.unsubscribers.push(
33468
+ piCodingAgentChannels.prompt.intercept(
33469
+ (target, thisArg, args, additional) => {
33470
+ const invokeTarget = () => Reflect.apply(target, thisArg, args);
33471
+ let state;
33472
+ try {
33473
+ state = startPiPromptRun(
33474
+ {
33475
+ ...additional,
33476
+ arguments: args,
33477
+ self: thisArg
33478
+ },
33479
+ (finalizedState) => {
33480
+ this.activePromptStates.delete(finalizedState);
33481
+ }
33482
+ );
33483
+ } catch (error) {
33484
+ logInstrumentationError4("Pi Coding Agent prompt start", error);
32024
33485
  }
32025
- return;
32026
- }
32027
- await finalizePiPromptRun(state);
32028
- },
32029
- error: async (event) => {
32030
- const state = states.get(event);
32031
- if (!state) {
32032
- return;
33486
+ if (!state) {
33487
+ return runWithAutoInstrumentationSuppressed(invokeTarget);
33488
+ }
33489
+ this.activePromptStates.add(state);
33490
+ return promptContextStore().run(
33491
+ state,
33492
+ () => runWithAutoInstrumentationSuppressed(() => {
33493
+ let result;
33494
+ try {
33495
+ result = invokeTarget();
33496
+ } catch (error) {
33497
+ finishPiPromptRun(state, error);
33498
+ throw error;
33499
+ }
33500
+ return Promise.resolve(result).then(
33501
+ (value) => {
33502
+ finishPiPromptCall(state);
33503
+ return value;
33504
+ },
33505
+ (error) => {
33506
+ finishPiPromptRun(state, error);
33507
+ throw error;
33508
+ }
33509
+ );
33510
+ })
33511
+ );
32033
33512
  }
32034
- states.delete(event);
32035
- await finalizePiPromptRun(state, event.error);
32036
- }
32037
- };
32038
- channel2.subscribe(handlers);
32039
- this.unsubscribers.push(() => {
32040
- unbindAutoInstrumentationSuppression?.();
32041
- channel2.unsubscribe(handlers);
32042
- });
33513
+ )
33514
+ );
32043
33515
  }
32044
33516
  };
33517
+ function finishPiPromptCall(state) {
33518
+ state.promptCallEnded = true;
33519
+ if (state.deferCompletionUntilTurnEnd && !state.turnEnded) {
33520
+ return;
33521
+ }
33522
+ finishPiPromptRun(state);
33523
+ }
32045
33524
  function startPiPromptRun(event, onFinalize) {
32046
33525
  const session = extractSession(event);
32047
33526
  const agent = session?.agent;
32048
33527
  if (!session || !isPiAgent(agent)) {
32049
33528
  return void 0;
32050
33529
  }
33530
+ installPiAgentInstrumentation(agent);
32051
33531
  const metadata = {
32052
33532
  ...extractSessionMetadata(session),
32053
33533
  ...extractPromptOptionsMetadata(event.arguments[1]),
@@ -32069,9 +33549,7 @@ function startPiPromptRun(event, onFinalize) {
32069
33549
  INSTRUMENTATION_NAMES.PI_CODING_AGENT
32070
33550
  )
32071
33551
  );
32072
- const streamPatchState = installPiStreamPatch(agent);
32073
33552
  const options = event.arguments[1];
32074
- const promptText = event.arguments[0];
32075
33553
  const state = {
32076
33554
  activeLlmSpans: /* @__PURE__ */ new Set(),
32077
33555
  activeToolSpans: /* @__PURE__ */ new Map(),
@@ -32083,29 +33561,10 @@ function startPiPromptRun(event, onFinalize) {
32083
33561
  metrics: {},
32084
33562
  onFinalize,
32085
33563
  promptCallEnded: false,
32086
- ...typeof promptText === "string" ? { promptText } : {},
32087
- queued: false,
32088
33564
  span,
32089
- sawStreamFn: false,
32090
33565
  startTime: getCurrentUnixTimestamp(),
32091
- streamPatchState,
32092
33566
  turnEnded: false
32093
33567
  };
32094
- state.restorePromptContext = enterPiPromptContext(state);
32095
- streamPatchState.activePromptStates.add(state);
32096
- try {
32097
- state.unsubscribeAgent = agent.subscribe(async (agentEvent) => {
32098
- try {
32099
- await runWithAutoInstrumentationSuppressed(
32100
- () => handlePiAgentEvent(state, agentEvent)
32101
- );
32102
- } catch (error) {
32103
- logInstrumentationError4("Pi Coding Agent event", error);
32104
- }
32105
- });
32106
- } catch (error) {
32107
- logInstrumentationError4("Pi Coding Agent event subscription", error);
32108
- }
32109
33568
  return state;
32110
33569
  }
32111
33570
  function extractSession(event) {
@@ -32119,111 +33578,55 @@ function promptContextStore() {
32119
33578
  piPromptContextStore ??= isomorph_default.newAsyncLocalStorage();
32120
33579
  return piPromptContextStore;
32121
33580
  }
32122
- function currentPromptContextFrames() {
32123
- return promptContextStore().getStore()?.frames ?? [];
32124
- }
32125
33581
  function currentPiPromptState() {
32126
- const frames = currentPromptContextFrames();
32127
- return frames[frames.length - 1]?.state;
32128
- }
32129
- function enterPiPromptContext(state) {
32130
- const frame = {
32131
- id: /* @__PURE__ */ Symbol("braintrust.pi-coding-agent.prompt"),
32132
- state
32133
- };
32134
- promptContextStore().enterWith({
32135
- frames: [...currentPromptContextFrames(), frame]
32136
- });
32137
- return () => {
32138
- const frames = currentPromptContextFrames().filter(
32139
- (candidate) => candidate.id !== frame.id
32140
- );
32141
- promptContextStore().enterWith(frames.length > 0 ? { frames } : void 0);
32142
- };
32143
- }
32144
- function installPiStreamPatch(agent) {
32145
- const existing = piStreamPatchStates.get(agent);
32146
- if (existing) {
32147
- if (agent.streamFn !== existing.wrappedStreamFn) {
32148
- debugLogger.debug(
32149
- "Pi Coding Agent streamFn changed while Braintrust instrumentation was active; preserving existing patch state."
32150
- );
32151
- }
32152
- return existing;
32153
- }
32154
- const patchState = {
32155
- activePromptStates: /* @__PURE__ */ new Set(),
32156
- agent,
32157
- originalStreamFn: agent.streamFn,
32158
- queuedPromptStates: [],
32159
- wrappedStreamFn: agent.streamFn
32160
- };
32161
- patchState.wrappedStreamFn = makeSharedInstrumentedStreamFn(patchState);
32162
- agent.streamFn = patchState.wrappedStreamFn;
32163
- piStreamPatchStates.set(agent, patchState);
32164
- return patchState;
32165
- }
32166
- function resolveStreamPromptState(patchState, context) {
32167
- let lastUserText;
32168
- if (Array.isArray(context.messages)) {
32169
- for (let i = context.messages.length - 1; i >= 0; i--) {
32170
- const message = context.messages[i];
32171
- if (isPiUserMessage(message)) {
32172
- if (typeof message.content === "string") {
32173
- lastUserText = message.content;
32174
- } else {
32175
- lastUserText = message.content.flatMap((part) => part.type === "text" ? [part.text] : []).join("");
32176
- }
32177
- break;
32178
- }
32179
- }
32180
- }
32181
- if (lastUserText !== void 0) {
32182
- const queuedMatch = patchState.queuedPromptStates.find(
32183
- (state) => state.promptText === lastUserText
32184
- );
32185
- if (queuedMatch) {
32186
- return queuedMatch;
32187
- }
32188
- const matches = [...patchState.activePromptStates].filter(
32189
- (state) => state.promptText === lastUserText
33582
+ return promptContextStore().getStore();
33583
+ }
33584
+ function installPiAgentInstrumentation(agent) {
33585
+ const existing = piAgentPatchStates.get(agent);
33586
+ if (!existing || agent.streamFn !== existing.wrappedStreamFn) {
33587
+ const patchState = {
33588
+ originalStreamFn: agent.streamFn,
33589
+ wrappedStreamFn: agent.streamFn
33590
+ };
33591
+ patchState.wrappedStreamFn = makeInstrumentedStreamFn(
33592
+ agent,
33593
+ patchState.originalStreamFn
32190
33594
  );
32191
- if (matches.length === 1) {
32192
- return matches[0];
32193
- }
33595
+ agent.streamFn = patchState.wrappedStreamFn;
33596
+ piAgentPatchStates.set(agent, patchState);
32194
33597
  }
32195
- const contextState = currentPiPromptState();
32196
- if (contextState && patchState.activePromptStates.has(contextState) && (!contextState.queued || lastUserText !== void 0 && contextState.promptText === lastUserText)) {
32197
- return contextState;
33598
+ if (piAgentEventSubscriptions.has(agent)) {
33599
+ return;
32198
33600
  }
32199
- if (patchState.activePromptStates.size === 1) {
32200
- return [...patchState.activePromptStates][0];
33601
+ try {
33602
+ agent.subscribe(async (event) => {
33603
+ const state = currentPiPromptState();
33604
+ if (!state || state.agent !== agent || state.finalized) {
33605
+ return;
33606
+ }
33607
+ try {
33608
+ await runWithAutoInstrumentationSuppressed(
33609
+ () => handlePiAgentEvent(state, event)
33610
+ );
33611
+ } catch (error) {
33612
+ logInstrumentationError4("Pi Coding Agent event", error);
33613
+ }
33614
+ });
33615
+ piAgentEventSubscriptions.add(agent);
33616
+ } catch (error) {
33617
+ logInstrumentationError4("Pi Coding Agent event subscription", error);
32201
33618
  }
32202
- return void 0;
32203
33619
  }
32204
- function makeSharedInstrumentedStreamFn(patchState) {
33620
+ function makeInstrumentedStreamFn(agent, originalStreamFn) {
32205
33621
  return async function instrumentedPiStreamFn(model, context, options) {
32206
- const state = resolveStreamPromptState(patchState, context);
32207
- if (!state) {
32208
- const invokeOriginal = () => Reflect.apply(patchState.originalStreamFn, this, [
32209
- model,
32210
- context,
32211
- options
32212
- ]);
32213
- return patchState.activePromptStates.size > 0 ? runWithAutoInstrumentationSuppressed(invokeOriginal) : invokeOriginal();
33622
+ const invokeOriginal = () => Reflect.apply(originalStreamFn, this, [model, context, options]);
33623
+ const state = currentPiPromptState();
33624
+ if (!state || state.agent !== agent || state.finalized) {
33625
+ return invokeOriginal();
32214
33626
  }
32215
- state.sawStreamFn = true;
32216
- removeQueuedPromptState(state);
32217
- state.streamPatchState.eventPromptState = state;
32218
33627
  const llmState = await startPiLlmSpan(state, model, context, options);
32219
33628
  try {
32220
- const stream = await runWithAutoInstrumentationSuppressed(
32221
- () => Reflect.apply(patchState.originalStreamFn, this, [
32222
- model,
32223
- context,
32224
- options
32225
- ])
32226
- );
33629
+ const stream = await runWithAutoInstrumentationSuppressed(invokeOriginal);
32227
33630
  return patchAssistantMessageStream(stream, state, llmState);
32228
33631
  } catch (error) {
32229
33632
  finishPiLlmSpan(state, llmState, void 0, error);
@@ -32370,13 +33773,6 @@ async function handlePiAgentEvent(state, event) {
32370
33773
  if (state.finalized) {
32371
33774
  return;
32372
33775
  }
32373
- const eventPromptState = state.streamPatchState.eventPromptState;
32374
- if (eventPromptState && eventPromptState !== state) {
32375
- return;
32376
- }
32377
- if (!eventPromptState && (state.queued || state.streamPatchState.activePromptStates.size > 1 && currentPiPromptState() !== state)) {
32378
- return;
32379
- }
32380
33776
  switch (event.type) {
32381
33777
  case "message_end":
32382
33778
  if (isPiAssistantMessage(event.message)) {
@@ -32391,11 +33787,8 @@ async function handlePiAgentEvent(state, event) {
32391
33787
  addMetrics(state.metrics, extractUsageMetrics2(event.message.usage));
32392
33788
  }
32393
33789
  }
32394
- if (state.streamPatchState.eventPromptState === state) {
32395
- state.streamPatchState.eventPromptState = void 0;
32396
- }
32397
33790
  if (state.promptCallEnded && state.deferCompletionUntilTurnEnd) {
32398
- await finalizePiPromptRun(state);
33791
+ finishPiPromptRun(state);
32399
33792
  }
32400
33793
  return;
32401
33794
  case "tool_execution_start":
@@ -32468,19 +33861,13 @@ function finishPiToolSpan(state, event) {
32468
33861
  }
32469
33862
  }
32470
33863
  }
32471
- async function finalizePiPromptRun(state, error) {
33864
+ function finishPiPromptRun(state, error) {
32472
33865
  if (state.finalized) {
32473
33866
  return;
32474
33867
  }
32475
33868
  state.finalized = true;
32476
33869
  state.onFinalize?.(state);
32477
- restorePiStreamFn(state);
32478
- try {
32479
- state.unsubscribeAgent?.();
32480
- } catch (unsubscribeError) {
32481
- logInstrumentationError4("Pi Coding Agent unsubscribe", unsubscribeError);
32482
- }
32483
- await finishOpenLlmSpans(state, error);
33870
+ finishOpenLlmSpans(state, error);
32484
33871
  finishOpenToolSpans(state, error);
32485
33872
  const metadata = {
32486
33873
  ...state.metadata,
@@ -32497,34 +33884,14 @@ async function finalizePiPromptRun(state, error) {
32497
33884
  output: state.output
32498
33885
  });
32499
33886
  } finally {
32500
- state.span.end();
32501
- }
32502
- }
32503
- function restorePiStreamFn(state) {
32504
- const patchState = state.streamPatchState;
32505
- patchState.activePromptStates.delete(state);
32506
- removeQueuedPromptState(state);
32507
- if (patchState.eventPromptState === state) {
32508
- patchState.eventPromptState = void 0;
32509
- }
32510
- state.restorePromptContext?.();
32511
- if (patchState.activePromptStates.size > 0) {
32512
- return;
32513
- }
32514
- if (patchState.agent.streamFn === patchState.wrappedStreamFn) {
32515
- patchState.agent.streamFn = patchState.originalStreamFn;
32516
- }
32517
- piStreamPatchStates.delete(patchState.agent);
32518
- }
32519
- function removeQueuedPromptState(state) {
32520
- state.queued = false;
32521
- const queuedPromptStates = state.streamPatchState.queuedPromptStates;
32522
- const index = queuedPromptStates.indexOf(state);
32523
- if (index >= 0) {
32524
- queuedPromptStates.splice(index, 1);
33887
+ try {
33888
+ state.span.end();
33889
+ } catch (endError) {
33890
+ logInstrumentationError4("Pi Coding Agent prompt end", endError);
33891
+ }
32525
33892
  }
32526
33893
  }
32527
- async function finishOpenLlmSpans(state, error) {
33894
+ function finishOpenLlmSpans(state, error) {
32528
33895
  for (const llmState of [...state.activeLlmSpans]) {
32529
33896
  finishPiLlmSpan(state, llmState, void 0, error);
32530
33897
  }
@@ -32605,7 +33972,7 @@ function normalizeAssistantMessage(message) {
32605
33972
  (part) => part.type === "thinking" && !part.redacted ? [part.thinking] : []
32606
33973
  ).join("");
32607
33974
  const toolCalls2 = message.content.flatMap(
32608
- (part) => part.type === "toolCall" ? [normalizeToolCall(part)] : []
33975
+ (part) => part.type === "toolCall" ? [normalizeToolCall2(part)] : []
32609
33976
  );
32610
33977
  return {
32611
33978
  role: "assistant",
@@ -32640,13 +34007,13 @@ function normalizeUserContent(content) {
32640
34007
  return part;
32641
34008
  });
32642
34009
  }
32643
- function normalizeToolCall(toolCall) {
34010
+ function normalizeToolCall2(toolCall) {
32644
34011
  return {
32645
34012
  id: toolCall.id,
32646
34013
  type: "function",
32647
34014
  function: {
32648
34015
  name: toolCall.name,
32649
- arguments: stringifyArguments(toolCall.arguments)
34016
+ arguments: stringifyArguments2(toolCall.arguments)
32650
34017
  }
32651
34018
  };
32652
34019
  }
@@ -32829,7 +34196,7 @@ function cleanMetrics5(metrics) {
32829
34196
  }
32830
34197
  return cleaned;
32831
34198
  }
32832
- function stringifyArguments(value) {
34199
+ function stringifyArguments2(value) {
32833
34200
  if (typeof value === "string") {
32834
34201
  return value;
32835
34202
  }
@@ -34420,6 +35787,7 @@ var BraintrustPlugin = class extends BasePlugin {
34420
35787
  anthropicPlugin = null;
34421
35788
  aiSDKPlugin = null;
34422
35789
  claudeAgentSDKPlugin = null;
35790
+ cloudflareThinkPlugin = null;
34423
35791
  cursorSDKPlugin = null;
34424
35792
  openAIAgentsPlugin = null;
34425
35793
  googleGenAIPlugin = null;
@@ -34428,6 +35796,7 @@ var BraintrustPlugin = class extends BasePlugin {
34428
35796
  openRouterPlugin = null;
34429
35797
  openRouterAgentPlugin = null;
34430
35798
  mistralPlugin = null;
35799
+ ollamaPlugin = null;
34431
35800
  googleADKPlugin = null;
34432
35801
  coherePlugin = null;
34433
35802
  groqPlugin = null;
@@ -34467,6 +35836,10 @@ var BraintrustPlugin = class extends BasePlugin {
34467
35836
  this.claudeAgentSDKPlugin = new ClaudeAgentSDKPlugin();
34468
35837
  this.claudeAgentSDKPlugin.enable();
34469
35838
  }
35839
+ if (integrations.cloudflareThink !== false) {
35840
+ this.cloudflareThinkPlugin = new CloudflareThinkPlugin();
35841
+ this.cloudflareThinkPlugin.enable();
35842
+ }
34470
35843
  if (integrations.cursorSDK !== false && integrations.cursor !== false) {
34471
35844
  this.cursorSDKPlugin = new CursorSDKPlugin();
34472
35845
  this.cursorSDKPlugin.enable();
@@ -34497,6 +35870,10 @@ var BraintrustPlugin = class extends BasePlugin {
34497
35870
  this.mistralPlugin = new MistralPlugin();
34498
35871
  this.mistralPlugin.enable();
34499
35872
  }
35873
+ if (integrations.ollama !== false) {
35874
+ this.ollamaPlugin = new OllamaPlugin();
35875
+ this.ollamaPlugin.enable();
35876
+ }
34500
35877
  if (integrations.googleADK !== false) {
34501
35878
  this.googleADKPlugin = new GoogleADKPlugin();
34502
35879
  this.googleADKPlugin.enable();
@@ -34573,6 +35950,10 @@ var BraintrustPlugin = class extends BasePlugin {
34573
35950
  this.claudeAgentSDKPlugin.disable();
34574
35951
  this.claudeAgentSDKPlugin = null;
34575
35952
  }
35953
+ if (this.cloudflareThinkPlugin) {
35954
+ this.cloudflareThinkPlugin.disable();
35955
+ this.cloudflareThinkPlugin = null;
35956
+ }
34576
35957
  if (this.cursorSDKPlugin) {
34577
35958
  this.cursorSDKPlugin.disable();
34578
35959
  this.cursorSDKPlugin = null;
@@ -34605,6 +35986,10 @@ var BraintrustPlugin = class extends BasePlugin {
34605
35986
  this.mistralPlugin.disable();
34606
35987
  this.mistralPlugin = null;
34607
35988
  }
35989
+ if (this.ollamaPlugin) {
35990
+ this.ollamaPlugin.disable();
35991
+ this.ollamaPlugin = null;
35992
+ }
34608
35993
  if (this.googleADKPlugin) {
34609
35994
  this.googleADKPlugin.disable();
34610
35995
  this.googleADKPlugin = null;
@@ -34690,6 +36075,7 @@ var envIntegrationAliases = {
34690
36075
  cloudflareaichat: "cloudflareAIChat",
34691
36076
  "cloudflare-ai-chat": "cloudflareAIChat",
34692
36077
  "@cloudflare/ai-chat": "cloudflareAIChat",
36078
+ cloudflarethink: "cloudflareThink",
34693
36079
  cursor: "cursor",
34694
36080
  "cursor-sdk": "cursorSDK",
34695
36081
  cursorsdk: "cursorSDK",
@@ -34710,6 +36096,7 @@ var envIntegrationAliases = {
34710
36096
  openrouteragent: "openrouterAgent",
34711
36097
  "openrouter-agent": "openrouterAgent",
34712
36098
  mistral: "mistral",
36099
+ ollama: "ollama",
34713
36100
  googleadk: "googleADK",
34714
36101
  "google-adk": "googleADK",
34715
36102
  cohere: "cohere",
@@ -34745,6 +36132,7 @@ function getDefaultInstrumentationIntegrations() {
34745
36132
  huggingface: true,
34746
36133
  claudeAgentSDK: true,
34747
36134
  cloudflareAIChat: true,
36135
+ cloudflareThink: true,
34748
36136
  cursor: true,
34749
36137
  cursorSDK: true,
34750
36138
  flue: true,
@@ -34753,6 +36141,7 @@ function getDefaultInstrumentationIntegrations() {
34753
36141
  openrouter: true,
34754
36142
  openrouterAgent: true,
34755
36143
  mistral: true,
36144
+ ollama: true,
34756
36145
  cohere: true,
34757
36146
  groq: true,
34758
36147
  bedrock: true,
@@ -34987,6 +36376,7 @@ __export(exports_exports, {
34987
36376
  braintrustFlueObserver: () => braintrustFlueObserver,
34988
36377
  braintrustStreamChunkSchema: () => braintrustStreamChunkSchema,
34989
36378
  buildLocalSummary: () => buildLocalSummary,
36379
+ collectAnthropicSession: () => collectAnthropicSession,
34990
36380
  configureInstrumentation: () => configureInstrumentation,
34991
36381
  constructLogs3OverflowRequest: () => constructLogs3OverflowRequest,
34992
36382
  createFinalValuePassThroughStream: () => createFinalValuePassThroughStream,
@@ -35066,6 +36456,7 @@ __export(exports_exports, {
35066
36456
  wrapClaudeAgentSDK: () => wrapClaudeAgentSDK,
35067
36457
  wrapCloudflareAIChat: () => wrapCloudflareAIChat,
35068
36458
  wrapCloudflareAgent: () => wrapCloudflareAgent,
36459
+ wrapCloudflareThink: () => wrapCloudflareThink,
35069
36460
  wrapCohere: () => wrapCohere,
35070
36461
  wrapCopilotClient: () => wrapCopilotClient,
35071
36462
  wrapCursorSDK: () => wrapCursorSDK,
@@ -35080,6 +36471,7 @@ __export(exports_exports, {
35080
36471
  wrapLangSmithTraceable: () => wrapLangSmithTraceable,
35081
36472
  wrapMastraAgent: () => wrapMastraAgent,
35082
36473
  wrapMistral: () => wrapMistral,
36474
+ wrapOllama: () => wrapOllama,
35083
36475
  wrapOpenAI: () => wrapOpenAI,
35084
36476
  wrapOpenAICodexSDK: () => wrapOpenAICodexSDK,
35085
36477
  wrapOpenAIv4: () => wrapOpenAIv4,
@@ -36354,7 +37746,7 @@ function normalizeUsageMetrics(usage, provider, providerMetadata) {
36354
37746
  }
36355
37747
  return metrics;
36356
37748
  }
36357
- function normalizeFinishReason(reason) {
37749
+ function normalizeFinishReason2(reason) {
36358
37750
  if (typeof reason !== "string") return void 0;
36359
37751
  return reason.replace(/-/g, "_");
36360
37752
  }
@@ -36363,7 +37755,7 @@ function buildAssistantOutputWithToolCalls(result, toolCalls2) {
36363
37755
  {
36364
37756
  index: 0,
36365
37757
  logprobs: null,
36366
- finish_reason: normalizeFinishReason(result?.finishReason) ?? (toolCalls2.length ? "tool_calls" : void 0),
37758
+ finish_reason: normalizeFinishReason2(result?.finishReason) ?? (toolCalls2.length ? "tool_calls" : void 0),
36367
37759
  message: {
36368
37760
  role: "assistant",
36369
37761
  tool_calls: toolCalls2.length > 0 ? toolCalls2 : void 0
@@ -38284,6 +39676,66 @@ function betaProxy(beta, anthropic) {
38284
39676
  if (prop === "messages") {
38285
39677
  return betaMessagesProxy(target.messages, anthropic);
38286
39678
  }
39679
+ if (prop === "sessions") {
39680
+ return target.sessions ? betaSessionsProxy(target.sessions) : target.sessions;
39681
+ }
39682
+ return Reflect.get(target, prop, receiver);
39683
+ }
39684
+ });
39685
+ }
39686
+ function betaSessionsProxy(sessions) {
39687
+ return new Proxy(sessions, {
39688
+ get(target, prop, receiver) {
39689
+ if (prop === "events") {
39690
+ return betaSessionEventsProxy(target.events);
39691
+ }
39692
+ if (prop === "threads") {
39693
+ return target.threads ? betaSessionThreadsProxy(target.threads) : target.threads;
39694
+ }
39695
+ return Reflect.get(target, prop, receiver);
39696
+ }
39697
+ });
39698
+ }
39699
+ function betaSessionEventsProxy(events) {
39700
+ return new Proxy(events, {
39701
+ get(target, prop, receiver) {
39702
+ if (prop === "stream") {
39703
+ return new TypedApplyProxy(target.stream, {
39704
+ apply(stream, thisArg, argArray) {
39705
+ return anthropicChannels.betaSessionsEventsStream.tracePromise(
39706
+ () => Reflect.apply(stream, thisArg, argArray),
39707
+ { arguments: argArray }
39708
+ );
39709
+ }
39710
+ });
39711
+ }
39712
+ return Reflect.get(target, prop, receiver);
39713
+ }
39714
+ });
39715
+ }
39716
+ function betaSessionThreadsProxy(threads) {
39717
+ return new Proxy(threads, {
39718
+ get(target, prop, receiver) {
39719
+ if (prop === "events") {
39720
+ return betaSessionThreadEventsProxy(target.events);
39721
+ }
39722
+ return Reflect.get(target, prop, receiver);
39723
+ }
39724
+ });
39725
+ }
39726
+ function betaSessionThreadEventsProxy(events) {
39727
+ return new Proxy(events, {
39728
+ get(target, prop, receiver) {
39729
+ if (prop === "stream") {
39730
+ return new TypedApplyProxy(target.stream, {
39731
+ apply(stream, thisArg, argArray) {
39732
+ return anthropicChannels.betaSessionsThreadsEventsStream.tracePromise(
39733
+ () => Reflect.apply(stream, thisArg, argArray),
39734
+ { arguments: argArray }
39735
+ );
39736
+ }
39737
+ });
39738
+ }
38287
39739
  return Reflect.get(target, prop, receiver);
38288
39740
  }
38289
39741
  });
@@ -38697,6 +40149,52 @@ function claudeAgentSDKProxy(sdk) {
38697
40149
  });
38698
40150
  }
38699
40151
 
40152
+ // src/wrappers/cloudflare-think.ts
40153
+ var WRAPPED_THINK = /* @__PURE__ */ Symbol.for("braintrust.cloudflare-think.wrapped");
40154
+ function wrapCloudflareThink(sdk) {
40155
+ if (!sdk || typeof sdk !== "object") {
40156
+ return sdk;
40157
+ }
40158
+ const thinkModule = sdk;
40159
+ if (typeof thinkModule.Think !== "function") {
40160
+ return sdk;
40161
+ }
40162
+ patchThinkClass(thinkModule.Think);
40163
+ return sdk;
40164
+ }
40165
+ function patchThinkClass(Think) {
40166
+ const prototype = Think.prototype;
40167
+ if (!prototype || prototype[WRAPPED_THINK]) {
40168
+ return;
40169
+ }
40170
+ const descriptor = Object.getOwnPropertyDescriptor(
40171
+ prototype,
40172
+ "_runInferenceLoop"
40173
+ );
40174
+ if (!descriptor || typeof descriptor.value !== "function") {
40175
+ return;
40176
+ }
40177
+ const original = descriptor.value;
40178
+ Object.defineProperty(prototype, "_runInferenceLoop", {
40179
+ ...descriptor,
40180
+ value: function wrappedCloudflareThinkRunInferenceLoop(input) {
40181
+ const args = [input];
40182
+ return cloudflareThinkChannels.runInferenceLoop.tracePromise(
40183
+ () => Reflect.apply(original, this, args),
40184
+ {
40185
+ arguments: args,
40186
+ self: this
40187
+ }
40188
+ );
40189
+ }
40190
+ });
40191
+ Object.defineProperty(prototype, WRAPPED_THINK, {
40192
+ configurable: false,
40193
+ enumerable: false,
40194
+ value: true
40195
+ });
40196
+ }
40197
+
38700
40198
  // src/wrappers/openai-codex.ts
38701
40199
  var WRAPPED_CLIENT = /* @__PURE__ */ Symbol.for("braintrust.openai-codex.wrapped-client");
38702
40200
  var WRAPPED_THREAD = /* @__PURE__ */ Symbol.for("braintrust.openai-codex.wrapped-thread");
@@ -38989,14 +40487,9 @@ function patchAgentSessionClass(AgentSession) {
38989
40487
  ...descriptor,
38990
40488
  value: function wrappedPiCodingAgentPrompt(text, options) {
38991
40489
  const args = [text, options];
38992
- return piCodingAgentChannels.prompt.tracePromise(
38993
- () => Reflect.apply(originalPrompt, this, args),
38994
- {
38995
- arguments: args,
38996
- self: this,
38997
- session: this
38998
- }
38999
- );
40490
+ return piCodingAgentChannels.prompt.invoke(originalPrompt, this, args, {
40491
+ session: this
40492
+ });
39000
40493
  }
39001
40494
  });
39002
40495
  Object.defineProperty(prototype, WRAPPED_PROMPT, {
@@ -40436,6 +41929,83 @@ function wrapAgentsStream(stream) {
40436
41929
  });
40437
41930
  }
40438
41931
 
41932
+ // src/wrappers/ollama.ts
41933
+ function wrapOllama(ollama) {
41934
+ if (isSupportedOllamaClient(ollama)) {
41935
+ return ollamaProxy(ollama);
41936
+ }
41937
+ debugLogger.warn("Unsupported Ollama library. Not wrapping.");
41938
+ return ollama;
41939
+ }
41940
+ var ollamaProxyCache = /* @__PURE__ */ new WeakMap();
41941
+ function isSupportedOllamaClient(value) {
41942
+ return isObject(value) && ["chat", "generate", "embed"].some(
41943
+ (name) => typeof value[name] === "function"
41944
+ );
41945
+ }
41946
+ function ollamaProxy(ollama) {
41947
+ const cached = ollamaProxyCache.get(ollama);
41948
+ if (cached) {
41949
+ return cached;
41950
+ }
41951
+ let chatSource;
41952
+ let wrappedChat;
41953
+ let generateSource;
41954
+ let wrappedGenerate;
41955
+ let embedSource;
41956
+ let wrappedEmbed;
41957
+ const proxy = new Proxy(ollama, {
41958
+ get(target, prop, receiver) {
41959
+ switch (prop) {
41960
+ case "chat": {
41961
+ const source = target.chat;
41962
+ if (source !== chatSource) {
41963
+ chatSource = source;
41964
+ wrappedChat = typeof source === "function" ? wrapChat(source.bind(target)) : source;
41965
+ }
41966
+ return wrappedChat;
41967
+ }
41968
+ case "generate": {
41969
+ const source = target.generate;
41970
+ if (source !== generateSource) {
41971
+ generateSource = source;
41972
+ wrappedGenerate = typeof source === "function" ? wrapGenerate2(source.bind(target)) : source;
41973
+ }
41974
+ return wrappedGenerate;
41975
+ }
41976
+ case "embed": {
41977
+ const source = target.embed;
41978
+ if (source !== embedSource) {
41979
+ embedSource = source;
41980
+ wrappedEmbed = typeof source === "function" ? wrapEmbed3(source.bind(target)) : source;
41981
+ }
41982
+ return wrappedEmbed;
41983
+ }
41984
+ default:
41985
+ return Reflect.get(target, prop, receiver);
41986
+ }
41987
+ }
41988
+ });
41989
+ ollamaProxyCache.set(ollama, proxy);
41990
+ ollamaProxyCache.set(proxy, proxy);
41991
+ return proxy;
41992
+ }
41993
+ function wrapChat(chat) {
41994
+ return (request) => ollamaChannels.chat.tracePromise(() => chat(request), {
41995
+ arguments: [request]
41996
+ });
41997
+ }
41998
+ function wrapGenerate2(generate) {
41999
+ return (request) => ollamaChannels.generate.tracePromise(() => generate(request), {
42000
+ arguments: [request]
42001
+ });
42002
+ }
42003
+ function wrapEmbed3(embed) {
42004
+ return (request) => ollamaChannels.embed.tracePromise(() => embed(request), {
42005
+ arguments: [request]
42006
+ });
42007
+ }
42008
+
40439
42009
  // src/wrappers/cohere.ts
40440
42010
  function wrapCohere(cohere) {
40441
42011
  if (isSupportedCohereClient(cohere)) {
@@ -40466,11 +42036,11 @@ function cohereProxy(cohere) {
40466
42036
  get(target, prop, receiver) {
40467
42037
  switch (prop) {
40468
42038
  case "chat":
40469
- return typeof target.chat === "function" ? wrapChat(target.chat.bind(target)) : target.chat;
42039
+ return typeof target.chat === "function" ? wrapChat2(target.chat.bind(target)) : target.chat;
40470
42040
  case "chatStream":
40471
42041
  return typeof target.chatStream === "function" ? wrapChatStream2(target.chatStream.bind(target)) : target.chatStream;
40472
42042
  case "embed":
40473
- return typeof target.embed === "function" ? wrapEmbed3(target.embed.bind(target)) : target.embed;
42043
+ return typeof target.embed === "function" ? wrapEmbed4(target.embed.bind(target)) : target.embed;
40474
42044
  case "rerank":
40475
42045
  return typeof target.rerank === "function" ? wrapRerank3(target.rerank.bind(target)) : target.rerank;
40476
42046
  default: {
@@ -40483,7 +42053,7 @@ function cohereProxy(cohere) {
40483
42053
  cohereProxyCache.set(cohere, proxy);
40484
42054
  return proxy;
40485
42055
  }
40486
- function wrapChat(chat) {
42056
+ function wrapChat2(chat) {
40487
42057
  return (request, options) => cohereChannels.chat.tracePromise(() => chat(request, options), {
40488
42058
  arguments: [request]
40489
42059
  });
@@ -40493,7 +42063,7 @@ function wrapChatStream2(chatStream) {
40493
42063
  arguments: [request]
40494
42064
  });
40495
42065
  }
40496
- function wrapEmbed3(embed) {
42066
+ function wrapEmbed4(embed) {
40497
42067
  return (request, options) => cohereChannels.embed.tracePromise(() => embed(request, options), {
40498
42068
  arguments: [request]
40499
42069
  });