braintrust 3.26.0 → 3.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dev/dist/index.js +2440 -1067
  2. package/dev/dist/index.mjs +1644 -271
  3. package/dist/apply-auto-instrumentation.js +320 -261
  4. package/dist/apply-auto-instrumentation.mjs +118 -59
  5. package/dist/auto-instrumentations/bundler/esbuild.cjs +377 -59
  6. package/dist/auto-instrumentations/bundler/esbuild.mjs +5 -4
  7. package/dist/auto-instrumentations/bundler/next.cjs +379 -61
  8. package/dist/auto-instrumentations/bundler/next.mjs +6 -5
  9. package/dist/auto-instrumentations/bundler/rollup.cjs +377 -59
  10. package/dist/auto-instrumentations/bundler/rollup.mjs +5 -4
  11. package/dist/auto-instrumentations/bundler/vite.cjs +406 -60
  12. package/dist/auto-instrumentations/bundler/vite.mjs +34 -5
  13. package/dist/auto-instrumentations/bundler/webpack-loader.cjs +363 -59
  14. package/dist/auto-instrumentations/bundler/webpack.cjs +377 -59
  15. package/dist/auto-instrumentations/bundler/webpack.mjs +6 -5
  16. package/dist/auto-instrumentations/{chunk-AKKPLXTP.mjs → chunk-2AMDGD65.mjs} +160 -57
  17. package/dist/auto-instrumentations/{chunk-V5LEODRX.mjs → chunk-BW33ULMW.mjs} +1 -1
  18. package/dist/auto-instrumentations/{chunk-XYN63IG5.mjs → chunk-I55G56ZL.mjs} +21 -58
  19. package/dist/auto-instrumentations/{chunk-NRE4QUQR.mjs → chunk-JPUFNW7X.mjs} +140 -0
  20. package/dist/auto-instrumentations/{chunk-6E22MYSW.mjs → chunk-XEYKUBLY.mjs} +30 -4
  21. package/dist/auto-instrumentations/{chunk-XZHHE4Y3.mjs → chunk-ZNHTSSGI.mjs} +155 -2
  22. package/dist/auto-instrumentations/hook.mjs +161 -3
  23. package/dist/auto-instrumentations/index.cjs +296 -1
  24. package/dist/auto-instrumentations/index.d.mts +5 -1
  25. package/dist/auto-instrumentations/index.d.ts +5 -1
  26. package/dist/auto-instrumentations/index.mjs +6 -2
  27. package/dist/auto-instrumentations/loader/cjs-patch.cjs +105 -57
  28. package/dist/auto-instrumentations/loader/cjs-patch.mjs +2 -2
  29. package/dist/auto-instrumentations/loader/esm-hook.mjs +1 -1
  30. package/dist/browser.d.mts +57 -5
  31. package/dist/browser.d.ts +57 -5
  32. package/dist/browser.js +1855 -285
  33. package/dist/browser.mjs +1855 -285
  34. package/dist/{chunk-PN7EWK66.mjs → chunk-CZM5JIQL.mjs} +209 -1
  35. package/dist/{chunk-VYNNEKSA.js → chunk-MF7NU6BT.js} +216 -8
  36. package/dist/{chunk-VRZZQPAA.js → chunk-QRHGVBKU.js} +2403 -1220
  37. package/dist/{chunk-XIZOM2HO.mjs → chunk-YKD22IMR.mjs} +1454 -271
  38. package/dist/cli.js +1645 -272
  39. package/dist/edge-light.d.mts +1 -1
  40. package/dist/edge-light.d.ts +1 -1
  41. package/dist/edge-light.js +1855 -285
  42. package/dist/edge-light.mjs +1855 -285
  43. package/dist/index.d.mts +57 -5
  44. package/dist/index.d.ts +57 -5
  45. package/dist/index.js +600 -413
  46. package/dist/index.mjs +201 -14
  47. package/dist/instrumentation/index.d.mts +8 -0
  48. package/dist/instrumentation/index.d.ts +8 -0
  49. package/dist/instrumentation/index.js +1839 -466
  50. package/dist/instrumentation/index.mjs +1839 -466
  51. package/dist/vitest-evals-reporter.js +45 -43
  52. package/dist/vitest-evals-reporter.mjs +5 -3
  53. package/dist/workerd.d.mts +1 -1
  54. package/dist/workerd.d.ts +1 -1
  55. package/dist/workerd.js +1855 -285
  56. package/dist/workerd.mjs +1855 -285
  57. package/package.json +1 -1
package/dist/workerd.mjs CHANGED
@@ -9,8 +9,10 @@ var GLOBAL_INSTRUMENTATION_HOOKS_KEY = "__braintrust_instrumentation_hooks";
9
9
  var GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION = 1;
10
10
  var GLOBAL_INSTRUMENTATION_HOOKS_REGISTRY_BRAND = "braintrust.global-instrumentation-hooks.registry";
11
11
  var GLOBAL_INSTRUMENTATION_HOOK_BRAND = "braintrust.global-instrumentation-hooks.hook";
12
+ var GLOBAL_INVOCATION_HOOK_BRAND = "braintrust.global-instrumentation-hooks.invocation-hook";
12
13
  var registryBrand = Symbol.for(GLOBAL_INSTRUMENTATION_HOOKS_REGISTRY_BRAND);
13
14
  var hookBrand = Symbol.for(GLOBAL_INSTRUMENTATION_HOOK_BRAND);
15
+ var invocationHookBrand = Symbol.for(GLOBAL_INVOCATION_HOOK_BRAND);
14
16
  var errorReporter;
15
17
  function setGlobalHookErrorReporter(reporter) {
16
18
  const previousReporter = errorReporter;
@@ -155,12 +157,69 @@ var traceEvents = [
155
157
  "asyncEnd",
156
158
  "error"
157
159
  ];
160
+ function traceInvocation(hook, operator, target, thisArg, args, additional, callbackIndex = -1) {
161
+ const context = {
162
+ ...additional,
163
+ arguments: args,
164
+ self: thisArg
165
+ };
166
+ const invoke2 = () => hook.invoke(target, thisArg, args, additional);
167
+ if (operator === "traceCallback") {
168
+ return hook.traceCallback(invoke2, callbackIndex, context);
169
+ }
170
+ if (operator === "tracePromise") {
171
+ return hook.tracePromise(invoke2, context);
172
+ }
173
+ return hook.traceSync(invoke2, context);
174
+ }
175
+ var InvocationHook = class {
176
+ interceptors = [];
177
+ get hasInterceptors() {
178
+ return this.interceptors.length > 0;
179
+ }
180
+ intercept(interceptor) {
181
+ if (typeof interceptor !== "function") {
182
+ throw new TypeError("interceptor must be a function");
183
+ }
184
+ this.interceptors = [...this.interceptors, interceptor];
185
+ let active = true;
186
+ return () => {
187
+ if (!active) {
188
+ return;
189
+ }
190
+ active = false;
191
+ const index = this.interceptors.indexOf(interceptor);
192
+ if (index !== -1) {
193
+ this.interceptors = [
194
+ ...this.interceptors.slice(0, index),
195
+ ...this.interceptors.slice(index + 1)
196
+ ];
197
+ }
198
+ };
199
+ }
200
+ invoke(target, thisArg, args, additional) {
201
+ const interceptors = this.interceptors;
202
+ if (interceptors.length === 0) {
203
+ return Reflect.apply(target, thisArg, args);
204
+ }
205
+ let next = target;
206
+ for (let index = interceptors.length - 1; index >= 0; index -= 1) {
207
+ const interceptor = interceptors[index];
208
+ const downstream = next;
209
+ next = function(...nextArgs) {
210
+ return interceptor(downstream, this, nextArgs, additional);
211
+ };
212
+ }
213
+ return Reflect.apply(next, thisArg, args);
214
+ }
215
+ };
158
216
  var TracingHook = class {
159
217
  start;
160
218
  end;
161
219
  asyncStart;
162
220
  asyncEnd;
163
221
  error;
222
+ invocationHook = new InvocationHook();
164
223
  constructor(nameOrChannels) {
165
224
  Object.defineProperty(this, hookBrand, {
166
225
  configurable: false,
@@ -168,6 +227,12 @@ var TracingHook = class {
168
227
  value: GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION,
169
228
  writable: false
170
229
  });
230
+ Object.defineProperty(this, invocationHookBrand, {
231
+ configurable: false,
232
+ enumerable: false,
233
+ value: GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION,
234
+ writable: false
235
+ });
171
236
  if (typeof nameOrChannels === "string") {
172
237
  this.start = new HookChannel(`tracing:${nameOrChannels}:start`);
173
238
  this.end = new HookChannel(`tracing:${nameOrChannels}:end`);
@@ -185,6 +250,26 @@ var TracingHook = class {
185
250
  get hasSubscribers() {
186
251
  return this.start.hasSubscribers || this.end.hasSubscribers || this.asyncStart.hasSubscribers || this.asyncEnd.hasSubscribers || this.error.hasSubscribers;
187
252
  }
253
+ get hasInterceptors() {
254
+ return this.invocationHook.hasInterceptors;
255
+ }
256
+ intercept(interceptor) {
257
+ return this.invocationHook.intercept(interceptor);
258
+ }
259
+ invoke(target, thisArg, args, additional) {
260
+ return this.invocationHook.invoke(target, thisArg, args, additional);
261
+ }
262
+ traceInvocation(operator, target, thisArg, args, additional, callbackIndex = -1) {
263
+ return traceInvocation(
264
+ this,
265
+ operator,
266
+ target,
267
+ thisArg,
268
+ args,
269
+ additional,
270
+ callbackIndex
271
+ );
272
+ }
188
273
  subscribe(handlers) {
189
274
  for (const eventName of traceEvents) {
190
275
  const handler = handlers[eventName];
@@ -406,6 +491,60 @@ function hasTracingHookShape(value) {
406
491
  return false;
407
492
  }
408
493
  }
494
+ function hasInvocationHookShape(value) {
495
+ if (typeof value !== "object" && typeof value !== "function" || value === null) {
496
+ return false;
497
+ }
498
+ try {
499
+ const hook = value;
500
+ return value[invocationHookBrand] === GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION && typeof hook.hasInterceptors === "boolean" && typeof hook.intercept === "function" && typeof hook.invoke === "function";
501
+ } catch {
502
+ return false;
503
+ }
504
+ }
505
+ function installInvocationHook(value) {
506
+ const hasInvocationHook = hasInvocationHookShape(value);
507
+ const invocationHook = new InvocationHook();
508
+ try {
509
+ if (!hasInvocationHook) {
510
+ Object.defineProperties(value, {
511
+ [invocationHookBrand]: {
512
+ configurable: false,
513
+ enumerable: false,
514
+ value: GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION,
515
+ writable: false
516
+ },
517
+ hasInterceptors: {
518
+ configurable: false,
519
+ enumerable: false,
520
+ get: () => invocationHook.hasInterceptors
521
+ },
522
+ intercept: {
523
+ configurable: false,
524
+ enumerable: false,
525
+ value: invocationHook.intercept.bind(invocationHook),
526
+ writable: false
527
+ },
528
+ invoke: {
529
+ configurable: false,
530
+ enumerable: false,
531
+ value: invocationHook.invoke.bind(invocationHook),
532
+ writable: false
533
+ }
534
+ });
535
+ }
536
+ if (typeof value.traceInvocation !== "function") {
537
+ Object.defineProperty(value, "traceInvocation", {
538
+ configurable: false,
539
+ enumerable: false,
540
+ value: traceInvocation.bind(void 0, value),
541
+ writable: false
542
+ });
543
+ }
544
+ } catch (error) {
545
+ reportError(error);
546
+ }
547
+ }
409
548
  function isCompatibleTracingHook(value) {
410
549
  try {
411
550
  return value[hookBrand] === GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION && hasTracingHookShape(value);
@@ -492,6 +631,7 @@ function newGlobalTracingChannel(nameOrChannels) {
492
631
  return inertTracingHook;
493
632
  }
494
633
  if (isCompatibleTracingHook(existing)) {
634
+ installInvocationHook(existing);
495
635
  return existing;
496
636
  }
497
637
  if (existing !== void 0) {
@@ -5329,6 +5469,7 @@ var INSTRUMENTATION_NAMES = {
5329
5469
  CLAUDE_AGENT_SDK: "claude-agent-sdk",
5330
5470
  CLOUDFLARE_AI_CHAT: "cloudflare-ai-chat",
5331
5471
  CLOUDFLARE_AGENTS: "cloudflare-agents",
5472
+ CLOUDFLARE_THINK: "cloudflare-think",
5332
5473
  COHERE: "cohere",
5333
5474
  CURSOR_SDK: "cursor-sdk",
5334
5475
  EVE: "eve",
@@ -5343,6 +5484,7 @@ var INSTRUMENTATION_NAMES = {
5343
5484
  LANGSMITH: "langsmith",
5344
5485
  MASTRA: "mastra",
5345
5486
  MISTRAL: "mistral",
5487
+ OLLAMA: "ollama",
5346
5488
  OPENAI: "openai",
5347
5489
  OPENAI_AGENTS: "openai-agents",
5348
5490
  OPENAI_CODEX: "openai-codex",
@@ -5354,7 +5496,7 @@ var INSTRUMENTATION_NAMES = {
5354
5496
  var INTERNAL_SPAN_INSTRUMENTATION_NAME = /* @__PURE__ */ Symbol.for(
5355
5497
  "braintrust.spanInstrumentationName"
5356
5498
  );
5357
- var SDK_VERSION = true ? "3.26.0" : "0.0.0";
5499
+ var SDK_VERSION = true ? "3.27.0" : "0.0.0";
5358
5500
  function withSpanInstrumentationName(args, instrumentationName) {
5359
5501
  return {
5360
5502
  ...args,
@@ -11527,6 +11669,34 @@ function patchStreamIfNeeded(stream, options) {
11527
11669
  );
11528
11670
  return stream;
11529
11671
  }
11672
+ const chunks = [];
11673
+ let completed = false;
11674
+ const notifyCancellation = async () => {
11675
+ try {
11676
+ await (options.onCancel ?? options.onComplete)(chunks);
11677
+ } catch (error) {
11678
+ debugLogger.error("Error in stream cancellation handler:", error);
11679
+ }
11680
+ };
11681
+ const patchAbortIfPresent = () => {
11682
+ try {
11683
+ if ("abort" in stream && typeof stream.abort === "function") {
11684
+ const originalAbort = stream.abort.bind(stream);
11685
+ stream.abort = (...args) => {
11686
+ try {
11687
+ return originalAbort(...args);
11688
+ } finally {
11689
+ if (!completed) {
11690
+ completed = true;
11691
+ void notifyCancellation();
11692
+ }
11693
+ }
11694
+ };
11695
+ }
11696
+ } catch (error) {
11697
+ debugLogger.warn("Failed to patch stream abort method:", error);
11698
+ }
11699
+ };
11530
11700
  if (hasAsyncIteratorMethods(stream) && isSelfAsyncIterator(stream)) {
11531
11701
  if ("__braintrust_patched_iterator_methods" in stream) {
11532
11702
  return stream;
@@ -11535,8 +11705,6 @@ function patchStreamIfNeeded(stream, options) {
11535
11705
  const originalNext = stream.next.bind(stream);
11536
11706
  const originalReturn = typeof stream.return === "function" ? stream.return.bind(stream) : null;
11537
11707
  const originalThrow = typeof stream.throw === "function" ? stream.throw.bind(stream) : null;
11538
- const chunks = [];
11539
- let completed = false;
11540
11708
  stream.next = async (...args) => {
11541
11709
  try {
11542
11710
  const result = await runNextWithWrapper(
@@ -11588,11 +11756,7 @@ function patchStreamIfNeeded(stream, options) {
11588
11756
  stream.return = async (...args) => {
11589
11757
  if (!completed) {
11590
11758
  completed = true;
11591
- try {
11592
- await options.onComplete(chunks);
11593
- } catch (error) {
11594
- console.error("Error in stream onComplete handler:", error);
11595
- }
11759
+ await notifyCancellation();
11596
11760
  }
11597
11761
  return originalReturn(...args);
11598
11762
  };
@@ -11617,6 +11781,7 @@ function patchStreamIfNeeded(stream, options) {
11617
11781
  Object.defineProperty(stream, "__braintrust_patched_iterator_methods", {
11618
11782
  value: true
11619
11783
  });
11784
+ patchAbortIfPresent();
11620
11785
  return stream;
11621
11786
  } catch (error) {
11622
11787
  console.warn("Failed to patch stream iterator methods:", error);
@@ -11630,8 +11795,6 @@ function patchStreamIfNeeded(stream, options) {
11630
11795
  const patchedIteratorFn = function() {
11631
11796
  const iterator = originalIteratorFn.call(this);
11632
11797
  const originalNext = iterator.next.bind(iterator);
11633
- const chunks = [];
11634
- let completed = false;
11635
11798
  iterator.next = async function(...args) {
11636
11799
  try {
11637
11800
  const result = await runNextWithWrapper(
@@ -11684,11 +11847,7 @@ function patchStreamIfNeeded(stream, options) {
11684
11847
  iterator.return = async function(...args) {
11685
11848
  if (!completed) {
11686
11849
  completed = true;
11687
- try {
11688
- await options.onComplete(chunks);
11689
- } catch (error) {
11690
- console.error("Error in stream onComplete handler:", error);
11691
- }
11850
+ await notifyCancellation();
11692
11851
  }
11693
11852
  return originalReturn(...args);
11694
11853
  };
@@ -11717,6 +11876,7 @@ function patchStreamIfNeeded(stream, options) {
11717
11876
  value: true
11718
11877
  });
11719
11878
  stream[Symbol.asyncIterator] = patchedIteratorFn;
11879
+ patchAbortIfPresent();
11720
11880
  return stream;
11721
11881
  } catch (error) {
11722
11882
  console.warn("Failed to patch stream:", error);
@@ -12465,6 +12625,33 @@ function traceStreamingChannel(channel2, config) {
12465
12625
  const { span, startTime } = spanData;
12466
12626
  if (isAsyncIterable(asyncEndEvent.result)) {
12467
12627
  let firstChunkTime;
12628
+ const handleStreamError = (error) => {
12629
+ try {
12630
+ span.log({ error });
12631
+ } catch (loggingError) {
12632
+ debugLogger.error(
12633
+ `Error logging failure for ${channelName}:`,
12634
+ loggingError
12635
+ );
12636
+ }
12637
+ try {
12638
+ span.end();
12639
+ } catch (endingError) {
12640
+ debugLogger.error(
12641
+ `Error ending span for ${channelName}:`,
12642
+ endingError
12643
+ );
12644
+ }
12645
+ states.delete(event);
12646
+ runStreamingErrorHook({
12647
+ channelName,
12648
+ config,
12649
+ error,
12650
+ event: asyncEndEvent,
12651
+ span,
12652
+ startTime
12653
+ });
12654
+ };
12468
12655
  patchStreamIfNeeded(asyncEndEvent.result, {
12469
12656
  onChunk: () => {
12470
12657
  if (firstChunkTime === void 0) {
@@ -12544,33 +12731,12 @@ function traceStreamingChannel(channel2, config) {
12544
12731
  });
12545
12732
  }
12546
12733
  },
12547
- onError: (error) => {
12548
- try {
12549
- span.log({ error });
12550
- } catch (loggingError) {
12551
- debugLogger.error(
12552
- `Error logging failure for ${channelName}:`,
12553
- loggingError
12554
- );
12555
- }
12556
- try {
12557
- span.end();
12558
- } catch (endingError) {
12559
- debugLogger.error(
12560
- `Error ending span for ${channelName}:`,
12561
- endingError
12562
- );
12563
- }
12564
- states.delete(event);
12565
- runStreamingErrorHook({
12566
- channelName,
12567
- config,
12568
- error,
12569
- event: asyncEndEvent,
12570
- span,
12571
- startTime
12572
- });
12573
- }
12734
+ onCancel: () => {
12735
+ const error = new Error("Stream cancelled before completion");
12736
+ error.name = "AbortError";
12737
+ handleStreamError(error);
12738
+ },
12739
+ onError: handleStreamError
12574
12740
  });
12575
12741
  return;
12576
12742
  }
@@ -12958,11 +13124,21 @@ function defineChannels(pkg, channels, options) {
12958
13124
  const tracingChannel2 = () => isomorph_default.newTracingChannel(
12959
13125
  fullChannelName
12960
13126
  );
13127
+ const intercept2 = (interceptor) => {
13128
+ const hook = tracingChannel2();
13129
+ return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
13130
+ };
13131
+ };
12961
13132
  return [
12962
13133
  key,
12963
13134
  {
12964
13135
  ...asyncSpec,
12965
13136
  instrumentationName,
13137
+ intercept: intercept2,
13138
+ invoke: (target, thisArg, args, additional) => {
13139
+ const hook = tracingChannel2();
13140
+ return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
13141
+ },
12966
13142
  tracingChannel: tracingChannel2,
12967
13143
  tracePromise: (fn, context) => tracingChannel2().tracePromise(
12968
13144
  fn,
@@ -12976,11 +13152,21 @@ function defineChannels(pkg, channels, options) {
12976
13152
  const tracingChannel = () => isomorph_default.newTracingChannel(
12977
13153
  fullChannelName
12978
13154
  );
13155
+ const intercept = (interceptor) => {
13156
+ const hook = tracingChannel();
13157
+ return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
13158
+ };
13159
+ };
12979
13160
  return [
12980
13161
  key,
12981
13162
  {
12982
13163
  ...syncSpec,
12983
13164
  instrumentationName,
13165
+ intercept,
13166
+ invoke: (target, thisArg, args, additional) => {
13167
+ const hook = tracingChannel();
13168
+ return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
13169
+ },
12984
13170
  tracingChannel,
12985
13171
  traceSync: (fn, context) => tracingChannel().traceSync(
12986
13172
  fn,
@@ -14231,6 +14417,25 @@ function extractAnthropicCacheTokens(cacheReadTokens = 0, cacheCreationTokens =
14231
14417
  return cacheTokens;
14232
14418
  }
14233
14419
 
14420
+ // src/wrappers/anthropic-session-collector.ts
14421
+ var sessionStreamCollectors = /* @__PURE__ */ new WeakMap();
14422
+ function registerAnthropicSessionStreamCollector(stream, collector) {
14423
+ sessionStreamCollectors.set(stream, collector);
14424
+ }
14425
+ function collectAnthropicSession(stream) {
14426
+ const collector = sessionStreamCollectors.get(stream);
14427
+ if (!collector) {
14428
+ return stream;
14429
+ }
14430
+ sessionStreamCollectors.delete(stream);
14431
+ try {
14432
+ collector();
14433
+ } catch (error) {
14434
+ debugLogger.error("Failed to collect Anthropic Sessions stream:", error);
14435
+ }
14436
+ return stream;
14437
+ }
14438
+
14234
14439
  // src/instrumentation/plugins/anthropic-channels.ts
14235
14440
  var anthropicChannels = defineChannels(
14236
14441
  "@anthropic-ai/sdk",
@@ -14246,6 +14451,14 @@ var anthropicChannels = defineChannels(
14246
14451
  betaMessagesToolRunner: channel({
14247
14452
  channelName: "beta.messages.toolRunner",
14248
14453
  kind: "sync-stream"
14454
+ }),
14455
+ betaSessionsEventsStream: channel({
14456
+ channelName: "beta.sessions.events.stream",
14457
+ kind: "async"
14458
+ }),
14459
+ betaSessionsThreadsEventsStream: channel({
14460
+ channelName: "beta.sessions.threads.events.stream",
14461
+ kind: "async"
14249
14462
  })
14250
14463
  },
14251
14464
  { instrumentationName: INSTRUMENTATION_NAMES.ANTHROPIC }
@@ -14259,6 +14472,7 @@ var AnthropicPlugin = class extends BasePlugin {
14259
14472
  onEnable() {
14260
14473
  this.subscribeToAnthropicChannels();
14261
14474
  this.subscribeToAnthropicToolRunner();
14475
+ this.subscribeToAnthropicSessionStreams();
14262
14476
  }
14263
14477
  onDisable() {
14264
14478
  this.unsubscribers = unsubscribeAll(this.unsubscribers);
@@ -14376,7 +14590,411 @@ var AnthropicPlugin = class extends BasePlugin {
14376
14590
  tracingChannel.unsubscribe(handlers);
14377
14591
  });
14378
14592
  }
14593
+ subscribeToAnthropicSessionStreams() {
14594
+ this.subscribeToAnthropicSessionStream(
14595
+ anthropicChannels.betaSessionsEventsStream,
14596
+ false
14597
+ );
14598
+ this.subscribeToAnthropicSessionStream(
14599
+ anthropicChannels.betaSessionsThreadsEventsStream,
14600
+ true
14601
+ );
14602
+ }
14603
+ subscribeToAnthropicSessionStream(channel2, isThread) {
14604
+ const tracingChannel = channel2.tracingChannel();
14605
+ const pending = /* @__PURE__ */ new WeakSet();
14606
+ const handlers = {
14607
+ start: (event) => {
14608
+ if (isAutoInstrumentationSuppressed()) {
14609
+ return;
14610
+ }
14611
+ pending.add(event);
14612
+ },
14613
+ asyncEnd: (event) => {
14614
+ if (!pending.delete(event)) {
14615
+ return;
14616
+ }
14617
+ const stream = event.result;
14618
+ if (!isAsyncIterable(stream)) {
14619
+ return;
14620
+ }
14621
+ registerAnthropicSessionStreamCollector(stream, () => {
14622
+ wrapAnthropicSessionEventStream(stream, isThread);
14623
+ });
14624
+ },
14625
+ error: (event) => {
14626
+ pending.delete(event);
14627
+ }
14628
+ };
14629
+ tracingChannel.subscribe(handlers);
14630
+ this.unsubscribers.push(() => tracingChannel.unsubscribe(handlers));
14631
+ }
14379
14632
  };
14633
+ function wrapAnthropicSessionEventStream(stream, isThread) {
14634
+ const state = {
14635
+ history: [],
14636
+ isThread,
14637
+ pendingInput: [],
14638
+ seenEventIds: /* @__PURE__ */ new Set()
14639
+ };
14640
+ patchStreamIfNeeded(stream, {
14641
+ onChunk: (event) => handleAnthropicSessionEvent(state, event),
14642
+ onComplete: () => finalizeAnthropicSessionTurn(state),
14643
+ onError: (error) => finalizeAnthropicSessionTurn(state, error)
14644
+ });
14645
+ return stream;
14646
+ }
14647
+ function handleAnthropicSessionEvent(state, event) {
14648
+ try {
14649
+ if (typeof event.id === "string" && event.type !== "event_delta" && state.seenEventIds.has(event.id)) {
14650
+ return;
14651
+ }
14652
+ if (typeof event.id === "string" && event.type !== "event_delta") {
14653
+ state.seenEventIds.add(event.id);
14654
+ }
14655
+ switch (event.type) {
14656
+ case "user.message":
14657
+ case "system.message":
14658
+ recordAnthropicSessionInput(
14659
+ state,
14660
+ event
14661
+ );
14662
+ break;
14663
+ case "session.status_running":
14664
+ if (!state.isThread) {
14665
+ ensureAnthropicSessionTurn(state);
14666
+ }
14667
+ break;
14668
+ case "session.thread_status_running":
14669
+ if (state.isThread) {
14670
+ ensureAnthropicSessionTurn(state);
14671
+ }
14672
+ break;
14673
+ case "span.model_request_start":
14674
+ if (typeof event.id === "string") {
14675
+ startAnthropicSessionModel(state, event.id);
14676
+ }
14677
+ break;
14678
+ case "event_delta":
14679
+ recordAnthropicSessionFirstToken(state, event);
14680
+ break;
14681
+ case "agent.message":
14682
+ recordAnthropicSessionMessage(
14683
+ state,
14684
+ event
14685
+ );
14686
+ break;
14687
+ case "agent.custom_tool_use":
14688
+ case "agent.mcp_tool_use":
14689
+ case "agent.tool_use":
14690
+ startAnthropicSessionTool(state, event);
14691
+ break;
14692
+ case "user.tool_confirmation":
14693
+ recordAnthropicSessionToolConfirmation(state, event);
14694
+ break;
14695
+ case "agent.mcp_tool_result":
14696
+ case "agent.tool_result":
14697
+ case "user.custom_tool_result":
14698
+ case "user.tool_result":
14699
+ finalizeAnthropicSessionTool(
14700
+ state,
14701
+ event
14702
+ );
14703
+ break;
14704
+ case "span.model_request_end":
14705
+ finalizeAnthropicSessionModel(
14706
+ state,
14707
+ event
14708
+ );
14709
+ break;
14710
+ case "session.status_idle":
14711
+ case "session.thread_status_idle": {
14712
+ if (event.type === "session.status_idle" && state.isThread || event.type === "session.thread_status_idle" && !state.isThread) {
14713
+ break;
14714
+ }
14715
+ const stopReason = isObject(event.stop_reason) ? event.stop_reason.type : void 0;
14716
+ if (stopReason === "end_turn") {
14717
+ finalizeAnthropicSessionTurn(state);
14718
+ } else if (stopReason === "retries_exhausted") {
14719
+ finalizeAnthropicSessionTurn(
14720
+ state,
14721
+ "Anthropic session retries exhausted"
14722
+ );
14723
+ }
14724
+ break;
14725
+ }
14726
+ case "session.error":
14727
+ finalizeAnthropicSessionTurn(state, event.error);
14728
+ break;
14729
+ case "session.deleted":
14730
+ case "session.status_terminated":
14731
+ case "session.thread_status_terminated":
14732
+ if (event.type === "session.deleted" || event.type === "session.status_terminated" && !state.isThread || event.type === "session.thread_status_terminated" && state.isThread) {
14733
+ finalizeAnthropicSessionTurn(state);
14734
+ }
14735
+ break;
14736
+ default:
14737
+ break;
14738
+ }
14739
+ } catch (error) {
14740
+ debugLogger.debug("Error processing Anthropic Sessions event:", error);
14741
+ }
14742
+ }
14743
+ function ensureAnthropicSessionTurn(state) {
14744
+ if (state.activeTurn) {
14745
+ return state.activeTurn;
14746
+ }
14747
+ const input = state.pendingInput;
14748
+ state.pendingInput = [];
14749
+ const span = startSpan(
14750
+ withSpanInstrumentationName(
14751
+ {
14752
+ event: {
14753
+ ...input.length > 0 ? { input } : {},
14754
+ metadata: { provider: "anthropic" }
14755
+ },
14756
+ name: state.isThread ? "anthropic.beta.sessions.thread.turn" : "anthropic.beta.sessions.turn",
14757
+ spanAttributes: { type: "task" /* TASK */ }
14758
+ },
14759
+ INSTRUMENTATION_NAMES.ANTHROPIC
14760
+ )
14761
+ );
14762
+ state.activeTurn = {
14763
+ activeTools: /* @__PURE__ */ new Map(),
14764
+ input: input.slice(),
14765
+ metrics: {},
14766
+ span
14767
+ };
14768
+ return state.activeTurn;
14769
+ }
14770
+ function recordAnthropicSessionInput(state, event) {
14771
+ const content = processAttachmentsInInput(event.content);
14772
+ const message = {
14773
+ role: event.type === "system.message" ? "system" : "user",
14774
+ content
14775
+ };
14776
+ state.history.push(message);
14777
+ if (state.activeTurn) {
14778
+ state.activeTurn.input.push(message);
14779
+ } else {
14780
+ state.pendingInput.push(message);
14781
+ }
14782
+ }
14783
+ function startAnthropicSessionModel(state, startEventId) {
14784
+ const turn = ensureAnthropicSessionTurn(state);
14785
+ if (turn.activeModel) {
14786
+ finalizeAnthropicSessionModelState(state, turn);
14787
+ }
14788
+ const span = withCurrent(
14789
+ turn.span,
14790
+ () => startSpan(
14791
+ withSpanInstrumentationName(
14792
+ {
14793
+ event: {
14794
+ ...state.history.length > 0 ? { input: state.history.slice() } : {},
14795
+ metadata: { provider: "anthropic" }
14796
+ },
14797
+ name: "anthropic.messages.create",
14798
+ spanAttributes: { type: "llm" /* LLM */ }
14799
+ },
14800
+ INSTRUMENTATION_NAMES.ANTHROPIC
14801
+ )
14802
+ )
14803
+ );
14804
+ turn.activeModel = {
14805
+ output: [],
14806
+ span,
14807
+ startEventId,
14808
+ startTime: getCurrentUnixTimestamp()
14809
+ };
14810
+ }
14811
+ function recordAnthropicSessionFirstToken(state, event) {
14812
+ const model = state.activeTurn?.activeModel;
14813
+ if (!model || model.firstTokenTime !== void 0 || !isObject(event.delta) || !isObject(event.delta.content) || typeof event.delta.content.text !== "string") {
14814
+ return;
14815
+ }
14816
+ model.firstTokenTime = getCurrentUnixTimestamp();
14817
+ }
14818
+ function recordAnthropicSessionMessage(state, event) {
14819
+ const turn = ensureAnthropicSessionTurn(state);
14820
+ const content = processAttachmentsInInput(
14821
+ event.content
14822
+ );
14823
+ if (turn.activeModel) {
14824
+ turn.activeModel.output.push(...content);
14825
+ } else {
14826
+ const output = { role: "assistant", content };
14827
+ turn.lastOutput = output;
14828
+ state.history.push(output);
14829
+ }
14830
+ }
14831
+ function startAnthropicSessionTool(state, event) {
14832
+ const turn = ensureAnthropicSessionTurn(state);
14833
+ if (turn.activeModel) {
14834
+ turn.activeModel.output.push({
14835
+ type: "tool_use",
14836
+ id: event.id,
14837
+ name: event.name,
14838
+ input: event.input
14839
+ });
14840
+ }
14841
+ const existing = turn.activeTools.get(event.id);
14842
+ if (existing) {
14843
+ existing.span.end();
14844
+ turn.activeTools.delete(event.id);
14845
+ }
14846
+ const span = withCurrent(
14847
+ turn.span,
14848
+ () => startSpan(
14849
+ withSpanInstrumentationName(
14850
+ {
14851
+ event: { input: event.input },
14852
+ name: event.name,
14853
+ spanAttributes: { type: "tool" /* TOOL */ }
14854
+ },
14855
+ INSTRUMENTATION_NAMES.ANTHROPIC
14856
+ )
14857
+ )
14858
+ );
14859
+ const toolState = {
14860
+ approval: event.evaluated_permission === "allow" ? "approved" : event.evaluated_permission === "deny" ? "denied" : void 0,
14861
+ span
14862
+ };
14863
+ turn.activeTools.set(event.id, toolState);
14864
+ if (toolState.approval === "denied") {
14865
+ finalizeAnthropicSessionToolState(toolState);
14866
+ turn.activeTools.delete(event.id);
14867
+ }
14868
+ }
14869
+ function recordAnthropicSessionToolConfirmation(state, event) {
14870
+ if (typeof event.tool_use_id !== "string" || event.result !== "allow" && event.result !== "deny") {
14871
+ return;
14872
+ }
14873
+ const turn = state.activeTurn;
14874
+ const tool = turn?.activeTools.get(event.tool_use_id);
14875
+ if (!turn || !tool) {
14876
+ return;
14877
+ }
14878
+ tool.approval = event.result === "allow" ? "approved" : "denied";
14879
+ if (tool.approval === "denied") {
14880
+ finalizeAnthropicSessionToolState(tool);
14881
+ turn.activeTools.delete(event.tool_use_id);
14882
+ }
14883
+ }
14884
+ function finalizeAnthropicSessionTool(state, event) {
14885
+ const toolUseId = event.tool_use_id ?? event.mcp_tool_use_id ?? event.custom_tool_use_id;
14886
+ if (!toolUseId) {
14887
+ return;
14888
+ }
14889
+ const content = processAttachmentsInInput(event.content);
14890
+ const turn = state.activeTurn;
14891
+ const tool = turn?.activeTools.get(toolUseId);
14892
+ if (turn && tool) {
14893
+ finalizeAnthropicSessionToolState(tool, event, content);
14894
+ turn.activeTools.delete(toolUseId);
14895
+ }
14896
+ const toolResult = {
14897
+ type: "tool_result",
14898
+ tool_use_id: toolUseId,
14899
+ ...content !== void 0 ? { content } : {},
14900
+ ...event.is_error === true ? { is_error: true } : {}
14901
+ };
14902
+ state.history.push({
14903
+ role: "user",
14904
+ content: [toolResult]
14905
+ });
14906
+ }
14907
+ function finalizeAnthropicSessionToolState(state, event, content = event?.content) {
14908
+ safeAnthropicSessionLog(state.span, {
14909
+ ...event?.is_error === true ? {
14910
+ error: content ?? "Anthropic session tool execution failed"
14911
+ } : {},
14912
+ ...state.approval ? { metadata: { tool_approval: state.approval } } : {},
14913
+ ...content !== void 0 ? { output: content } : {}
14914
+ });
14915
+ state.span.end();
14916
+ }
14917
+ function finalizeAnthropicSessionModel(state, event) {
14918
+ const turn = state.activeTurn;
14919
+ const model = turn?.activeModel;
14920
+ if (!turn || !model || model.startEventId !== event.model_request_start_id) {
14921
+ return;
14922
+ }
14923
+ finalizeAnthropicSessionModelState(state, turn, event);
14924
+ }
14925
+ function finalizeAnthropicSessionModelState(state, turn, event) {
14926
+ const model = turn.activeModel;
14927
+ if (!model) {
14928
+ return;
14929
+ }
14930
+ turn.activeModel = void 0;
14931
+ const metrics = event ? parseAnthropicSessionModelUsage(event.model_usage) : {};
14932
+ if (model.firstTokenTime !== void 0) {
14933
+ metrics.time_to_first_token = model.firstTokenTime - model.startTime;
14934
+ }
14935
+ const output = model.output.length > 0 ? { role: "assistant", content: model.output } : void 0;
14936
+ safeAnthropicSessionLog(model.span, {
14937
+ ...event?.is_error ? { error: "Anthropic session model request failed" } : {},
14938
+ ...Object.keys(metrics).length > 0 ? { metrics } : {},
14939
+ ...output ? { output } : {}
14940
+ });
14941
+ model.span.end();
14942
+ if (output) {
14943
+ turn.lastOutput = output;
14944
+ state.history.push(output);
14945
+ }
14946
+ for (const key of [
14947
+ "prompt_tokens",
14948
+ "completion_tokens",
14949
+ "tokens",
14950
+ "prompt_cached_tokens",
14951
+ "prompt_cache_creation_tokens"
14952
+ ]) {
14953
+ const value = metrics[key];
14954
+ if (typeof value === "number") {
14955
+ turn.metrics[key] = (turn.metrics[key] ?? 0) + value;
14956
+ }
14957
+ }
14958
+ }
14959
+ function parseAnthropicSessionModelUsage(usage) {
14960
+ const finalized = finalizeAnthropicTokens({
14961
+ completion_tokens: usage.output_tokens,
14962
+ prompt_cache_creation_tokens: usage.cache_creation_input_tokens,
14963
+ prompt_cached_tokens: usage.cache_read_input_tokens,
14964
+ prompt_tokens: usage.input_tokens
14965
+ });
14966
+ return Object.fromEntries(
14967
+ Object.entries(finalized).filter(
14968
+ (entry) => entry[1] !== void 0
14969
+ )
14970
+ );
14971
+ }
14972
+ function finalizeAnthropicSessionTurn(state, error) {
14973
+ const turn = state.activeTurn;
14974
+ if (!turn) {
14975
+ return;
14976
+ }
14977
+ state.activeTurn = void 0;
14978
+ finalizeAnthropicSessionModelState(state, turn);
14979
+ for (const tool of turn.activeTools.values()) {
14980
+ finalizeAnthropicSessionToolState(tool);
14981
+ }
14982
+ turn.activeTools.clear();
14983
+ safeAnthropicSessionLog(turn.span, {
14984
+ ...error !== void 0 ? { error: error instanceof Error ? error : toLoggedError(error) } : {},
14985
+ ...turn.input.length > 0 ? { input: turn.input } : {},
14986
+ ...turn.lastOutput ? { output: turn.lastOutput } : {},
14987
+ ...Object.keys(turn.metrics).length > 0 ? { metrics: turn.metrics } : {}
14988
+ });
14989
+ turn.span.end();
14990
+ }
14991
+ function safeAnthropicSessionLog(span, event) {
14992
+ try {
14993
+ span.log(event);
14994
+ } catch (error) {
14995
+ debugLogger.debug("Error logging Anthropic Sessions span:", error);
14996
+ }
14997
+ }
14380
14998
  function parseMetricsFromUsage2(usage) {
14381
14999
  if (!usage) {
14382
15000
  return {};
@@ -16250,6 +16868,29 @@ var harnessAgentChannels = defineChannels(
16250
16868
  { instrumentationName: INSTRUMENTATION_NAMES.AI_SDK }
16251
16869
  );
16252
16870
 
16871
+ // src/instrumentation/plugins/cloudflare-think-context.ts
16872
+ var cloudflareThinkSpans = /* @__PURE__ */ new Map();
16873
+ function registerCloudflareThinkSpan(span) {
16874
+ if (span.spanId) {
16875
+ cloudflareThinkSpans.set(span.spanId, span);
16876
+ }
16877
+ }
16878
+ function unregisterCloudflareThinkSpan(span) {
16879
+ if (span.spanId) {
16880
+ cloudflareThinkSpans.delete(span.spanId);
16881
+ }
16882
+ }
16883
+ function currentCloudflareThinkSpan() {
16884
+ const parentSpanIds = _internalGetGlobalState()?.contextManager.getParentSpanIds()?.spanParents ?? [];
16885
+ for (const parentSpanId of parentSpanIds) {
16886
+ const span = cloudflareThinkSpans.get(parentSpanId);
16887
+ if (span) {
16888
+ return span;
16889
+ }
16890
+ }
16891
+ return void 0;
16892
+ }
16893
+
16253
16894
  // src/instrumentation/plugins/ai-sdk-plugin.ts
16254
16895
  var DEFAULT_DENY_OUTPUT_PATHS = [
16255
16896
  // v3
@@ -16356,6 +16997,7 @@ var AISDKPlugin = class extends BasePlugin {
16356
16997
  traceStreamingChannel(aiSDKChannels.streamText, {
16357
16998
  name: "streamText",
16358
16999
  type: "function" /* FUNCTION */,
17000
+ shouldTrace: () => currentCloudflareThinkSpan() === void 0,
16359
17001
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
16360
17002
  extractOutput: (result, endEvent) => processAISDKOutput(
16361
17003
  result,
@@ -16376,6 +17018,7 @@ var AISDKPlugin = class extends BasePlugin {
16376
17018
  traceSyncStreamChannel(aiSDKChannels.streamTextSync, {
16377
17019
  name: "streamText",
16378
17020
  type: "function" /* FUNCTION */,
17021
+ shouldTrace: () => currentCloudflareThinkSpan() === void 0,
16379
17022
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
16380
17023
  patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
16381
17024
  defaultDenyOutputPaths: denyOutputPaths,
@@ -17361,6 +18004,23 @@ function prepareAISDKWorkflowAgentStreamInput(params, event, span, defaultDenyOu
17361
18004
  metadata
17362
18005
  };
17363
18006
  }
18007
+ function prepareAISDKAgentCallInput(params, event, span, defaultDenyOutputPaths = DEFAULT_DENY_OUTPUT_PATHS) {
18008
+ const { input } = processAISDKWorkflowAgentCallInput(params);
18009
+ const metadata = extractMetadataFromCallParams(params, event.self);
18010
+ const childTracing = prepareAISDKChildTracing(
18011
+ params,
18012
+ event.self,
18013
+ span,
18014
+ defaultDenyOutputPaths,
18015
+ event.aiSDK,
18016
+ { agentOwner: true }
18017
+ );
18018
+ event.modelWrapped = childTracing.modelWrapped;
18019
+ if (childTracing.cleanup) {
18020
+ event.__braintrust_ai_sdk_cleanup = childTracing.cleanup;
18021
+ }
18022
+ return { input, metadata };
18023
+ }
17364
18024
  function prepareAISDKEmbedInput(params, self) {
17365
18025
  return {
17366
18026
  input: { ...params },
@@ -17384,6 +18044,18 @@ function extractTopLevelAISDKMetrics(result, event, startTime) {
17384
18044
  }
17385
18045
  return metrics;
17386
18046
  }
18047
+ async function extractResolvedAISDKTokenMetrics(result) {
18048
+ for (const field of ["totalUsage", "usage"]) {
18049
+ try {
18050
+ const usage = await Promise.resolve(result[field]);
18051
+ if (usage !== void 0) {
18052
+ return extractTokenMetrics({ [field]: usage });
18053
+ }
18054
+ } catch {
18055
+ }
18056
+ }
18057
+ return extractTokenMetrics(result);
18058
+ }
17387
18059
  function hasModelChildTracing(event) {
17388
18060
  return event?.modelWrapped === true || event?.__braintrust_ai_sdk_model_wrapped === true;
17389
18061
  }
@@ -18201,13 +18873,15 @@ function patchAISDKStreamingResult(args) {
18201
18873
  const {
18202
18874
  defaultDenyOutputPaths,
18203
18875
  endEvent,
18876
+ forceTopLevelMetrics,
18204
18877
  onComplete,
18205
18878
  onCancel,
18206
18879
  onError,
18207
18880
  result,
18208
18881
  resolvePromiseUsage,
18209
18882
  span,
18210
- startTime
18883
+ startTime,
18884
+ transformOutput
18211
18885
  } = args;
18212
18886
  if (!result || typeof result !== "object") {
18213
18887
  return false;
@@ -18260,8 +18934,8 @@ function patchAISDKStreamingResult(args) {
18260
18934
  }
18261
18935
  outputLogged = true;
18262
18936
  try {
18263
- const metrics = extractTopLevelAISDKMetrics(result, endEvent);
18264
- if (resolvePromiseUsage) {
18937
+ const metrics = forceTopLevelMetrics ? await extractResolvedAISDKTokenMetrics(result) : extractTopLevelAISDKMetrics(result, endEvent);
18938
+ if (resolvePromiseUsage && !forceTopLevelMetrics) {
18265
18939
  try {
18266
18940
  const resultRecord2 = result;
18267
18941
  const pendingUsage = resultRecord2.totalUsage ?? resultRecord2.usage;
@@ -18280,10 +18954,11 @@ function patchAISDKStreamingResult(args) {
18280
18954
  if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
18281
18955
  metrics.time_to_first_token = firstChunkTime - startTime;
18282
18956
  }
18283
- const output = await processAISDKStreamingOutput(
18957
+ const processedOutput = await processAISDKStreamingOutput(
18284
18958
  result,
18285
18959
  resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
18286
18960
  );
18961
+ const output = transformOutput ? transformOutput(processedOutput) : processedOutput;
18287
18962
  const metadata = buildResolvedMetadataPayload(result).metadata;
18288
18963
  try {
18289
18964
  span.log({
@@ -20705,6 +21380,295 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
20705
21380
  }
20706
21381
  };
20707
21382
 
21383
+ // src/instrumentation/plugins/cloudflare-think-channels.ts
21384
+ var cloudflareThinkChannels = defineChannels(
21385
+ "@cloudflare/think",
21386
+ {
21387
+ runInferenceLoop: channel({
21388
+ channelName: "Think.runInferenceLoop",
21389
+ kind: "async"
21390
+ })
21391
+ },
21392
+ { instrumentationName: INSTRUMENTATION_NAMES.CLOUDFLARE_THINK }
21393
+ );
21394
+
21395
+ // src/instrumentation/plugins/cloudflare-think-plugin.ts
21396
+ var THINK_STATE_ID = /* @__PURE__ */ Symbol.for("braintrust.cloudflare-think.state-id");
21397
+ var CloudflareThinkPlugin = class extends BasePlugin {
21398
+ statesBySpanId = /* @__PURE__ */ new Map();
21399
+ onEnable() {
21400
+ this.subscribeToThinkRuns();
21401
+ this.subscribeToAISDKStreamTextSync();
21402
+ this.subscribeToAISDKStreamTextAsync();
21403
+ }
21404
+ onDisable() {
21405
+ for (const unsubscribe of this.unsubscribers) {
21406
+ unsubscribe();
21407
+ }
21408
+ this.unsubscribers = [];
21409
+ for (const state of this.statesBySpanId.values()) {
21410
+ this.finishState(state);
21411
+ }
21412
+ this.statesBySpanId.clear();
21413
+ }
21414
+ subscribeToThinkRuns() {
21415
+ const channel2 = cloudflareThinkChannels.runInferenceLoop.tracingChannel();
21416
+ const states = /* @__PURE__ */ new WeakMap();
21417
+ const state = _internalGetGlobalState();
21418
+ const contextManager = state?.contextManager;
21419
+ const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
21420
+ const ensureState2 = (event) => {
21421
+ if (isAutoInstrumentationSuppressed()) {
21422
+ return void 0;
21423
+ }
21424
+ const existing = states.get(event);
21425
+ if (existing) {
21426
+ return existing;
21427
+ }
21428
+ const span = startSpan(
21429
+ withSpanInstrumentationName(
21430
+ {
21431
+ name: "Think.runTurn",
21432
+ spanAttributes: { type: "task" /* TASK */ }
21433
+ },
21434
+ INSTRUMENTATION_NAMES.CLOUDFLARE_THINK
21435
+ )
21436
+ );
21437
+ const runState = {
21438
+ aiResultPatched: false,
21439
+ fallbackInput: extractFallbackInput(event.self?.messages),
21440
+ finalized: false,
21441
+ inputLogged: false,
21442
+ span,
21443
+ startTime: getCurrentUnixTimestamp()
21444
+ };
21445
+ const metadata = {
21446
+ braintrust: {
21447
+ integration_name: "cloudflare-think",
21448
+ sdk_language: "typescript"
21449
+ }
21450
+ };
21451
+ if (typeof event.moduleVersion === "string") {
21452
+ metadata["cloudflare_think.version"] = event.moduleVersion;
21453
+ }
21454
+ span.log({ metadata });
21455
+ states.set(event, runState);
21456
+ if (span.spanId) {
21457
+ this.statesBySpanId.set(span.spanId, runState);
21458
+ }
21459
+ registerCloudflareThinkSpan(span);
21460
+ return runState;
21461
+ };
21462
+ if (contextManager && currentSpanStore && channel2.start) {
21463
+ channel2.start.bindStore(currentSpanStore, (event) => {
21464
+ const runState = ensureState2(event);
21465
+ return runState ? contextManager.wrapSpanForStore(runState.span) : currentSpanStore.getStore();
21466
+ });
21467
+ this.unsubscribers.push(
21468
+ () => channel2.start?.unbindStore(currentSpanStore)
21469
+ );
21470
+ }
21471
+ const handlers = {
21472
+ start: (event) => {
21473
+ ensureState2(event);
21474
+ },
21475
+ asyncEnd: (event) => {
21476
+ const runState = states.get(event);
21477
+ states.delete(event);
21478
+ if (!runState || runState.finalized || runState.aiResultPatched) {
21479
+ return;
21480
+ }
21481
+ this.finishState(runState, void 0, event.result);
21482
+ },
21483
+ error: (event) => {
21484
+ const runState = states.get(event);
21485
+ states.delete(event);
21486
+ if (runState) {
21487
+ this.finishState(runState, event.error);
21488
+ }
21489
+ }
21490
+ };
21491
+ channel2.subscribe(handlers);
21492
+ this.unsubscribers.push(() => channel2.unsubscribe(handlers));
21493
+ }
21494
+ subscribeToAISDKStreamTextSync() {
21495
+ const channel2 = aiSDKChannels.streamTextSync.tracingChannel();
21496
+ const handlers = {
21497
+ start: (event) => {
21498
+ this.startAISDKStream(event);
21499
+ },
21500
+ end: (event) => {
21501
+ this.endAISDKStream(event);
21502
+ },
21503
+ error: (event) => {
21504
+ this.errorAISDKStream(event);
21505
+ }
21506
+ };
21507
+ channel2.subscribe(handlers);
21508
+ this.unsubscribers.push(() => channel2.unsubscribe(handlers));
21509
+ }
21510
+ subscribeToAISDKStreamTextAsync() {
21511
+ const channel2 = aiSDKChannels.streamText.tracingChannel();
21512
+ const handlers = {
21513
+ start: (event) => {
21514
+ this.startAISDKStream(event);
21515
+ },
21516
+ asyncEnd: (event) => {
21517
+ this.endAISDKStream(event);
21518
+ },
21519
+ error: (event) => {
21520
+ this.errorAISDKStream(event);
21521
+ }
21522
+ };
21523
+ channel2.subscribe(handlers);
21524
+ this.unsubscribers.push(() => channel2.unsubscribe(handlers));
21525
+ }
21526
+ startAISDKStream(event) {
21527
+ const runState = this.currentState();
21528
+ if (!runState || runState.finalized) {
21529
+ return;
21530
+ }
21531
+ try {
21532
+ const prepared = prepareAISDKAgentCallInput(
21533
+ event.arguments[0],
21534
+ event,
21535
+ runState.span
21536
+ );
21537
+ runState.span.log({
21538
+ input: extractThinkTaskInput(prepared.input),
21539
+ metadata: {
21540
+ ...prepared.metadata,
21541
+ braintrust: {
21542
+ integration_name: "cloudflare-think",
21543
+ sdk_language: "typescript"
21544
+ }
21545
+ }
21546
+ });
21547
+ runState.inputLogged = true;
21548
+ runState.aiEvent = event;
21549
+ Reflect.set(event, THINK_STATE_ID, runState.span.spanId);
21550
+ } catch (error) {
21551
+ debugLogger.error(
21552
+ "Error preparing @cloudflare/think AI SDK tracing:",
21553
+ error
21554
+ );
21555
+ }
21556
+ }
21557
+ endAISDKStream(event) {
21558
+ const runState = this.stateForAISDKEvent(event);
21559
+ if (!runState || runState.finalized) {
21560
+ return;
21561
+ }
21562
+ const patched = patchAISDKStreamingResult({
21563
+ defaultDenyOutputPaths: DEFAULT_DENY_OUTPUT_PATHS,
21564
+ endEvent: event,
21565
+ forceTopLevelMetrics: true,
21566
+ onComplete: () => this.releaseState(runState),
21567
+ result: event.result,
21568
+ span: runState.span,
21569
+ startTime: runState.startTime,
21570
+ transformOutput: extractThinkTaskOutput
21571
+ });
21572
+ runState.aiResultPatched = patched;
21573
+ if (!patched) {
21574
+ this.finishState(runState, void 0, event.result);
21575
+ }
21576
+ }
21577
+ errorAISDKStream(event) {
21578
+ const runState = this.stateForAISDKEvent(event);
21579
+ if (runState) {
21580
+ this.finishState(runState, event.error);
21581
+ }
21582
+ }
21583
+ currentState() {
21584
+ const parentIds = _internalGetGlobalState()?.contextManager.getParentSpanIds()?.spanParents ?? [];
21585
+ for (const parentId of parentIds) {
21586
+ const state = this.statesBySpanId.get(parentId);
21587
+ if (state) {
21588
+ return state;
21589
+ }
21590
+ }
21591
+ return void 0;
21592
+ }
21593
+ stateForAISDKEvent(event) {
21594
+ const spanId = Reflect.get(event, THINK_STATE_ID);
21595
+ return typeof spanId === "string" ? this.statesBySpanId.get(spanId) : void 0;
21596
+ }
21597
+ finishState(state, error, output) {
21598
+ if (state.finalized) {
21599
+ return;
21600
+ }
21601
+ state.finalized = true;
21602
+ try {
21603
+ if (!state.inputLogged && state.fallbackInput !== void 0) {
21604
+ state.span.log({ input: state.fallbackInput });
21605
+ }
21606
+ if (error !== void 0) {
21607
+ state.span.log({ error });
21608
+ } else if (output !== void 0) {
21609
+ state.span.log({ output: extractThinkTaskOutput(output) });
21610
+ }
21611
+ finalizeAISDKChildTracing(state.aiEvent);
21612
+ state.span.end();
21613
+ } finally {
21614
+ this.releaseState(state);
21615
+ }
21616
+ }
21617
+ releaseState(state) {
21618
+ state.finalized = true;
21619
+ unregisterCloudflareThinkSpan(state.span);
21620
+ if (state.span.spanId) {
21621
+ this.statesBySpanId.delete(state.span.spanId);
21622
+ }
21623
+ }
21624
+ };
21625
+ function extractFallbackInput(messages) {
21626
+ if (!Array.isArray(messages) || messages.length === 0) {
21627
+ return void 0;
21628
+ }
21629
+ let latestUserIndex = -1;
21630
+ for (let index = messages.length - 1; index >= 0; index--) {
21631
+ if (messages[index]?.role === "user") {
21632
+ latestUserIndex = index;
21633
+ break;
21634
+ }
21635
+ }
21636
+ const selected = latestUserIndex >= 0 ? messages.slice(latestUserIndex) : [];
21637
+ return selected.map((message) => ({
21638
+ role: message.role,
21639
+ content: message.content ?? message.parts
21640
+ }));
21641
+ }
21642
+ function extractThinkTaskOutput(output) {
21643
+ if (!isObject(output)) {
21644
+ return output;
21645
+ }
21646
+ if (typeof output.text === "string") {
21647
+ return { role: "assistant", content: output.text };
21648
+ }
21649
+ if (output.object !== void 0) {
21650
+ return output.object;
21651
+ }
21652
+ return output;
21653
+ }
21654
+ function extractThinkTaskInput(input) {
21655
+ if (!isObject(input)) {
21656
+ return input;
21657
+ }
21658
+ const system = input.instructions ?? input.system;
21659
+ if (Array.isArray(input.messages)) {
21660
+ return system === void 0 ? input.messages : [{ role: "system", content: system }, ...input.messages];
21661
+ }
21662
+ if (Array.isArray(input.prompt)) {
21663
+ return system === void 0 ? input.prompt : [{ role: "system", content: system }, ...input.prompt];
21664
+ }
21665
+ if (typeof input.prompt === "string") {
21666
+ const messages = [{ role: "user", content: input.prompt }];
21667
+ return system === void 0 ? messages : [{ role: "system", content: system }, ...messages];
21668
+ }
21669
+ return input;
21670
+ }
21671
+
20708
21672
  // src/instrumentation/plugins/cursor-sdk-channels.ts
20709
21673
  var cursorSDKChannels = defineChannels(
20710
21674
  "@cursor/sdk",
@@ -26470,6 +27434,470 @@ function aggregateMistralStreamChunks(chunks) {
26470
27434
  };
26471
27435
  }
26472
27436
 
27437
+ // src/instrumentation/plugins/ollama-channels.ts
27438
+ var ollamaChannels = defineChannels(
27439
+ "ollama",
27440
+ {
27441
+ chat: channel({
27442
+ channelName: "chat",
27443
+ kind: "async"
27444
+ }),
27445
+ generate: channel({
27446
+ channelName: "generate",
27447
+ kind: "async"
27448
+ }),
27449
+ embed: channel({
27450
+ channelName: "embed",
27451
+ kind: "async"
27452
+ })
27453
+ },
27454
+ { instrumentationName: INSTRUMENTATION_NAMES.OLLAMA }
27455
+ );
27456
+
27457
+ // src/instrumentation/plugins/ollama-plugin.ts
27458
+ var OllamaPlugin = class extends BasePlugin {
27459
+ onEnable() {
27460
+ this.unsubscribers.push(
27461
+ traceStreamingChannel(ollamaChannels.chat, {
27462
+ name: "ollama.chat",
27463
+ type: "llm" /* LLM */,
27464
+ extractInput: extractOllamaChatInput,
27465
+ extractOutput: (result, event) => extractOllamaChatOutput(
27466
+ result,
27467
+ countOllamaToolCalls(event?.arguments?.[0]?.messages)
27468
+ ),
27469
+ extractMetadata: extractOllamaResponseMetadata,
27470
+ extractMetrics: extractOllamaMetrics,
27471
+ aggregateChunks: aggregateOllamaChatChunks
27472
+ }),
27473
+ traceStreamingChannel(ollamaChannels.generate, {
27474
+ name: "ollama.generate",
27475
+ type: "llm" /* LLM */,
27476
+ extractInput: extractOllamaGenerateInput,
27477
+ extractOutput: extractOllamaGenerateOutput,
27478
+ extractMetadata: extractOllamaResponseMetadata,
27479
+ extractMetrics: extractOllamaMetrics,
27480
+ aggregateChunks: aggregateOllamaGenerateChunks
27481
+ }),
27482
+ traceAsyncChannel(ollamaChannels.embed, {
27483
+ name: "ollama.embed",
27484
+ type: "llm" /* LLM */,
27485
+ extractInput: extractOllamaEmbedInput,
27486
+ extractOutput: extractOllamaEmbedOutput,
27487
+ extractMetadata: extractOllamaResponseMetadata,
27488
+ extractMetrics: extractOllamaMetrics
27489
+ })
27490
+ );
27491
+ }
27492
+ onDisable() {
27493
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
27494
+ }
27495
+ };
27496
+ function isNonNegativeNumber(value) {
27497
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
27498
+ }
27499
+ function normalizeFinishReason(response, hasToolCalls = false) {
27500
+ if (hasToolCalls) {
27501
+ return "tool_calls";
27502
+ }
27503
+ return response?.done_reason || "stop";
27504
+ }
27505
+ function stringifyArguments(value) {
27506
+ if (typeof value === "string") {
27507
+ return value;
27508
+ }
27509
+ try {
27510
+ return JSON.stringify(value ?? {});
27511
+ } catch {
27512
+ return String(value);
27513
+ }
27514
+ }
27515
+ function syntheticToolCallId(name, index) {
27516
+ const normalizedName = name.replace(/[^a-zA-Z0-9_-]/g, "_") || "tool";
27517
+ return `ollama_call_${normalizedName}_${index}`;
27518
+ }
27519
+ function normalizeToolCall(toolCall, index) {
27520
+ const name = toolCall.function?.name;
27521
+ if (typeof name !== "string" || name.length === 0) {
27522
+ return void 0;
27523
+ }
27524
+ return {
27525
+ id: typeof toolCall.id === "string" && toolCall.id.length > 0 ? toolCall.id : syntheticToolCallId(name, index),
27526
+ type: "function",
27527
+ function: {
27528
+ name,
27529
+ arguments: stringifyArguments(toolCall.function?.arguments)
27530
+ }
27531
+ };
27532
+ }
27533
+ function normalizeToolCalls(toolCalls2, syntheticIdOffset = 0) {
27534
+ if (!Array.isArray(toolCalls2)) {
27535
+ return [];
27536
+ }
27537
+ return toolCalls2.flatMap((toolCall, index) => {
27538
+ const normalized = normalizeToolCall(toolCall, syntheticIdOffset + index);
27539
+ return normalized ? [normalized] : [];
27540
+ });
27541
+ }
27542
+ function countOllamaToolCalls(messages) {
27543
+ if (!Array.isArray(messages)) {
27544
+ return 0;
27545
+ }
27546
+ return messages.reduce(
27547
+ (count, message) => count + (isObject(message) && Array.isArray(message.tool_calls) ? message.tool_calls.length : 0),
27548
+ 0
27549
+ );
27550
+ }
27551
+ function imageBytes(value) {
27552
+ if (value instanceof Uint8Array) {
27553
+ return value;
27554
+ }
27555
+ if (value instanceof ArrayBuffer) {
27556
+ return new Uint8Array(value);
27557
+ }
27558
+ if (typeof value !== "string" || value.startsWith("data:")) {
27559
+ return void 0;
27560
+ }
27561
+ try {
27562
+ const decoded = atob(value.slice(0, 24));
27563
+ return Uint8Array.from(decoded, (character) => character.charCodeAt(0));
27564
+ } catch {
27565
+ return void 0;
27566
+ }
27567
+ }
27568
+ function inferImageMediaType(value) {
27569
+ if (typeof value === "string") {
27570
+ const dataUrlType = value.match(/^data:(image\/[^;]+);base64,/i)?.[1];
27571
+ if (dataUrlType) {
27572
+ return dataUrlType;
27573
+ }
27574
+ }
27575
+ const bytes = imageBytes(value);
27576
+ if (!bytes) {
27577
+ return void 0;
27578
+ }
27579
+ if (bytes[0] === 137 && bytes[1] === 80 && bytes[2] === 78 && bytes[3] === 71) {
27580
+ return "image/png";
27581
+ }
27582
+ if (bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255) {
27583
+ return "image/jpeg";
27584
+ }
27585
+ const signature = String.fromCharCode(...bytes.slice(0, 12));
27586
+ if (signature.startsWith("GIF87a") || signature.startsWith("GIF89a")) {
27587
+ return "image/gif";
27588
+ }
27589
+ if (signature.startsWith("RIFF") && signature.slice(8, 12) === "WEBP") {
27590
+ return "image/webp";
27591
+ }
27592
+ return void 0;
27593
+ }
27594
+ function normalizeTextAndImages(content, images) {
27595
+ if (!images || images.length === 0) {
27596
+ return { content };
27597
+ }
27598
+ const imageParts = [];
27599
+ const unrecognizedImages = [];
27600
+ for (const image of images) {
27601
+ let localImagePath;
27602
+ let localPathMediaType;
27603
+ if (typeof image === "string" && !/^data:/i.test(image) && !/^https?:\/\//i.test(image)) {
27604
+ const extension = image.match(/\.([a-z0-9]+)$/i)?.[1]?.toLowerCase();
27605
+ const extensionMediaType = {
27606
+ png: "image/png",
27607
+ jpg: "image/jpeg",
27608
+ jpeg: "image/jpeg",
27609
+ gif: "image/gif",
27610
+ webp: "image/webp"
27611
+ }[extension ?? ""];
27612
+ if (extensionMediaType && isomorph_default.statSync) {
27613
+ try {
27614
+ if (isomorph_default.statSync(image).isFile()) {
27615
+ localImagePath = image;
27616
+ localPathMediaType = extensionMediaType;
27617
+ }
27618
+ } catch {
27619
+ }
27620
+ }
27621
+ }
27622
+ const mediaType = localPathMediaType ?? inferImageMediaType(image);
27623
+ if (!mediaType) {
27624
+ unrecognizedImages.push(image);
27625
+ continue;
27626
+ }
27627
+ const processedImage = localImagePath ? new Attachment({
27628
+ data: localImagePath,
27629
+ filename: localImagePath.split(/[\\/]/).at(-1) ?? "image",
27630
+ contentType: mediaType
27631
+ }) : processInputAttachments({
27632
+ type: "image",
27633
+ image,
27634
+ mediaType
27635
+ }).image;
27636
+ imageParts.push({
27637
+ type: "image_url",
27638
+ image_url: { url: processedImage }
27639
+ });
27640
+ }
27641
+ return {
27642
+ content: imageParts.length > 0 ? [...content ? [{ type: "text", text: content }] : [], ...imageParts] : content,
27643
+ ...unrecognizedImages.length > 0 ? { unrecognizedImages } : {}
27644
+ };
27645
+ }
27646
+ function normalizeMessage(message, toolCallId, syntheticToolCallIdOffset = 0) {
27647
+ if (typeof message.role !== "string") {
27648
+ return void 0;
27649
+ }
27650
+ const toolCalls2 = normalizeToolCalls(
27651
+ message.tool_calls,
27652
+ syntheticToolCallIdOffset
27653
+ );
27654
+ if (message.role === "tool") {
27655
+ const toolName = typeof message.tool_name === "string" && message.tool_name.length > 0 ? message.tool_name : "tool";
27656
+ return {
27657
+ role: "tool",
27658
+ tool_call_id: toolCallId ?? syntheticToolCallId(toolName, 0),
27659
+ content: typeof message.content === "string" ? message.content : ""
27660
+ };
27661
+ }
27662
+ const normalizedContent = normalizeTextAndImages(
27663
+ typeof message.content === "string" ? message.content || (toolCalls2.length > 0 ? null : "") : toolCalls2.length > 0 ? null : "",
27664
+ message.images
27665
+ );
27666
+ return {
27667
+ role: message.role,
27668
+ content: normalizedContent.content,
27669
+ ...typeof message.thinking === "string" && message.thinking.length > 0 ? { reasoning: message.thinking } : {},
27670
+ ...toolCalls2.length > 0 ? { tool_calls: toolCalls2 } : {},
27671
+ ...normalizedContent.unrecognizedImages ? { images: normalizedContent.unrecognizedImages } : {}
27672
+ };
27673
+ }
27674
+ function normalizeMessages(messages) {
27675
+ if (!Array.isArray(messages)) {
27676
+ return [];
27677
+ }
27678
+ const pendingToolCallIds = /* @__PURE__ */ new Map();
27679
+ let syntheticToolCallIdOffset = 0;
27680
+ return messages.flatMap((message) => {
27681
+ if (!isObject(message)) {
27682
+ return [];
27683
+ }
27684
+ const ollamaMessage = message;
27685
+ let toolCallId;
27686
+ if (ollamaMessage.role === "tool") {
27687
+ const toolName = ollamaMessage.tool_name;
27688
+ if (typeof toolName === "string") {
27689
+ toolCallId = pendingToolCallIds.get(toolName)?.shift();
27690
+ }
27691
+ }
27692
+ const normalized = normalizeMessage(
27693
+ ollamaMessage,
27694
+ toolCallId,
27695
+ syntheticToolCallIdOffset
27696
+ );
27697
+ if (Array.isArray(ollamaMessage.tool_calls)) {
27698
+ syntheticToolCallIdOffset += ollamaMessage.tool_calls.length;
27699
+ }
27700
+ if (ollamaMessage.role === "assistant" && normalized) {
27701
+ const toolCalls2 = Array.isArray(normalized.tool_calls) ? normalized.tool_calls : [];
27702
+ for (const toolCall of toolCalls2) {
27703
+ if (!isObject(toolCall) || !isObject(toolCall.function)) {
27704
+ continue;
27705
+ }
27706
+ const name = toolCall.function.name;
27707
+ const id = toolCall.id;
27708
+ if (typeof name === "string" && typeof id === "string") {
27709
+ const ids = pendingToolCallIds.get(name) ?? [];
27710
+ ids.push(id);
27711
+ pendingToolCallIds.set(name, ids);
27712
+ }
27713
+ }
27714
+ }
27715
+ return normalized ? [normalized] : [];
27716
+ });
27717
+ }
27718
+ function normalizeToolDefinition(tool) {
27719
+ const fn = tool.function;
27720
+ if (!fn || typeof fn.name !== "string" || fn.name.length === 0) {
27721
+ return void 0;
27722
+ }
27723
+ return {
27724
+ type: "function",
27725
+ function: {
27726
+ name: fn.name,
27727
+ ...typeof fn.description === "string" ? { description: fn.description } : {},
27728
+ ...isObject(fn.parameters) ? { parameters: fn.parameters } : {}
27729
+ }
27730
+ };
27731
+ }
27732
+ function extractToolsMetadata(tools) {
27733
+ if (!Array.isArray(tools)) {
27734
+ return {};
27735
+ }
27736
+ const normalized = tools.flatMap((tool) => {
27737
+ if (!isObject(tool)) {
27738
+ return [];
27739
+ }
27740
+ const definition = normalizeToolDefinition(tool);
27741
+ return definition ? [definition] : [];
27742
+ });
27743
+ return normalized.length > 0 ? { tools: normalized } : {};
27744
+ }
27745
+ function extractOptionsMetadata(options) {
27746
+ if (!isObject(options)) {
27747
+ return {};
27748
+ }
27749
+ const metadata = {};
27750
+ const mappings = [
27751
+ ["temperature", "temperature"],
27752
+ ["top_p", "top_p"],
27753
+ ["num_predict", "max_tokens"],
27754
+ ["frequency_penalty", "frequency_penalty"],
27755
+ ["presence_penalty", "presence_penalty"],
27756
+ ["stop", "stop"]
27757
+ ];
27758
+ for (const [source, target] of mappings) {
27759
+ if (options[source] !== void 0) {
27760
+ metadata[target] = options[source];
27761
+ }
27762
+ }
27763
+ return metadata;
27764
+ }
27765
+ function extractRequestMetadata(request) {
27766
+ return {
27767
+ provider: "ollama",
27768
+ ...typeof request?.model === "string" ? { model: request.model } : {},
27769
+ ...extractOptionsMetadata(request?.options),
27770
+ ...request?.format !== void 0 ? { response_format: request.format } : {}
27771
+ };
27772
+ }
27773
+ function extractOllamaChatInput([request]) {
27774
+ return {
27775
+ input: normalizeMessages(request.messages),
27776
+ metadata: {
27777
+ ...extractRequestMetadata(request),
27778
+ ...extractToolsMetadata(request.tools)
27779
+ }
27780
+ };
27781
+ }
27782
+ function extractOllamaGenerateInput([request]) {
27783
+ const normalizedPrompt = normalizeTextAndImages(
27784
+ typeof request.prompt === "string" ? request.prompt : "",
27785
+ Array.isArray(request.images) ? request.images : void 0
27786
+ );
27787
+ const input = [
27788
+ ...typeof request.system === "string" ? [{ role: "system", content: request.system }] : [],
27789
+ {
27790
+ role: "user",
27791
+ content: normalizedPrompt.content,
27792
+ ...typeof request.suffix === "string" ? { suffix: request.suffix } : {},
27793
+ ...normalizedPrompt.unrecognizedImages ? { images: normalizedPrompt.unrecognizedImages } : {}
27794
+ }
27795
+ ];
27796
+ return {
27797
+ input,
27798
+ metadata: extractRequestMetadata(request)
27799
+ };
27800
+ }
27801
+ function extractOllamaEmbedInput([request]) {
27802
+ return {
27803
+ input: request.input,
27804
+ metadata: extractRequestMetadata(request)
27805
+ };
27806
+ }
27807
+ function extractOllamaChatOutput(result, syntheticToolCallIdOffset = 0) {
27808
+ if (!isObject(result) || !isObject(result.message)) {
27809
+ return void 0;
27810
+ }
27811
+ const message = normalizeMessage(
27812
+ result.message,
27813
+ void 0,
27814
+ syntheticToolCallIdOffset
27815
+ );
27816
+ if (!message) {
27817
+ return void 0;
27818
+ }
27819
+ const toolCalls2 = Array.isArray(message.tool_calls) ? message.tool_calls : [];
27820
+ return [
27821
+ {
27822
+ index: 0,
27823
+ finish_reason: normalizeFinishReason(result, toolCalls2.length > 0),
27824
+ message
27825
+ }
27826
+ ];
27827
+ }
27828
+ function extractOllamaGenerateOutput(result) {
27829
+ if (!isObject(result) || typeof result.response !== "string") {
27830
+ return void 0;
27831
+ }
27832
+ return [
27833
+ {
27834
+ index: 0,
27835
+ finish_reason: normalizeFinishReason(result),
27836
+ message: {
27837
+ role: "assistant",
27838
+ content: result.response,
27839
+ ...typeof result.thinking === "string" && result.thinking.length > 0 ? { reasoning: result.thinking } : {}
27840
+ }
27841
+ }
27842
+ ];
27843
+ }
27844
+ function extractOllamaEmbedOutput(result) {
27845
+ const embedding = Array.isArray(result?.embeddings) ? result.embeddings[0] : void 0;
27846
+ return Array.isArray(embedding) ? { embedding_length: embedding.length } : void 0;
27847
+ }
27848
+ function extractOllamaResponseMetadata(result) {
27849
+ return typeof result?.model === "string" ? { model: result.model } : void 0;
27850
+ }
27851
+ function extractOllamaMetrics(result) {
27852
+ const metrics = {};
27853
+ const promptTokens = result?.prompt_eval_count;
27854
+ const completionTokens = result?.eval_count;
27855
+ if (isNonNegativeNumber(promptTokens)) {
27856
+ metrics.prompt_tokens = promptTokens;
27857
+ }
27858
+ if (isNonNegativeNumber(completionTokens)) {
27859
+ metrics.completion_tokens = completionTokens;
27860
+ }
27861
+ if (isNonNegativeNumber(promptTokens) || isNonNegativeNumber(completionTokens)) {
27862
+ metrics.tokens = (isNonNegativeNumber(promptTokens) ? promptTokens : 0) + (isNonNegativeNumber(completionTokens) ? completionTokens : 0);
27863
+ }
27864
+ return metrics;
27865
+ }
27866
+ function aggregateOllamaChatChunks(chunks, _result, event, _startTime) {
27867
+ const last = chunks.at(-1);
27868
+ const message = {
27869
+ role: "assistant",
27870
+ content: chunks.map((chunk) => chunk.message?.content ?? "").join(""),
27871
+ thinking: chunks.map((chunk) => chunk.message?.thinking ?? "").join(""),
27872
+ tool_calls: chunks.flatMap((chunk) => chunk.message?.tool_calls ?? [])
27873
+ };
27874
+ const response = {
27875
+ ...last,
27876
+ message
27877
+ };
27878
+ return {
27879
+ output: extractOllamaChatOutput(
27880
+ response,
27881
+ countOllamaToolCalls(event?.arguments?.[0]?.messages)
27882
+ ),
27883
+ metrics: extractOllamaMetrics(last ?? {}),
27884
+ metadata: extractOllamaResponseMetadata(last ?? {})
27885
+ };
27886
+ }
27887
+ function aggregateOllamaGenerateChunks(chunks, _result, _event, _startTime) {
27888
+ const last = chunks.at(-1);
27889
+ const response = {
27890
+ ...last,
27891
+ response: chunks.map((chunk) => chunk.response ?? "").join(""),
27892
+ thinking: chunks.map((chunk) => chunk.thinking ?? "").join("")
27893
+ };
27894
+ return {
27895
+ output: extractOllamaGenerateOutput(response),
27896
+ metrics: extractOllamaMetrics(last ?? {}),
27897
+ metadata: extractOllamaResponseMetadata(last ?? {})
27898
+ };
27899
+ }
27900
+
26473
27901
  // src/instrumentation/plugins/google-adk-channels.ts
26474
27902
  var googleADKChannels = defineChannels(
26475
27903
  "@google/adk",
@@ -30223,7 +31651,7 @@ var FlueObserveBridge = class {
30223
31651
  return;
30224
31652
  }
30225
31653
  const state = this.operationsById.get(event.operationId) ?? this.startSyntheticOperation(event);
30226
- const output = operationOutput(event);
31654
+ const output = operationOutput(event) ?? outputFromAgentTurn(state.latestAgentOutput);
30227
31655
  const metadata = {
30228
31656
  ...state.metadata,
30229
31657
  ...extractEventMetadata(event),
@@ -30232,7 +31660,7 @@ var FlueObserveBridge = class {
30232
31660
  };
30233
31661
  this.finishPendingChildrenForOperation(event, output);
30234
31662
  safeLog3(state.span, {
30235
- ...event.isError ? { error: toLoggedError(event.error) } : {},
31663
+ ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.error) } : {},
30236
31664
  metadata,
30237
31665
  metrics: durationMetrics2(event.durationMs),
30238
31666
  output
@@ -30263,7 +31691,7 @@ var FlueObserveBridge = class {
30263
31691
  };
30264
31692
  const parent = this.parentSpanForTurn(event);
30265
31693
  const span = startFlueSpan(parent, {
30266
- name: `llm:${model ?? event.purpose ?? "unknown"}`,
31694
+ name: "flue.turn",
30267
31695
  spanAttributes: { type: "llm" /* LLM */ },
30268
31696
  startTime: eventTime(event.timestamp),
30269
31697
  event: {
@@ -30307,6 +31735,12 @@ var FlueObserveBridge = class {
30307
31735
  },
30308
31736
  output
30309
31737
  });
31738
+ if (event.purpose === "agent" && event.operationId) {
31739
+ const operation = this.operationsById.get(event.operationId);
31740
+ if (operation) {
31741
+ operation.latestAgentOutput = output;
31742
+ }
31743
+ }
30310
31744
  safeEnd(state.span, eventTime(event.timestamp));
30311
31745
  this.turnsByKey.delete(key);
30312
31746
  }
@@ -30386,7 +31820,7 @@ var FlueObserveBridge = class {
30386
31820
  return;
30387
31821
  }
30388
31822
  safeLog3(state.span, {
30389
- ...event.isError ? { error: toLoggedError(event.result) } : {},
31823
+ ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.result) } : {},
30390
31824
  metadata: {
30391
31825
  ...state.metadata,
30392
31826
  ...extractEventMetadata(event),
@@ -30432,6 +31866,7 @@ var FlueObserveBridge = class {
30432
31866
  ...event.usage ? { "flue.usage": event.usage } : {}
30433
31867
  };
30434
31868
  safeLog3(state.span, {
31869
+ ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.error) } : {},
30435
31870
  metadata,
30436
31871
  metrics: {
30437
31872
  ...durationMetrics2(event.durationMs),
@@ -30536,7 +31971,7 @@ var FlueObserveBridge = class {
30536
31971
  ...event.purpose ? { "flue.turn_purpose": event.purpose } : {}
30537
31972
  };
30538
31973
  const span = startFlueSpan(this.parentSpanForEvent(event), {
30539
- name: `llm:${model ?? event.purpose ?? "unknown"}`,
31974
+ name: "flue.turn",
30540
31975
  spanAttributes: { type: "llm" /* LLM */ },
30541
31976
  startTime: eventTime(event.timestamp),
30542
31977
  event: { metadata }
@@ -30668,7 +32103,10 @@ function extractEventMetadata(event, ctx) {
30668
32103
  return {
30669
32104
  ...event.runId ? { "flue.run_id": event.runId } : {},
30670
32105
  ...event.instanceId ? { "flue.instance_id": event.instanceId } : {},
32106
+ ...event.submissionId ? { "flue.submission_id": event.submissionId } : {},
30671
32107
  ...event.dispatchId ? { "flue.dispatch_id": event.dispatchId } : {},
32108
+ ...event.agentName ? { "flue.agent_name": event.agentName } : {},
32109
+ ...event.conversationId ? { "flue.conversation_id": event.conversationId } : {},
30672
32110
  ...typeof event.eventIndex === "number" ? { "flue.event_index": event.eventIndex } : {},
30673
32111
  ...event.session ? { "flue.session": event.session } : {},
30674
32112
  ...event.parentSession ? { "flue.parent_session": event.parentSession } : {},
@@ -30697,7 +32135,7 @@ function flueTurnRequestInput(event) {
30697
32135
  return event.request?.input ?? event.input;
30698
32136
  }
30699
32137
  function flueTurnRequestModel(event) {
30700
- return event.request?.model ?? event.model;
32138
+ return event.request?.requestedModel ?? event.request?.model ?? event.model;
30701
32139
  }
30702
32140
  function flueTurnRequestProvider(event) {
30703
32141
  return event.request?.providerName ?? event.provider ?? event.request?.providerId;
@@ -30706,10 +32144,10 @@ function flueTurnRequestApi(event) {
30706
32144
  return event.request?.api ?? event.api;
30707
32145
  }
30708
32146
  function flueTurnRequestReasoning(event) {
30709
- return event.request?.reasoning ?? event.reasoning;
32147
+ return event.request?.reasoningLevel ?? event.request?.reasoning ?? event.reasoning;
30710
32148
  }
30711
32149
  function flueTurnModel(event) {
30712
- return event.request?.model ?? event.model;
32150
+ return event.response?.responseModel ?? event.request?.requestedModel ?? event.request?.model ?? event.model;
30713
32151
  }
30714
32152
  function flueTurnProvider(event) {
30715
32153
  return event.request?.providerName ?? event.provider ?? event.request?.providerId;
@@ -30724,7 +32162,7 @@ function flueTurnOutput(event) {
30724
32162
  return event.response?.output ?? event.output;
30725
32163
  }
30726
32164
  function flueTurnStopReason(event) {
30727
- return event.response?.stopReason ?? event.stopReason;
32165
+ return event.response?.finishReason ?? event.response?.stopReason ?? event.stopReason;
30728
32166
  }
30729
32167
  function flueTurnError(event) {
30730
32168
  return event.response?.error ?? event.response?.errorInfo?.message ?? event.error;
@@ -30739,6 +32177,9 @@ function flueToolInput(event) {
30739
32177
  return event.input;
30740
32178
  }
30741
32179
  function flueToolOutput(event) {
32180
+ if (Object.hasOwn(event, "effectiveResult")) {
32181
+ return event.effectiveResult;
32182
+ }
30742
32183
  return event.output !== void 0 ? event.output : event.result;
30743
32184
  }
30744
32185
  function flueToolError(event) {
@@ -30746,10 +32187,36 @@ function flueToolError(event) {
30746
32187
  }
30747
32188
  function operationOutput(event) {
30748
32189
  if (event.operationKind === "prompt" || event.operationKind === "skill") {
30749
- return llmResultFromOperationResult(event.result);
32190
+ return outputFromAgentInvocation(event.agentOutput) ?? llmResultFromOperationResult(event.result);
30750
32191
  }
30751
32192
  return event.result ?? (event.operationKind === "compact" ? { completed: true } : void 0);
30752
32193
  }
32194
+ function outputFromAgentInvocation(output) {
32195
+ if (output?.type === "text") {
32196
+ return output.text;
32197
+ }
32198
+ if (output?.type === "data") {
32199
+ return output.data;
32200
+ }
32201
+ return void 0;
32202
+ }
32203
+ function outputFromAgentTurn(output) {
32204
+ if (!isObjectLike(output)) {
32205
+ return output;
32206
+ }
32207
+ const content = Reflect.get(output, "content");
32208
+ if (!Array.isArray(content)) {
32209
+ return output;
32210
+ }
32211
+ const text = content.flatMap((part) => {
32212
+ if (!isObjectLike(part) || Reflect.get(part, "type") !== "text") {
32213
+ return [];
32214
+ }
32215
+ const value = Reflect.get(part, "text");
32216
+ return typeof value === "string" ? [value] : [];
32217
+ });
32218
+ return text.length > 0 ? text.join("") : output;
32219
+ }
30753
32220
  function llmResultFromOperationResult(result) {
30754
32221
  if (!isObjectLike(result)) {
30755
32222
  return result;
@@ -30848,7 +32315,7 @@ function safeEnd(span, endTime) {
30848
32315
  }
30849
32316
  }
30850
32317
  function logInstrumentationError3(label, error) {
30851
- console.error(`Error in ${label} instrumentation:`, error);
32318
+ debugLogger.debug(`Error in ${label} instrumentation:`, error);
30852
32319
  }
30853
32320
 
30854
32321
  // src/wrappers/langchain/callback-handler.ts
@@ -31777,12 +33244,13 @@ var piCodingAgentChannels = defineChannels(
31777
33244
  );
31778
33245
 
31779
33246
  // src/instrumentation/plugins/pi-coding-agent-plugin.ts
31780
- var piStreamPatchStates = /* @__PURE__ */ new WeakMap();
33247
+ var piAgentPatchStates = /* @__PURE__ */ new WeakMap();
33248
+ var piAgentEventSubscriptions = /* @__PURE__ */ new WeakSet();
31781
33249
  var piPromptContextStore;
31782
33250
  var PiCodingAgentPlugin = class extends BasePlugin {
31783
33251
  activePromptStates = /* @__PURE__ */ new Set();
31784
33252
  onEnable() {
31785
- this.subscribeToPrompt();
33253
+ this.interceptPrompt();
31786
33254
  }
31787
33255
  onDisable() {
31788
33256
  for (const unsubscribe of this.unsubscribers) {
@@ -31790,65 +33258,74 @@ var PiCodingAgentPlugin = class extends BasePlugin {
31790
33258
  }
31791
33259
  this.unsubscribers = [];
31792
33260
  for (const state of [...this.activePromptStates]) {
31793
- void finalizePiPromptRun(state).catch((error) => {
31794
- logInstrumentationError4("Pi Coding Agent disable cleanup", error);
31795
- });
33261
+ finishPiPromptRun(state);
31796
33262
  }
31797
33263
  }
31798
- subscribeToPrompt() {
31799
- const channel2 = piCodingAgentChannels.prompt.tracingChannel();
31800
- const states = /* @__PURE__ */ new WeakMap();
31801
- const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(channel2);
31802
- const handlers = {
31803
- start: (event) => {
31804
- const state = startPiPromptRun(event, (state2) => {
31805
- this.activePromptStates.delete(state2);
31806
- });
31807
- if (state) {
31808
- this.activePromptStates.add(state);
31809
- states.set(event, state);
31810
- }
31811
- },
31812
- asyncEnd: async (event) => {
31813
- const state = states.get(event);
31814
- if (!state) {
31815
- return;
31816
- }
31817
- states.delete(event);
31818
- state.promptCallEnded = true;
31819
- if (!state.finalized && state.deferCompletionUntilTurnEnd && !state.turnEnded) {
31820
- if (!state.sawStreamFn) {
31821
- state.queued = true;
31822
- if (!state.streamPatchState.queuedPromptStates.includes(state)) {
31823
- state.streamPatchState.queuedPromptStates.push(state);
31824
- }
33264
+ interceptPrompt() {
33265
+ this.unsubscribers.push(
33266
+ piCodingAgentChannels.prompt.intercept(
33267
+ (target, thisArg, args, additional) => {
33268
+ const invokeTarget = () => Reflect.apply(target, thisArg, args);
33269
+ let state;
33270
+ try {
33271
+ state = startPiPromptRun(
33272
+ {
33273
+ ...additional,
33274
+ arguments: args,
33275
+ self: thisArg
33276
+ },
33277
+ (finalizedState) => {
33278
+ this.activePromptStates.delete(finalizedState);
33279
+ }
33280
+ );
33281
+ } catch (error) {
33282
+ logInstrumentationError4("Pi Coding Agent prompt start", error);
31825
33283
  }
31826
- return;
31827
- }
31828
- await finalizePiPromptRun(state);
31829
- },
31830
- error: async (event) => {
31831
- const state = states.get(event);
31832
- if (!state) {
31833
- return;
33284
+ if (!state) {
33285
+ return runWithAutoInstrumentationSuppressed(invokeTarget);
33286
+ }
33287
+ this.activePromptStates.add(state);
33288
+ return promptContextStore().run(
33289
+ state,
33290
+ () => runWithAutoInstrumentationSuppressed(() => {
33291
+ let result;
33292
+ try {
33293
+ result = invokeTarget();
33294
+ } catch (error) {
33295
+ finishPiPromptRun(state, error);
33296
+ throw error;
33297
+ }
33298
+ return Promise.resolve(result).then(
33299
+ (value) => {
33300
+ finishPiPromptCall(state);
33301
+ return value;
33302
+ },
33303
+ (error) => {
33304
+ finishPiPromptRun(state, error);
33305
+ throw error;
33306
+ }
33307
+ );
33308
+ })
33309
+ );
31834
33310
  }
31835
- states.delete(event);
31836
- await finalizePiPromptRun(state, event.error);
31837
- }
31838
- };
31839
- channel2.subscribe(handlers);
31840
- this.unsubscribers.push(() => {
31841
- unbindAutoInstrumentationSuppression?.();
31842
- channel2.unsubscribe(handlers);
31843
- });
33311
+ )
33312
+ );
31844
33313
  }
31845
33314
  };
33315
+ function finishPiPromptCall(state) {
33316
+ state.promptCallEnded = true;
33317
+ if (state.deferCompletionUntilTurnEnd && !state.turnEnded) {
33318
+ return;
33319
+ }
33320
+ finishPiPromptRun(state);
33321
+ }
31846
33322
  function startPiPromptRun(event, onFinalize) {
31847
33323
  const session = extractSession(event);
31848
33324
  const agent = session?.agent;
31849
33325
  if (!session || !isPiAgent(agent)) {
31850
33326
  return void 0;
31851
33327
  }
33328
+ installPiAgentInstrumentation(agent);
31852
33329
  const metadata = {
31853
33330
  ...extractSessionMetadata(session),
31854
33331
  ...extractPromptOptionsMetadata(event.arguments[1]),
@@ -31870,9 +33347,7 @@ function startPiPromptRun(event, onFinalize) {
31870
33347
  INSTRUMENTATION_NAMES.PI_CODING_AGENT
31871
33348
  )
31872
33349
  );
31873
- const streamPatchState = installPiStreamPatch(agent);
31874
33350
  const options = event.arguments[1];
31875
- const promptText = event.arguments[0];
31876
33351
  const state = {
31877
33352
  activeLlmSpans: /* @__PURE__ */ new Set(),
31878
33353
  activeToolSpans: /* @__PURE__ */ new Map(),
@@ -31884,29 +33359,10 @@ function startPiPromptRun(event, onFinalize) {
31884
33359
  metrics: {},
31885
33360
  onFinalize,
31886
33361
  promptCallEnded: false,
31887
- ...typeof promptText === "string" ? { promptText } : {},
31888
- queued: false,
31889
33362
  span,
31890
- sawStreamFn: false,
31891
33363
  startTime: getCurrentUnixTimestamp(),
31892
- streamPatchState,
31893
33364
  turnEnded: false
31894
33365
  };
31895
- state.restorePromptContext = enterPiPromptContext(state);
31896
- streamPatchState.activePromptStates.add(state);
31897
- try {
31898
- state.unsubscribeAgent = agent.subscribe(async (agentEvent) => {
31899
- try {
31900
- await runWithAutoInstrumentationSuppressed(
31901
- () => handlePiAgentEvent(state, agentEvent)
31902
- );
31903
- } catch (error) {
31904
- logInstrumentationError4("Pi Coding Agent event", error);
31905
- }
31906
- });
31907
- } catch (error) {
31908
- logInstrumentationError4("Pi Coding Agent event subscription", error);
31909
- }
31910
33366
  return state;
31911
33367
  }
31912
33368
  function extractSession(event) {
@@ -31920,111 +33376,55 @@ function promptContextStore() {
31920
33376
  piPromptContextStore ??= isomorph_default.newAsyncLocalStorage();
31921
33377
  return piPromptContextStore;
31922
33378
  }
31923
- function currentPromptContextFrames() {
31924
- return promptContextStore().getStore()?.frames ?? [];
31925
- }
31926
33379
  function currentPiPromptState() {
31927
- const frames = currentPromptContextFrames();
31928
- return frames[frames.length - 1]?.state;
31929
- }
31930
- function enterPiPromptContext(state) {
31931
- const frame = {
31932
- id: /* @__PURE__ */ Symbol("braintrust.pi-coding-agent.prompt"),
31933
- state
31934
- };
31935
- promptContextStore().enterWith({
31936
- frames: [...currentPromptContextFrames(), frame]
31937
- });
31938
- return () => {
31939
- const frames = currentPromptContextFrames().filter(
31940
- (candidate) => candidate.id !== frame.id
31941
- );
31942
- promptContextStore().enterWith(frames.length > 0 ? { frames } : void 0);
31943
- };
31944
- }
31945
- function installPiStreamPatch(agent) {
31946
- const existing = piStreamPatchStates.get(agent);
31947
- if (existing) {
31948
- if (agent.streamFn !== existing.wrappedStreamFn) {
31949
- debugLogger.debug(
31950
- "Pi Coding Agent streamFn changed while Braintrust instrumentation was active; preserving existing patch state."
31951
- );
31952
- }
31953
- return existing;
31954
- }
31955
- const patchState = {
31956
- activePromptStates: /* @__PURE__ */ new Set(),
31957
- agent,
31958
- originalStreamFn: agent.streamFn,
31959
- queuedPromptStates: [],
31960
- wrappedStreamFn: agent.streamFn
31961
- };
31962
- patchState.wrappedStreamFn = makeSharedInstrumentedStreamFn(patchState);
31963
- agent.streamFn = patchState.wrappedStreamFn;
31964
- piStreamPatchStates.set(agent, patchState);
31965
- return patchState;
31966
- }
31967
- function resolveStreamPromptState(patchState, context) {
31968
- let lastUserText;
31969
- if (Array.isArray(context.messages)) {
31970
- for (let i = context.messages.length - 1; i >= 0; i--) {
31971
- const message = context.messages[i];
31972
- if (isPiUserMessage(message)) {
31973
- if (typeof message.content === "string") {
31974
- lastUserText = message.content;
31975
- } else {
31976
- lastUserText = message.content.flatMap((part) => part.type === "text" ? [part.text] : []).join("");
31977
- }
31978
- break;
31979
- }
31980
- }
31981
- }
31982
- if (lastUserText !== void 0) {
31983
- const queuedMatch = patchState.queuedPromptStates.find(
31984
- (state) => state.promptText === lastUserText
31985
- );
31986
- if (queuedMatch) {
31987
- return queuedMatch;
31988
- }
31989
- const matches = [...patchState.activePromptStates].filter(
31990
- (state) => state.promptText === lastUserText
33380
+ return promptContextStore().getStore();
33381
+ }
33382
+ function installPiAgentInstrumentation(agent) {
33383
+ const existing = piAgentPatchStates.get(agent);
33384
+ if (!existing || agent.streamFn !== existing.wrappedStreamFn) {
33385
+ const patchState = {
33386
+ originalStreamFn: agent.streamFn,
33387
+ wrappedStreamFn: agent.streamFn
33388
+ };
33389
+ patchState.wrappedStreamFn = makeInstrumentedStreamFn(
33390
+ agent,
33391
+ patchState.originalStreamFn
31991
33392
  );
31992
- if (matches.length === 1) {
31993
- return matches[0];
31994
- }
33393
+ agent.streamFn = patchState.wrappedStreamFn;
33394
+ piAgentPatchStates.set(agent, patchState);
31995
33395
  }
31996
- const contextState = currentPiPromptState();
31997
- if (contextState && patchState.activePromptStates.has(contextState) && (!contextState.queued || lastUserText !== void 0 && contextState.promptText === lastUserText)) {
31998
- return contextState;
33396
+ if (piAgentEventSubscriptions.has(agent)) {
33397
+ return;
31999
33398
  }
32000
- if (patchState.activePromptStates.size === 1) {
32001
- return [...patchState.activePromptStates][0];
33399
+ try {
33400
+ agent.subscribe(async (event) => {
33401
+ const state = currentPiPromptState();
33402
+ if (!state || state.agent !== agent || state.finalized) {
33403
+ return;
33404
+ }
33405
+ try {
33406
+ await runWithAutoInstrumentationSuppressed(
33407
+ () => handlePiAgentEvent(state, event)
33408
+ );
33409
+ } catch (error) {
33410
+ logInstrumentationError4("Pi Coding Agent event", error);
33411
+ }
33412
+ });
33413
+ piAgentEventSubscriptions.add(agent);
33414
+ } catch (error) {
33415
+ logInstrumentationError4("Pi Coding Agent event subscription", error);
32002
33416
  }
32003
- return void 0;
32004
33417
  }
32005
- function makeSharedInstrumentedStreamFn(patchState) {
33418
+ function makeInstrumentedStreamFn(agent, originalStreamFn) {
32006
33419
  return async function instrumentedPiStreamFn(model, context, options) {
32007
- const state = resolveStreamPromptState(patchState, context);
32008
- if (!state) {
32009
- const invokeOriginal = () => Reflect.apply(patchState.originalStreamFn, this, [
32010
- model,
32011
- context,
32012
- options
32013
- ]);
32014
- return patchState.activePromptStates.size > 0 ? runWithAutoInstrumentationSuppressed(invokeOriginal) : invokeOriginal();
33420
+ const invokeOriginal = () => Reflect.apply(originalStreamFn, this, [model, context, options]);
33421
+ const state = currentPiPromptState();
33422
+ if (!state || state.agent !== agent || state.finalized) {
33423
+ return invokeOriginal();
32015
33424
  }
32016
- state.sawStreamFn = true;
32017
- removeQueuedPromptState(state);
32018
- state.streamPatchState.eventPromptState = state;
32019
33425
  const llmState = await startPiLlmSpan(state, model, context, options);
32020
33426
  try {
32021
- const stream = await runWithAutoInstrumentationSuppressed(
32022
- () => Reflect.apply(patchState.originalStreamFn, this, [
32023
- model,
32024
- context,
32025
- options
32026
- ])
32027
- );
33427
+ const stream = await runWithAutoInstrumentationSuppressed(invokeOriginal);
32028
33428
  return patchAssistantMessageStream(stream, state, llmState);
32029
33429
  } catch (error) {
32030
33430
  finishPiLlmSpan(state, llmState, void 0, error);
@@ -32171,13 +33571,6 @@ async function handlePiAgentEvent(state, event) {
32171
33571
  if (state.finalized) {
32172
33572
  return;
32173
33573
  }
32174
- const eventPromptState = state.streamPatchState.eventPromptState;
32175
- if (eventPromptState && eventPromptState !== state) {
32176
- return;
32177
- }
32178
- if (!eventPromptState && (state.queued || state.streamPatchState.activePromptStates.size > 1 && currentPiPromptState() !== state)) {
32179
- return;
32180
- }
32181
33574
  switch (event.type) {
32182
33575
  case "message_end":
32183
33576
  if (isPiAssistantMessage(event.message)) {
@@ -32192,11 +33585,8 @@ async function handlePiAgentEvent(state, event) {
32192
33585
  addMetrics(state.metrics, extractUsageMetrics2(event.message.usage));
32193
33586
  }
32194
33587
  }
32195
- if (state.streamPatchState.eventPromptState === state) {
32196
- state.streamPatchState.eventPromptState = void 0;
32197
- }
32198
33588
  if (state.promptCallEnded && state.deferCompletionUntilTurnEnd) {
32199
- await finalizePiPromptRun(state);
33589
+ finishPiPromptRun(state);
32200
33590
  }
32201
33591
  return;
32202
33592
  case "tool_execution_start":
@@ -32269,19 +33659,13 @@ function finishPiToolSpan(state, event) {
32269
33659
  }
32270
33660
  }
32271
33661
  }
32272
- async function finalizePiPromptRun(state, error) {
33662
+ function finishPiPromptRun(state, error) {
32273
33663
  if (state.finalized) {
32274
33664
  return;
32275
33665
  }
32276
33666
  state.finalized = true;
32277
33667
  state.onFinalize?.(state);
32278
- restorePiStreamFn(state);
32279
- try {
32280
- state.unsubscribeAgent?.();
32281
- } catch (unsubscribeError) {
32282
- logInstrumentationError4("Pi Coding Agent unsubscribe", unsubscribeError);
32283
- }
32284
- await finishOpenLlmSpans(state, error);
33668
+ finishOpenLlmSpans(state, error);
32285
33669
  finishOpenToolSpans(state, error);
32286
33670
  const metadata = {
32287
33671
  ...state.metadata,
@@ -32298,34 +33682,14 @@ async function finalizePiPromptRun(state, error) {
32298
33682
  output: state.output
32299
33683
  });
32300
33684
  } finally {
32301
- state.span.end();
32302
- }
32303
- }
32304
- function restorePiStreamFn(state) {
32305
- const patchState = state.streamPatchState;
32306
- patchState.activePromptStates.delete(state);
32307
- removeQueuedPromptState(state);
32308
- if (patchState.eventPromptState === state) {
32309
- patchState.eventPromptState = void 0;
32310
- }
32311
- state.restorePromptContext?.();
32312
- if (patchState.activePromptStates.size > 0) {
32313
- return;
32314
- }
32315
- if (patchState.agent.streamFn === patchState.wrappedStreamFn) {
32316
- patchState.agent.streamFn = patchState.originalStreamFn;
32317
- }
32318
- piStreamPatchStates.delete(patchState.agent);
32319
- }
32320
- function removeQueuedPromptState(state) {
32321
- state.queued = false;
32322
- const queuedPromptStates = state.streamPatchState.queuedPromptStates;
32323
- const index = queuedPromptStates.indexOf(state);
32324
- if (index >= 0) {
32325
- queuedPromptStates.splice(index, 1);
33685
+ try {
33686
+ state.span.end();
33687
+ } catch (endError) {
33688
+ logInstrumentationError4("Pi Coding Agent prompt end", endError);
33689
+ }
32326
33690
  }
32327
33691
  }
32328
- async function finishOpenLlmSpans(state, error) {
33692
+ function finishOpenLlmSpans(state, error) {
32329
33693
  for (const llmState of [...state.activeLlmSpans]) {
32330
33694
  finishPiLlmSpan(state, llmState, void 0, error);
32331
33695
  }
@@ -32406,7 +33770,7 @@ function normalizeAssistantMessage(message) {
32406
33770
  (part) => part.type === "thinking" && !part.redacted ? [part.thinking] : []
32407
33771
  ).join("");
32408
33772
  const toolCalls2 = message.content.flatMap(
32409
- (part) => part.type === "toolCall" ? [normalizeToolCall(part)] : []
33773
+ (part) => part.type === "toolCall" ? [normalizeToolCall2(part)] : []
32410
33774
  );
32411
33775
  return {
32412
33776
  role: "assistant",
@@ -32441,13 +33805,13 @@ function normalizeUserContent(content) {
32441
33805
  return part;
32442
33806
  });
32443
33807
  }
32444
- function normalizeToolCall(toolCall) {
33808
+ function normalizeToolCall2(toolCall) {
32445
33809
  return {
32446
33810
  id: toolCall.id,
32447
33811
  type: "function",
32448
33812
  function: {
32449
33813
  name: toolCall.name,
32450
- arguments: stringifyArguments(toolCall.arguments)
33814
+ arguments: stringifyArguments2(toolCall.arguments)
32451
33815
  }
32452
33816
  };
32453
33817
  }
@@ -32630,7 +33994,7 @@ function cleanMetrics5(metrics) {
32630
33994
  }
32631
33995
  return cleaned;
32632
33996
  }
32633
- function stringifyArguments(value) {
33997
+ function stringifyArguments2(value) {
32634
33998
  if (typeof value === "string") {
32635
33999
  return value;
32636
34000
  }
@@ -34221,6 +35585,7 @@ var BraintrustPlugin = class extends BasePlugin {
34221
35585
  anthropicPlugin = null;
34222
35586
  aiSDKPlugin = null;
34223
35587
  claudeAgentSDKPlugin = null;
35588
+ cloudflareThinkPlugin = null;
34224
35589
  cursorSDKPlugin = null;
34225
35590
  openAIAgentsPlugin = null;
34226
35591
  googleGenAIPlugin = null;
@@ -34229,6 +35594,7 @@ var BraintrustPlugin = class extends BasePlugin {
34229
35594
  openRouterPlugin = null;
34230
35595
  openRouterAgentPlugin = null;
34231
35596
  mistralPlugin = null;
35597
+ ollamaPlugin = null;
34232
35598
  googleADKPlugin = null;
34233
35599
  coherePlugin = null;
34234
35600
  groqPlugin = null;
@@ -34268,6 +35634,10 @@ var BraintrustPlugin = class extends BasePlugin {
34268
35634
  this.claudeAgentSDKPlugin = new ClaudeAgentSDKPlugin();
34269
35635
  this.claudeAgentSDKPlugin.enable();
34270
35636
  }
35637
+ if (integrations.cloudflareThink !== false) {
35638
+ this.cloudflareThinkPlugin = new CloudflareThinkPlugin();
35639
+ this.cloudflareThinkPlugin.enable();
35640
+ }
34271
35641
  if (integrations.cursorSDK !== false && integrations.cursor !== false) {
34272
35642
  this.cursorSDKPlugin = new CursorSDKPlugin();
34273
35643
  this.cursorSDKPlugin.enable();
@@ -34298,6 +35668,10 @@ var BraintrustPlugin = class extends BasePlugin {
34298
35668
  this.mistralPlugin = new MistralPlugin();
34299
35669
  this.mistralPlugin.enable();
34300
35670
  }
35671
+ if (integrations.ollama !== false) {
35672
+ this.ollamaPlugin = new OllamaPlugin();
35673
+ this.ollamaPlugin.enable();
35674
+ }
34301
35675
  if (integrations.googleADK !== false) {
34302
35676
  this.googleADKPlugin = new GoogleADKPlugin();
34303
35677
  this.googleADKPlugin.enable();
@@ -34374,6 +35748,10 @@ var BraintrustPlugin = class extends BasePlugin {
34374
35748
  this.claudeAgentSDKPlugin.disable();
34375
35749
  this.claudeAgentSDKPlugin = null;
34376
35750
  }
35751
+ if (this.cloudflareThinkPlugin) {
35752
+ this.cloudflareThinkPlugin.disable();
35753
+ this.cloudflareThinkPlugin = null;
35754
+ }
34377
35755
  if (this.cursorSDKPlugin) {
34378
35756
  this.cursorSDKPlugin.disable();
34379
35757
  this.cursorSDKPlugin = null;
@@ -34406,6 +35784,10 @@ var BraintrustPlugin = class extends BasePlugin {
34406
35784
  this.mistralPlugin.disable();
34407
35785
  this.mistralPlugin = null;
34408
35786
  }
35787
+ if (this.ollamaPlugin) {
35788
+ this.ollamaPlugin.disable();
35789
+ this.ollamaPlugin = null;
35790
+ }
34409
35791
  if (this.googleADKPlugin) {
34410
35792
  this.googleADKPlugin.disable();
34411
35793
  this.googleADKPlugin = null;
@@ -34491,6 +35873,7 @@ var envIntegrationAliases = {
34491
35873
  cloudflareaichat: "cloudflareAIChat",
34492
35874
  "cloudflare-ai-chat": "cloudflareAIChat",
34493
35875
  "@cloudflare/ai-chat": "cloudflareAIChat",
35876
+ cloudflarethink: "cloudflareThink",
34494
35877
  cursor: "cursor",
34495
35878
  "cursor-sdk": "cursorSDK",
34496
35879
  cursorsdk: "cursorSDK",
@@ -34511,6 +35894,7 @@ var envIntegrationAliases = {
34511
35894
  openrouteragent: "openrouterAgent",
34512
35895
  "openrouter-agent": "openrouterAgent",
34513
35896
  mistral: "mistral",
35897
+ ollama: "ollama",
34514
35898
  googleadk: "googleADK",
34515
35899
  "google-adk": "googleADK",
34516
35900
  cohere: "cohere",
@@ -34546,6 +35930,7 @@ function getDefaultInstrumentationIntegrations() {
34546
35930
  huggingface: true,
34547
35931
  claudeAgentSDK: true,
34548
35932
  cloudflareAIChat: true,
35933
+ cloudflareThink: true,
34549
35934
  cursor: true,
34550
35935
  cursorSDK: true,
34551
35936
  flue: true,
@@ -34554,6 +35939,7 @@ function getDefaultInstrumentationIntegrations() {
34554
35939
  openrouter: true,
34555
35940
  openrouterAgent: true,
34556
35941
  mistral: true,
35942
+ ollama: true,
34557
35943
  cohere: true,
34558
35944
  groq: true,
34559
35945
  bedrock: true,
@@ -34788,6 +36174,7 @@ __export(exports_exports, {
34788
36174
  braintrustFlueObserver: () => braintrustFlueObserver,
34789
36175
  braintrustStreamChunkSchema: () => braintrustStreamChunkSchema,
34790
36176
  buildLocalSummary: () => buildLocalSummary,
36177
+ collectAnthropicSession: () => collectAnthropicSession,
34791
36178
  configureInstrumentation: () => configureInstrumentation,
34792
36179
  constructLogs3OverflowRequest: () => constructLogs3OverflowRequest,
34793
36180
  createFinalValuePassThroughStream: () => createFinalValuePassThroughStream,
@@ -34867,6 +36254,7 @@ __export(exports_exports, {
34867
36254
  wrapClaudeAgentSDK: () => wrapClaudeAgentSDK,
34868
36255
  wrapCloudflareAIChat: () => wrapCloudflareAIChat,
34869
36256
  wrapCloudflareAgent: () => wrapCloudflareAgent,
36257
+ wrapCloudflareThink: () => wrapCloudflareThink,
34870
36258
  wrapCohere: () => wrapCohere,
34871
36259
  wrapCopilotClient: () => wrapCopilotClient,
34872
36260
  wrapCursorSDK: () => wrapCursorSDK,
@@ -34881,6 +36269,7 @@ __export(exports_exports, {
34881
36269
  wrapLangSmithTraceable: () => wrapLangSmithTraceable,
34882
36270
  wrapMastraAgent: () => wrapMastraAgent,
34883
36271
  wrapMistral: () => wrapMistral,
36272
+ wrapOllama: () => wrapOllama,
34884
36273
  wrapOpenAI: () => wrapOpenAI,
34885
36274
  wrapOpenAICodexSDK: () => wrapOpenAICodexSDK,
34886
36275
  wrapOpenAIv4: () => wrapOpenAIv4,
@@ -36155,7 +37544,7 @@ function normalizeUsageMetrics(usage, provider, providerMetadata) {
36155
37544
  }
36156
37545
  return metrics;
36157
37546
  }
36158
- function normalizeFinishReason(reason) {
37547
+ function normalizeFinishReason2(reason) {
36159
37548
  if (typeof reason !== "string") return void 0;
36160
37549
  return reason.replace(/-/g, "_");
36161
37550
  }
@@ -36164,7 +37553,7 @@ function buildAssistantOutputWithToolCalls(result, toolCalls2) {
36164
37553
  {
36165
37554
  index: 0,
36166
37555
  logprobs: null,
36167
- finish_reason: normalizeFinishReason(result?.finishReason) ?? (toolCalls2.length ? "tool_calls" : void 0),
37556
+ finish_reason: normalizeFinishReason2(result?.finishReason) ?? (toolCalls2.length ? "tool_calls" : void 0),
36168
37557
  message: {
36169
37558
  role: "assistant",
36170
37559
  tool_calls: toolCalls2.length > 0 ? toolCalls2 : void 0
@@ -38085,6 +39474,66 @@ function betaProxy(beta, anthropic) {
38085
39474
  if (prop === "messages") {
38086
39475
  return betaMessagesProxy(target.messages, anthropic);
38087
39476
  }
39477
+ if (prop === "sessions") {
39478
+ return target.sessions ? betaSessionsProxy(target.sessions) : target.sessions;
39479
+ }
39480
+ return Reflect.get(target, prop, receiver);
39481
+ }
39482
+ });
39483
+ }
39484
+ function betaSessionsProxy(sessions) {
39485
+ return new Proxy(sessions, {
39486
+ get(target, prop, receiver) {
39487
+ if (prop === "events") {
39488
+ return betaSessionEventsProxy(target.events);
39489
+ }
39490
+ if (prop === "threads") {
39491
+ return target.threads ? betaSessionThreadsProxy(target.threads) : target.threads;
39492
+ }
39493
+ return Reflect.get(target, prop, receiver);
39494
+ }
39495
+ });
39496
+ }
39497
+ function betaSessionEventsProxy(events) {
39498
+ return new Proxy(events, {
39499
+ get(target, prop, receiver) {
39500
+ if (prop === "stream") {
39501
+ return new TypedApplyProxy(target.stream, {
39502
+ apply(stream, thisArg, argArray) {
39503
+ return anthropicChannels.betaSessionsEventsStream.tracePromise(
39504
+ () => Reflect.apply(stream, thisArg, argArray),
39505
+ { arguments: argArray }
39506
+ );
39507
+ }
39508
+ });
39509
+ }
39510
+ return Reflect.get(target, prop, receiver);
39511
+ }
39512
+ });
39513
+ }
39514
+ function betaSessionThreadsProxy(threads) {
39515
+ return new Proxy(threads, {
39516
+ get(target, prop, receiver) {
39517
+ if (prop === "events") {
39518
+ return betaSessionThreadEventsProxy(target.events);
39519
+ }
39520
+ return Reflect.get(target, prop, receiver);
39521
+ }
39522
+ });
39523
+ }
39524
+ function betaSessionThreadEventsProxy(events) {
39525
+ return new Proxy(events, {
39526
+ get(target, prop, receiver) {
39527
+ if (prop === "stream") {
39528
+ return new TypedApplyProxy(target.stream, {
39529
+ apply(stream, thisArg, argArray) {
39530
+ return anthropicChannels.betaSessionsThreadsEventsStream.tracePromise(
39531
+ () => Reflect.apply(stream, thisArg, argArray),
39532
+ { arguments: argArray }
39533
+ );
39534
+ }
39535
+ });
39536
+ }
38088
39537
  return Reflect.get(target, prop, receiver);
38089
39538
  }
38090
39539
  });
@@ -38498,6 +39947,52 @@ function claudeAgentSDKProxy(sdk) {
38498
39947
  });
38499
39948
  }
38500
39949
 
39950
+ // src/wrappers/cloudflare-think.ts
39951
+ var WRAPPED_THINK = /* @__PURE__ */ Symbol.for("braintrust.cloudflare-think.wrapped");
39952
+ function wrapCloudflareThink(sdk) {
39953
+ if (!sdk || typeof sdk !== "object") {
39954
+ return sdk;
39955
+ }
39956
+ const thinkModule = sdk;
39957
+ if (typeof thinkModule.Think !== "function") {
39958
+ return sdk;
39959
+ }
39960
+ patchThinkClass(thinkModule.Think);
39961
+ return sdk;
39962
+ }
39963
+ function patchThinkClass(Think) {
39964
+ const prototype = Think.prototype;
39965
+ if (!prototype || prototype[WRAPPED_THINK]) {
39966
+ return;
39967
+ }
39968
+ const descriptor = Object.getOwnPropertyDescriptor(
39969
+ prototype,
39970
+ "_runInferenceLoop"
39971
+ );
39972
+ if (!descriptor || typeof descriptor.value !== "function") {
39973
+ return;
39974
+ }
39975
+ const original = descriptor.value;
39976
+ Object.defineProperty(prototype, "_runInferenceLoop", {
39977
+ ...descriptor,
39978
+ value: function wrappedCloudflareThinkRunInferenceLoop(input) {
39979
+ const args = [input];
39980
+ return cloudflareThinkChannels.runInferenceLoop.tracePromise(
39981
+ () => Reflect.apply(original, this, args),
39982
+ {
39983
+ arguments: args,
39984
+ self: this
39985
+ }
39986
+ );
39987
+ }
39988
+ });
39989
+ Object.defineProperty(prototype, WRAPPED_THINK, {
39990
+ configurable: false,
39991
+ enumerable: false,
39992
+ value: true
39993
+ });
39994
+ }
39995
+
38501
39996
  // src/wrappers/openai-codex.ts
38502
39997
  var WRAPPED_CLIENT = /* @__PURE__ */ Symbol.for("braintrust.openai-codex.wrapped-client");
38503
39998
  var WRAPPED_THREAD = /* @__PURE__ */ Symbol.for("braintrust.openai-codex.wrapped-thread");
@@ -38790,14 +40285,9 @@ function patchAgentSessionClass(AgentSession) {
38790
40285
  ...descriptor,
38791
40286
  value: function wrappedPiCodingAgentPrompt(text, options) {
38792
40287
  const args = [text, options];
38793
- return piCodingAgentChannels.prompt.tracePromise(
38794
- () => Reflect.apply(originalPrompt, this, args),
38795
- {
38796
- arguments: args,
38797
- self: this,
38798
- session: this
38799
- }
38800
- );
40288
+ return piCodingAgentChannels.prompt.invoke(originalPrompt, this, args, {
40289
+ session: this
40290
+ });
38801
40291
  }
38802
40292
  });
38803
40293
  Object.defineProperty(prototype, WRAPPED_PROMPT, {
@@ -40237,6 +41727,83 @@ function wrapAgentsStream(stream) {
40237
41727
  });
40238
41728
  }
40239
41729
 
41730
+ // src/wrappers/ollama.ts
41731
+ function wrapOllama(ollama) {
41732
+ if (isSupportedOllamaClient(ollama)) {
41733
+ return ollamaProxy(ollama);
41734
+ }
41735
+ debugLogger.warn("Unsupported Ollama library. Not wrapping.");
41736
+ return ollama;
41737
+ }
41738
+ var ollamaProxyCache = /* @__PURE__ */ new WeakMap();
41739
+ function isSupportedOllamaClient(value) {
41740
+ return isObject(value) && ["chat", "generate", "embed"].some(
41741
+ (name) => typeof value[name] === "function"
41742
+ );
41743
+ }
41744
+ function ollamaProxy(ollama) {
41745
+ const cached = ollamaProxyCache.get(ollama);
41746
+ if (cached) {
41747
+ return cached;
41748
+ }
41749
+ let chatSource;
41750
+ let wrappedChat;
41751
+ let generateSource;
41752
+ let wrappedGenerate;
41753
+ let embedSource;
41754
+ let wrappedEmbed;
41755
+ const proxy = new Proxy(ollama, {
41756
+ get(target, prop, receiver) {
41757
+ switch (prop) {
41758
+ case "chat": {
41759
+ const source = target.chat;
41760
+ if (source !== chatSource) {
41761
+ chatSource = source;
41762
+ wrappedChat = typeof source === "function" ? wrapChat(source.bind(target)) : source;
41763
+ }
41764
+ return wrappedChat;
41765
+ }
41766
+ case "generate": {
41767
+ const source = target.generate;
41768
+ if (source !== generateSource) {
41769
+ generateSource = source;
41770
+ wrappedGenerate = typeof source === "function" ? wrapGenerate2(source.bind(target)) : source;
41771
+ }
41772
+ return wrappedGenerate;
41773
+ }
41774
+ case "embed": {
41775
+ const source = target.embed;
41776
+ if (source !== embedSource) {
41777
+ embedSource = source;
41778
+ wrappedEmbed = typeof source === "function" ? wrapEmbed3(source.bind(target)) : source;
41779
+ }
41780
+ return wrappedEmbed;
41781
+ }
41782
+ default:
41783
+ return Reflect.get(target, prop, receiver);
41784
+ }
41785
+ }
41786
+ });
41787
+ ollamaProxyCache.set(ollama, proxy);
41788
+ ollamaProxyCache.set(proxy, proxy);
41789
+ return proxy;
41790
+ }
41791
+ function wrapChat(chat) {
41792
+ return (request) => ollamaChannels.chat.tracePromise(() => chat(request), {
41793
+ arguments: [request]
41794
+ });
41795
+ }
41796
+ function wrapGenerate2(generate) {
41797
+ return (request) => ollamaChannels.generate.tracePromise(() => generate(request), {
41798
+ arguments: [request]
41799
+ });
41800
+ }
41801
+ function wrapEmbed3(embed) {
41802
+ return (request) => ollamaChannels.embed.tracePromise(() => embed(request), {
41803
+ arguments: [request]
41804
+ });
41805
+ }
41806
+
40240
41807
  // src/wrappers/cohere.ts
40241
41808
  function wrapCohere(cohere) {
40242
41809
  if (isSupportedCohereClient(cohere)) {
@@ -40267,11 +41834,11 @@ function cohereProxy(cohere) {
40267
41834
  get(target, prop, receiver) {
40268
41835
  switch (prop) {
40269
41836
  case "chat":
40270
- return typeof target.chat === "function" ? wrapChat(target.chat.bind(target)) : target.chat;
41837
+ return typeof target.chat === "function" ? wrapChat2(target.chat.bind(target)) : target.chat;
40271
41838
  case "chatStream":
40272
41839
  return typeof target.chatStream === "function" ? wrapChatStream2(target.chatStream.bind(target)) : target.chatStream;
40273
41840
  case "embed":
40274
- return typeof target.embed === "function" ? wrapEmbed3(target.embed.bind(target)) : target.embed;
41841
+ return typeof target.embed === "function" ? wrapEmbed4(target.embed.bind(target)) : target.embed;
40275
41842
  case "rerank":
40276
41843
  return typeof target.rerank === "function" ? wrapRerank3(target.rerank.bind(target)) : target.rerank;
40277
41844
  default: {
@@ -40284,7 +41851,7 @@ function cohereProxy(cohere) {
40284
41851
  cohereProxyCache.set(cohere, proxy);
40285
41852
  return proxy;
40286
41853
  }
40287
- function wrapChat(chat) {
41854
+ function wrapChat2(chat) {
40288
41855
  return (request, options) => cohereChannels.chat.tracePromise(() => chat(request, options), {
40289
41856
  arguments: [request]
40290
41857
  });
@@ -40294,7 +41861,7 @@ function wrapChatStream2(chatStream) {
40294
41861
  arguments: [request]
40295
41862
  });
40296
41863
  }
40297
- function wrapEmbed3(embed) {
41864
+ function wrapEmbed4(embed) {
40298
41865
  return (request, options) => cohereChannels.embed.tracePromise(() => embed(request, options), {
40299
41866
  arguments: [request]
40300
41867
  });
@@ -45187,6 +46754,7 @@ export {
45187
46754
  braintrustFlueObserver,
45188
46755
  braintrustStreamChunkSchema,
45189
46756
  buildLocalSummary,
46757
+ collectAnthropicSession,
45190
46758
  configureInstrumentation,
45191
46759
  constructLogs3OverflowRequest,
45192
46760
  createFinalValuePassThroughStream,
@@ -45267,6 +46835,7 @@ export {
45267
46835
  wrapClaudeAgentSDK,
45268
46836
  wrapCloudflareAIChat,
45269
46837
  wrapCloudflareAgent,
46838
+ wrapCloudflareThink,
45270
46839
  wrapCohere,
45271
46840
  wrapCopilotClient,
45272
46841
  wrapCursorSDK,
@@ -45281,6 +46850,7 @@ export {
45281
46850
  wrapLangSmithTraceable,
45282
46851
  wrapMastraAgent,
45283
46852
  wrapMistral,
46853
+ wrapOllama,
45284
46854
  wrapOpenAI,
45285
46855
  wrapOpenAICodexSDK,
45286
46856
  wrapOpenAIv4,