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/browser.js CHANGED
@@ -99,6 +99,7 @@ __export(browser_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(browser_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(browser_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,
@@ -11692,6 +11837,34 @@ function patchStreamIfNeeded(stream, options) {
11692
11837
  );
11693
11838
  return stream;
11694
11839
  }
11840
+ const chunks = [];
11841
+ let completed = false;
11842
+ const notifyCancellation = async () => {
11843
+ try {
11844
+ await (options.onCancel ?? options.onComplete)(chunks);
11845
+ } catch (error) {
11846
+ debugLogger.error("Error in stream cancellation handler:", error);
11847
+ }
11848
+ };
11849
+ const patchAbortIfPresent = () => {
11850
+ try {
11851
+ if ("abort" in stream && typeof stream.abort === "function") {
11852
+ const originalAbort = stream.abort.bind(stream);
11853
+ stream.abort = (...args) => {
11854
+ try {
11855
+ return originalAbort(...args);
11856
+ } finally {
11857
+ if (!completed) {
11858
+ completed = true;
11859
+ void notifyCancellation();
11860
+ }
11861
+ }
11862
+ };
11863
+ }
11864
+ } catch (error) {
11865
+ debugLogger.warn("Failed to patch stream abort method:", error);
11866
+ }
11867
+ };
11695
11868
  if (hasAsyncIteratorMethods(stream) && isSelfAsyncIterator(stream)) {
11696
11869
  if ("__braintrust_patched_iterator_methods" in stream) {
11697
11870
  return stream;
@@ -11700,8 +11873,6 @@ function patchStreamIfNeeded(stream, options) {
11700
11873
  const originalNext = stream.next.bind(stream);
11701
11874
  const originalReturn = typeof stream.return === "function" ? stream.return.bind(stream) : null;
11702
11875
  const originalThrow = typeof stream.throw === "function" ? stream.throw.bind(stream) : null;
11703
- const chunks = [];
11704
- let completed = false;
11705
11876
  stream.next = async (...args) => {
11706
11877
  try {
11707
11878
  const result = await runNextWithWrapper(
@@ -11753,11 +11924,7 @@ function patchStreamIfNeeded(stream, options) {
11753
11924
  stream.return = async (...args) => {
11754
11925
  if (!completed) {
11755
11926
  completed = true;
11756
- try {
11757
- await options.onComplete(chunks);
11758
- } catch (error) {
11759
- console.error("Error in stream onComplete handler:", error);
11760
- }
11927
+ await notifyCancellation();
11761
11928
  }
11762
11929
  return originalReturn(...args);
11763
11930
  };
@@ -11782,6 +11949,7 @@ function patchStreamIfNeeded(stream, options) {
11782
11949
  Object.defineProperty(stream, "__braintrust_patched_iterator_methods", {
11783
11950
  value: true
11784
11951
  });
11952
+ patchAbortIfPresent();
11785
11953
  return stream;
11786
11954
  } catch (error) {
11787
11955
  console.warn("Failed to patch stream iterator methods:", error);
@@ -11795,8 +11963,6 @@ function patchStreamIfNeeded(stream, options) {
11795
11963
  const patchedIteratorFn = function() {
11796
11964
  const iterator = originalIteratorFn.call(this);
11797
11965
  const originalNext = iterator.next.bind(iterator);
11798
- const chunks = [];
11799
- let completed = false;
11800
11966
  iterator.next = async function(...args) {
11801
11967
  try {
11802
11968
  const result = await runNextWithWrapper(
@@ -11849,11 +12015,7 @@ function patchStreamIfNeeded(stream, options) {
11849
12015
  iterator.return = async function(...args) {
11850
12016
  if (!completed) {
11851
12017
  completed = true;
11852
- try {
11853
- await options.onComplete(chunks);
11854
- } catch (error) {
11855
- console.error("Error in stream onComplete handler:", error);
11856
- }
12018
+ await notifyCancellation();
11857
12019
  }
11858
12020
  return originalReturn(...args);
11859
12021
  };
@@ -11882,6 +12044,7 @@ function patchStreamIfNeeded(stream, options) {
11882
12044
  value: true
11883
12045
  });
11884
12046
  stream[Symbol.asyncIterator] = patchedIteratorFn;
12047
+ patchAbortIfPresent();
11885
12048
  return stream;
11886
12049
  } catch (error) {
11887
12050
  console.warn("Failed to patch stream:", error);
@@ -12630,6 +12793,33 @@ function traceStreamingChannel(channel2, config) {
12630
12793
  const { span, startTime } = spanData;
12631
12794
  if (isAsyncIterable(asyncEndEvent.result)) {
12632
12795
  let firstChunkTime;
12796
+ const handleStreamError = (error) => {
12797
+ try {
12798
+ span.log({ error });
12799
+ } catch (loggingError) {
12800
+ debugLogger.error(
12801
+ `Error logging failure for ${channelName}:`,
12802
+ loggingError
12803
+ );
12804
+ }
12805
+ try {
12806
+ span.end();
12807
+ } catch (endingError) {
12808
+ debugLogger.error(
12809
+ `Error ending span for ${channelName}:`,
12810
+ endingError
12811
+ );
12812
+ }
12813
+ states.delete(event);
12814
+ runStreamingErrorHook({
12815
+ channelName,
12816
+ config,
12817
+ error,
12818
+ event: asyncEndEvent,
12819
+ span,
12820
+ startTime
12821
+ });
12822
+ };
12633
12823
  patchStreamIfNeeded(asyncEndEvent.result, {
12634
12824
  onChunk: () => {
12635
12825
  if (firstChunkTime === void 0) {
@@ -12709,33 +12899,12 @@ function traceStreamingChannel(channel2, config) {
12709
12899
  });
12710
12900
  }
12711
12901
  },
12712
- onError: (error) => {
12713
- try {
12714
- span.log({ error });
12715
- } catch (loggingError) {
12716
- debugLogger.error(
12717
- `Error logging failure for ${channelName}:`,
12718
- loggingError
12719
- );
12720
- }
12721
- try {
12722
- span.end();
12723
- } catch (endingError) {
12724
- debugLogger.error(
12725
- `Error ending span for ${channelName}:`,
12726
- endingError
12727
- );
12728
- }
12729
- states.delete(event);
12730
- runStreamingErrorHook({
12731
- channelName,
12732
- config,
12733
- error,
12734
- event: asyncEndEvent,
12735
- span,
12736
- startTime
12737
- });
12738
- }
12902
+ onCancel: () => {
12903
+ const error = new Error("Stream cancelled before completion");
12904
+ error.name = "AbortError";
12905
+ handleStreamError(error);
12906
+ },
12907
+ onError: handleStreamError
12739
12908
  });
12740
12909
  return;
12741
12910
  }
@@ -13123,11 +13292,21 @@ function defineChannels(pkg, channels, options) {
13123
13292
  const tracingChannel2 = () => isomorph_default.newTracingChannel(
13124
13293
  fullChannelName
13125
13294
  );
13295
+ const intercept2 = (interceptor) => {
13296
+ const hook = tracingChannel2();
13297
+ return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
13298
+ };
13299
+ };
13126
13300
  return [
13127
13301
  key,
13128
13302
  {
13129
13303
  ...asyncSpec,
13130
13304
  instrumentationName,
13305
+ intercept: intercept2,
13306
+ invoke: (target, thisArg, args, additional) => {
13307
+ const hook = tracingChannel2();
13308
+ return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
13309
+ },
13131
13310
  tracingChannel: tracingChannel2,
13132
13311
  tracePromise: (fn, context) => tracingChannel2().tracePromise(
13133
13312
  fn,
@@ -13141,11 +13320,21 @@ function defineChannels(pkg, channels, options) {
13141
13320
  const tracingChannel = () => isomorph_default.newTracingChannel(
13142
13321
  fullChannelName
13143
13322
  );
13323
+ const intercept = (interceptor) => {
13324
+ const hook = tracingChannel();
13325
+ return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
13326
+ };
13327
+ };
13144
13328
  return [
13145
13329
  key,
13146
13330
  {
13147
13331
  ...syncSpec,
13148
13332
  instrumentationName,
13333
+ intercept,
13334
+ invoke: (target, thisArg, args, additional) => {
13335
+ const hook = tracingChannel();
13336
+ return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
13337
+ },
13149
13338
  tracingChannel,
13150
13339
  traceSync: (fn, context) => tracingChannel().traceSync(
13151
13340
  fn,
@@ -14396,6 +14585,25 @@ function extractAnthropicCacheTokens(cacheReadTokens = 0, cacheCreationTokens =
14396
14585
  return cacheTokens;
14397
14586
  }
14398
14587
 
14588
+ // src/wrappers/anthropic-session-collector.ts
14589
+ var sessionStreamCollectors = /* @__PURE__ */ new WeakMap();
14590
+ function registerAnthropicSessionStreamCollector(stream, collector) {
14591
+ sessionStreamCollectors.set(stream, collector);
14592
+ }
14593
+ function collectAnthropicSession(stream) {
14594
+ const collector = sessionStreamCollectors.get(stream);
14595
+ if (!collector) {
14596
+ return stream;
14597
+ }
14598
+ sessionStreamCollectors.delete(stream);
14599
+ try {
14600
+ collector();
14601
+ } catch (error) {
14602
+ debugLogger.error("Failed to collect Anthropic Sessions stream:", error);
14603
+ }
14604
+ return stream;
14605
+ }
14606
+
14399
14607
  // src/instrumentation/plugins/anthropic-channels.ts
14400
14608
  var anthropicChannels = defineChannels(
14401
14609
  "@anthropic-ai/sdk",
@@ -14411,6 +14619,14 @@ var anthropicChannels = defineChannels(
14411
14619
  betaMessagesToolRunner: channel({
14412
14620
  channelName: "beta.messages.toolRunner",
14413
14621
  kind: "sync-stream"
14622
+ }),
14623
+ betaSessionsEventsStream: channel({
14624
+ channelName: "beta.sessions.events.stream",
14625
+ kind: "async"
14626
+ }),
14627
+ betaSessionsThreadsEventsStream: channel({
14628
+ channelName: "beta.sessions.threads.events.stream",
14629
+ kind: "async"
14414
14630
  })
14415
14631
  },
14416
14632
  { instrumentationName: INSTRUMENTATION_NAMES.ANTHROPIC }
@@ -14424,6 +14640,7 @@ var AnthropicPlugin = class extends BasePlugin {
14424
14640
  onEnable() {
14425
14641
  this.subscribeToAnthropicChannels();
14426
14642
  this.subscribeToAnthropicToolRunner();
14643
+ this.subscribeToAnthropicSessionStreams();
14427
14644
  }
14428
14645
  onDisable() {
14429
14646
  this.unsubscribers = unsubscribeAll(this.unsubscribers);
@@ -14541,7 +14758,411 @@ var AnthropicPlugin = class extends BasePlugin {
14541
14758
  tracingChannel.unsubscribe(handlers);
14542
14759
  });
14543
14760
  }
14761
+ subscribeToAnthropicSessionStreams() {
14762
+ this.subscribeToAnthropicSessionStream(
14763
+ anthropicChannels.betaSessionsEventsStream,
14764
+ false
14765
+ );
14766
+ this.subscribeToAnthropicSessionStream(
14767
+ anthropicChannels.betaSessionsThreadsEventsStream,
14768
+ true
14769
+ );
14770
+ }
14771
+ subscribeToAnthropicSessionStream(channel2, isThread) {
14772
+ const tracingChannel = channel2.tracingChannel();
14773
+ const pending = /* @__PURE__ */ new WeakSet();
14774
+ const handlers = {
14775
+ start: (event) => {
14776
+ if (isAutoInstrumentationSuppressed()) {
14777
+ return;
14778
+ }
14779
+ pending.add(event);
14780
+ },
14781
+ asyncEnd: (event) => {
14782
+ if (!pending.delete(event)) {
14783
+ return;
14784
+ }
14785
+ const stream = event.result;
14786
+ if (!isAsyncIterable(stream)) {
14787
+ return;
14788
+ }
14789
+ registerAnthropicSessionStreamCollector(stream, () => {
14790
+ wrapAnthropicSessionEventStream(stream, isThread);
14791
+ });
14792
+ },
14793
+ error: (event) => {
14794
+ pending.delete(event);
14795
+ }
14796
+ };
14797
+ tracingChannel.subscribe(handlers);
14798
+ this.unsubscribers.push(() => tracingChannel.unsubscribe(handlers));
14799
+ }
14544
14800
  };
14801
+ function wrapAnthropicSessionEventStream(stream, isThread) {
14802
+ const state = {
14803
+ history: [],
14804
+ isThread,
14805
+ pendingInput: [],
14806
+ seenEventIds: /* @__PURE__ */ new Set()
14807
+ };
14808
+ patchStreamIfNeeded(stream, {
14809
+ onChunk: (event) => handleAnthropicSessionEvent(state, event),
14810
+ onComplete: () => finalizeAnthropicSessionTurn(state),
14811
+ onError: (error) => finalizeAnthropicSessionTurn(state, error)
14812
+ });
14813
+ return stream;
14814
+ }
14815
+ function handleAnthropicSessionEvent(state, event) {
14816
+ try {
14817
+ if (typeof event.id === "string" && event.type !== "event_delta" && state.seenEventIds.has(event.id)) {
14818
+ return;
14819
+ }
14820
+ if (typeof event.id === "string" && event.type !== "event_delta") {
14821
+ state.seenEventIds.add(event.id);
14822
+ }
14823
+ switch (event.type) {
14824
+ case "user.message":
14825
+ case "system.message":
14826
+ recordAnthropicSessionInput(
14827
+ state,
14828
+ event
14829
+ );
14830
+ break;
14831
+ case "session.status_running":
14832
+ if (!state.isThread) {
14833
+ ensureAnthropicSessionTurn(state);
14834
+ }
14835
+ break;
14836
+ case "session.thread_status_running":
14837
+ if (state.isThread) {
14838
+ ensureAnthropicSessionTurn(state);
14839
+ }
14840
+ break;
14841
+ case "span.model_request_start":
14842
+ if (typeof event.id === "string") {
14843
+ startAnthropicSessionModel(state, event.id);
14844
+ }
14845
+ break;
14846
+ case "event_delta":
14847
+ recordAnthropicSessionFirstToken(state, event);
14848
+ break;
14849
+ case "agent.message":
14850
+ recordAnthropicSessionMessage(
14851
+ state,
14852
+ event
14853
+ );
14854
+ break;
14855
+ case "agent.custom_tool_use":
14856
+ case "agent.mcp_tool_use":
14857
+ case "agent.tool_use":
14858
+ startAnthropicSessionTool(state, event);
14859
+ break;
14860
+ case "user.tool_confirmation":
14861
+ recordAnthropicSessionToolConfirmation(state, event);
14862
+ break;
14863
+ case "agent.mcp_tool_result":
14864
+ case "agent.tool_result":
14865
+ case "user.custom_tool_result":
14866
+ case "user.tool_result":
14867
+ finalizeAnthropicSessionTool(
14868
+ state,
14869
+ event
14870
+ );
14871
+ break;
14872
+ case "span.model_request_end":
14873
+ finalizeAnthropicSessionModel(
14874
+ state,
14875
+ event
14876
+ );
14877
+ break;
14878
+ case "session.status_idle":
14879
+ case "session.thread_status_idle": {
14880
+ if (event.type === "session.status_idle" && state.isThread || event.type === "session.thread_status_idle" && !state.isThread) {
14881
+ break;
14882
+ }
14883
+ const stopReason = isObject(event.stop_reason) ? event.stop_reason.type : void 0;
14884
+ if (stopReason === "end_turn") {
14885
+ finalizeAnthropicSessionTurn(state);
14886
+ } else if (stopReason === "retries_exhausted") {
14887
+ finalizeAnthropicSessionTurn(
14888
+ state,
14889
+ "Anthropic session retries exhausted"
14890
+ );
14891
+ }
14892
+ break;
14893
+ }
14894
+ case "session.error":
14895
+ finalizeAnthropicSessionTurn(state, event.error);
14896
+ break;
14897
+ case "session.deleted":
14898
+ case "session.status_terminated":
14899
+ case "session.thread_status_terminated":
14900
+ if (event.type === "session.deleted" || event.type === "session.status_terminated" && !state.isThread || event.type === "session.thread_status_terminated" && state.isThread) {
14901
+ finalizeAnthropicSessionTurn(state);
14902
+ }
14903
+ break;
14904
+ default:
14905
+ break;
14906
+ }
14907
+ } catch (error) {
14908
+ debugLogger.debug("Error processing Anthropic Sessions event:", error);
14909
+ }
14910
+ }
14911
+ function ensureAnthropicSessionTurn(state) {
14912
+ if (state.activeTurn) {
14913
+ return state.activeTurn;
14914
+ }
14915
+ const input = state.pendingInput;
14916
+ state.pendingInput = [];
14917
+ const span = startSpan(
14918
+ withSpanInstrumentationName(
14919
+ {
14920
+ event: {
14921
+ ...input.length > 0 ? { input } : {},
14922
+ metadata: { provider: "anthropic" }
14923
+ },
14924
+ name: state.isThread ? "anthropic.beta.sessions.thread.turn" : "anthropic.beta.sessions.turn",
14925
+ spanAttributes: { type: "task" /* TASK */ }
14926
+ },
14927
+ INSTRUMENTATION_NAMES.ANTHROPIC
14928
+ )
14929
+ );
14930
+ state.activeTurn = {
14931
+ activeTools: /* @__PURE__ */ new Map(),
14932
+ input: input.slice(),
14933
+ metrics: {},
14934
+ span
14935
+ };
14936
+ return state.activeTurn;
14937
+ }
14938
+ function recordAnthropicSessionInput(state, event) {
14939
+ const content = processAttachmentsInInput(event.content);
14940
+ const message = {
14941
+ role: event.type === "system.message" ? "system" : "user",
14942
+ content
14943
+ };
14944
+ state.history.push(message);
14945
+ if (state.activeTurn) {
14946
+ state.activeTurn.input.push(message);
14947
+ } else {
14948
+ state.pendingInput.push(message);
14949
+ }
14950
+ }
14951
+ function startAnthropicSessionModel(state, startEventId) {
14952
+ const turn = ensureAnthropicSessionTurn(state);
14953
+ if (turn.activeModel) {
14954
+ finalizeAnthropicSessionModelState(state, turn);
14955
+ }
14956
+ const span = withCurrent(
14957
+ turn.span,
14958
+ () => startSpan(
14959
+ withSpanInstrumentationName(
14960
+ {
14961
+ event: {
14962
+ ...state.history.length > 0 ? { input: state.history.slice() } : {},
14963
+ metadata: { provider: "anthropic" }
14964
+ },
14965
+ name: "anthropic.messages.create",
14966
+ spanAttributes: { type: "llm" /* LLM */ }
14967
+ },
14968
+ INSTRUMENTATION_NAMES.ANTHROPIC
14969
+ )
14970
+ )
14971
+ );
14972
+ turn.activeModel = {
14973
+ output: [],
14974
+ span,
14975
+ startEventId,
14976
+ startTime: getCurrentUnixTimestamp()
14977
+ };
14978
+ }
14979
+ function recordAnthropicSessionFirstToken(state, event) {
14980
+ const model = state.activeTurn?.activeModel;
14981
+ if (!model || model.firstTokenTime !== void 0 || !isObject(event.delta) || !isObject(event.delta.content) || typeof event.delta.content.text !== "string") {
14982
+ return;
14983
+ }
14984
+ model.firstTokenTime = getCurrentUnixTimestamp();
14985
+ }
14986
+ function recordAnthropicSessionMessage(state, event) {
14987
+ const turn = ensureAnthropicSessionTurn(state);
14988
+ const content = processAttachmentsInInput(
14989
+ event.content
14990
+ );
14991
+ if (turn.activeModel) {
14992
+ turn.activeModel.output.push(...content);
14993
+ } else {
14994
+ const output = { role: "assistant", content };
14995
+ turn.lastOutput = output;
14996
+ state.history.push(output);
14997
+ }
14998
+ }
14999
+ function startAnthropicSessionTool(state, event) {
15000
+ const turn = ensureAnthropicSessionTurn(state);
15001
+ if (turn.activeModel) {
15002
+ turn.activeModel.output.push({
15003
+ type: "tool_use",
15004
+ id: event.id,
15005
+ name: event.name,
15006
+ input: event.input
15007
+ });
15008
+ }
15009
+ const existing = turn.activeTools.get(event.id);
15010
+ if (existing) {
15011
+ existing.span.end();
15012
+ turn.activeTools.delete(event.id);
15013
+ }
15014
+ const span = withCurrent(
15015
+ turn.span,
15016
+ () => startSpan(
15017
+ withSpanInstrumentationName(
15018
+ {
15019
+ event: { input: event.input },
15020
+ name: event.name,
15021
+ spanAttributes: { type: "tool" /* TOOL */ }
15022
+ },
15023
+ INSTRUMENTATION_NAMES.ANTHROPIC
15024
+ )
15025
+ )
15026
+ );
15027
+ const toolState = {
15028
+ approval: event.evaluated_permission === "allow" ? "approved" : event.evaluated_permission === "deny" ? "denied" : void 0,
15029
+ span
15030
+ };
15031
+ turn.activeTools.set(event.id, toolState);
15032
+ if (toolState.approval === "denied") {
15033
+ finalizeAnthropicSessionToolState(toolState);
15034
+ turn.activeTools.delete(event.id);
15035
+ }
15036
+ }
15037
+ function recordAnthropicSessionToolConfirmation(state, event) {
15038
+ if (typeof event.tool_use_id !== "string" || event.result !== "allow" && event.result !== "deny") {
15039
+ return;
15040
+ }
15041
+ const turn = state.activeTurn;
15042
+ const tool = turn?.activeTools.get(event.tool_use_id);
15043
+ if (!turn || !tool) {
15044
+ return;
15045
+ }
15046
+ tool.approval = event.result === "allow" ? "approved" : "denied";
15047
+ if (tool.approval === "denied") {
15048
+ finalizeAnthropicSessionToolState(tool);
15049
+ turn.activeTools.delete(event.tool_use_id);
15050
+ }
15051
+ }
15052
+ function finalizeAnthropicSessionTool(state, event) {
15053
+ const toolUseId = event.tool_use_id ?? event.mcp_tool_use_id ?? event.custom_tool_use_id;
15054
+ if (!toolUseId) {
15055
+ return;
15056
+ }
15057
+ const content = processAttachmentsInInput(event.content);
15058
+ const turn = state.activeTurn;
15059
+ const tool = turn?.activeTools.get(toolUseId);
15060
+ if (turn && tool) {
15061
+ finalizeAnthropicSessionToolState(tool, event, content);
15062
+ turn.activeTools.delete(toolUseId);
15063
+ }
15064
+ const toolResult = {
15065
+ type: "tool_result",
15066
+ tool_use_id: toolUseId,
15067
+ ...content !== void 0 ? { content } : {},
15068
+ ...event.is_error === true ? { is_error: true } : {}
15069
+ };
15070
+ state.history.push({
15071
+ role: "user",
15072
+ content: [toolResult]
15073
+ });
15074
+ }
15075
+ function finalizeAnthropicSessionToolState(state, event, content = event?.content) {
15076
+ safeAnthropicSessionLog(state.span, {
15077
+ ...event?.is_error === true ? {
15078
+ error: content ?? "Anthropic session tool execution failed"
15079
+ } : {},
15080
+ ...state.approval ? { metadata: { tool_approval: state.approval } } : {},
15081
+ ...content !== void 0 ? { output: content } : {}
15082
+ });
15083
+ state.span.end();
15084
+ }
15085
+ function finalizeAnthropicSessionModel(state, event) {
15086
+ const turn = state.activeTurn;
15087
+ const model = turn?.activeModel;
15088
+ if (!turn || !model || model.startEventId !== event.model_request_start_id) {
15089
+ return;
15090
+ }
15091
+ finalizeAnthropicSessionModelState(state, turn, event);
15092
+ }
15093
+ function finalizeAnthropicSessionModelState(state, turn, event) {
15094
+ const model = turn.activeModel;
15095
+ if (!model) {
15096
+ return;
15097
+ }
15098
+ turn.activeModel = void 0;
15099
+ const metrics = event ? parseAnthropicSessionModelUsage(event.model_usage) : {};
15100
+ if (model.firstTokenTime !== void 0) {
15101
+ metrics.time_to_first_token = model.firstTokenTime - model.startTime;
15102
+ }
15103
+ const output = model.output.length > 0 ? { role: "assistant", content: model.output } : void 0;
15104
+ safeAnthropicSessionLog(model.span, {
15105
+ ...event?.is_error ? { error: "Anthropic session model request failed" } : {},
15106
+ ...Object.keys(metrics).length > 0 ? { metrics } : {},
15107
+ ...output ? { output } : {}
15108
+ });
15109
+ model.span.end();
15110
+ if (output) {
15111
+ turn.lastOutput = output;
15112
+ state.history.push(output);
15113
+ }
15114
+ for (const key of [
15115
+ "prompt_tokens",
15116
+ "completion_tokens",
15117
+ "tokens",
15118
+ "prompt_cached_tokens",
15119
+ "prompt_cache_creation_tokens"
15120
+ ]) {
15121
+ const value = metrics[key];
15122
+ if (typeof value === "number") {
15123
+ turn.metrics[key] = (turn.metrics[key] ?? 0) + value;
15124
+ }
15125
+ }
15126
+ }
15127
+ function parseAnthropicSessionModelUsage(usage) {
15128
+ const finalized = finalizeAnthropicTokens({
15129
+ completion_tokens: usage.output_tokens,
15130
+ prompt_cache_creation_tokens: usage.cache_creation_input_tokens,
15131
+ prompt_cached_tokens: usage.cache_read_input_tokens,
15132
+ prompt_tokens: usage.input_tokens
15133
+ });
15134
+ return Object.fromEntries(
15135
+ Object.entries(finalized).filter(
15136
+ (entry) => entry[1] !== void 0
15137
+ )
15138
+ );
15139
+ }
15140
+ function finalizeAnthropicSessionTurn(state, error) {
15141
+ const turn = state.activeTurn;
15142
+ if (!turn) {
15143
+ return;
15144
+ }
15145
+ state.activeTurn = void 0;
15146
+ finalizeAnthropicSessionModelState(state, turn);
15147
+ for (const tool of turn.activeTools.values()) {
15148
+ finalizeAnthropicSessionToolState(tool);
15149
+ }
15150
+ turn.activeTools.clear();
15151
+ safeAnthropicSessionLog(turn.span, {
15152
+ ...error !== void 0 ? { error: error instanceof Error ? error : toLoggedError(error) } : {},
15153
+ ...turn.input.length > 0 ? { input: turn.input } : {},
15154
+ ...turn.lastOutput ? { output: turn.lastOutput } : {},
15155
+ ...Object.keys(turn.metrics).length > 0 ? { metrics: turn.metrics } : {}
15156
+ });
15157
+ turn.span.end();
15158
+ }
15159
+ function safeAnthropicSessionLog(span, event) {
15160
+ try {
15161
+ span.log(event);
15162
+ } catch (error) {
15163
+ debugLogger.debug("Error logging Anthropic Sessions span:", error);
15164
+ }
15165
+ }
14545
15166
  function parseMetricsFromUsage2(usage) {
14546
15167
  if (!usage) {
14547
15168
  return {};
@@ -16415,6 +17036,29 @@ var harnessAgentChannels = defineChannels(
16415
17036
  { instrumentationName: INSTRUMENTATION_NAMES.AI_SDK }
16416
17037
  );
16417
17038
 
17039
+ // src/instrumentation/plugins/cloudflare-think-context.ts
17040
+ var cloudflareThinkSpans = /* @__PURE__ */ new Map();
17041
+ function registerCloudflareThinkSpan(span) {
17042
+ if (span.spanId) {
17043
+ cloudflareThinkSpans.set(span.spanId, span);
17044
+ }
17045
+ }
17046
+ function unregisterCloudflareThinkSpan(span) {
17047
+ if (span.spanId) {
17048
+ cloudflareThinkSpans.delete(span.spanId);
17049
+ }
17050
+ }
17051
+ function currentCloudflareThinkSpan() {
17052
+ const parentSpanIds = _internalGetGlobalState()?.contextManager.getParentSpanIds()?.spanParents ?? [];
17053
+ for (const parentSpanId of parentSpanIds) {
17054
+ const span = cloudflareThinkSpans.get(parentSpanId);
17055
+ if (span) {
17056
+ return span;
17057
+ }
17058
+ }
17059
+ return void 0;
17060
+ }
17061
+
16418
17062
  // src/instrumentation/plugins/ai-sdk-plugin.ts
16419
17063
  var DEFAULT_DENY_OUTPUT_PATHS = [
16420
17064
  // v3
@@ -16521,6 +17165,7 @@ var AISDKPlugin = class extends BasePlugin {
16521
17165
  traceStreamingChannel(aiSDKChannels.streamText, {
16522
17166
  name: "streamText",
16523
17167
  type: "function" /* FUNCTION */,
17168
+ shouldTrace: () => currentCloudflareThinkSpan() === void 0,
16524
17169
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
16525
17170
  extractOutput: (result, endEvent) => processAISDKOutput(
16526
17171
  result,
@@ -16541,6 +17186,7 @@ var AISDKPlugin = class extends BasePlugin {
16541
17186
  traceSyncStreamChannel(aiSDKChannels.streamTextSync, {
16542
17187
  name: "streamText",
16543
17188
  type: "function" /* FUNCTION */,
17189
+ shouldTrace: () => currentCloudflareThinkSpan() === void 0,
16544
17190
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
16545
17191
  patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
16546
17192
  defaultDenyOutputPaths: denyOutputPaths,
@@ -17526,6 +18172,23 @@ function prepareAISDKWorkflowAgentStreamInput(params, event, span, defaultDenyOu
17526
18172
  metadata
17527
18173
  };
17528
18174
  }
18175
+ function prepareAISDKAgentCallInput(params, event, span, defaultDenyOutputPaths = DEFAULT_DENY_OUTPUT_PATHS) {
18176
+ const { input } = processAISDKWorkflowAgentCallInput(params);
18177
+ const metadata = extractMetadataFromCallParams(params, event.self);
18178
+ const childTracing = prepareAISDKChildTracing(
18179
+ params,
18180
+ event.self,
18181
+ span,
18182
+ defaultDenyOutputPaths,
18183
+ event.aiSDK,
18184
+ { agentOwner: true }
18185
+ );
18186
+ event.modelWrapped = childTracing.modelWrapped;
18187
+ if (childTracing.cleanup) {
18188
+ event.__braintrust_ai_sdk_cleanup = childTracing.cleanup;
18189
+ }
18190
+ return { input, metadata };
18191
+ }
17529
18192
  function prepareAISDKEmbedInput(params, self) {
17530
18193
  return {
17531
18194
  input: { ...params },
@@ -17549,6 +18212,18 @@ function extractTopLevelAISDKMetrics(result, event, startTime) {
17549
18212
  }
17550
18213
  return metrics;
17551
18214
  }
18215
+ async function extractResolvedAISDKTokenMetrics(result) {
18216
+ for (const field of ["totalUsage", "usage"]) {
18217
+ try {
18218
+ const usage = await Promise.resolve(result[field]);
18219
+ if (usage !== void 0) {
18220
+ return extractTokenMetrics({ [field]: usage });
18221
+ }
18222
+ } catch {
18223
+ }
18224
+ }
18225
+ return extractTokenMetrics(result);
18226
+ }
17552
18227
  function hasModelChildTracing(event) {
17553
18228
  return event?.modelWrapped === true || event?.__braintrust_ai_sdk_model_wrapped === true;
17554
18229
  }
@@ -18366,13 +19041,15 @@ function patchAISDKStreamingResult(args) {
18366
19041
  const {
18367
19042
  defaultDenyOutputPaths,
18368
19043
  endEvent,
19044
+ forceTopLevelMetrics,
18369
19045
  onComplete,
18370
19046
  onCancel,
18371
19047
  onError,
18372
19048
  result,
18373
19049
  resolvePromiseUsage,
18374
19050
  span,
18375
- startTime
19051
+ startTime,
19052
+ transformOutput
18376
19053
  } = args;
18377
19054
  if (!result || typeof result !== "object") {
18378
19055
  return false;
@@ -18425,8 +19102,8 @@ function patchAISDKStreamingResult(args) {
18425
19102
  }
18426
19103
  outputLogged = true;
18427
19104
  try {
18428
- const metrics = extractTopLevelAISDKMetrics(result, endEvent);
18429
- if (resolvePromiseUsage) {
19105
+ const metrics = forceTopLevelMetrics ? await extractResolvedAISDKTokenMetrics(result) : extractTopLevelAISDKMetrics(result, endEvent);
19106
+ if (resolvePromiseUsage && !forceTopLevelMetrics) {
18430
19107
  try {
18431
19108
  const resultRecord2 = result;
18432
19109
  const pendingUsage = resultRecord2.totalUsage ?? resultRecord2.usage;
@@ -18445,10 +19122,11 @@ function patchAISDKStreamingResult(args) {
18445
19122
  if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
18446
19123
  metrics.time_to_first_token = firstChunkTime - startTime;
18447
19124
  }
18448
- const output = await processAISDKStreamingOutput(
19125
+ const processedOutput = await processAISDKStreamingOutput(
18449
19126
  result,
18450
19127
  resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
18451
19128
  );
19129
+ const output = transformOutput ? transformOutput(processedOutput) : processedOutput;
18452
19130
  const metadata = buildResolvedMetadataPayload(result).metadata;
18453
19131
  try {
18454
19132
  span.log({
@@ -20870,6 +21548,295 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
20870
21548
  }
20871
21549
  };
20872
21550
 
21551
+ // src/instrumentation/plugins/cloudflare-think-channels.ts
21552
+ var cloudflareThinkChannels = defineChannels(
21553
+ "@cloudflare/think",
21554
+ {
21555
+ runInferenceLoop: channel({
21556
+ channelName: "Think.runInferenceLoop",
21557
+ kind: "async"
21558
+ })
21559
+ },
21560
+ { instrumentationName: INSTRUMENTATION_NAMES.CLOUDFLARE_THINK }
21561
+ );
21562
+
21563
+ // src/instrumentation/plugins/cloudflare-think-plugin.ts
21564
+ var THINK_STATE_ID = /* @__PURE__ */ Symbol.for("braintrust.cloudflare-think.state-id");
21565
+ var CloudflareThinkPlugin = class extends BasePlugin {
21566
+ statesBySpanId = /* @__PURE__ */ new Map();
21567
+ onEnable() {
21568
+ this.subscribeToThinkRuns();
21569
+ this.subscribeToAISDKStreamTextSync();
21570
+ this.subscribeToAISDKStreamTextAsync();
21571
+ }
21572
+ onDisable() {
21573
+ for (const unsubscribe of this.unsubscribers) {
21574
+ unsubscribe();
21575
+ }
21576
+ this.unsubscribers = [];
21577
+ for (const state of this.statesBySpanId.values()) {
21578
+ this.finishState(state);
21579
+ }
21580
+ this.statesBySpanId.clear();
21581
+ }
21582
+ subscribeToThinkRuns() {
21583
+ const channel2 = cloudflareThinkChannels.runInferenceLoop.tracingChannel();
21584
+ const states = /* @__PURE__ */ new WeakMap();
21585
+ const state = _internalGetGlobalState();
21586
+ const contextManager = state?.contextManager;
21587
+ const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
21588
+ const ensureState2 = (event) => {
21589
+ if (isAutoInstrumentationSuppressed()) {
21590
+ return void 0;
21591
+ }
21592
+ const existing = states.get(event);
21593
+ if (existing) {
21594
+ return existing;
21595
+ }
21596
+ const span = startSpan(
21597
+ withSpanInstrumentationName(
21598
+ {
21599
+ name: "Think.runTurn",
21600
+ spanAttributes: { type: "task" /* TASK */ }
21601
+ },
21602
+ INSTRUMENTATION_NAMES.CLOUDFLARE_THINK
21603
+ )
21604
+ );
21605
+ const runState = {
21606
+ aiResultPatched: false,
21607
+ fallbackInput: extractFallbackInput(event.self?.messages),
21608
+ finalized: false,
21609
+ inputLogged: false,
21610
+ span,
21611
+ startTime: getCurrentUnixTimestamp()
21612
+ };
21613
+ const metadata = {
21614
+ braintrust: {
21615
+ integration_name: "cloudflare-think",
21616
+ sdk_language: "typescript"
21617
+ }
21618
+ };
21619
+ if (typeof event.moduleVersion === "string") {
21620
+ metadata["cloudflare_think.version"] = event.moduleVersion;
21621
+ }
21622
+ span.log({ metadata });
21623
+ states.set(event, runState);
21624
+ if (span.spanId) {
21625
+ this.statesBySpanId.set(span.spanId, runState);
21626
+ }
21627
+ registerCloudflareThinkSpan(span);
21628
+ return runState;
21629
+ };
21630
+ if (contextManager && currentSpanStore && channel2.start) {
21631
+ channel2.start.bindStore(currentSpanStore, (event) => {
21632
+ const runState = ensureState2(event);
21633
+ return runState ? contextManager.wrapSpanForStore(runState.span) : currentSpanStore.getStore();
21634
+ });
21635
+ this.unsubscribers.push(
21636
+ () => channel2.start?.unbindStore(currentSpanStore)
21637
+ );
21638
+ }
21639
+ const handlers = {
21640
+ start: (event) => {
21641
+ ensureState2(event);
21642
+ },
21643
+ asyncEnd: (event) => {
21644
+ const runState = states.get(event);
21645
+ states.delete(event);
21646
+ if (!runState || runState.finalized || runState.aiResultPatched) {
21647
+ return;
21648
+ }
21649
+ this.finishState(runState, void 0, event.result);
21650
+ },
21651
+ error: (event) => {
21652
+ const runState = states.get(event);
21653
+ states.delete(event);
21654
+ if (runState) {
21655
+ this.finishState(runState, event.error);
21656
+ }
21657
+ }
21658
+ };
21659
+ channel2.subscribe(handlers);
21660
+ this.unsubscribers.push(() => channel2.unsubscribe(handlers));
21661
+ }
21662
+ subscribeToAISDKStreamTextSync() {
21663
+ const channel2 = aiSDKChannels.streamTextSync.tracingChannel();
21664
+ const handlers = {
21665
+ start: (event) => {
21666
+ this.startAISDKStream(event);
21667
+ },
21668
+ end: (event) => {
21669
+ this.endAISDKStream(event);
21670
+ },
21671
+ error: (event) => {
21672
+ this.errorAISDKStream(event);
21673
+ }
21674
+ };
21675
+ channel2.subscribe(handlers);
21676
+ this.unsubscribers.push(() => channel2.unsubscribe(handlers));
21677
+ }
21678
+ subscribeToAISDKStreamTextAsync() {
21679
+ const channel2 = aiSDKChannels.streamText.tracingChannel();
21680
+ const handlers = {
21681
+ start: (event) => {
21682
+ this.startAISDKStream(event);
21683
+ },
21684
+ asyncEnd: (event) => {
21685
+ this.endAISDKStream(event);
21686
+ },
21687
+ error: (event) => {
21688
+ this.errorAISDKStream(event);
21689
+ }
21690
+ };
21691
+ channel2.subscribe(handlers);
21692
+ this.unsubscribers.push(() => channel2.unsubscribe(handlers));
21693
+ }
21694
+ startAISDKStream(event) {
21695
+ const runState = this.currentState();
21696
+ if (!runState || runState.finalized) {
21697
+ return;
21698
+ }
21699
+ try {
21700
+ const prepared = prepareAISDKAgentCallInput(
21701
+ event.arguments[0],
21702
+ event,
21703
+ runState.span
21704
+ );
21705
+ runState.span.log({
21706
+ input: extractThinkTaskInput(prepared.input),
21707
+ metadata: {
21708
+ ...prepared.metadata,
21709
+ braintrust: {
21710
+ integration_name: "cloudflare-think",
21711
+ sdk_language: "typescript"
21712
+ }
21713
+ }
21714
+ });
21715
+ runState.inputLogged = true;
21716
+ runState.aiEvent = event;
21717
+ Reflect.set(event, THINK_STATE_ID, runState.span.spanId);
21718
+ } catch (error) {
21719
+ debugLogger.error(
21720
+ "Error preparing @cloudflare/think AI SDK tracing:",
21721
+ error
21722
+ );
21723
+ }
21724
+ }
21725
+ endAISDKStream(event) {
21726
+ const runState = this.stateForAISDKEvent(event);
21727
+ if (!runState || runState.finalized) {
21728
+ return;
21729
+ }
21730
+ const patched = patchAISDKStreamingResult({
21731
+ defaultDenyOutputPaths: DEFAULT_DENY_OUTPUT_PATHS,
21732
+ endEvent: event,
21733
+ forceTopLevelMetrics: true,
21734
+ onComplete: () => this.releaseState(runState),
21735
+ result: event.result,
21736
+ span: runState.span,
21737
+ startTime: runState.startTime,
21738
+ transformOutput: extractThinkTaskOutput
21739
+ });
21740
+ runState.aiResultPatched = patched;
21741
+ if (!patched) {
21742
+ this.finishState(runState, void 0, event.result);
21743
+ }
21744
+ }
21745
+ errorAISDKStream(event) {
21746
+ const runState = this.stateForAISDKEvent(event);
21747
+ if (runState) {
21748
+ this.finishState(runState, event.error);
21749
+ }
21750
+ }
21751
+ currentState() {
21752
+ const parentIds = _internalGetGlobalState()?.contextManager.getParentSpanIds()?.spanParents ?? [];
21753
+ for (const parentId of parentIds) {
21754
+ const state = this.statesBySpanId.get(parentId);
21755
+ if (state) {
21756
+ return state;
21757
+ }
21758
+ }
21759
+ return void 0;
21760
+ }
21761
+ stateForAISDKEvent(event) {
21762
+ const spanId = Reflect.get(event, THINK_STATE_ID);
21763
+ return typeof spanId === "string" ? this.statesBySpanId.get(spanId) : void 0;
21764
+ }
21765
+ finishState(state, error, output) {
21766
+ if (state.finalized) {
21767
+ return;
21768
+ }
21769
+ state.finalized = true;
21770
+ try {
21771
+ if (!state.inputLogged && state.fallbackInput !== void 0) {
21772
+ state.span.log({ input: state.fallbackInput });
21773
+ }
21774
+ if (error !== void 0) {
21775
+ state.span.log({ error });
21776
+ } else if (output !== void 0) {
21777
+ state.span.log({ output: extractThinkTaskOutput(output) });
21778
+ }
21779
+ finalizeAISDKChildTracing(state.aiEvent);
21780
+ state.span.end();
21781
+ } finally {
21782
+ this.releaseState(state);
21783
+ }
21784
+ }
21785
+ releaseState(state) {
21786
+ state.finalized = true;
21787
+ unregisterCloudflareThinkSpan(state.span);
21788
+ if (state.span.spanId) {
21789
+ this.statesBySpanId.delete(state.span.spanId);
21790
+ }
21791
+ }
21792
+ };
21793
+ function extractFallbackInput(messages) {
21794
+ if (!Array.isArray(messages) || messages.length === 0) {
21795
+ return void 0;
21796
+ }
21797
+ let latestUserIndex = -1;
21798
+ for (let index = messages.length - 1; index >= 0; index--) {
21799
+ if (messages[index]?.role === "user") {
21800
+ latestUserIndex = index;
21801
+ break;
21802
+ }
21803
+ }
21804
+ const selected = latestUserIndex >= 0 ? messages.slice(latestUserIndex) : [];
21805
+ return selected.map((message) => ({
21806
+ role: message.role,
21807
+ content: message.content ?? message.parts
21808
+ }));
21809
+ }
21810
+ function extractThinkTaskOutput(output) {
21811
+ if (!isObject(output)) {
21812
+ return output;
21813
+ }
21814
+ if (typeof output.text === "string") {
21815
+ return { role: "assistant", content: output.text };
21816
+ }
21817
+ if (output.object !== void 0) {
21818
+ return output.object;
21819
+ }
21820
+ return output;
21821
+ }
21822
+ function extractThinkTaskInput(input) {
21823
+ if (!isObject(input)) {
21824
+ return input;
21825
+ }
21826
+ const system = input.instructions ?? input.system;
21827
+ if (Array.isArray(input.messages)) {
21828
+ return system === void 0 ? input.messages : [{ role: "system", content: system }, ...input.messages];
21829
+ }
21830
+ if (Array.isArray(input.prompt)) {
21831
+ return system === void 0 ? input.prompt : [{ role: "system", content: system }, ...input.prompt];
21832
+ }
21833
+ if (typeof input.prompt === "string") {
21834
+ const messages = [{ role: "user", content: input.prompt }];
21835
+ return system === void 0 ? messages : [{ role: "system", content: system }, ...messages];
21836
+ }
21837
+ return input;
21838
+ }
21839
+
20873
21840
  // src/instrumentation/plugins/cursor-sdk-channels.ts
20874
21841
  var cursorSDKChannels = defineChannels(
20875
21842
  "@cursor/sdk",
@@ -26635,6 +27602,470 @@ function aggregateMistralStreamChunks(chunks) {
26635
27602
  };
26636
27603
  }
26637
27604
 
27605
+ // src/instrumentation/plugins/ollama-channels.ts
27606
+ var ollamaChannels = defineChannels(
27607
+ "ollama",
27608
+ {
27609
+ chat: channel({
27610
+ channelName: "chat",
27611
+ kind: "async"
27612
+ }),
27613
+ generate: channel({
27614
+ channelName: "generate",
27615
+ kind: "async"
27616
+ }),
27617
+ embed: channel({
27618
+ channelName: "embed",
27619
+ kind: "async"
27620
+ })
27621
+ },
27622
+ { instrumentationName: INSTRUMENTATION_NAMES.OLLAMA }
27623
+ );
27624
+
27625
+ // src/instrumentation/plugins/ollama-plugin.ts
27626
+ var OllamaPlugin = class extends BasePlugin {
27627
+ onEnable() {
27628
+ this.unsubscribers.push(
27629
+ traceStreamingChannel(ollamaChannels.chat, {
27630
+ name: "ollama.chat",
27631
+ type: "llm" /* LLM */,
27632
+ extractInput: extractOllamaChatInput,
27633
+ extractOutput: (result, event) => extractOllamaChatOutput(
27634
+ result,
27635
+ countOllamaToolCalls(event?.arguments?.[0]?.messages)
27636
+ ),
27637
+ extractMetadata: extractOllamaResponseMetadata,
27638
+ extractMetrics: extractOllamaMetrics,
27639
+ aggregateChunks: aggregateOllamaChatChunks
27640
+ }),
27641
+ traceStreamingChannel(ollamaChannels.generate, {
27642
+ name: "ollama.generate",
27643
+ type: "llm" /* LLM */,
27644
+ extractInput: extractOllamaGenerateInput,
27645
+ extractOutput: extractOllamaGenerateOutput,
27646
+ extractMetadata: extractOllamaResponseMetadata,
27647
+ extractMetrics: extractOllamaMetrics,
27648
+ aggregateChunks: aggregateOllamaGenerateChunks
27649
+ }),
27650
+ traceAsyncChannel(ollamaChannels.embed, {
27651
+ name: "ollama.embed",
27652
+ type: "llm" /* LLM */,
27653
+ extractInput: extractOllamaEmbedInput,
27654
+ extractOutput: extractOllamaEmbedOutput,
27655
+ extractMetadata: extractOllamaResponseMetadata,
27656
+ extractMetrics: extractOllamaMetrics
27657
+ })
27658
+ );
27659
+ }
27660
+ onDisable() {
27661
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
27662
+ }
27663
+ };
27664
+ function isNonNegativeNumber(value) {
27665
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
27666
+ }
27667
+ function normalizeFinishReason(response, hasToolCalls = false) {
27668
+ if (hasToolCalls) {
27669
+ return "tool_calls";
27670
+ }
27671
+ return response?.done_reason || "stop";
27672
+ }
27673
+ function stringifyArguments(value) {
27674
+ if (typeof value === "string") {
27675
+ return value;
27676
+ }
27677
+ try {
27678
+ return JSON.stringify(value ?? {});
27679
+ } catch {
27680
+ return String(value);
27681
+ }
27682
+ }
27683
+ function syntheticToolCallId(name, index) {
27684
+ const normalizedName = name.replace(/[^a-zA-Z0-9_-]/g, "_") || "tool";
27685
+ return `ollama_call_${normalizedName}_${index}`;
27686
+ }
27687
+ function normalizeToolCall(toolCall, index) {
27688
+ const name = toolCall.function?.name;
27689
+ if (typeof name !== "string" || name.length === 0) {
27690
+ return void 0;
27691
+ }
27692
+ return {
27693
+ id: typeof toolCall.id === "string" && toolCall.id.length > 0 ? toolCall.id : syntheticToolCallId(name, index),
27694
+ type: "function",
27695
+ function: {
27696
+ name,
27697
+ arguments: stringifyArguments(toolCall.function?.arguments)
27698
+ }
27699
+ };
27700
+ }
27701
+ function normalizeToolCalls(toolCalls2, syntheticIdOffset = 0) {
27702
+ if (!Array.isArray(toolCalls2)) {
27703
+ return [];
27704
+ }
27705
+ return toolCalls2.flatMap((toolCall, index) => {
27706
+ const normalized = normalizeToolCall(toolCall, syntheticIdOffset + index);
27707
+ return normalized ? [normalized] : [];
27708
+ });
27709
+ }
27710
+ function countOllamaToolCalls(messages) {
27711
+ if (!Array.isArray(messages)) {
27712
+ return 0;
27713
+ }
27714
+ return messages.reduce(
27715
+ (count, message) => count + (isObject(message) && Array.isArray(message.tool_calls) ? message.tool_calls.length : 0),
27716
+ 0
27717
+ );
27718
+ }
27719
+ function imageBytes(value) {
27720
+ if (value instanceof Uint8Array) {
27721
+ return value;
27722
+ }
27723
+ if (value instanceof ArrayBuffer) {
27724
+ return new Uint8Array(value);
27725
+ }
27726
+ if (typeof value !== "string" || value.startsWith("data:")) {
27727
+ return void 0;
27728
+ }
27729
+ try {
27730
+ const decoded = atob(value.slice(0, 24));
27731
+ return Uint8Array.from(decoded, (character) => character.charCodeAt(0));
27732
+ } catch {
27733
+ return void 0;
27734
+ }
27735
+ }
27736
+ function inferImageMediaType(value) {
27737
+ if (typeof value === "string") {
27738
+ const dataUrlType = value.match(/^data:(image\/[^;]+);base64,/i)?.[1];
27739
+ if (dataUrlType) {
27740
+ return dataUrlType;
27741
+ }
27742
+ }
27743
+ const bytes = imageBytes(value);
27744
+ if (!bytes) {
27745
+ return void 0;
27746
+ }
27747
+ if (bytes[0] === 137 && bytes[1] === 80 && bytes[2] === 78 && bytes[3] === 71) {
27748
+ return "image/png";
27749
+ }
27750
+ if (bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255) {
27751
+ return "image/jpeg";
27752
+ }
27753
+ const signature = String.fromCharCode(...bytes.slice(0, 12));
27754
+ if (signature.startsWith("GIF87a") || signature.startsWith("GIF89a")) {
27755
+ return "image/gif";
27756
+ }
27757
+ if (signature.startsWith("RIFF") && signature.slice(8, 12) === "WEBP") {
27758
+ return "image/webp";
27759
+ }
27760
+ return void 0;
27761
+ }
27762
+ function normalizeTextAndImages(content, images) {
27763
+ if (!images || images.length === 0) {
27764
+ return { content };
27765
+ }
27766
+ const imageParts = [];
27767
+ const unrecognizedImages = [];
27768
+ for (const image of images) {
27769
+ let localImagePath;
27770
+ let localPathMediaType;
27771
+ if (typeof image === "string" && !/^data:/i.test(image) && !/^https?:\/\//i.test(image)) {
27772
+ const extension = image.match(/\.([a-z0-9]+)$/i)?.[1]?.toLowerCase();
27773
+ const extensionMediaType = {
27774
+ png: "image/png",
27775
+ jpg: "image/jpeg",
27776
+ jpeg: "image/jpeg",
27777
+ gif: "image/gif",
27778
+ webp: "image/webp"
27779
+ }[extension ?? ""];
27780
+ if (extensionMediaType && isomorph_default.statSync) {
27781
+ try {
27782
+ if (isomorph_default.statSync(image).isFile()) {
27783
+ localImagePath = image;
27784
+ localPathMediaType = extensionMediaType;
27785
+ }
27786
+ } catch {
27787
+ }
27788
+ }
27789
+ }
27790
+ const mediaType = localPathMediaType ?? inferImageMediaType(image);
27791
+ if (!mediaType) {
27792
+ unrecognizedImages.push(image);
27793
+ continue;
27794
+ }
27795
+ const processedImage = localImagePath ? new Attachment({
27796
+ data: localImagePath,
27797
+ filename: localImagePath.split(/[\\/]/).at(-1) ?? "image",
27798
+ contentType: mediaType
27799
+ }) : processInputAttachments({
27800
+ type: "image",
27801
+ image,
27802
+ mediaType
27803
+ }).image;
27804
+ imageParts.push({
27805
+ type: "image_url",
27806
+ image_url: { url: processedImage }
27807
+ });
27808
+ }
27809
+ return {
27810
+ content: imageParts.length > 0 ? [...content ? [{ type: "text", text: content }] : [], ...imageParts] : content,
27811
+ ...unrecognizedImages.length > 0 ? { unrecognizedImages } : {}
27812
+ };
27813
+ }
27814
+ function normalizeMessage(message, toolCallId, syntheticToolCallIdOffset = 0) {
27815
+ if (typeof message.role !== "string") {
27816
+ return void 0;
27817
+ }
27818
+ const toolCalls2 = normalizeToolCalls(
27819
+ message.tool_calls,
27820
+ syntheticToolCallIdOffset
27821
+ );
27822
+ if (message.role === "tool") {
27823
+ const toolName = typeof message.tool_name === "string" && message.tool_name.length > 0 ? message.tool_name : "tool";
27824
+ return {
27825
+ role: "tool",
27826
+ tool_call_id: toolCallId ?? syntheticToolCallId(toolName, 0),
27827
+ content: typeof message.content === "string" ? message.content : ""
27828
+ };
27829
+ }
27830
+ const normalizedContent = normalizeTextAndImages(
27831
+ typeof message.content === "string" ? message.content || (toolCalls2.length > 0 ? null : "") : toolCalls2.length > 0 ? null : "",
27832
+ message.images
27833
+ );
27834
+ return {
27835
+ role: message.role,
27836
+ content: normalizedContent.content,
27837
+ ...typeof message.thinking === "string" && message.thinking.length > 0 ? { reasoning: message.thinking } : {},
27838
+ ...toolCalls2.length > 0 ? { tool_calls: toolCalls2 } : {},
27839
+ ...normalizedContent.unrecognizedImages ? { images: normalizedContent.unrecognizedImages } : {}
27840
+ };
27841
+ }
27842
+ function normalizeMessages(messages) {
27843
+ if (!Array.isArray(messages)) {
27844
+ return [];
27845
+ }
27846
+ const pendingToolCallIds = /* @__PURE__ */ new Map();
27847
+ let syntheticToolCallIdOffset = 0;
27848
+ return messages.flatMap((message) => {
27849
+ if (!isObject(message)) {
27850
+ return [];
27851
+ }
27852
+ const ollamaMessage = message;
27853
+ let toolCallId;
27854
+ if (ollamaMessage.role === "tool") {
27855
+ const toolName = ollamaMessage.tool_name;
27856
+ if (typeof toolName === "string") {
27857
+ toolCallId = pendingToolCallIds.get(toolName)?.shift();
27858
+ }
27859
+ }
27860
+ const normalized = normalizeMessage(
27861
+ ollamaMessage,
27862
+ toolCallId,
27863
+ syntheticToolCallIdOffset
27864
+ );
27865
+ if (Array.isArray(ollamaMessage.tool_calls)) {
27866
+ syntheticToolCallIdOffset += ollamaMessage.tool_calls.length;
27867
+ }
27868
+ if (ollamaMessage.role === "assistant" && normalized) {
27869
+ const toolCalls2 = Array.isArray(normalized.tool_calls) ? normalized.tool_calls : [];
27870
+ for (const toolCall of toolCalls2) {
27871
+ if (!isObject(toolCall) || !isObject(toolCall.function)) {
27872
+ continue;
27873
+ }
27874
+ const name = toolCall.function.name;
27875
+ const id = toolCall.id;
27876
+ if (typeof name === "string" && typeof id === "string") {
27877
+ const ids = pendingToolCallIds.get(name) ?? [];
27878
+ ids.push(id);
27879
+ pendingToolCallIds.set(name, ids);
27880
+ }
27881
+ }
27882
+ }
27883
+ return normalized ? [normalized] : [];
27884
+ });
27885
+ }
27886
+ function normalizeToolDefinition(tool) {
27887
+ const fn = tool.function;
27888
+ if (!fn || typeof fn.name !== "string" || fn.name.length === 0) {
27889
+ return void 0;
27890
+ }
27891
+ return {
27892
+ type: "function",
27893
+ function: {
27894
+ name: fn.name,
27895
+ ...typeof fn.description === "string" ? { description: fn.description } : {},
27896
+ ...isObject(fn.parameters) ? { parameters: fn.parameters } : {}
27897
+ }
27898
+ };
27899
+ }
27900
+ function extractToolsMetadata(tools) {
27901
+ if (!Array.isArray(tools)) {
27902
+ return {};
27903
+ }
27904
+ const normalized = tools.flatMap((tool) => {
27905
+ if (!isObject(tool)) {
27906
+ return [];
27907
+ }
27908
+ const definition = normalizeToolDefinition(tool);
27909
+ return definition ? [definition] : [];
27910
+ });
27911
+ return normalized.length > 0 ? { tools: normalized } : {};
27912
+ }
27913
+ function extractOptionsMetadata(options) {
27914
+ if (!isObject(options)) {
27915
+ return {};
27916
+ }
27917
+ const metadata = {};
27918
+ const mappings = [
27919
+ ["temperature", "temperature"],
27920
+ ["top_p", "top_p"],
27921
+ ["num_predict", "max_tokens"],
27922
+ ["frequency_penalty", "frequency_penalty"],
27923
+ ["presence_penalty", "presence_penalty"],
27924
+ ["stop", "stop"]
27925
+ ];
27926
+ for (const [source, target] of mappings) {
27927
+ if (options[source] !== void 0) {
27928
+ metadata[target] = options[source];
27929
+ }
27930
+ }
27931
+ return metadata;
27932
+ }
27933
+ function extractRequestMetadata(request) {
27934
+ return {
27935
+ provider: "ollama",
27936
+ ...typeof request?.model === "string" ? { model: request.model } : {},
27937
+ ...extractOptionsMetadata(request?.options),
27938
+ ...request?.format !== void 0 ? { response_format: request.format } : {}
27939
+ };
27940
+ }
27941
+ function extractOllamaChatInput([request]) {
27942
+ return {
27943
+ input: normalizeMessages(request.messages),
27944
+ metadata: {
27945
+ ...extractRequestMetadata(request),
27946
+ ...extractToolsMetadata(request.tools)
27947
+ }
27948
+ };
27949
+ }
27950
+ function extractOllamaGenerateInput([request]) {
27951
+ const normalizedPrompt = normalizeTextAndImages(
27952
+ typeof request.prompt === "string" ? request.prompt : "",
27953
+ Array.isArray(request.images) ? request.images : void 0
27954
+ );
27955
+ const input = [
27956
+ ...typeof request.system === "string" ? [{ role: "system", content: request.system }] : [],
27957
+ {
27958
+ role: "user",
27959
+ content: normalizedPrompt.content,
27960
+ ...typeof request.suffix === "string" ? { suffix: request.suffix } : {},
27961
+ ...normalizedPrompt.unrecognizedImages ? { images: normalizedPrompt.unrecognizedImages } : {}
27962
+ }
27963
+ ];
27964
+ return {
27965
+ input,
27966
+ metadata: extractRequestMetadata(request)
27967
+ };
27968
+ }
27969
+ function extractOllamaEmbedInput([request]) {
27970
+ return {
27971
+ input: request.input,
27972
+ metadata: extractRequestMetadata(request)
27973
+ };
27974
+ }
27975
+ function extractOllamaChatOutput(result, syntheticToolCallIdOffset = 0) {
27976
+ if (!isObject(result) || !isObject(result.message)) {
27977
+ return void 0;
27978
+ }
27979
+ const message = normalizeMessage(
27980
+ result.message,
27981
+ void 0,
27982
+ syntheticToolCallIdOffset
27983
+ );
27984
+ if (!message) {
27985
+ return void 0;
27986
+ }
27987
+ const toolCalls2 = Array.isArray(message.tool_calls) ? message.tool_calls : [];
27988
+ return [
27989
+ {
27990
+ index: 0,
27991
+ finish_reason: normalizeFinishReason(result, toolCalls2.length > 0),
27992
+ message
27993
+ }
27994
+ ];
27995
+ }
27996
+ function extractOllamaGenerateOutput(result) {
27997
+ if (!isObject(result) || typeof result.response !== "string") {
27998
+ return void 0;
27999
+ }
28000
+ return [
28001
+ {
28002
+ index: 0,
28003
+ finish_reason: normalizeFinishReason(result),
28004
+ message: {
28005
+ role: "assistant",
28006
+ content: result.response,
28007
+ ...typeof result.thinking === "string" && result.thinking.length > 0 ? { reasoning: result.thinking } : {}
28008
+ }
28009
+ }
28010
+ ];
28011
+ }
28012
+ function extractOllamaEmbedOutput(result) {
28013
+ const embedding = Array.isArray(result?.embeddings) ? result.embeddings[0] : void 0;
28014
+ return Array.isArray(embedding) ? { embedding_length: embedding.length } : void 0;
28015
+ }
28016
+ function extractOllamaResponseMetadata(result) {
28017
+ return typeof result?.model === "string" ? { model: result.model } : void 0;
28018
+ }
28019
+ function extractOllamaMetrics(result) {
28020
+ const metrics = {};
28021
+ const promptTokens = result?.prompt_eval_count;
28022
+ const completionTokens = result?.eval_count;
28023
+ if (isNonNegativeNumber(promptTokens)) {
28024
+ metrics.prompt_tokens = promptTokens;
28025
+ }
28026
+ if (isNonNegativeNumber(completionTokens)) {
28027
+ metrics.completion_tokens = completionTokens;
28028
+ }
28029
+ if (isNonNegativeNumber(promptTokens) || isNonNegativeNumber(completionTokens)) {
28030
+ metrics.tokens = (isNonNegativeNumber(promptTokens) ? promptTokens : 0) + (isNonNegativeNumber(completionTokens) ? completionTokens : 0);
28031
+ }
28032
+ return metrics;
28033
+ }
28034
+ function aggregateOllamaChatChunks(chunks, _result, event, _startTime) {
28035
+ const last = chunks.at(-1);
28036
+ const message = {
28037
+ role: "assistant",
28038
+ content: chunks.map((chunk) => chunk.message?.content ?? "").join(""),
28039
+ thinking: chunks.map((chunk) => chunk.message?.thinking ?? "").join(""),
28040
+ tool_calls: chunks.flatMap((chunk) => chunk.message?.tool_calls ?? [])
28041
+ };
28042
+ const response = {
28043
+ ...last,
28044
+ message
28045
+ };
28046
+ return {
28047
+ output: extractOllamaChatOutput(
28048
+ response,
28049
+ countOllamaToolCalls(event?.arguments?.[0]?.messages)
28050
+ ),
28051
+ metrics: extractOllamaMetrics(last ?? {}),
28052
+ metadata: extractOllamaResponseMetadata(last ?? {})
28053
+ };
28054
+ }
28055
+ function aggregateOllamaGenerateChunks(chunks, _result, _event, _startTime) {
28056
+ const last = chunks.at(-1);
28057
+ const response = {
28058
+ ...last,
28059
+ response: chunks.map((chunk) => chunk.response ?? "").join(""),
28060
+ thinking: chunks.map((chunk) => chunk.thinking ?? "").join("")
28061
+ };
28062
+ return {
28063
+ output: extractOllamaGenerateOutput(response),
28064
+ metrics: extractOllamaMetrics(last ?? {}),
28065
+ metadata: extractOllamaResponseMetadata(last ?? {})
28066
+ };
28067
+ }
28068
+
26638
28069
  // src/instrumentation/plugins/google-adk-channels.ts
26639
28070
  var googleADKChannels = defineChannels(
26640
28071
  "@google/adk",
@@ -30388,7 +31819,7 @@ var FlueObserveBridge = class {
30388
31819
  return;
30389
31820
  }
30390
31821
  const state = this.operationsById.get(event.operationId) ?? this.startSyntheticOperation(event);
30391
- const output = operationOutput(event);
31822
+ const output = operationOutput(event) ?? outputFromAgentTurn(state.latestAgentOutput);
30392
31823
  const metadata = {
30393
31824
  ...state.metadata,
30394
31825
  ...extractEventMetadata(event),
@@ -30397,7 +31828,7 @@ var FlueObserveBridge = class {
30397
31828
  };
30398
31829
  this.finishPendingChildrenForOperation(event, output);
30399
31830
  safeLog3(state.span, {
30400
- ...event.isError ? { error: toLoggedError(event.error) } : {},
31831
+ ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.error) } : {},
30401
31832
  metadata,
30402
31833
  metrics: durationMetrics2(event.durationMs),
30403
31834
  output
@@ -30428,7 +31859,7 @@ var FlueObserveBridge = class {
30428
31859
  };
30429
31860
  const parent = this.parentSpanForTurn(event);
30430
31861
  const span = startFlueSpan(parent, {
30431
- name: `llm:${model ?? event.purpose ?? "unknown"}`,
31862
+ name: "flue.turn",
30432
31863
  spanAttributes: { type: "llm" /* LLM */ },
30433
31864
  startTime: eventTime(event.timestamp),
30434
31865
  event: {
@@ -30472,6 +31903,12 @@ var FlueObserveBridge = class {
30472
31903
  },
30473
31904
  output
30474
31905
  });
31906
+ if (event.purpose === "agent" && event.operationId) {
31907
+ const operation = this.operationsById.get(event.operationId);
31908
+ if (operation) {
31909
+ operation.latestAgentOutput = output;
31910
+ }
31911
+ }
30475
31912
  safeEnd(state.span, eventTime(event.timestamp));
30476
31913
  this.turnsByKey.delete(key);
30477
31914
  }
@@ -30551,7 +31988,7 @@ var FlueObserveBridge = class {
30551
31988
  return;
30552
31989
  }
30553
31990
  safeLog3(state.span, {
30554
- ...event.isError ? { error: toLoggedError(event.result) } : {},
31991
+ ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.result) } : {},
30555
31992
  metadata: {
30556
31993
  ...state.metadata,
30557
31994
  ...extractEventMetadata(event),
@@ -30597,6 +32034,7 @@ var FlueObserveBridge = class {
30597
32034
  ...event.usage ? { "flue.usage": event.usage } : {}
30598
32035
  };
30599
32036
  safeLog3(state.span, {
32037
+ ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.error) } : {},
30600
32038
  metadata,
30601
32039
  metrics: {
30602
32040
  ...durationMetrics2(event.durationMs),
@@ -30701,7 +32139,7 @@ var FlueObserveBridge = class {
30701
32139
  ...event.purpose ? { "flue.turn_purpose": event.purpose } : {}
30702
32140
  };
30703
32141
  const span = startFlueSpan(this.parentSpanForEvent(event), {
30704
- name: `llm:${model ?? event.purpose ?? "unknown"}`,
32142
+ name: "flue.turn",
30705
32143
  spanAttributes: { type: "llm" /* LLM */ },
30706
32144
  startTime: eventTime(event.timestamp),
30707
32145
  event: { metadata }
@@ -30833,7 +32271,10 @@ function extractEventMetadata(event, ctx) {
30833
32271
  return {
30834
32272
  ...event.runId ? { "flue.run_id": event.runId } : {},
30835
32273
  ...event.instanceId ? { "flue.instance_id": event.instanceId } : {},
32274
+ ...event.submissionId ? { "flue.submission_id": event.submissionId } : {},
30836
32275
  ...event.dispatchId ? { "flue.dispatch_id": event.dispatchId } : {},
32276
+ ...event.agentName ? { "flue.agent_name": event.agentName } : {},
32277
+ ...event.conversationId ? { "flue.conversation_id": event.conversationId } : {},
30837
32278
  ...typeof event.eventIndex === "number" ? { "flue.event_index": event.eventIndex } : {},
30838
32279
  ...event.session ? { "flue.session": event.session } : {},
30839
32280
  ...event.parentSession ? { "flue.parent_session": event.parentSession } : {},
@@ -30862,7 +32303,7 @@ function flueTurnRequestInput(event) {
30862
32303
  return event.request?.input ?? event.input;
30863
32304
  }
30864
32305
  function flueTurnRequestModel(event) {
30865
- return event.request?.model ?? event.model;
32306
+ return event.request?.requestedModel ?? event.request?.model ?? event.model;
30866
32307
  }
30867
32308
  function flueTurnRequestProvider(event) {
30868
32309
  return event.request?.providerName ?? event.provider ?? event.request?.providerId;
@@ -30871,10 +32312,10 @@ function flueTurnRequestApi(event) {
30871
32312
  return event.request?.api ?? event.api;
30872
32313
  }
30873
32314
  function flueTurnRequestReasoning(event) {
30874
- return event.request?.reasoning ?? event.reasoning;
32315
+ return event.request?.reasoningLevel ?? event.request?.reasoning ?? event.reasoning;
30875
32316
  }
30876
32317
  function flueTurnModel(event) {
30877
- return event.request?.model ?? event.model;
32318
+ return event.response?.responseModel ?? event.request?.requestedModel ?? event.request?.model ?? event.model;
30878
32319
  }
30879
32320
  function flueTurnProvider(event) {
30880
32321
  return event.request?.providerName ?? event.provider ?? event.request?.providerId;
@@ -30889,7 +32330,7 @@ function flueTurnOutput(event) {
30889
32330
  return event.response?.output ?? event.output;
30890
32331
  }
30891
32332
  function flueTurnStopReason(event) {
30892
- return event.response?.stopReason ?? event.stopReason;
32333
+ return event.response?.finishReason ?? event.response?.stopReason ?? event.stopReason;
30893
32334
  }
30894
32335
  function flueTurnError(event) {
30895
32336
  return event.response?.error ?? event.response?.errorInfo?.message ?? event.error;
@@ -30904,6 +32345,9 @@ function flueToolInput(event) {
30904
32345
  return event.input;
30905
32346
  }
30906
32347
  function flueToolOutput(event) {
32348
+ if (Object.hasOwn(event, "effectiveResult")) {
32349
+ return event.effectiveResult;
32350
+ }
30907
32351
  return event.output !== void 0 ? event.output : event.result;
30908
32352
  }
30909
32353
  function flueToolError(event) {
@@ -30911,10 +32355,36 @@ function flueToolError(event) {
30911
32355
  }
30912
32356
  function operationOutput(event) {
30913
32357
  if (event.operationKind === "prompt" || event.operationKind === "skill") {
30914
- return llmResultFromOperationResult(event.result);
32358
+ return outputFromAgentInvocation(event.agentOutput) ?? llmResultFromOperationResult(event.result);
30915
32359
  }
30916
32360
  return event.result ?? (event.operationKind === "compact" ? { completed: true } : void 0);
30917
32361
  }
32362
+ function outputFromAgentInvocation(output) {
32363
+ if (output?.type === "text") {
32364
+ return output.text;
32365
+ }
32366
+ if (output?.type === "data") {
32367
+ return output.data;
32368
+ }
32369
+ return void 0;
32370
+ }
32371
+ function outputFromAgentTurn(output) {
32372
+ if (!isObjectLike(output)) {
32373
+ return output;
32374
+ }
32375
+ const content = Reflect.get(output, "content");
32376
+ if (!Array.isArray(content)) {
32377
+ return output;
32378
+ }
32379
+ const text = content.flatMap((part) => {
32380
+ if (!isObjectLike(part) || Reflect.get(part, "type") !== "text") {
32381
+ return [];
32382
+ }
32383
+ const value = Reflect.get(part, "text");
32384
+ return typeof value === "string" ? [value] : [];
32385
+ });
32386
+ return text.length > 0 ? text.join("") : output;
32387
+ }
30918
32388
  function llmResultFromOperationResult(result) {
30919
32389
  if (!isObjectLike(result)) {
30920
32390
  return result;
@@ -31013,7 +32483,7 @@ function safeEnd(span, endTime) {
31013
32483
  }
31014
32484
  }
31015
32485
  function logInstrumentationError3(label, error) {
31016
- console.error(`Error in ${label} instrumentation:`, error);
32486
+ debugLogger.debug(`Error in ${label} instrumentation:`, error);
31017
32487
  }
31018
32488
 
31019
32489
  // src/wrappers/langchain/callback-handler.ts
@@ -31942,12 +33412,13 @@ var piCodingAgentChannels = defineChannels(
31942
33412
  );
31943
33413
 
31944
33414
  // src/instrumentation/plugins/pi-coding-agent-plugin.ts
31945
- var piStreamPatchStates = /* @__PURE__ */ new WeakMap();
33415
+ var piAgentPatchStates = /* @__PURE__ */ new WeakMap();
33416
+ var piAgentEventSubscriptions = /* @__PURE__ */ new WeakSet();
31946
33417
  var piPromptContextStore;
31947
33418
  var PiCodingAgentPlugin = class extends BasePlugin {
31948
33419
  activePromptStates = /* @__PURE__ */ new Set();
31949
33420
  onEnable() {
31950
- this.subscribeToPrompt();
33421
+ this.interceptPrompt();
31951
33422
  }
31952
33423
  onDisable() {
31953
33424
  for (const unsubscribe of this.unsubscribers) {
@@ -31955,65 +33426,74 @@ var PiCodingAgentPlugin = class extends BasePlugin {
31955
33426
  }
31956
33427
  this.unsubscribers = [];
31957
33428
  for (const state of [...this.activePromptStates]) {
31958
- void finalizePiPromptRun(state).catch((error) => {
31959
- logInstrumentationError4("Pi Coding Agent disable cleanup", error);
31960
- });
33429
+ finishPiPromptRun(state);
31961
33430
  }
31962
33431
  }
31963
- subscribeToPrompt() {
31964
- const channel2 = piCodingAgentChannels.prompt.tracingChannel();
31965
- const states = /* @__PURE__ */ new WeakMap();
31966
- const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(channel2);
31967
- const handlers = {
31968
- start: (event) => {
31969
- const state = startPiPromptRun(event, (state2) => {
31970
- this.activePromptStates.delete(state2);
31971
- });
31972
- if (state) {
31973
- this.activePromptStates.add(state);
31974
- states.set(event, state);
31975
- }
31976
- },
31977
- asyncEnd: async (event) => {
31978
- const state = states.get(event);
31979
- if (!state) {
31980
- return;
31981
- }
31982
- states.delete(event);
31983
- state.promptCallEnded = true;
31984
- if (!state.finalized && state.deferCompletionUntilTurnEnd && !state.turnEnded) {
31985
- if (!state.sawStreamFn) {
31986
- state.queued = true;
31987
- if (!state.streamPatchState.queuedPromptStates.includes(state)) {
31988
- state.streamPatchState.queuedPromptStates.push(state);
31989
- }
33432
+ interceptPrompt() {
33433
+ this.unsubscribers.push(
33434
+ piCodingAgentChannels.prompt.intercept(
33435
+ (target, thisArg, args, additional) => {
33436
+ const invokeTarget = () => Reflect.apply(target, thisArg, args);
33437
+ let state;
33438
+ try {
33439
+ state = startPiPromptRun(
33440
+ {
33441
+ ...additional,
33442
+ arguments: args,
33443
+ self: thisArg
33444
+ },
33445
+ (finalizedState) => {
33446
+ this.activePromptStates.delete(finalizedState);
33447
+ }
33448
+ );
33449
+ } catch (error) {
33450
+ logInstrumentationError4("Pi Coding Agent prompt start", error);
31990
33451
  }
31991
- return;
31992
- }
31993
- await finalizePiPromptRun(state);
31994
- },
31995
- error: async (event) => {
31996
- const state = states.get(event);
31997
- if (!state) {
31998
- return;
33452
+ if (!state) {
33453
+ return runWithAutoInstrumentationSuppressed(invokeTarget);
33454
+ }
33455
+ this.activePromptStates.add(state);
33456
+ return promptContextStore().run(
33457
+ state,
33458
+ () => runWithAutoInstrumentationSuppressed(() => {
33459
+ let result;
33460
+ try {
33461
+ result = invokeTarget();
33462
+ } catch (error) {
33463
+ finishPiPromptRun(state, error);
33464
+ throw error;
33465
+ }
33466
+ return Promise.resolve(result).then(
33467
+ (value) => {
33468
+ finishPiPromptCall(state);
33469
+ return value;
33470
+ },
33471
+ (error) => {
33472
+ finishPiPromptRun(state, error);
33473
+ throw error;
33474
+ }
33475
+ );
33476
+ })
33477
+ );
31999
33478
  }
32000
- states.delete(event);
32001
- await finalizePiPromptRun(state, event.error);
32002
- }
32003
- };
32004
- channel2.subscribe(handlers);
32005
- this.unsubscribers.push(() => {
32006
- unbindAutoInstrumentationSuppression?.();
32007
- channel2.unsubscribe(handlers);
32008
- });
33479
+ )
33480
+ );
32009
33481
  }
32010
33482
  };
33483
+ function finishPiPromptCall(state) {
33484
+ state.promptCallEnded = true;
33485
+ if (state.deferCompletionUntilTurnEnd && !state.turnEnded) {
33486
+ return;
33487
+ }
33488
+ finishPiPromptRun(state);
33489
+ }
32011
33490
  function startPiPromptRun(event, onFinalize) {
32012
33491
  const session = extractSession(event);
32013
33492
  const agent = session?.agent;
32014
33493
  if (!session || !isPiAgent(agent)) {
32015
33494
  return void 0;
32016
33495
  }
33496
+ installPiAgentInstrumentation(agent);
32017
33497
  const metadata = {
32018
33498
  ...extractSessionMetadata(session),
32019
33499
  ...extractPromptOptionsMetadata(event.arguments[1]),
@@ -32035,9 +33515,7 @@ function startPiPromptRun(event, onFinalize) {
32035
33515
  INSTRUMENTATION_NAMES.PI_CODING_AGENT
32036
33516
  )
32037
33517
  );
32038
- const streamPatchState = installPiStreamPatch(agent);
32039
33518
  const options = event.arguments[1];
32040
- const promptText = event.arguments[0];
32041
33519
  const state = {
32042
33520
  activeLlmSpans: /* @__PURE__ */ new Set(),
32043
33521
  activeToolSpans: /* @__PURE__ */ new Map(),
@@ -32049,29 +33527,10 @@ function startPiPromptRun(event, onFinalize) {
32049
33527
  metrics: {},
32050
33528
  onFinalize,
32051
33529
  promptCallEnded: false,
32052
- ...typeof promptText === "string" ? { promptText } : {},
32053
- queued: false,
32054
33530
  span,
32055
- sawStreamFn: false,
32056
33531
  startTime: getCurrentUnixTimestamp(),
32057
- streamPatchState,
32058
33532
  turnEnded: false
32059
33533
  };
32060
- state.restorePromptContext = enterPiPromptContext(state);
32061
- streamPatchState.activePromptStates.add(state);
32062
- try {
32063
- state.unsubscribeAgent = agent.subscribe(async (agentEvent) => {
32064
- try {
32065
- await runWithAutoInstrumentationSuppressed(
32066
- () => handlePiAgentEvent(state, agentEvent)
32067
- );
32068
- } catch (error) {
32069
- logInstrumentationError4("Pi Coding Agent event", error);
32070
- }
32071
- });
32072
- } catch (error) {
32073
- logInstrumentationError4("Pi Coding Agent event subscription", error);
32074
- }
32075
33534
  return state;
32076
33535
  }
32077
33536
  function extractSession(event) {
@@ -32085,111 +33544,55 @@ function promptContextStore() {
32085
33544
  piPromptContextStore ??= isomorph_default.newAsyncLocalStorage();
32086
33545
  return piPromptContextStore;
32087
33546
  }
32088
- function currentPromptContextFrames() {
32089
- return promptContextStore().getStore()?.frames ?? [];
32090
- }
32091
33547
  function currentPiPromptState() {
32092
- const frames = currentPromptContextFrames();
32093
- return frames[frames.length - 1]?.state;
32094
- }
32095
- function enterPiPromptContext(state) {
32096
- const frame = {
32097
- id: /* @__PURE__ */ Symbol("braintrust.pi-coding-agent.prompt"),
32098
- state
32099
- };
32100
- promptContextStore().enterWith({
32101
- frames: [...currentPromptContextFrames(), frame]
32102
- });
32103
- return () => {
32104
- const frames = currentPromptContextFrames().filter(
32105
- (candidate) => candidate.id !== frame.id
32106
- );
32107
- promptContextStore().enterWith(frames.length > 0 ? { frames } : void 0);
32108
- };
32109
- }
32110
- function installPiStreamPatch(agent) {
32111
- const existing = piStreamPatchStates.get(agent);
32112
- if (existing) {
32113
- if (agent.streamFn !== existing.wrappedStreamFn) {
32114
- debugLogger.debug(
32115
- "Pi Coding Agent streamFn changed while Braintrust instrumentation was active; preserving existing patch state."
32116
- );
32117
- }
32118
- return existing;
32119
- }
32120
- const patchState = {
32121
- activePromptStates: /* @__PURE__ */ new Set(),
32122
- agent,
32123
- originalStreamFn: agent.streamFn,
32124
- queuedPromptStates: [],
32125
- wrappedStreamFn: agent.streamFn
32126
- };
32127
- patchState.wrappedStreamFn = makeSharedInstrumentedStreamFn(patchState);
32128
- agent.streamFn = patchState.wrappedStreamFn;
32129
- piStreamPatchStates.set(agent, patchState);
32130
- return patchState;
32131
- }
32132
- function resolveStreamPromptState(patchState, context) {
32133
- let lastUserText;
32134
- if (Array.isArray(context.messages)) {
32135
- for (let i = context.messages.length - 1; i >= 0; i--) {
32136
- const message = context.messages[i];
32137
- if (isPiUserMessage(message)) {
32138
- if (typeof message.content === "string") {
32139
- lastUserText = message.content;
32140
- } else {
32141
- lastUserText = message.content.flatMap((part) => part.type === "text" ? [part.text] : []).join("");
32142
- }
32143
- break;
32144
- }
32145
- }
32146
- }
32147
- if (lastUserText !== void 0) {
32148
- const queuedMatch = patchState.queuedPromptStates.find(
32149
- (state) => state.promptText === lastUserText
32150
- );
32151
- if (queuedMatch) {
32152
- return queuedMatch;
32153
- }
32154
- const matches = [...patchState.activePromptStates].filter(
32155
- (state) => state.promptText === lastUserText
33548
+ return promptContextStore().getStore();
33549
+ }
33550
+ function installPiAgentInstrumentation(agent) {
33551
+ const existing = piAgentPatchStates.get(agent);
33552
+ if (!existing || agent.streamFn !== existing.wrappedStreamFn) {
33553
+ const patchState = {
33554
+ originalStreamFn: agent.streamFn,
33555
+ wrappedStreamFn: agent.streamFn
33556
+ };
33557
+ patchState.wrappedStreamFn = makeInstrumentedStreamFn(
33558
+ agent,
33559
+ patchState.originalStreamFn
32156
33560
  );
32157
- if (matches.length === 1) {
32158
- return matches[0];
32159
- }
33561
+ agent.streamFn = patchState.wrappedStreamFn;
33562
+ piAgentPatchStates.set(agent, patchState);
32160
33563
  }
32161
- const contextState = currentPiPromptState();
32162
- if (contextState && patchState.activePromptStates.has(contextState) && (!contextState.queued || lastUserText !== void 0 && contextState.promptText === lastUserText)) {
32163
- return contextState;
33564
+ if (piAgentEventSubscriptions.has(agent)) {
33565
+ return;
32164
33566
  }
32165
- if (patchState.activePromptStates.size === 1) {
32166
- return [...patchState.activePromptStates][0];
33567
+ try {
33568
+ agent.subscribe(async (event) => {
33569
+ const state = currentPiPromptState();
33570
+ if (!state || state.agent !== agent || state.finalized) {
33571
+ return;
33572
+ }
33573
+ try {
33574
+ await runWithAutoInstrumentationSuppressed(
33575
+ () => handlePiAgentEvent(state, event)
33576
+ );
33577
+ } catch (error) {
33578
+ logInstrumentationError4("Pi Coding Agent event", error);
33579
+ }
33580
+ });
33581
+ piAgentEventSubscriptions.add(agent);
33582
+ } catch (error) {
33583
+ logInstrumentationError4("Pi Coding Agent event subscription", error);
32167
33584
  }
32168
- return void 0;
32169
33585
  }
32170
- function makeSharedInstrumentedStreamFn(patchState) {
33586
+ function makeInstrumentedStreamFn(agent, originalStreamFn) {
32171
33587
  return async function instrumentedPiStreamFn(model, context, options) {
32172
- const state = resolveStreamPromptState(patchState, context);
32173
- if (!state) {
32174
- const invokeOriginal = () => Reflect.apply(patchState.originalStreamFn, this, [
32175
- model,
32176
- context,
32177
- options
32178
- ]);
32179
- return patchState.activePromptStates.size > 0 ? runWithAutoInstrumentationSuppressed(invokeOriginal) : invokeOriginal();
33588
+ const invokeOriginal = () => Reflect.apply(originalStreamFn, this, [model, context, options]);
33589
+ const state = currentPiPromptState();
33590
+ if (!state || state.agent !== agent || state.finalized) {
33591
+ return invokeOriginal();
32180
33592
  }
32181
- state.sawStreamFn = true;
32182
- removeQueuedPromptState(state);
32183
- state.streamPatchState.eventPromptState = state;
32184
33593
  const llmState = await startPiLlmSpan(state, model, context, options);
32185
33594
  try {
32186
- const stream = await runWithAutoInstrumentationSuppressed(
32187
- () => Reflect.apply(patchState.originalStreamFn, this, [
32188
- model,
32189
- context,
32190
- options
32191
- ])
32192
- );
33595
+ const stream = await runWithAutoInstrumentationSuppressed(invokeOriginal);
32193
33596
  return patchAssistantMessageStream(stream, state, llmState);
32194
33597
  } catch (error) {
32195
33598
  finishPiLlmSpan(state, llmState, void 0, error);
@@ -32336,13 +33739,6 @@ async function handlePiAgentEvent(state, event) {
32336
33739
  if (state.finalized) {
32337
33740
  return;
32338
33741
  }
32339
- const eventPromptState = state.streamPatchState.eventPromptState;
32340
- if (eventPromptState && eventPromptState !== state) {
32341
- return;
32342
- }
32343
- if (!eventPromptState && (state.queued || state.streamPatchState.activePromptStates.size > 1 && currentPiPromptState() !== state)) {
32344
- return;
32345
- }
32346
33742
  switch (event.type) {
32347
33743
  case "message_end":
32348
33744
  if (isPiAssistantMessage(event.message)) {
@@ -32357,11 +33753,8 @@ async function handlePiAgentEvent(state, event) {
32357
33753
  addMetrics(state.metrics, extractUsageMetrics2(event.message.usage));
32358
33754
  }
32359
33755
  }
32360
- if (state.streamPatchState.eventPromptState === state) {
32361
- state.streamPatchState.eventPromptState = void 0;
32362
- }
32363
33756
  if (state.promptCallEnded && state.deferCompletionUntilTurnEnd) {
32364
- await finalizePiPromptRun(state);
33757
+ finishPiPromptRun(state);
32365
33758
  }
32366
33759
  return;
32367
33760
  case "tool_execution_start":
@@ -32434,19 +33827,13 @@ function finishPiToolSpan(state, event) {
32434
33827
  }
32435
33828
  }
32436
33829
  }
32437
- async function finalizePiPromptRun(state, error) {
33830
+ function finishPiPromptRun(state, error) {
32438
33831
  if (state.finalized) {
32439
33832
  return;
32440
33833
  }
32441
33834
  state.finalized = true;
32442
33835
  state.onFinalize?.(state);
32443
- restorePiStreamFn(state);
32444
- try {
32445
- state.unsubscribeAgent?.();
32446
- } catch (unsubscribeError) {
32447
- logInstrumentationError4("Pi Coding Agent unsubscribe", unsubscribeError);
32448
- }
32449
- await finishOpenLlmSpans(state, error);
33836
+ finishOpenLlmSpans(state, error);
32450
33837
  finishOpenToolSpans(state, error);
32451
33838
  const metadata = {
32452
33839
  ...state.metadata,
@@ -32463,34 +33850,14 @@ async function finalizePiPromptRun(state, error) {
32463
33850
  output: state.output
32464
33851
  });
32465
33852
  } finally {
32466
- state.span.end();
32467
- }
32468
- }
32469
- function restorePiStreamFn(state) {
32470
- const patchState = state.streamPatchState;
32471
- patchState.activePromptStates.delete(state);
32472
- removeQueuedPromptState(state);
32473
- if (patchState.eventPromptState === state) {
32474
- patchState.eventPromptState = void 0;
32475
- }
32476
- state.restorePromptContext?.();
32477
- if (patchState.activePromptStates.size > 0) {
32478
- return;
32479
- }
32480
- if (patchState.agent.streamFn === patchState.wrappedStreamFn) {
32481
- patchState.agent.streamFn = patchState.originalStreamFn;
32482
- }
32483
- piStreamPatchStates.delete(patchState.agent);
32484
- }
32485
- function removeQueuedPromptState(state) {
32486
- state.queued = false;
32487
- const queuedPromptStates = state.streamPatchState.queuedPromptStates;
32488
- const index = queuedPromptStates.indexOf(state);
32489
- if (index >= 0) {
32490
- queuedPromptStates.splice(index, 1);
33853
+ try {
33854
+ state.span.end();
33855
+ } catch (endError) {
33856
+ logInstrumentationError4("Pi Coding Agent prompt end", endError);
33857
+ }
32491
33858
  }
32492
33859
  }
32493
- async function finishOpenLlmSpans(state, error) {
33860
+ function finishOpenLlmSpans(state, error) {
32494
33861
  for (const llmState of [...state.activeLlmSpans]) {
32495
33862
  finishPiLlmSpan(state, llmState, void 0, error);
32496
33863
  }
@@ -32571,7 +33938,7 @@ function normalizeAssistantMessage(message) {
32571
33938
  (part) => part.type === "thinking" && !part.redacted ? [part.thinking] : []
32572
33939
  ).join("");
32573
33940
  const toolCalls2 = message.content.flatMap(
32574
- (part) => part.type === "toolCall" ? [normalizeToolCall(part)] : []
33941
+ (part) => part.type === "toolCall" ? [normalizeToolCall2(part)] : []
32575
33942
  );
32576
33943
  return {
32577
33944
  role: "assistant",
@@ -32606,13 +33973,13 @@ function normalizeUserContent(content) {
32606
33973
  return part;
32607
33974
  });
32608
33975
  }
32609
- function normalizeToolCall(toolCall) {
33976
+ function normalizeToolCall2(toolCall) {
32610
33977
  return {
32611
33978
  id: toolCall.id,
32612
33979
  type: "function",
32613
33980
  function: {
32614
33981
  name: toolCall.name,
32615
- arguments: stringifyArguments(toolCall.arguments)
33982
+ arguments: stringifyArguments2(toolCall.arguments)
32616
33983
  }
32617
33984
  };
32618
33985
  }
@@ -32795,7 +34162,7 @@ function cleanMetrics5(metrics) {
32795
34162
  }
32796
34163
  return cleaned;
32797
34164
  }
32798
- function stringifyArguments(value) {
34165
+ function stringifyArguments2(value) {
32799
34166
  if (typeof value === "string") {
32800
34167
  return value;
32801
34168
  }
@@ -34386,6 +35753,7 @@ var BraintrustPlugin = class extends BasePlugin {
34386
35753
  anthropicPlugin = null;
34387
35754
  aiSDKPlugin = null;
34388
35755
  claudeAgentSDKPlugin = null;
35756
+ cloudflareThinkPlugin = null;
34389
35757
  cursorSDKPlugin = null;
34390
35758
  openAIAgentsPlugin = null;
34391
35759
  googleGenAIPlugin = null;
@@ -34394,6 +35762,7 @@ var BraintrustPlugin = class extends BasePlugin {
34394
35762
  openRouterPlugin = null;
34395
35763
  openRouterAgentPlugin = null;
34396
35764
  mistralPlugin = null;
35765
+ ollamaPlugin = null;
34397
35766
  googleADKPlugin = null;
34398
35767
  coherePlugin = null;
34399
35768
  groqPlugin = null;
@@ -34433,6 +35802,10 @@ var BraintrustPlugin = class extends BasePlugin {
34433
35802
  this.claudeAgentSDKPlugin = new ClaudeAgentSDKPlugin();
34434
35803
  this.claudeAgentSDKPlugin.enable();
34435
35804
  }
35805
+ if (integrations.cloudflareThink !== false) {
35806
+ this.cloudflareThinkPlugin = new CloudflareThinkPlugin();
35807
+ this.cloudflareThinkPlugin.enable();
35808
+ }
34436
35809
  if (integrations.cursorSDK !== false && integrations.cursor !== false) {
34437
35810
  this.cursorSDKPlugin = new CursorSDKPlugin();
34438
35811
  this.cursorSDKPlugin.enable();
@@ -34463,6 +35836,10 @@ var BraintrustPlugin = class extends BasePlugin {
34463
35836
  this.mistralPlugin = new MistralPlugin();
34464
35837
  this.mistralPlugin.enable();
34465
35838
  }
35839
+ if (integrations.ollama !== false) {
35840
+ this.ollamaPlugin = new OllamaPlugin();
35841
+ this.ollamaPlugin.enable();
35842
+ }
34466
35843
  if (integrations.googleADK !== false) {
34467
35844
  this.googleADKPlugin = new GoogleADKPlugin();
34468
35845
  this.googleADKPlugin.enable();
@@ -34539,6 +35916,10 @@ var BraintrustPlugin = class extends BasePlugin {
34539
35916
  this.claudeAgentSDKPlugin.disable();
34540
35917
  this.claudeAgentSDKPlugin = null;
34541
35918
  }
35919
+ if (this.cloudflareThinkPlugin) {
35920
+ this.cloudflareThinkPlugin.disable();
35921
+ this.cloudflareThinkPlugin = null;
35922
+ }
34542
35923
  if (this.cursorSDKPlugin) {
34543
35924
  this.cursorSDKPlugin.disable();
34544
35925
  this.cursorSDKPlugin = null;
@@ -34571,6 +35952,10 @@ var BraintrustPlugin = class extends BasePlugin {
34571
35952
  this.mistralPlugin.disable();
34572
35953
  this.mistralPlugin = null;
34573
35954
  }
35955
+ if (this.ollamaPlugin) {
35956
+ this.ollamaPlugin.disable();
35957
+ this.ollamaPlugin = null;
35958
+ }
34574
35959
  if (this.googleADKPlugin) {
34575
35960
  this.googleADKPlugin.disable();
34576
35961
  this.googleADKPlugin = null;
@@ -34656,6 +36041,7 @@ var envIntegrationAliases = {
34656
36041
  cloudflareaichat: "cloudflareAIChat",
34657
36042
  "cloudflare-ai-chat": "cloudflareAIChat",
34658
36043
  "@cloudflare/ai-chat": "cloudflareAIChat",
36044
+ cloudflarethink: "cloudflareThink",
34659
36045
  cursor: "cursor",
34660
36046
  "cursor-sdk": "cursorSDK",
34661
36047
  cursorsdk: "cursorSDK",
@@ -34676,6 +36062,7 @@ var envIntegrationAliases = {
34676
36062
  openrouteragent: "openrouterAgent",
34677
36063
  "openrouter-agent": "openrouterAgent",
34678
36064
  mistral: "mistral",
36065
+ ollama: "ollama",
34679
36066
  googleadk: "googleADK",
34680
36067
  "google-adk": "googleADK",
34681
36068
  cohere: "cohere",
@@ -34711,6 +36098,7 @@ function getDefaultInstrumentationIntegrations() {
34711
36098
  huggingface: true,
34712
36099
  claudeAgentSDK: true,
34713
36100
  cloudflareAIChat: true,
36101
+ cloudflareThink: true,
34714
36102
  cursor: true,
34715
36103
  cursorSDK: true,
34716
36104
  flue: true,
@@ -34719,6 +36107,7 @@ function getDefaultInstrumentationIntegrations() {
34719
36107
  openrouter: true,
34720
36108
  openrouterAgent: true,
34721
36109
  mistral: true,
36110
+ ollama: true,
34722
36111
  cohere: true,
34723
36112
  groq: true,
34724
36113
  bedrock: true,
@@ -34955,6 +36344,7 @@ __export(exports_exports, {
34955
36344
  braintrustFlueObserver: () => braintrustFlueObserver,
34956
36345
  braintrustStreamChunkSchema: () => braintrustStreamChunkSchema,
34957
36346
  buildLocalSummary: () => buildLocalSummary,
36347
+ collectAnthropicSession: () => collectAnthropicSession,
34958
36348
  configureInstrumentation: () => configureInstrumentation,
34959
36349
  constructLogs3OverflowRequest: () => constructLogs3OverflowRequest,
34960
36350
  createFinalValuePassThroughStream: () => createFinalValuePassThroughStream,
@@ -35034,6 +36424,7 @@ __export(exports_exports, {
35034
36424
  wrapClaudeAgentSDK: () => wrapClaudeAgentSDK,
35035
36425
  wrapCloudflareAIChat: () => wrapCloudflareAIChat,
35036
36426
  wrapCloudflareAgent: () => wrapCloudflareAgent,
36427
+ wrapCloudflareThink: () => wrapCloudflareThink,
35037
36428
  wrapCohere: () => wrapCohere,
35038
36429
  wrapCopilotClient: () => wrapCopilotClient,
35039
36430
  wrapCursorSDK: () => wrapCursorSDK,
@@ -35048,6 +36439,7 @@ __export(exports_exports, {
35048
36439
  wrapLangSmithTraceable: () => wrapLangSmithTraceable,
35049
36440
  wrapMastraAgent: () => wrapMastraAgent,
35050
36441
  wrapMistral: () => wrapMistral,
36442
+ wrapOllama: () => wrapOllama,
35051
36443
  wrapOpenAI: () => wrapOpenAI,
35052
36444
  wrapOpenAICodexSDK: () => wrapOpenAICodexSDK,
35053
36445
  wrapOpenAIv4: () => wrapOpenAIv4,
@@ -36322,7 +37714,7 @@ function normalizeUsageMetrics(usage, provider, providerMetadata) {
36322
37714
  }
36323
37715
  return metrics;
36324
37716
  }
36325
- function normalizeFinishReason(reason) {
37717
+ function normalizeFinishReason2(reason) {
36326
37718
  if (typeof reason !== "string") return void 0;
36327
37719
  return reason.replace(/-/g, "_");
36328
37720
  }
@@ -36331,7 +37723,7 @@ function buildAssistantOutputWithToolCalls(result, toolCalls2) {
36331
37723
  {
36332
37724
  index: 0,
36333
37725
  logprobs: null,
36334
- finish_reason: normalizeFinishReason(result?.finishReason) ?? (toolCalls2.length ? "tool_calls" : void 0),
37726
+ finish_reason: normalizeFinishReason2(result?.finishReason) ?? (toolCalls2.length ? "tool_calls" : void 0),
36335
37727
  message: {
36336
37728
  role: "assistant",
36337
37729
  tool_calls: toolCalls2.length > 0 ? toolCalls2 : void 0
@@ -38252,6 +39644,66 @@ function betaProxy(beta, anthropic) {
38252
39644
  if (prop === "messages") {
38253
39645
  return betaMessagesProxy(target.messages, anthropic);
38254
39646
  }
39647
+ if (prop === "sessions") {
39648
+ return target.sessions ? betaSessionsProxy(target.sessions) : target.sessions;
39649
+ }
39650
+ return Reflect.get(target, prop, receiver);
39651
+ }
39652
+ });
39653
+ }
39654
+ function betaSessionsProxy(sessions) {
39655
+ return new Proxy(sessions, {
39656
+ get(target, prop, receiver) {
39657
+ if (prop === "events") {
39658
+ return betaSessionEventsProxy(target.events);
39659
+ }
39660
+ if (prop === "threads") {
39661
+ return target.threads ? betaSessionThreadsProxy(target.threads) : target.threads;
39662
+ }
39663
+ return Reflect.get(target, prop, receiver);
39664
+ }
39665
+ });
39666
+ }
39667
+ function betaSessionEventsProxy(events) {
39668
+ return new Proxy(events, {
39669
+ get(target, prop, receiver) {
39670
+ if (prop === "stream") {
39671
+ return new TypedApplyProxy(target.stream, {
39672
+ apply(stream, thisArg, argArray) {
39673
+ return anthropicChannels.betaSessionsEventsStream.tracePromise(
39674
+ () => Reflect.apply(stream, thisArg, argArray),
39675
+ { arguments: argArray }
39676
+ );
39677
+ }
39678
+ });
39679
+ }
39680
+ return Reflect.get(target, prop, receiver);
39681
+ }
39682
+ });
39683
+ }
39684
+ function betaSessionThreadsProxy(threads) {
39685
+ return new Proxy(threads, {
39686
+ get(target, prop, receiver) {
39687
+ if (prop === "events") {
39688
+ return betaSessionThreadEventsProxy(target.events);
39689
+ }
39690
+ return Reflect.get(target, prop, receiver);
39691
+ }
39692
+ });
39693
+ }
39694
+ function betaSessionThreadEventsProxy(events) {
39695
+ return new Proxy(events, {
39696
+ get(target, prop, receiver) {
39697
+ if (prop === "stream") {
39698
+ return new TypedApplyProxy(target.stream, {
39699
+ apply(stream, thisArg, argArray) {
39700
+ return anthropicChannels.betaSessionsThreadsEventsStream.tracePromise(
39701
+ () => Reflect.apply(stream, thisArg, argArray),
39702
+ { arguments: argArray }
39703
+ );
39704
+ }
39705
+ });
39706
+ }
38255
39707
  return Reflect.get(target, prop, receiver);
38256
39708
  }
38257
39709
  });
@@ -38665,6 +40117,52 @@ function claudeAgentSDKProxy(sdk) {
38665
40117
  });
38666
40118
  }
38667
40119
 
40120
+ // src/wrappers/cloudflare-think.ts
40121
+ var WRAPPED_THINK = /* @__PURE__ */ Symbol.for("braintrust.cloudflare-think.wrapped");
40122
+ function wrapCloudflareThink(sdk) {
40123
+ if (!sdk || typeof sdk !== "object") {
40124
+ return sdk;
40125
+ }
40126
+ const thinkModule = sdk;
40127
+ if (typeof thinkModule.Think !== "function") {
40128
+ return sdk;
40129
+ }
40130
+ patchThinkClass(thinkModule.Think);
40131
+ return sdk;
40132
+ }
40133
+ function patchThinkClass(Think) {
40134
+ const prototype = Think.prototype;
40135
+ if (!prototype || prototype[WRAPPED_THINK]) {
40136
+ return;
40137
+ }
40138
+ const descriptor = Object.getOwnPropertyDescriptor(
40139
+ prototype,
40140
+ "_runInferenceLoop"
40141
+ );
40142
+ if (!descriptor || typeof descriptor.value !== "function") {
40143
+ return;
40144
+ }
40145
+ const original = descriptor.value;
40146
+ Object.defineProperty(prototype, "_runInferenceLoop", {
40147
+ ...descriptor,
40148
+ value: function wrappedCloudflareThinkRunInferenceLoop(input) {
40149
+ const args = [input];
40150
+ return cloudflareThinkChannels.runInferenceLoop.tracePromise(
40151
+ () => Reflect.apply(original, this, args),
40152
+ {
40153
+ arguments: args,
40154
+ self: this
40155
+ }
40156
+ );
40157
+ }
40158
+ });
40159
+ Object.defineProperty(prototype, WRAPPED_THINK, {
40160
+ configurable: false,
40161
+ enumerable: false,
40162
+ value: true
40163
+ });
40164
+ }
40165
+
38668
40166
  // src/wrappers/openai-codex.ts
38669
40167
  var WRAPPED_CLIENT = /* @__PURE__ */ Symbol.for("braintrust.openai-codex.wrapped-client");
38670
40168
  var WRAPPED_THREAD = /* @__PURE__ */ Symbol.for("braintrust.openai-codex.wrapped-thread");
@@ -38957,14 +40455,9 @@ function patchAgentSessionClass(AgentSession) {
38957
40455
  ...descriptor,
38958
40456
  value: function wrappedPiCodingAgentPrompt(text, options) {
38959
40457
  const args = [text, options];
38960
- return piCodingAgentChannels.prompt.tracePromise(
38961
- () => Reflect.apply(originalPrompt, this, args),
38962
- {
38963
- arguments: args,
38964
- self: this,
38965
- session: this
38966
- }
38967
- );
40458
+ return piCodingAgentChannels.prompt.invoke(originalPrompt, this, args, {
40459
+ session: this
40460
+ });
38968
40461
  }
38969
40462
  });
38970
40463
  Object.defineProperty(prototype, WRAPPED_PROMPT, {
@@ -40404,6 +41897,83 @@ function wrapAgentsStream(stream) {
40404
41897
  });
40405
41898
  }
40406
41899
 
41900
+ // src/wrappers/ollama.ts
41901
+ function wrapOllama(ollama) {
41902
+ if (isSupportedOllamaClient(ollama)) {
41903
+ return ollamaProxy(ollama);
41904
+ }
41905
+ debugLogger.warn("Unsupported Ollama library. Not wrapping.");
41906
+ return ollama;
41907
+ }
41908
+ var ollamaProxyCache = /* @__PURE__ */ new WeakMap();
41909
+ function isSupportedOllamaClient(value) {
41910
+ return isObject(value) && ["chat", "generate", "embed"].some(
41911
+ (name) => typeof value[name] === "function"
41912
+ );
41913
+ }
41914
+ function ollamaProxy(ollama) {
41915
+ const cached = ollamaProxyCache.get(ollama);
41916
+ if (cached) {
41917
+ return cached;
41918
+ }
41919
+ let chatSource;
41920
+ let wrappedChat;
41921
+ let generateSource;
41922
+ let wrappedGenerate;
41923
+ let embedSource;
41924
+ let wrappedEmbed;
41925
+ const proxy = new Proxy(ollama, {
41926
+ get(target, prop, receiver) {
41927
+ switch (prop) {
41928
+ case "chat": {
41929
+ const source = target.chat;
41930
+ if (source !== chatSource) {
41931
+ chatSource = source;
41932
+ wrappedChat = typeof source === "function" ? wrapChat(source.bind(target)) : source;
41933
+ }
41934
+ return wrappedChat;
41935
+ }
41936
+ case "generate": {
41937
+ const source = target.generate;
41938
+ if (source !== generateSource) {
41939
+ generateSource = source;
41940
+ wrappedGenerate = typeof source === "function" ? wrapGenerate2(source.bind(target)) : source;
41941
+ }
41942
+ return wrappedGenerate;
41943
+ }
41944
+ case "embed": {
41945
+ const source = target.embed;
41946
+ if (source !== embedSource) {
41947
+ embedSource = source;
41948
+ wrappedEmbed = typeof source === "function" ? wrapEmbed3(source.bind(target)) : source;
41949
+ }
41950
+ return wrappedEmbed;
41951
+ }
41952
+ default:
41953
+ return Reflect.get(target, prop, receiver);
41954
+ }
41955
+ }
41956
+ });
41957
+ ollamaProxyCache.set(ollama, proxy);
41958
+ ollamaProxyCache.set(proxy, proxy);
41959
+ return proxy;
41960
+ }
41961
+ function wrapChat(chat) {
41962
+ return (request) => ollamaChannels.chat.tracePromise(() => chat(request), {
41963
+ arguments: [request]
41964
+ });
41965
+ }
41966
+ function wrapGenerate2(generate) {
41967
+ return (request) => ollamaChannels.generate.tracePromise(() => generate(request), {
41968
+ arguments: [request]
41969
+ });
41970
+ }
41971
+ function wrapEmbed3(embed) {
41972
+ return (request) => ollamaChannels.embed.tracePromise(() => embed(request), {
41973
+ arguments: [request]
41974
+ });
41975
+ }
41976
+
40407
41977
  // src/wrappers/cohere.ts
40408
41978
  function wrapCohere(cohere) {
40409
41979
  if (isSupportedCohereClient(cohere)) {
@@ -40434,11 +42004,11 @@ function cohereProxy(cohere) {
40434
42004
  get(target, prop, receiver) {
40435
42005
  switch (prop) {
40436
42006
  case "chat":
40437
- return typeof target.chat === "function" ? wrapChat(target.chat.bind(target)) : target.chat;
42007
+ return typeof target.chat === "function" ? wrapChat2(target.chat.bind(target)) : target.chat;
40438
42008
  case "chatStream":
40439
42009
  return typeof target.chatStream === "function" ? wrapChatStream2(target.chatStream.bind(target)) : target.chatStream;
40440
42010
  case "embed":
40441
- return typeof target.embed === "function" ? wrapEmbed3(target.embed.bind(target)) : target.embed;
42011
+ return typeof target.embed === "function" ? wrapEmbed4(target.embed.bind(target)) : target.embed;
40442
42012
  case "rerank":
40443
42013
  return typeof target.rerank === "function" ? wrapRerank3(target.rerank.bind(target)) : target.rerank;
40444
42014
  default: {
@@ -40451,7 +42021,7 @@ function cohereProxy(cohere) {
40451
42021
  cohereProxyCache.set(cohere, proxy);
40452
42022
  return proxy;
40453
42023
  }
40454
- function wrapChat(chat) {
42024
+ function wrapChat2(chat) {
40455
42025
  return (request, options) => cohereChannels.chat.tracePromise(() => chat(request, options), {
40456
42026
  arguments: [request]
40457
42027
  });
@@ -40461,7 +42031,7 @@ function wrapChatStream2(chatStream) {
40461
42031
  arguments: [request]
40462
42032
  });
40463
42033
  }
40464
- function wrapEmbed3(embed) {
42034
+ function wrapEmbed4(embed) {
40465
42035
  return (request, options) => cohereChannels.embed.tracePromise(() => embed(request, options), {
40466
42036
  arguments: [request]
40467
42037
  });