braintrust 3.26.0 → 3.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dev/dist/index.js +2440 -1067
  2. package/dev/dist/index.mjs +1644 -271
  3. package/dist/apply-auto-instrumentation.js +320 -261
  4. package/dist/apply-auto-instrumentation.mjs +118 -59
  5. package/dist/auto-instrumentations/bundler/esbuild.cjs +377 -59
  6. package/dist/auto-instrumentations/bundler/esbuild.mjs +5 -4
  7. package/dist/auto-instrumentations/bundler/next.cjs +379 -61
  8. package/dist/auto-instrumentations/bundler/next.mjs +6 -5
  9. package/dist/auto-instrumentations/bundler/rollup.cjs +377 -59
  10. package/dist/auto-instrumentations/bundler/rollup.mjs +5 -4
  11. package/dist/auto-instrumentations/bundler/vite.cjs +406 -60
  12. package/dist/auto-instrumentations/bundler/vite.mjs +34 -5
  13. package/dist/auto-instrumentations/bundler/webpack-loader.cjs +363 -59
  14. package/dist/auto-instrumentations/bundler/webpack.cjs +377 -59
  15. package/dist/auto-instrumentations/bundler/webpack.mjs +6 -5
  16. package/dist/auto-instrumentations/{chunk-AKKPLXTP.mjs → chunk-2AMDGD65.mjs} +160 -57
  17. package/dist/auto-instrumentations/{chunk-V5LEODRX.mjs → chunk-BW33ULMW.mjs} +1 -1
  18. package/dist/auto-instrumentations/{chunk-XYN63IG5.mjs → chunk-I55G56ZL.mjs} +21 -58
  19. package/dist/auto-instrumentations/{chunk-NRE4QUQR.mjs → chunk-JPUFNW7X.mjs} +140 -0
  20. package/dist/auto-instrumentations/{chunk-6E22MYSW.mjs → chunk-XEYKUBLY.mjs} +30 -4
  21. package/dist/auto-instrumentations/{chunk-XZHHE4Y3.mjs → chunk-ZNHTSSGI.mjs} +155 -2
  22. package/dist/auto-instrumentations/hook.mjs +161 -3
  23. package/dist/auto-instrumentations/index.cjs +296 -1
  24. package/dist/auto-instrumentations/index.d.mts +5 -1
  25. package/dist/auto-instrumentations/index.d.ts +5 -1
  26. package/dist/auto-instrumentations/index.mjs +6 -2
  27. package/dist/auto-instrumentations/loader/cjs-patch.cjs +105 -57
  28. package/dist/auto-instrumentations/loader/cjs-patch.mjs +2 -2
  29. package/dist/auto-instrumentations/loader/esm-hook.mjs +1 -1
  30. package/dist/browser.d.mts +57 -5
  31. package/dist/browser.d.ts +57 -5
  32. package/dist/browser.js +1855 -285
  33. package/dist/browser.mjs +1855 -285
  34. package/dist/{chunk-PN7EWK66.mjs → chunk-CZM5JIQL.mjs} +209 -1
  35. package/dist/{chunk-VYNNEKSA.js → chunk-MF7NU6BT.js} +216 -8
  36. package/dist/{chunk-VRZZQPAA.js → chunk-QRHGVBKU.js} +2403 -1220
  37. package/dist/{chunk-XIZOM2HO.mjs → chunk-YKD22IMR.mjs} +1454 -271
  38. package/dist/cli.js +1645 -272
  39. package/dist/edge-light.d.mts +1 -1
  40. package/dist/edge-light.d.ts +1 -1
  41. package/dist/edge-light.js +1855 -285
  42. package/dist/edge-light.mjs +1855 -285
  43. package/dist/index.d.mts +57 -5
  44. package/dist/index.d.ts +57 -5
  45. package/dist/index.js +600 -413
  46. package/dist/index.mjs +201 -14
  47. package/dist/instrumentation/index.d.mts +8 -0
  48. package/dist/instrumentation/index.d.ts +8 -0
  49. package/dist/instrumentation/index.js +1839 -466
  50. package/dist/instrumentation/index.mjs +1839 -466
  51. package/dist/vitest-evals-reporter.js +45 -43
  52. package/dist/vitest-evals-reporter.mjs +5 -3
  53. package/dist/workerd.d.mts +1 -1
  54. package/dist/workerd.d.ts +1 -1
  55. package/dist/workerd.js +1855 -285
  56. package/dist/workerd.mjs +1855 -285
  57. package/package.json +1 -1
package/dist/browser.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,
@@ -11493,6 +11635,34 @@ function patchStreamIfNeeded(stream, options) {
11493
11635
  );
11494
11636
  return stream;
11495
11637
  }
11638
+ const chunks = [];
11639
+ let completed = false;
11640
+ const notifyCancellation = async () => {
11641
+ try {
11642
+ await (options.onCancel ?? options.onComplete)(chunks);
11643
+ } catch (error) {
11644
+ debugLogger.error("Error in stream cancellation handler:", error);
11645
+ }
11646
+ };
11647
+ const patchAbortIfPresent = () => {
11648
+ try {
11649
+ if ("abort" in stream && typeof stream.abort === "function") {
11650
+ const originalAbort = stream.abort.bind(stream);
11651
+ stream.abort = (...args) => {
11652
+ try {
11653
+ return originalAbort(...args);
11654
+ } finally {
11655
+ if (!completed) {
11656
+ completed = true;
11657
+ void notifyCancellation();
11658
+ }
11659
+ }
11660
+ };
11661
+ }
11662
+ } catch (error) {
11663
+ debugLogger.warn("Failed to patch stream abort method:", error);
11664
+ }
11665
+ };
11496
11666
  if (hasAsyncIteratorMethods(stream) && isSelfAsyncIterator(stream)) {
11497
11667
  if ("__braintrust_patched_iterator_methods" in stream) {
11498
11668
  return stream;
@@ -11501,8 +11671,6 @@ function patchStreamIfNeeded(stream, options) {
11501
11671
  const originalNext = stream.next.bind(stream);
11502
11672
  const originalReturn = typeof stream.return === "function" ? stream.return.bind(stream) : null;
11503
11673
  const originalThrow = typeof stream.throw === "function" ? stream.throw.bind(stream) : null;
11504
- const chunks = [];
11505
- let completed = false;
11506
11674
  stream.next = async (...args) => {
11507
11675
  try {
11508
11676
  const result = await runNextWithWrapper(
@@ -11554,11 +11722,7 @@ function patchStreamIfNeeded(stream, options) {
11554
11722
  stream.return = async (...args) => {
11555
11723
  if (!completed) {
11556
11724
  completed = true;
11557
- try {
11558
- await options.onComplete(chunks);
11559
- } catch (error) {
11560
- console.error("Error in stream onComplete handler:", error);
11561
- }
11725
+ await notifyCancellation();
11562
11726
  }
11563
11727
  return originalReturn(...args);
11564
11728
  };
@@ -11583,6 +11747,7 @@ function patchStreamIfNeeded(stream, options) {
11583
11747
  Object.defineProperty(stream, "__braintrust_patched_iterator_methods", {
11584
11748
  value: true
11585
11749
  });
11750
+ patchAbortIfPresent();
11586
11751
  return stream;
11587
11752
  } catch (error) {
11588
11753
  console.warn("Failed to patch stream iterator methods:", error);
@@ -11596,8 +11761,6 @@ function patchStreamIfNeeded(stream, options) {
11596
11761
  const patchedIteratorFn = function() {
11597
11762
  const iterator = originalIteratorFn.call(this);
11598
11763
  const originalNext = iterator.next.bind(iterator);
11599
- const chunks = [];
11600
- let completed = false;
11601
11764
  iterator.next = async function(...args) {
11602
11765
  try {
11603
11766
  const result = await runNextWithWrapper(
@@ -11650,11 +11813,7 @@ function patchStreamIfNeeded(stream, options) {
11650
11813
  iterator.return = async function(...args) {
11651
11814
  if (!completed) {
11652
11815
  completed = true;
11653
- try {
11654
- await options.onComplete(chunks);
11655
- } catch (error) {
11656
- console.error("Error in stream onComplete handler:", error);
11657
- }
11816
+ await notifyCancellation();
11658
11817
  }
11659
11818
  return originalReturn(...args);
11660
11819
  };
@@ -11683,6 +11842,7 @@ function patchStreamIfNeeded(stream, options) {
11683
11842
  value: true
11684
11843
  });
11685
11844
  stream[Symbol.asyncIterator] = patchedIteratorFn;
11845
+ patchAbortIfPresent();
11686
11846
  return stream;
11687
11847
  } catch (error) {
11688
11848
  console.warn("Failed to patch stream:", error);
@@ -12431,6 +12591,33 @@ function traceStreamingChannel(channel2, config) {
12431
12591
  const { span, startTime } = spanData;
12432
12592
  if (isAsyncIterable(asyncEndEvent.result)) {
12433
12593
  let firstChunkTime;
12594
+ const handleStreamError = (error) => {
12595
+ try {
12596
+ span.log({ error });
12597
+ } catch (loggingError) {
12598
+ debugLogger.error(
12599
+ `Error logging failure for ${channelName}:`,
12600
+ loggingError
12601
+ );
12602
+ }
12603
+ try {
12604
+ span.end();
12605
+ } catch (endingError) {
12606
+ debugLogger.error(
12607
+ `Error ending span for ${channelName}:`,
12608
+ endingError
12609
+ );
12610
+ }
12611
+ states.delete(event);
12612
+ runStreamingErrorHook({
12613
+ channelName,
12614
+ config,
12615
+ error,
12616
+ event: asyncEndEvent,
12617
+ span,
12618
+ startTime
12619
+ });
12620
+ };
12434
12621
  patchStreamIfNeeded(asyncEndEvent.result, {
12435
12622
  onChunk: () => {
12436
12623
  if (firstChunkTime === void 0) {
@@ -12510,33 +12697,12 @@ function traceStreamingChannel(channel2, config) {
12510
12697
  });
12511
12698
  }
12512
12699
  },
12513
- onError: (error) => {
12514
- try {
12515
- span.log({ error });
12516
- } catch (loggingError) {
12517
- debugLogger.error(
12518
- `Error logging failure for ${channelName}:`,
12519
- loggingError
12520
- );
12521
- }
12522
- try {
12523
- span.end();
12524
- } catch (endingError) {
12525
- debugLogger.error(
12526
- `Error ending span for ${channelName}:`,
12527
- endingError
12528
- );
12529
- }
12530
- states.delete(event);
12531
- runStreamingErrorHook({
12532
- channelName,
12533
- config,
12534
- error,
12535
- event: asyncEndEvent,
12536
- span,
12537
- startTime
12538
- });
12539
- }
12700
+ onCancel: () => {
12701
+ const error = new Error("Stream cancelled before completion");
12702
+ error.name = "AbortError";
12703
+ handleStreamError(error);
12704
+ },
12705
+ onError: handleStreamError
12540
12706
  });
12541
12707
  return;
12542
12708
  }
@@ -12924,11 +13090,21 @@ function defineChannels(pkg, channels, options) {
12924
13090
  const tracingChannel2 = () => isomorph_default.newTracingChannel(
12925
13091
  fullChannelName
12926
13092
  );
13093
+ const intercept2 = (interceptor) => {
13094
+ const hook = tracingChannel2();
13095
+ return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
13096
+ };
13097
+ };
12927
13098
  return [
12928
13099
  key,
12929
13100
  {
12930
13101
  ...asyncSpec,
12931
13102
  instrumentationName,
13103
+ intercept: intercept2,
13104
+ invoke: (target, thisArg, args, additional) => {
13105
+ const hook = tracingChannel2();
13106
+ return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
13107
+ },
12932
13108
  tracingChannel: tracingChannel2,
12933
13109
  tracePromise: (fn, context) => tracingChannel2().tracePromise(
12934
13110
  fn,
@@ -12942,11 +13118,21 @@ function defineChannels(pkg, channels, options) {
12942
13118
  const tracingChannel = () => isomorph_default.newTracingChannel(
12943
13119
  fullChannelName
12944
13120
  );
13121
+ const intercept = (interceptor) => {
13122
+ const hook = tracingChannel();
13123
+ return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
13124
+ };
13125
+ };
12945
13126
  return [
12946
13127
  key,
12947
13128
  {
12948
13129
  ...syncSpec,
12949
13130
  instrumentationName,
13131
+ intercept,
13132
+ invoke: (target, thisArg, args, additional) => {
13133
+ const hook = tracingChannel();
13134
+ return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
13135
+ },
12950
13136
  tracingChannel,
12951
13137
  traceSync: (fn, context) => tracingChannel().traceSync(
12952
13138
  fn,
@@ -14197,6 +14383,25 @@ function extractAnthropicCacheTokens(cacheReadTokens = 0, cacheCreationTokens =
14197
14383
  return cacheTokens;
14198
14384
  }
14199
14385
 
14386
+ // src/wrappers/anthropic-session-collector.ts
14387
+ var sessionStreamCollectors = /* @__PURE__ */ new WeakMap();
14388
+ function registerAnthropicSessionStreamCollector(stream, collector) {
14389
+ sessionStreamCollectors.set(stream, collector);
14390
+ }
14391
+ function collectAnthropicSession(stream) {
14392
+ const collector = sessionStreamCollectors.get(stream);
14393
+ if (!collector) {
14394
+ return stream;
14395
+ }
14396
+ sessionStreamCollectors.delete(stream);
14397
+ try {
14398
+ collector();
14399
+ } catch (error) {
14400
+ debugLogger.error("Failed to collect Anthropic Sessions stream:", error);
14401
+ }
14402
+ return stream;
14403
+ }
14404
+
14200
14405
  // src/instrumentation/plugins/anthropic-channels.ts
14201
14406
  var anthropicChannels = defineChannels(
14202
14407
  "@anthropic-ai/sdk",
@@ -14212,6 +14417,14 @@ var anthropicChannels = defineChannels(
14212
14417
  betaMessagesToolRunner: channel({
14213
14418
  channelName: "beta.messages.toolRunner",
14214
14419
  kind: "sync-stream"
14420
+ }),
14421
+ betaSessionsEventsStream: channel({
14422
+ channelName: "beta.sessions.events.stream",
14423
+ kind: "async"
14424
+ }),
14425
+ betaSessionsThreadsEventsStream: channel({
14426
+ channelName: "beta.sessions.threads.events.stream",
14427
+ kind: "async"
14215
14428
  })
14216
14429
  },
14217
14430
  { instrumentationName: INSTRUMENTATION_NAMES.ANTHROPIC }
@@ -14225,6 +14438,7 @@ var AnthropicPlugin = class extends BasePlugin {
14225
14438
  onEnable() {
14226
14439
  this.subscribeToAnthropicChannels();
14227
14440
  this.subscribeToAnthropicToolRunner();
14441
+ this.subscribeToAnthropicSessionStreams();
14228
14442
  }
14229
14443
  onDisable() {
14230
14444
  this.unsubscribers = unsubscribeAll(this.unsubscribers);
@@ -14342,7 +14556,411 @@ var AnthropicPlugin = class extends BasePlugin {
14342
14556
  tracingChannel.unsubscribe(handlers);
14343
14557
  });
14344
14558
  }
14559
+ subscribeToAnthropicSessionStreams() {
14560
+ this.subscribeToAnthropicSessionStream(
14561
+ anthropicChannels.betaSessionsEventsStream,
14562
+ false
14563
+ );
14564
+ this.subscribeToAnthropicSessionStream(
14565
+ anthropicChannels.betaSessionsThreadsEventsStream,
14566
+ true
14567
+ );
14568
+ }
14569
+ subscribeToAnthropicSessionStream(channel2, isThread) {
14570
+ const tracingChannel = channel2.tracingChannel();
14571
+ const pending = /* @__PURE__ */ new WeakSet();
14572
+ const handlers = {
14573
+ start: (event) => {
14574
+ if (isAutoInstrumentationSuppressed()) {
14575
+ return;
14576
+ }
14577
+ pending.add(event);
14578
+ },
14579
+ asyncEnd: (event) => {
14580
+ if (!pending.delete(event)) {
14581
+ return;
14582
+ }
14583
+ const stream = event.result;
14584
+ if (!isAsyncIterable(stream)) {
14585
+ return;
14586
+ }
14587
+ registerAnthropicSessionStreamCollector(stream, () => {
14588
+ wrapAnthropicSessionEventStream(stream, isThread);
14589
+ });
14590
+ },
14591
+ error: (event) => {
14592
+ pending.delete(event);
14593
+ }
14594
+ };
14595
+ tracingChannel.subscribe(handlers);
14596
+ this.unsubscribers.push(() => tracingChannel.unsubscribe(handlers));
14597
+ }
14345
14598
  };
14599
+ function wrapAnthropicSessionEventStream(stream, isThread) {
14600
+ const state = {
14601
+ history: [],
14602
+ isThread,
14603
+ pendingInput: [],
14604
+ seenEventIds: /* @__PURE__ */ new Set()
14605
+ };
14606
+ patchStreamIfNeeded(stream, {
14607
+ onChunk: (event) => handleAnthropicSessionEvent(state, event),
14608
+ onComplete: () => finalizeAnthropicSessionTurn(state),
14609
+ onError: (error) => finalizeAnthropicSessionTurn(state, error)
14610
+ });
14611
+ return stream;
14612
+ }
14613
+ function handleAnthropicSessionEvent(state, event) {
14614
+ try {
14615
+ if (typeof event.id === "string" && event.type !== "event_delta" && state.seenEventIds.has(event.id)) {
14616
+ return;
14617
+ }
14618
+ if (typeof event.id === "string" && event.type !== "event_delta") {
14619
+ state.seenEventIds.add(event.id);
14620
+ }
14621
+ switch (event.type) {
14622
+ case "user.message":
14623
+ case "system.message":
14624
+ recordAnthropicSessionInput(
14625
+ state,
14626
+ event
14627
+ );
14628
+ break;
14629
+ case "session.status_running":
14630
+ if (!state.isThread) {
14631
+ ensureAnthropicSessionTurn(state);
14632
+ }
14633
+ break;
14634
+ case "session.thread_status_running":
14635
+ if (state.isThread) {
14636
+ ensureAnthropicSessionTurn(state);
14637
+ }
14638
+ break;
14639
+ case "span.model_request_start":
14640
+ if (typeof event.id === "string") {
14641
+ startAnthropicSessionModel(state, event.id);
14642
+ }
14643
+ break;
14644
+ case "event_delta":
14645
+ recordAnthropicSessionFirstToken(state, event);
14646
+ break;
14647
+ case "agent.message":
14648
+ recordAnthropicSessionMessage(
14649
+ state,
14650
+ event
14651
+ );
14652
+ break;
14653
+ case "agent.custom_tool_use":
14654
+ case "agent.mcp_tool_use":
14655
+ case "agent.tool_use":
14656
+ startAnthropicSessionTool(state, event);
14657
+ break;
14658
+ case "user.tool_confirmation":
14659
+ recordAnthropicSessionToolConfirmation(state, event);
14660
+ break;
14661
+ case "agent.mcp_tool_result":
14662
+ case "agent.tool_result":
14663
+ case "user.custom_tool_result":
14664
+ case "user.tool_result":
14665
+ finalizeAnthropicSessionTool(
14666
+ state,
14667
+ event
14668
+ );
14669
+ break;
14670
+ case "span.model_request_end":
14671
+ finalizeAnthropicSessionModel(
14672
+ state,
14673
+ event
14674
+ );
14675
+ break;
14676
+ case "session.status_idle":
14677
+ case "session.thread_status_idle": {
14678
+ if (event.type === "session.status_idle" && state.isThread || event.type === "session.thread_status_idle" && !state.isThread) {
14679
+ break;
14680
+ }
14681
+ const stopReason = isObject(event.stop_reason) ? event.stop_reason.type : void 0;
14682
+ if (stopReason === "end_turn") {
14683
+ finalizeAnthropicSessionTurn(state);
14684
+ } else if (stopReason === "retries_exhausted") {
14685
+ finalizeAnthropicSessionTurn(
14686
+ state,
14687
+ "Anthropic session retries exhausted"
14688
+ );
14689
+ }
14690
+ break;
14691
+ }
14692
+ case "session.error":
14693
+ finalizeAnthropicSessionTurn(state, event.error);
14694
+ break;
14695
+ case "session.deleted":
14696
+ case "session.status_terminated":
14697
+ case "session.thread_status_terminated":
14698
+ if (event.type === "session.deleted" || event.type === "session.status_terminated" && !state.isThread || event.type === "session.thread_status_terminated" && state.isThread) {
14699
+ finalizeAnthropicSessionTurn(state);
14700
+ }
14701
+ break;
14702
+ default:
14703
+ break;
14704
+ }
14705
+ } catch (error) {
14706
+ debugLogger.debug("Error processing Anthropic Sessions event:", error);
14707
+ }
14708
+ }
14709
+ function ensureAnthropicSessionTurn(state) {
14710
+ if (state.activeTurn) {
14711
+ return state.activeTurn;
14712
+ }
14713
+ const input = state.pendingInput;
14714
+ state.pendingInput = [];
14715
+ const span = startSpan(
14716
+ withSpanInstrumentationName(
14717
+ {
14718
+ event: {
14719
+ ...input.length > 0 ? { input } : {},
14720
+ metadata: { provider: "anthropic" }
14721
+ },
14722
+ name: state.isThread ? "anthropic.beta.sessions.thread.turn" : "anthropic.beta.sessions.turn",
14723
+ spanAttributes: { type: "task" /* TASK */ }
14724
+ },
14725
+ INSTRUMENTATION_NAMES.ANTHROPIC
14726
+ )
14727
+ );
14728
+ state.activeTurn = {
14729
+ activeTools: /* @__PURE__ */ new Map(),
14730
+ input: input.slice(),
14731
+ metrics: {},
14732
+ span
14733
+ };
14734
+ return state.activeTurn;
14735
+ }
14736
+ function recordAnthropicSessionInput(state, event) {
14737
+ const content = processAttachmentsInInput(event.content);
14738
+ const message = {
14739
+ role: event.type === "system.message" ? "system" : "user",
14740
+ content
14741
+ };
14742
+ state.history.push(message);
14743
+ if (state.activeTurn) {
14744
+ state.activeTurn.input.push(message);
14745
+ } else {
14746
+ state.pendingInput.push(message);
14747
+ }
14748
+ }
14749
+ function startAnthropicSessionModel(state, startEventId) {
14750
+ const turn = ensureAnthropicSessionTurn(state);
14751
+ if (turn.activeModel) {
14752
+ finalizeAnthropicSessionModelState(state, turn);
14753
+ }
14754
+ const span = withCurrent(
14755
+ turn.span,
14756
+ () => startSpan(
14757
+ withSpanInstrumentationName(
14758
+ {
14759
+ event: {
14760
+ ...state.history.length > 0 ? { input: state.history.slice() } : {},
14761
+ metadata: { provider: "anthropic" }
14762
+ },
14763
+ name: "anthropic.messages.create",
14764
+ spanAttributes: { type: "llm" /* LLM */ }
14765
+ },
14766
+ INSTRUMENTATION_NAMES.ANTHROPIC
14767
+ )
14768
+ )
14769
+ );
14770
+ turn.activeModel = {
14771
+ output: [],
14772
+ span,
14773
+ startEventId,
14774
+ startTime: getCurrentUnixTimestamp()
14775
+ };
14776
+ }
14777
+ function recordAnthropicSessionFirstToken(state, event) {
14778
+ const model = state.activeTurn?.activeModel;
14779
+ if (!model || model.firstTokenTime !== void 0 || !isObject(event.delta) || !isObject(event.delta.content) || typeof event.delta.content.text !== "string") {
14780
+ return;
14781
+ }
14782
+ model.firstTokenTime = getCurrentUnixTimestamp();
14783
+ }
14784
+ function recordAnthropicSessionMessage(state, event) {
14785
+ const turn = ensureAnthropicSessionTurn(state);
14786
+ const content = processAttachmentsInInput(
14787
+ event.content
14788
+ );
14789
+ if (turn.activeModel) {
14790
+ turn.activeModel.output.push(...content);
14791
+ } else {
14792
+ const output = { role: "assistant", content };
14793
+ turn.lastOutput = output;
14794
+ state.history.push(output);
14795
+ }
14796
+ }
14797
+ function startAnthropicSessionTool(state, event) {
14798
+ const turn = ensureAnthropicSessionTurn(state);
14799
+ if (turn.activeModel) {
14800
+ turn.activeModel.output.push({
14801
+ type: "tool_use",
14802
+ id: event.id,
14803
+ name: event.name,
14804
+ input: event.input
14805
+ });
14806
+ }
14807
+ const existing = turn.activeTools.get(event.id);
14808
+ if (existing) {
14809
+ existing.span.end();
14810
+ turn.activeTools.delete(event.id);
14811
+ }
14812
+ const span = withCurrent(
14813
+ turn.span,
14814
+ () => startSpan(
14815
+ withSpanInstrumentationName(
14816
+ {
14817
+ event: { input: event.input },
14818
+ name: event.name,
14819
+ spanAttributes: { type: "tool" /* TOOL */ }
14820
+ },
14821
+ INSTRUMENTATION_NAMES.ANTHROPIC
14822
+ )
14823
+ )
14824
+ );
14825
+ const toolState = {
14826
+ approval: event.evaluated_permission === "allow" ? "approved" : event.evaluated_permission === "deny" ? "denied" : void 0,
14827
+ span
14828
+ };
14829
+ turn.activeTools.set(event.id, toolState);
14830
+ if (toolState.approval === "denied") {
14831
+ finalizeAnthropicSessionToolState(toolState);
14832
+ turn.activeTools.delete(event.id);
14833
+ }
14834
+ }
14835
+ function recordAnthropicSessionToolConfirmation(state, event) {
14836
+ if (typeof event.tool_use_id !== "string" || event.result !== "allow" && event.result !== "deny") {
14837
+ return;
14838
+ }
14839
+ const turn = state.activeTurn;
14840
+ const tool = turn?.activeTools.get(event.tool_use_id);
14841
+ if (!turn || !tool) {
14842
+ return;
14843
+ }
14844
+ tool.approval = event.result === "allow" ? "approved" : "denied";
14845
+ if (tool.approval === "denied") {
14846
+ finalizeAnthropicSessionToolState(tool);
14847
+ turn.activeTools.delete(event.tool_use_id);
14848
+ }
14849
+ }
14850
+ function finalizeAnthropicSessionTool(state, event) {
14851
+ const toolUseId = event.tool_use_id ?? event.mcp_tool_use_id ?? event.custom_tool_use_id;
14852
+ if (!toolUseId) {
14853
+ return;
14854
+ }
14855
+ const content = processAttachmentsInInput(event.content);
14856
+ const turn = state.activeTurn;
14857
+ const tool = turn?.activeTools.get(toolUseId);
14858
+ if (turn && tool) {
14859
+ finalizeAnthropicSessionToolState(tool, event, content);
14860
+ turn.activeTools.delete(toolUseId);
14861
+ }
14862
+ const toolResult = {
14863
+ type: "tool_result",
14864
+ tool_use_id: toolUseId,
14865
+ ...content !== void 0 ? { content } : {},
14866
+ ...event.is_error === true ? { is_error: true } : {}
14867
+ };
14868
+ state.history.push({
14869
+ role: "user",
14870
+ content: [toolResult]
14871
+ });
14872
+ }
14873
+ function finalizeAnthropicSessionToolState(state, event, content = event?.content) {
14874
+ safeAnthropicSessionLog(state.span, {
14875
+ ...event?.is_error === true ? {
14876
+ error: content ?? "Anthropic session tool execution failed"
14877
+ } : {},
14878
+ ...state.approval ? { metadata: { tool_approval: state.approval } } : {},
14879
+ ...content !== void 0 ? { output: content } : {}
14880
+ });
14881
+ state.span.end();
14882
+ }
14883
+ function finalizeAnthropicSessionModel(state, event) {
14884
+ const turn = state.activeTurn;
14885
+ const model = turn?.activeModel;
14886
+ if (!turn || !model || model.startEventId !== event.model_request_start_id) {
14887
+ return;
14888
+ }
14889
+ finalizeAnthropicSessionModelState(state, turn, event);
14890
+ }
14891
+ function finalizeAnthropicSessionModelState(state, turn, event) {
14892
+ const model = turn.activeModel;
14893
+ if (!model) {
14894
+ return;
14895
+ }
14896
+ turn.activeModel = void 0;
14897
+ const metrics = event ? parseAnthropicSessionModelUsage(event.model_usage) : {};
14898
+ if (model.firstTokenTime !== void 0) {
14899
+ metrics.time_to_first_token = model.firstTokenTime - model.startTime;
14900
+ }
14901
+ const output = model.output.length > 0 ? { role: "assistant", content: model.output } : void 0;
14902
+ safeAnthropicSessionLog(model.span, {
14903
+ ...event?.is_error ? { error: "Anthropic session model request failed" } : {},
14904
+ ...Object.keys(metrics).length > 0 ? { metrics } : {},
14905
+ ...output ? { output } : {}
14906
+ });
14907
+ model.span.end();
14908
+ if (output) {
14909
+ turn.lastOutput = output;
14910
+ state.history.push(output);
14911
+ }
14912
+ for (const key of [
14913
+ "prompt_tokens",
14914
+ "completion_tokens",
14915
+ "tokens",
14916
+ "prompt_cached_tokens",
14917
+ "prompt_cache_creation_tokens"
14918
+ ]) {
14919
+ const value = metrics[key];
14920
+ if (typeof value === "number") {
14921
+ turn.metrics[key] = (turn.metrics[key] ?? 0) + value;
14922
+ }
14923
+ }
14924
+ }
14925
+ function parseAnthropicSessionModelUsage(usage) {
14926
+ const finalized = finalizeAnthropicTokens({
14927
+ completion_tokens: usage.output_tokens,
14928
+ prompt_cache_creation_tokens: usage.cache_creation_input_tokens,
14929
+ prompt_cached_tokens: usage.cache_read_input_tokens,
14930
+ prompt_tokens: usage.input_tokens
14931
+ });
14932
+ return Object.fromEntries(
14933
+ Object.entries(finalized).filter(
14934
+ (entry) => entry[1] !== void 0
14935
+ )
14936
+ );
14937
+ }
14938
+ function finalizeAnthropicSessionTurn(state, error) {
14939
+ const turn = state.activeTurn;
14940
+ if (!turn) {
14941
+ return;
14942
+ }
14943
+ state.activeTurn = void 0;
14944
+ finalizeAnthropicSessionModelState(state, turn);
14945
+ for (const tool of turn.activeTools.values()) {
14946
+ finalizeAnthropicSessionToolState(tool);
14947
+ }
14948
+ turn.activeTools.clear();
14949
+ safeAnthropicSessionLog(turn.span, {
14950
+ ...error !== void 0 ? { error: error instanceof Error ? error : toLoggedError(error) } : {},
14951
+ ...turn.input.length > 0 ? { input: turn.input } : {},
14952
+ ...turn.lastOutput ? { output: turn.lastOutput } : {},
14953
+ ...Object.keys(turn.metrics).length > 0 ? { metrics: turn.metrics } : {}
14954
+ });
14955
+ turn.span.end();
14956
+ }
14957
+ function safeAnthropicSessionLog(span, event) {
14958
+ try {
14959
+ span.log(event);
14960
+ } catch (error) {
14961
+ debugLogger.debug("Error logging Anthropic Sessions span:", error);
14962
+ }
14963
+ }
14346
14964
  function parseMetricsFromUsage2(usage) {
14347
14965
  if (!usage) {
14348
14966
  return {};
@@ -16216,6 +16834,29 @@ var harnessAgentChannels = defineChannels(
16216
16834
  { instrumentationName: INSTRUMENTATION_NAMES.AI_SDK }
16217
16835
  );
16218
16836
 
16837
+ // src/instrumentation/plugins/cloudflare-think-context.ts
16838
+ var cloudflareThinkSpans = /* @__PURE__ */ new Map();
16839
+ function registerCloudflareThinkSpan(span) {
16840
+ if (span.spanId) {
16841
+ cloudflareThinkSpans.set(span.spanId, span);
16842
+ }
16843
+ }
16844
+ function unregisterCloudflareThinkSpan(span) {
16845
+ if (span.spanId) {
16846
+ cloudflareThinkSpans.delete(span.spanId);
16847
+ }
16848
+ }
16849
+ function currentCloudflareThinkSpan() {
16850
+ const parentSpanIds = _internalGetGlobalState()?.contextManager.getParentSpanIds()?.spanParents ?? [];
16851
+ for (const parentSpanId of parentSpanIds) {
16852
+ const span = cloudflareThinkSpans.get(parentSpanId);
16853
+ if (span) {
16854
+ return span;
16855
+ }
16856
+ }
16857
+ return void 0;
16858
+ }
16859
+
16219
16860
  // src/instrumentation/plugins/ai-sdk-plugin.ts
16220
16861
  var DEFAULT_DENY_OUTPUT_PATHS = [
16221
16862
  // v3
@@ -16322,6 +16963,7 @@ var AISDKPlugin = class extends BasePlugin {
16322
16963
  traceStreamingChannel(aiSDKChannels.streamText, {
16323
16964
  name: "streamText",
16324
16965
  type: "function" /* FUNCTION */,
16966
+ shouldTrace: () => currentCloudflareThinkSpan() === void 0,
16325
16967
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
16326
16968
  extractOutput: (result, endEvent) => processAISDKOutput(
16327
16969
  result,
@@ -16342,6 +16984,7 @@ var AISDKPlugin = class extends BasePlugin {
16342
16984
  traceSyncStreamChannel(aiSDKChannels.streamTextSync, {
16343
16985
  name: "streamText",
16344
16986
  type: "function" /* FUNCTION */,
16987
+ shouldTrace: () => currentCloudflareThinkSpan() === void 0,
16345
16988
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
16346
16989
  patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
16347
16990
  defaultDenyOutputPaths: denyOutputPaths,
@@ -17327,6 +17970,23 @@ function prepareAISDKWorkflowAgentStreamInput(params, event, span, defaultDenyOu
17327
17970
  metadata
17328
17971
  };
17329
17972
  }
17973
+ function prepareAISDKAgentCallInput(params, event, span, defaultDenyOutputPaths = DEFAULT_DENY_OUTPUT_PATHS) {
17974
+ const { input } = processAISDKWorkflowAgentCallInput(params);
17975
+ const metadata = extractMetadataFromCallParams(params, event.self);
17976
+ const childTracing = prepareAISDKChildTracing(
17977
+ params,
17978
+ event.self,
17979
+ span,
17980
+ defaultDenyOutputPaths,
17981
+ event.aiSDK,
17982
+ { agentOwner: true }
17983
+ );
17984
+ event.modelWrapped = childTracing.modelWrapped;
17985
+ if (childTracing.cleanup) {
17986
+ event.__braintrust_ai_sdk_cleanup = childTracing.cleanup;
17987
+ }
17988
+ return { input, metadata };
17989
+ }
17330
17990
  function prepareAISDKEmbedInput(params, self) {
17331
17991
  return {
17332
17992
  input: { ...params },
@@ -17350,6 +18010,18 @@ function extractTopLevelAISDKMetrics(result, event, startTime) {
17350
18010
  }
17351
18011
  return metrics;
17352
18012
  }
18013
+ async function extractResolvedAISDKTokenMetrics(result) {
18014
+ for (const field of ["totalUsage", "usage"]) {
18015
+ try {
18016
+ const usage = await Promise.resolve(result[field]);
18017
+ if (usage !== void 0) {
18018
+ return extractTokenMetrics({ [field]: usage });
18019
+ }
18020
+ } catch {
18021
+ }
18022
+ }
18023
+ return extractTokenMetrics(result);
18024
+ }
17353
18025
  function hasModelChildTracing(event) {
17354
18026
  return event?.modelWrapped === true || event?.__braintrust_ai_sdk_model_wrapped === true;
17355
18027
  }
@@ -18167,13 +18839,15 @@ function patchAISDKStreamingResult(args) {
18167
18839
  const {
18168
18840
  defaultDenyOutputPaths,
18169
18841
  endEvent,
18842
+ forceTopLevelMetrics,
18170
18843
  onComplete,
18171
18844
  onCancel,
18172
18845
  onError,
18173
18846
  result,
18174
18847
  resolvePromiseUsage,
18175
18848
  span,
18176
- startTime
18849
+ startTime,
18850
+ transformOutput
18177
18851
  } = args;
18178
18852
  if (!result || typeof result !== "object") {
18179
18853
  return false;
@@ -18226,8 +18900,8 @@ function patchAISDKStreamingResult(args) {
18226
18900
  }
18227
18901
  outputLogged = true;
18228
18902
  try {
18229
- const metrics = extractTopLevelAISDKMetrics(result, endEvent);
18230
- if (resolvePromiseUsage) {
18903
+ const metrics = forceTopLevelMetrics ? await extractResolvedAISDKTokenMetrics(result) : extractTopLevelAISDKMetrics(result, endEvent);
18904
+ if (resolvePromiseUsage && !forceTopLevelMetrics) {
18231
18905
  try {
18232
18906
  const resultRecord2 = result;
18233
18907
  const pendingUsage = resultRecord2.totalUsage ?? resultRecord2.usage;
@@ -18246,10 +18920,11 @@ function patchAISDKStreamingResult(args) {
18246
18920
  if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
18247
18921
  metrics.time_to_first_token = firstChunkTime - startTime;
18248
18922
  }
18249
- const output = await processAISDKStreamingOutput(
18923
+ const processedOutput = await processAISDKStreamingOutput(
18250
18924
  result,
18251
18925
  resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
18252
18926
  );
18927
+ const output = transformOutput ? transformOutput(processedOutput) : processedOutput;
18253
18928
  const metadata = buildResolvedMetadataPayload(result).metadata;
18254
18929
  try {
18255
18930
  span.log({
@@ -20671,6 +21346,295 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
20671
21346
  }
20672
21347
  };
20673
21348
 
21349
+ // src/instrumentation/plugins/cloudflare-think-channels.ts
21350
+ var cloudflareThinkChannels = defineChannels(
21351
+ "@cloudflare/think",
21352
+ {
21353
+ runInferenceLoop: channel({
21354
+ channelName: "Think.runInferenceLoop",
21355
+ kind: "async"
21356
+ })
21357
+ },
21358
+ { instrumentationName: INSTRUMENTATION_NAMES.CLOUDFLARE_THINK }
21359
+ );
21360
+
21361
+ // src/instrumentation/plugins/cloudflare-think-plugin.ts
21362
+ var THINK_STATE_ID = /* @__PURE__ */ Symbol.for("braintrust.cloudflare-think.state-id");
21363
+ var CloudflareThinkPlugin = class extends BasePlugin {
21364
+ statesBySpanId = /* @__PURE__ */ new Map();
21365
+ onEnable() {
21366
+ this.subscribeToThinkRuns();
21367
+ this.subscribeToAISDKStreamTextSync();
21368
+ this.subscribeToAISDKStreamTextAsync();
21369
+ }
21370
+ onDisable() {
21371
+ for (const unsubscribe of this.unsubscribers) {
21372
+ unsubscribe();
21373
+ }
21374
+ this.unsubscribers = [];
21375
+ for (const state of this.statesBySpanId.values()) {
21376
+ this.finishState(state);
21377
+ }
21378
+ this.statesBySpanId.clear();
21379
+ }
21380
+ subscribeToThinkRuns() {
21381
+ const channel2 = cloudflareThinkChannels.runInferenceLoop.tracingChannel();
21382
+ const states = /* @__PURE__ */ new WeakMap();
21383
+ const state = _internalGetGlobalState();
21384
+ const contextManager = state?.contextManager;
21385
+ const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
21386
+ const ensureState2 = (event) => {
21387
+ if (isAutoInstrumentationSuppressed()) {
21388
+ return void 0;
21389
+ }
21390
+ const existing = states.get(event);
21391
+ if (existing) {
21392
+ return existing;
21393
+ }
21394
+ const span = startSpan(
21395
+ withSpanInstrumentationName(
21396
+ {
21397
+ name: "Think.runTurn",
21398
+ spanAttributes: { type: "task" /* TASK */ }
21399
+ },
21400
+ INSTRUMENTATION_NAMES.CLOUDFLARE_THINK
21401
+ )
21402
+ );
21403
+ const runState = {
21404
+ aiResultPatched: false,
21405
+ fallbackInput: extractFallbackInput(event.self?.messages),
21406
+ finalized: false,
21407
+ inputLogged: false,
21408
+ span,
21409
+ startTime: getCurrentUnixTimestamp()
21410
+ };
21411
+ const metadata = {
21412
+ braintrust: {
21413
+ integration_name: "cloudflare-think",
21414
+ sdk_language: "typescript"
21415
+ }
21416
+ };
21417
+ if (typeof event.moduleVersion === "string") {
21418
+ metadata["cloudflare_think.version"] = event.moduleVersion;
21419
+ }
21420
+ span.log({ metadata });
21421
+ states.set(event, runState);
21422
+ if (span.spanId) {
21423
+ this.statesBySpanId.set(span.spanId, runState);
21424
+ }
21425
+ registerCloudflareThinkSpan(span);
21426
+ return runState;
21427
+ };
21428
+ if (contextManager && currentSpanStore && channel2.start) {
21429
+ channel2.start.bindStore(currentSpanStore, (event) => {
21430
+ const runState = ensureState2(event);
21431
+ return runState ? contextManager.wrapSpanForStore(runState.span) : currentSpanStore.getStore();
21432
+ });
21433
+ this.unsubscribers.push(
21434
+ () => channel2.start?.unbindStore(currentSpanStore)
21435
+ );
21436
+ }
21437
+ const handlers = {
21438
+ start: (event) => {
21439
+ ensureState2(event);
21440
+ },
21441
+ asyncEnd: (event) => {
21442
+ const runState = states.get(event);
21443
+ states.delete(event);
21444
+ if (!runState || runState.finalized || runState.aiResultPatched) {
21445
+ return;
21446
+ }
21447
+ this.finishState(runState, void 0, event.result);
21448
+ },
21449
+ error: (event) => {
21450
+ const runState = states.get(event);
21451
+ states.delete(event);
21452
+ if (runState) {
21453
+ this.finishState(runState, event.error);
21454
+ }
21455
+ }
21456
+ };
21457
+ channel2.subscribe(handlers);
21458
+ this.unsubscribers.push(() => channel2.unsubscribe(handlers));
21459
+ }
21460
+ subscribeToAISDKStreamTextSync() {
21461
+ const channel2 = aiSDKChannels.streamTextSync.tracingChannel();
21462
+ const handlers = {
21463
+ start: (event) => {
21464
+ this.startAISDKStream(event);
21465
+ },
21466
+ end: (event) => {
21467
+ this.endAISDKStream(event);
21468
+ },
21469
+ error: (event) => {
21470
+ this.errorAISDKStream(event);
21471
+ }
21472
+ };
21473
+ channel2.subscribe(handlers);
21474
+ this.unsubscribers.push(() => channel2.unsubscribe(handlers));
21475
+ }
21476
+ subscribeToAISDKStreamTextAsync() {
21477
+ const channel2 = aiSDKChannels.streamText.tracingChannel();
21478
+ const handlers = {
21479
+ start: (event) => {
21480
+ this.startAISDKStream(event);
21481
+ },
21482
+ asyncEnd: (event) => {
21483
+ this.endAISDKStream(event);
21484
+ },
21485
+ error: (event) => {
21486
+ this.errorAISDKStream(event);
21487
+ }
21488
+ };
21489
+ channel2.subscribe(handlers);
21490
+ this.unsubscribers.push(() => channel2.unsubscribe(handlers));
21491
+ }
21492
+ startAISDKStream(event) {
21493
+ const runState = this.currentState();
21494
+ if (!runState || runState.finalized) {
21495
+ return;
21496
+ }
21497
+ try {
21498
+ const prepared = prepareAISDKAgentCallInput(
21499
+ event.arguments[0],
21500
+ event,
21501
+ runState.span
21502
+ );
21503
+ runState.span.log({
21504
+ input: extractThinkTaskInput(prepared.input),
21505
+ metadata: {
21506
+ ...prepared.metadata,
21507
+ braintrust: {
21508
+ integration_name: "cloudflare-think",
21509
+ sdk_language: "typescript"
21510
+ }
21511
+ }
21512
+ });
21513
+ runState.inputLogged = true;
21514
+ runState.aiEvent = event;
21515
+ Reflect.set(event, THINK_STATE_ID, runState.span.spanId);
21516
+ } catch (error) {
21517
+ debugLogger.error(
21518
+ "Error preparing @cloudflare/think AI SDK tracing:",
21519
+ error
21520
+ );
21521
+ }
21522
+ }
21523
+ endAISDKStream(event) {
21524
+ const runState = this.stateForAISDKEvent(event);
21525
+ if (!runState || runState.finalized) {
21526
+ return;
21527
+ }
21528
+ const patched = patchAISDKStreamingResult({
21529
+ defaultDenyOutputPaths: DEFAULT_DENY_OUTPUT_PATHS,
21530
+ endEvent: event,
21531
+ forceTopLevelMetrics: true,
21532
+ onComplete: () => this.releaseState(runState),
21533
+ result: event.result,
21534
+ span: runState.span,
21535
+ startTime: runState.startTime,
21536
+ transformOutput: extractThinkTaskOutput
21537
+ });
21538
+ runState.aiResultPatched = patched;
21539
+ if (!patched) {
21540
+ this.finishState(runState, void 0, event.result);
21541
+ }
21542
+ }
21543
+ errorAISDKStream(event) {
21544
+ const runState = this.stateForAISDKEvent(event);
21545
+ if (runState) {
21546
+ this.finishState(runState, event.error);
21547
+ }
21548
+ }
21549
+ currentState() {
21550
+ const parentIds = _internalGetGlobalState()?.contextManager.getParentSpanIds()?.spanParents ?? [];
21551
+ for (const parentId of parentIds) {
21552
+ const state = this.statesBySpanId.get(parentId);
21553
+ if (state) {
21554
+ return state;
21555
+ }
21556
+ }
21557
+ return void 0;
21558
+ }
21559
+ stateForAISDKEvent(event) {
21560
+ const spanId = Reflect.get(event, THINK_STATE_ID);
21561
+ return typeof spanId === "string" ? this.statesBySpanId.get(spanId) : void 0;
21562
+ }
21563
+ finishState(state, error, output) {
21564
+ if (state.finalized) {
21565
+ return;
21566
+ }
21567
+ state.finalized = true;
21568
+ try {
21569
+ if (!state.inputLogged && state.fallbackInput !== void 0) {
21570
+ state.span.log({ input: state.fallbackInput });
21571
+ }
21572
+ if (error !== void 0) {
21573
+ state.span.log({ error });
21574
+ } else if (output !== void 0) {
21575
+ state.span.log({ output: extractThinkTaskOutput(output) });
21576
+ }
21577
+ finalizeAISDKChildTracing(state.aiEvent);
21578
+ state.span.end();
21579
+ } finally {
21580
+ this.releaseState(state);
21581
+ }
21582
+ }
21583
+ releaseState(state) {
21584
+ state.finalized = true;
21585
+ unregisterCloudflareThinkSpan(state.span);
21586
+ if (state.span.spanId) {
21587
+ this.statesBySpanId.delete(state.span.spanId);
21588
+ }
21589
+ }
21590
+ };
21591
+ function extractFallbackInput(messages) {
21592
+ if (!Array.isArray(messages) || messages.length === 0) {
21593
+ return void 0;
21594
+ }
21595
+ let latestUserIndex = -1;
21596
+ for (let index = messages.length - 1; index >= 0; index--) {
21597
+ if (messages[index]?.role === "user") {
21598
+ latestUserIndex = index;
21599
+ break;
21600
+ }
21601
+ }
21602
+ const selected = latestUserIndex >= 0 ? messages.slice(latestUserIndex) : [];
21603
+ return selected.map((message) => ({
21604
+ role: message.role,
21605
+ content: message.content ?? message.parts
21606
+ }));
21607
+ }
21608
+ function extractThinkTaskOutput(output) {
21609
+ if (!isObject(output)) {
21610
+ return output;
21611
+ }
21612
+ if (typeof output.text === "string") {
21613
+ return { role: "assistant", content: output.text };
21614
+ }
21615
+ if (output.object !== void 0) {
21616
+ return output.object;
21617
+ }
21618
+ return output;
21619
+ }
21620
+ function extractThinkTaskInput(input) {
21621
+ if (!isObject(input)) {
21622
+ return input;
21623
+ }
21624
+ const system = input.instructions ?? input.system;
21625
+ if (Array.isArray(input.messages)) {
21626
+ return system === void 0 ? input.messages : [{ role: "system", content: system }, ...input.messages];
21627
+ }
21628
+ if (Array.isArray(input.prompt)) {
21629
+ return system === void 0 ? input.prompt : [{ role: "system", content: system }, ...input.prompt];
21630
+ }
21631
+ if (typeof input.prompt === "string") {
21632
+ const messages = [{ role: "user", content: input.prompt }];
21633
+ return system === void 0 ? messages : [{ role: "system", content: system }, ...messages];
21634
+ }
21635
+ return input;
21636
+ }
21637
+
20674
21638
  // src/instrumentation/plugins/cursor-sdk-channels.ts
20675
21639
  var cursorSDKChannels = defineChannels(
20676
21640
  "@cursor/sdk",
@@ -26436,6 +27400,470 @@ function aggregateMistralStreamChunks(chunks) {
26436
27400
  };
26437
27401
  }
26438
27402
 
27403
+ // src/instrumentation/plugins/ollama-channels.ts
27404
+ var ollamaChannels = defineChannels(
27405
+ "ollama",
27406
+ {
27407
+ chat: channel({
27408
+ channelName: "chat",
27409
+ kind: "async"
27410
+ }),
27411
+ generate: channel({
27412
+ channelName: "generate",
27413
+ kind: "async"
27414
+ }),
27415
+ embed: channel({
27416
+ channelName: "embed",
27417
+ kind: "async"
27418
+ })
27419
+ },
27420
+ { instrumentationName: INSTRUMENTATION_NAMES.OLLAMA }
27421
+ );
27422
+
27423
+ // src/instrumentation/plugins/ollama-plugin.ts
27424
+ var OllamaPlugin = class extends BasePlugin {
27425
+ onEnable() {
27426
+ this.unsubscribers.push(
27427
+ traceStreamingChannel(ollamaChannels.chat, {
27428
+ name: "ollama.chat",
27429
+ type: "llm" /* LLM */,
27430
+ extractInput: extractOllamaChatInput,
27431
+ extractOutput: (result, event) => extractOllamaChatOutput(
27432
+ result,
27433
+ countOllamaToolCalls(event?.arguments?.[0]?.messages)
27434
+ ),
27435
+ extractMetadata: extractOllamaResponseMetadata,
27436
+ extractMetrics: extractOllamaMetrics,
27437
+ aggregateChunks: aggregateOllamaChatChunks
27438
+ }),
27439
+ traceStreamingChannel(ollamaChannels.generate, {
27440
+ name: "ollama.generate",
27441
+ type: "llm" /* LLM */,
27442
+ extractInput: extractOllamaGenerateInput,
27443
+ extractOutput: extractOllamaGenerateOutput,
27444
+ extractMetadata: extractOllamaResponseMetadata,
27445
+ extractMetrics: extractOllamaMetrics,
27446
+ aggregateChunks: aggregateOllamaGenerateChunks
27447
+ }),
27448
+ traceAsyncChannel(ollamaChannels.embed, {
27449
+ name: "ollama.embed",
27450
+ type: "llm" /* LLM */,
27451
+ extractInput: extractOllamaEmbedInput,
27452
+ extractOutput: extractOllamaEmbedOutput,
27453
+ extractMetadata: extractOllamaResponseMetadata,
27454
+ extractMetrics: extractOllamaMetrics
27455
+ })
27456
+ );
27457
+ }
27458
+ onDisable() {
27459
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
27460
+ }
27461
+ };
27462
+ function isNonNegativeNumber(value) {
27463
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
27464
+ }
27465
+ function normalizeFinishReason(response, hasToolCalls = false) {
27466
+ if (hasToolCalls) {
27467
+ return "tool_calls";
27468
+ }
27469
+ return response?.done_reason || "stop";
27470
+ }
27471
+ function stringifyArguments(value) {
27472
+ if (typeof value === "string") {
27473
+ return value;
27474
+ }
27475
+ try {
27476
+ return JSON.stringify(value ?? {});
27477
+ } catch {
27478
+ return String(value);
27479
+ }
27480
+ }
27481
+ function syntheticToolCallId(name, index) {
27482
+ const normalizedName = name.replace(/[^a-zA-Z0-9_-]/g, "_") || "tool";
27483
+ return `ollama_call_${normalizedName}_${index}`;
27484
+ }
27485
+ function normalizeToolCall(toolCall, index) {
27486
+ const name = toolCall.function?.name;
27487
+ if (typeof name !== "string" || name.length === 0) {
27488
+ return void 0;
27489
+ }
27490
+ return {
27491
+ id: typeof toolCall.id === "string" && toolCall.id.length > 0 ? toolCall.id : syntheticToolCallId(name, index),
27492
+ type: "function",
27493
+ function: {
27494
+ name,
27495
+ arguments: stringifyArguments(toolCall.function?.arguments)
27496
+ }
27497
+ };
27498
+ }
27499
+ function normalizeToolCalls(toolCalls2, syntheticIdOffset = 0) {
27500
+ if (!Array.isArray(toolCalls2)) {
27501
+ return [];
27502
+ }
27503
+ return toolCalls2.flatMap((toolCall, index) => {
27504
+ const normalized = normalizeToolCall(toolCall, syntheticIdOffset + index);
27505
+ return normalized ? [normalized] : [];
27506
+ });
27507
+ }
27508
+ function countOllamaToolCalls(messages) {
27509
+ if (!Array.isArray(messages)) {
27510
+ return 0;
27511
+ }
27512
+ return messages.reduce(
27513
+ (count, message) => count + (isObject(message) && Array.isArray(message.tool_calls) ? message.tool_calls.length : 0),
27514
+ 0
27515
+ );
27516
+ }
27517
+ function imageBytes(value) {
27518
+ if (value instanceof Uint8Array) {
27519
+ return value;
27520
+ }
27521
+ if (value instanceof ArrayBuffer) {
27522
+ return new Uint8Array(value);
27523
+ }
27524
+ if (typeof value !== "string" || value.startsWith("data:")) {
27525
+ return void 0;
27526
+ }
27527
+ try {
27528
+ const decoded = atob(value.slice(0, 24));
27529
+ return Uint8Array.from(decoded, (character) => character.charCodeAt(0));
27530
+ } catch {
27531
+ return void 0;
27532
+ }
27533
+ }
27534
+ function inferImageMediaType(value) {
27535
+ if (typeof value === "string") {
27536
+ const dataUrlType = value.match(/^data:(image\/[^;]+);base64,/i)?.[1];
27537
+ if (dataUrlType) {
27538
+ return dataUrlType;
27539
+ }
27540
+ }
27541
+ const bytes = imageBytes(value);
27542
+ if (!bytes) {
27543
+ return void 0;
27544
+ }
27545
+ if (bytes[0] === 137 && bytes[1] === 80 && bytes[2] === 78 && bytes[3] === 71) {
27546
+ return "image/png";
27547
+ }
27548
+ if (bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255) {
27549
+ return "image/jpeg";
27550
+ }
27551
+ const signature = String.fromCharCode(...bytes.slice(0, 12));
27552
+ if (signature.startsWith("GIF87a") || signature.startsWith("GIF89a")) {
27553
+ return "image/gif";
27554
+ }
27555
+ if (signature.startsWith("RIFF") && signature.slice(8, 12) === "WEBP") {
27556
+ return "image/webp";
27557
+ }
27558
+ return void 0;
27559
+ }
27560
+ function normalizeTextAndImages(content, images) {
27561
+ if (!images || images.length === 0) {
27562
+ return { content };
27563
+ }
27564
+ const imageParts = [];
27565
+ const unrecognizedImages = [];
27566
+ for (const image of images) {
27567
+ let localImagePath;
27568
+ let localPathMediaType;
27569
+ if (typeof image === "string" && !/^data:/i.test(image) && !/^https?:\/\//i.test(image)) {
27570
+ const extension = image.match(/\.([a-z0-9]+)$/i)?.[1]?.toLowerCase();
27571
+ const extensionMediaType = {
27572
+ png: "image/png",
27573
+ jpg: "image/jpeg",
27574
+ jpeg: "image/jpeg",
27575
+ gif: "image/gif",
27576
+ webp: "image/webp"
27577
+ }[extension ?? ""];
27578
+ if (extensionMediaType && isomorph_default.statSync) {
27579
+ try {
27580
+ if (isomorph_default.statSync(image).isFile()) {
27581
+ localImagePath = image;
27582
+ localPathMediaType = extensionMediaType;
27583
+ }
27584
+ } catch {
27585
+ }
27586
+ }
27587
+ }
27588
+ const mediaType = localPathMediaType ?? inferImageMediaType(image);
27589
+ if (!mediaType) {
27590
+ unrecognizedImages.push(image);
27591
+ continue;
27592
+ }
27593
+ const processedImage = localImagePath ? new Attachment({
27594
+ data: localImagePath,
27595
+ filename: localImagePath.split(/[\\/]/).at(-1) ?? "image",
27596
+ contentType: mediaType
27597
+ }) : processInputAttachments({
27598
+ type: "image",
27599
+ image,
27600
+ mediaType
27601
+ }).image;
27602
+ imageParts.push({
27603
+ type: "image_url",
27604
+ image_url: { url: processedImage }
27605
+ });
27606
+ }
27607
+ return {
27608
+ content: imageParts.length > 0 ? [...content ? [{ type: "text", text: content }] : [], ...imageParts] : content,
27609
+ ...unrecognizedImages.length > 0 ? { unrecognizedImages } : {}
27610
+ };
27611
+ }
27612
+ function normalizeMessage(message, toolCallId, syntheticToolCallIdOffset = 0) {
27613
+ if (typeof message.role !== "string") {
27614
+ return void 0;
27615
+ }
27616
+ const toolCalls2 = normalizeToolCalls(
27617
+ message.tool_calls,
27618
+ syntheticToolCallIdOffset
27619
+ );
27620
+ if (message.role === "tool") {
27621
+ const toolName = typeof message.tool_name === "string" && message.tool_name.length > 0 ? message.tool_name : "tool";
27622
+ return {
27623
+ role: "tool",
27624
+ tool_call_id: toolCallId ?? syntheticToolCallId(toolName, 0),
27625
+ content: typeof message.content === "string" ? message.content : ""
27626
+ };
27627
+ }
27628
+ const normalizedContent = normalizeTextAndImages(
27629
+ typeof message.content === "string" ? message.content || (toolCalls2.length > 0 ? null : "") : toolCalls2.length > 0 ? null : "",
27630
+ message.images
27631
+ );
27632
+ return {
27633
+ role: message.role,
27634
+ content: normalizedContent.content,
27635
+ ...typeof message.thinking === "string" && message.thinking.length > 0 ? { reasoning: message.thinking } : {},
27636
+ ...toolCalls2.length > 0 ? { tool_calls: toolCalls2 } : {},
27637
+ ...normalizedContent.unrecognizedImages ? { images: normalizedContent.unrecognizedImages } : {}
27638
+ };
27639
+ }
27640
+ function normalizeMessages(messages) {
27641
+ if (!Array.isArray(messages)) {
27642
+ return [];
27643
+ }
27644
+ const pendingToolCallIds = /* @__PURE__ */ new Map();
27645
+ let syntheticToolCallIdOffset = 0;
27646
+ return messages.flatMap((message) => {
27647
+ if (!isObject(message)) {
27648
+ return [];
27649
+ }
27650
+ const ollamaMessage = message;
27651
+ let toolCallId;
27652
+ if (ollamaMessage.role === "tool") {
27653
+ const toolName = ollamaMessage.tool_name;
27654
+ if (typeof toolName === "string") {
27655
+ toolCallId = pendingToolCallIds.get(toolName)?.shift();
27656
+ }
27657
+ }
27658
+ const normalized = normalizeMessage(
27659
+ ollamaMessage,
27660
+ toolCallId,
27661
+ syntheticToolCallIdOffset
27662
+ );
27663
+ if (Array.isArray(ollamaMessage.tool_calls)) {
27664
+ syntheticToolCallIdOffset += ollamaMessage.tool_calls.length;
27665
+ }
27666
+ if (ollamaMessage.role === "assistant" && normalized) {
27667
+ const toolCalls2 = Array.isArray(normalized.tool_calls) ? normalized.tool_calls : [];
27668
+ for (const toolCall of toolCalls2) {
27669
+ if (!isObject(toolCall) || !isObject(toolCall.function)) {
27670
+ continue;
27671
+ }
27672
+ const name = toolCall.function.name;
27673
+ const id = toolCall.id;
27674
+ if (typeof name === "string" && typeof id === "string") {
27675
+ const ids = pendingToolCallIds.get(name) ?? [];
27676
+ ids.push(id);
27677
+ pendingToolCallIds.set(name, ids);
27678
+ }
27679
+ }
27680
+ }
27681
+ return normalized ? [normalized] : [];
27682
+ });
27683
+ }
27684
+ function normalizeToolDefinition(tool) {
27685
+ const fn = tool.function;
27686
+ if (!fn || typeof fn.name !== "string" || fn.name.length === 0) {
27687
+ return void 0;
27688
+ }
27689
+ return {
27690
+ type: "function",
27691
+ function: {
27692
+ name: fn.name,
27693
+ ...typeof fn.description === "string" ? { description: fn.description } : {},
27694
+ ...isObject(fn.parameters) ? { parameters: fn.parameters } : {}
27695
+ }
27696
+ };
27697
+ }
27698
+ function extractToolsMetadata(tools) {
27699
+ if (!Array.isArray(tools)) {
27700
+ return {};
27701
+ }
27702
+ const normalized = tools.flatMap((tool) => {
27703
+ if (!isObject(tool)) {
27704
+ return [];
27705
+ }
27706
+ const definition = normalizeToolDefinition(tool);
27707
+ return definition ? [definition] : [];
27708
+ });
27709
+ return normalized.length > 0 ? { tools: normalized } : {};
27710
+ }
27711
+ function extractOptionsMetadata(options) {
27712
+ if (!isObject(options)) {
27713
+ return {};
27714
+ }
27715
+ const metadata = {};
27716
+ const mappings = [
27717
+ ["temperature", "temperature"],
27718
+ ["top_p", "top_p"],
27719
+ ["num_predict", "max_tokens"],
27720
+ ["frequency_penalty", "frequency_penalty"],
27721
+ ["presence_penalty", "presence_penalty"],
27722
+ ["stop", "stop"]
27723
+ ];
27724
+ for (const [source, target] of mappings) {
27725
+ if (options[source] !== void 0) {
27726
+ metadata[target] = options[source];
27727
+ }
27728
+ }
27729
+ return metadata;
27730
+ }
27731
+ function extractRequestMetadata(request) {
27732
+ return {
27733
+ provider: "ollama",
27734
+ ...typeof request?.model === "string" ? { model: request.model } : {},
27735
+ ...extractOptionsMetadata(request?.options),
27736
+ ...request?.format !== void 0 ? { response_format: request.format } : {}
27737
+ };
27738
+ }
27739
+ function extractOllamaChatInput([request]) {
27740
+ return {
27741
+ input: normalizeMessages(request.messages),
27742
+ metadata: {
27743
+ ...extractRequestMetadata(request),
27744
+ ...extractToolsMetadata(request.tools)
27745
+ }
27746
+ };
27747
+ }
27748
+ function extractOllamaGenerateInput([request]) {
27749
+ const normalizedPrompt = normalizeTextAndImages(
27750
+ typeof request.prompt === "string" ? request.prompt : "",
27751
+ Array.isArray(request.images) ? request.images : void 0
27752
+ );
27753
+ const input = [
27754
+ ...typeof request.system === "string" ? [{ role: "system", content: request.system }] : [],
27755
+ {
27756
+ role: "user",
27757
+ content: normalizedPrompt.content,
27758
+ ...typeof request.suffix === "string" ? { suffix: request.suffix } : {},
27759
+ ...normalizedPrompt.unrecognizedImages ? { images: normalizedPrompt.unrecognizedImages } : {}
27760
+ }
27761
+ ];
27762
+ return {
27763
+ input,
27764
+ metadata: extractRequestMetadata(request)
27765
+ };
27766
+ }
27767
+ function extractOllamaEmbedInput([request]) {
27768
+ return {
27769
+ input: request.input,
27770
+ metadata: extractRequestMetadata(request)
27771
+ };
27772
+ }
27773
+ function extractOllamaChatOutput(result, syntheticToolCallIdOffset = 0) {
27774
+ if (!isObject(result) || !isObject(result.message)) {
27775
+ return void 0;
27776
+ }
27777
+ const message = normalizeMessage(
27778
+ result.message,
27779
+ void 0,
27780
+ syntheticToolCallIdOffset
27781
+ );
27782
+ if (!message) {
27783
+ return void 0;
27784
+ }
27785
+ const toolCalls2 = Array.isArray(message.tool_calls) ? message.tool_calls : [];
27786
+ return [
27787
+ {
27788
+ index: 0,
27789
+ finish_reason: normalizeFinishReason(result, toolCalls2.length > 0),
27790
+ message
27791
+ }
27792
+ ];
27793
+ }
27794
+ function extractOllamaGenerateOutput(result) {
27795
+ if (!isObject(result) || typeof result.response !== "string") {
27796
+ return void 0;
27797
+ }
27798
+ return [
27799
+ {
27800
+ index: 0,
27801
+ finish_reason: normalizeFinishReason(result),
27802
+ message: {
27803
+ role: "assistant",
27804
+ content: result.response,
27805
+ ...typeof result.thinking === "string" && result.thinking.length > 0 ? { reasoning: result.thinking } : {}
27806
+ }
27807
+ }
27808
+ ];
27809
+ }
27810
+ function extractOllamaEmbedOutput(result) {
27811
+ const embedding = Array.isArray(result?.embeddings) ? result.embeddings[0] : void 0;
27812
+ return Array.isArray(embedding) ? { embedding_length: embedding.length } : void 0;
27813
+ }
27814
+ function extractOllamaResponseMetadata(result) {
27815
+ return typeof result?.model === "string" ? { model: result.model } : void 0;
27816
+ }
27817
+ function extractOllamaMetrics(result) {
27818
+ const metrics = {};
27819
+ const promptTokens = result?.prompt_eval_count;
27820
+ const completionTokens = result?.eval_count;
27821
+ if (isNonNegativeNumber(promptTokens)) {
27822
+ metrics.prompt_tokens = promptTokens;
27823
+ }
27824
+ if (isNonNegativeNumber(completionTokens)) {
27825
+ metrics.completion_tokens = completionTokens;
27826
+ }
27827
+ if (isNonNegativeNumber(promptTokens) || isNonNegativeNumber(completionTokens)) {
27828
+ metrics.tokens = (isNonNegativeNumber(promptTokens) ? promptTokens : 0) + (isNonNegativeNumber(completionTokens) ? completionTokens : 0);
27829
+ }
27830
+ return metrics;
27831
+ }
27832
+ function aggregateOllamaChatChunks(chunks, _result, event, _startTime) {
27833
+ const last = chunks.at(-1);
27834
+ const message = {
27835
+ role: "assistant",
27836
+ content: chunks.map((chunk) => chunk.message?.content ?? "").join(""),
27837
+ thinking: chunks.map((chunk) => chunk.message?.thinking ?? "").join(""),
27838
+ tool_calls: chunks.flatMap((chunk) => chunk.message?.tool_calls ?? [])
27839
+ };
27840
+ const response = {
27841
+ ...last,
27842
+ message
27843
+ };
27844
+ return {
27845
+ output: extractOllamaChatOutput(
27846
+ response,
27847
+ countOllamaToolCalls(event?.arguments?.[0]?.messages)
27848
+ ),
27849
+ metrics: extractOllamaMetrics(last ?? {}),
27850
+ metadata: extractOllamaResponseMetadata(last ?? {})
27851
+ };
27852
+ }
27853
+ function aggregateOllamaGenerateChunks(chunks, _result, _event, _startTime) {
27854
+ const last = chunks.at(-1);
27855
+ const response = {
27856
+ ...last,
27857
+ response: chunks.map((chunk) => chunk.response ?? "").join(""),
27858
+ thinking: chunks.map((chunk) => chunk.thinking ?? "").join("")
27859
+ };
27860
+ return {
27861
+ output: extractOllamaGenerateOutput(response),
27862
+ metrics: extractOllamaMetrics(last ?? {}),
27863
+ metadata: extractOllamaResponseMetadata(last ?? {})
27864
+ };
27865
+ }
27866
+
26439
27867
  // src/instrumentation/plugins/google-adk-channels.ts
26440
27868
  var googleADKChannels = defineChannels(
26441
27869
  "@google/adk",
@@ -30189,7 +31617,7 @@ var FlueObserveBridge = class {
30189
31617
  return;
30190
31618
  }
30191
31619
  const state = this.operationsById.get(event.operationId) ?? this.startSyntheticOperation(event);
30192
- const output = operationOutput(event);
31620
+ const output = operationOutput(event) ?? outputFromAgentTurn(state.latestAgentOutput);
30193
31621
  const metadata = {
30194
31622
  ...state.metadata,
30195
31623
  ...extractEventMetadata(event),
@@ -30198,7 +31626,7 @@ var FlueObserveBridge = class {
30198
31626
  };
30199
31627
  this.finishPendingChildrenForOperation(event, output);
30200
31628
  safeLog3(state.span, {
30201
- ...event.isError ? { error: toLoggedError(event.error) } : {},
31629
+ ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.error) } : {},
30202
31630
  metadata,
30203
31631
  metrics: durationMetrics2(event.durationMs),
30204
31632
  output
@@ -30229,7 +31657,7 @@ var FlueObserveBridge = class {
30229
31657
  };
30230
31658
  const parent = this.parentSpanForTurn(event);
30231
31659
  const span = startFlueSpan(parent, {
30232
- name: `llm:${model ?? event.purpose ?? "unknown"}`,
31660
+ name: "flue.turn",
30233
31661
  spanAttributes: { type: "llm" /* LLM */ },
30234
31662
  startTime: eventTime(event.timestamp),
30235
31663
  event: {
@@ -30273,6 +31701,12 @@ var FlueObserveBridge = class {
30273
31701
  },
30274
31702
  output
30275
31703
  });
31704
+ if (event.purpose === "agent" && event.operationId) {
31705
+ const operation = this.operationsById.get(event.operationId);
31706
+ if (operation) {
31707
+ operation.latestAgentOutput = output;
31708
+ }
31709
+ }
30276
31710
  safeEnd(state.span, eventTime(event.timestamp));
30277
31711
  this.turnsByKey.delete(key);
30278
31712
  }
@@ -30352,7 +31786,7 @@ var FlueObserveBridge = class {
30352
31786
  return;
30353
31787
  }
30354
31788
  safeLog3(state.span, {
30355
- ...event.isError ? { error: toLoggedError(event.result) } : {},
31789
+ ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.result) } : {},
30356
31790
  metadata: {
30357
31791
  ...state.metadata,
30358
31792
  ...extractEventMetadata(event),
@@ -30398,6 +31832,7 @@ var FlueObserveBridge = class {
30398
31832
  ...event.usage ? { "flue.usage": event.usage } : {}
30399
31833
  };
30400
31834
  safeLog3(state.span, {
31835
+ ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.error) } : {},
30401
31836
  metadata,
30402
31837
  metrics: {
30403
31838
  ...durationMetrics2(event.durationMs),
@@ -30502,7 +31937,7 @@ var FlueObserveBridge = class {
30502
31937
  ...event.purpose ? { "flue.turn_purpose": event.purpose } : {}
30503
31938
  };
30504
31939
  const span = startFlueSpan(this.parentSpanForEvent(event), {
30505
- name: `llm:${model ?? event.purpose ?? "unknown"}`,
31940
+ name: "flue.turn",
30506
31941
  spanAttributes: { type: "llm" /* LLM */ },
30507
31942
  startTime: eventTime(event.timestamp),
30508
31943
  event: { metadata }
@@ -30634,7 +32069,10 @@ function extractEventMetadata(event, ctx) {
30634
32069
  return {
30635
32070
  ...event.runId ? { "flue.run_id": event.runId } : {},
30636
32071
  ...event.instanceId ? { "flue.instance_id": event.instanceId } : {},
32072
+ ...event.submissionId ? { "flue.submission_id": event.submissionId } : {},
30637
32073
  ...event.dispatchId ? { "flue.dispatch_id": event.dispatchId } : {},
32074
+ ...event.agentName ? { "flue.agent_name": event.agentName } : {},
32075
+ ...event.conversationId ? { "flue.conversation_id": event.conversationId } : {},
30638
32076
  ...typeof event.eventIndex === "number" ? { "flue.event_index": event.eventIndex } : {},
30639
32077
  ...event.session ? { "flue.session": event.session } : {},
30640
32078
  ...event.parentSession ? { "flue.parent_session": event.parentSession } : {},
@@ -30663,7 +32101,7 @@ function flueTurnRequestInput(event) {
30663
32101
  return event.request?.input ?? event.input;
30664
32102
  }
30665
32103
  function flueTurnRequestModel(event) {
30666
- return event.request?.model ?? event.model;
32104
+ return event.request?.requestedModel ?? event.request?.model ?? event.model;
30667
32105
  }
30668
32106
  function flueTurnRequestProvider(event) {
30669
32107
  return event.request?.providerName ?? event.provider ?? event.request?.providerId;
@@ -30672,10 +32110,10 @@ function flueTurnRequestApi(event) {
30672
32110
  return event.request?.api ?? event.api;
30673
32111
  }
30674
32112
  function flueTurnRequestReasoning(event) {
30675
- return event.request?.reasoning ?? event.reasoning;
32113
+ return event.request?.reasoningLevel ?? event.request?.reasoning ?? event.reasoning;
30676
32114
  }
30677
32115
  function flueTurnModel(event) {
30678
- return event.request?.model ?? event.model;
32116
+ return event.response?.responseModel ?? event.request?.requestedModel ?? event.request?.model ?? event.model;
30679
32117
  }
30680
32118
  function flueTurnProvider(event) {
30681
32119
  return event.request?.providerName ?? event.provider ?? event.request?.providerId;
@@ -30690,7 +32128,7 @@ function flueTurnOutput(event) {
30690
32128
  return event.response?.output ?? event.output;
30691
32129
  }
30692
32130
  function flueTurnStopReason(event) {
30693
- return event.response?.stopReason ?? event.stopReason;
32131
+ return event.response?.finishReason ?? event.response?.stopReason ?? event.stopReason;
30694
32132
  }
30695
32133
  function flueTurnError(event) {
30696
32134
  return event.response?.error ?? event.response?.errorInfo?.message ?? event.error;
@@ -30705,6 +32143,9 @@ function flueToolInput(event) {
30705
32143
  return event.input;
30706
32144
  }
30707
32145
  function flueToolOutput(event) {
32146
+ if (Object.hasOwn(event, "effectiveResult")) {
32147
+ return event.effectiveResult;
32148
+ }
30708
32149
  return event.output !== void 0 ? event.output : event.result;
30709
32150
  }
30710
32151
  function flueToolError(event) {
@@ -30712,10 +32153,36 @@ function flueToolError(event) {
30712
32153
  }
30713
32154
  function operationOutput(event) {
30714
32155
  if (event.operationKind === "prompt" || event.operationKind === "skill") {
30715
- return llmResultFromOperationResult(event.result);
32156
+ return outputFromAgentInvocation(event.agentOutput) ?? llmResultFromOperationResult(event.result);
30716
32157
  }
30717
32158
  return event.result ?? (event.operationKind === "compact" ? { completed: true } : void 0);
30718
32159
  }
32160
+ function outputFromAgentInvocation(output) {
32161
+ if (output?.type === "text") {
32162
+ return output.text;
32163
+ }
32164
+ if (output?.type === "data") {
32165
+ return output.data;
32166
+ }
32167
+ return void 0;
32168
+ }
32169
+ function outputFromAgentTurn(output) {
32170
+ if (!isObjectLike(output)) {
32171
+ return output;
32172
+ }
32173
+ const content = Reflect.get(output, "content");
32174
+ if (!Array.isArray(content)) {
32175
+ return output;
32176
+ }
32177
+ const text = content.flatMap((part) => {
32178
+ if (!isObjectLike(part) || Reflect.get(part, "type") !== "text") {
32179
+ return [];
32180
+ }
32181
+ const value = Reflect.get(part, "text");
32182
+ return typeof value === "string" ? [value] : [];
32183
+ });
32184
+ return text.length > 0 ? text.join("") : output;
32185
+ }
30719
32186
  function llmResultFromOperationResult(result) {
30720
32187
  if (!isObjectLike(result)) {
30721
32188
  return result;
@@ -30814,7 +32281,7 @@ function safeEnd(span, endTime) {
30814
32281
  }
30815
32282
  }
30816
32283
  function logInstrumentationError3(label, error) {
30817
- console.error(`Error in ${label} instrumentation:`, error);
32284
+ debugLogger.debug(`Error in ${label} instrumentation:`, error);
30818
32285
  }
30819
32286
 
30820
32287
  // src/wrappers/langchain/callback-handler.ts
@@ -31743,12 +33210,13 @@ var piCodingAgentChannels = defineChannels(
31743
33210
  );
31744
33211
 
31745
33212
  // src/instrumentation/plugins/pi-coding-agent-plugin.ts
31746
- var piStreamPatchStates = /* @__PURE__ */ new WeakMap();
33213
+ var piAgentPatchStates = /* @__PURE__ */ new WeakMap();
33214
+ var piAgentEventSubscriptions = /* @__PURE__ */ new WeakSet();
31747
33215
  var piPromptContextStore;
31748
33216
  var PiCodingAgentPlugin = class extends BasePlugin {
31749
33217
  activePromptStates = /* @__PURE__ */ new Set();
31750
33218
  onEnable() {
31751
- this.subscribeToPrompt();
33219
+ this.interceptPrompt();
31752
33220
  }
31753
33221
  onDisable() {
31754
33222
  for (const unsubscribe of this.unsubscribers) {
@@ -31756,65 +33224,74 @@ var PiCodingAgentPlugin = class extends BasePlugin {
31756
33224
  }
31757
33225
  this.unsubscribers = [];
31758
33226
  for (const state of [...this.activePromptStates]) {
31759
- void finalizePiPromptRun(state).catch((error) => {
31760
- logInstrumentationError4("Pi Coding Agent disable cleanup", error);
31761
- });
33227
+ finishPiPromptRun(state);
31762
33228
  }
31763
33229
  }
31764
- subscribeToPrompt() {
31765
- const channel2 = piCodingAgentChannels.prompt.tracingChannel();
31766
- const states = /* @__PURE__ */ new WeakMap();
31767
- const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(channel2);
31768
- const handlers = {
31769
- start: (event) => {
31770
- const state = startPiPromptRun(event, (state2) => {
31771
- this.activePromptStates.delete(state2);
31772
- });
31773
- if (state) {
31774
- this.activePromptStates.add(state);
31775
- states.set(event, state);
31776
- }
31777
- },
31778
- asyncEnd: async (event) => {
31779
- const state = states.get(event);
31780
- if (!state) {
31781
- return;
31782
- }
31783
- states.delete(event);
31784
- state.promptCallEnded = true;
31785
- if (!state.finalized && state.deferCompletionUntilTurnEnd && !state.turnEnded) {
31786
- if (!state.sawStreamFn) {
31787
- state.queued = true;
31788
- if (!state.streamPatchState.queuedPromptStates.includes(state)) {
31789
- state.streamPatchState.queuedPromptStates.push(state);
31790
- }
33230
+ interceptPrompt() {
33231
+ this.unsubscribers.push(
33232
+ piCodingAgentChannels.prompt.intercept(
33233
+ (target, thisArg, args, additional) => {
33234
+ const invokeTarget = () => Reflect.apply(target, thisArg, args);
33235
+ let state;
33236
+ try {
33237
+ state = startPiPromptRun(
33238
+ {
33239
+ ...additional,
33240
+ arguments: args,
33241
+ self: thisArg
33242
+ },
33243
+ (finalizedState) => {
33244
+ this.activePromptStates.delete(finalizedState);
33245
+ }
33246
+ );
33247
+ } catch (error) {
33248
+ logInstrumentationError4("Pi Coding Agent prompt start", error);
31791
33249
  }
31792
- return;
31793
- }
31794
- await finalizePiPromptRun(state);
31795
- },
31796
- error: async (event) => {
31797
- const state = states.get(event);
31798
- if (!state) {
31799
- return;
33250
+ if (!state) {
33251
+ return runWithAutoInstrumentationSuppressed(invokeTarget);
33252
+ }
33253
+ this.activePromptStates.add(state);
33254
+ return promptContextStore().run(
33255
+ state,
33256
+ () => runWithAutoInstrumentationSuppressed(() => {
33257
+ let result;
33258
+ try {
33259
+ result = invokeTarget();
33260
+ } catch (error) {
33261
+ finishPiPromptRun(state, error);
33262
+ throw error;
33263
+ }
33264
+ return Promise.resolve(result).then(
33265
+ (value) => {
33266
+ finishPiPromptCall(state);
33267
+ return value;
33268
+ },
33269
+ (error) => {
33270
+ finishPiPromptRun(state, error);
33271
+ throw error;
33272
+ }
33273
+ );
33274
+ })
33275
+ );
31800
33276
  }
31801
- states.delete(event);
31802
- await finalizePiPromptRun(state, event.error);
31803
- }
31804
- };
31805
- channel2.subscribe(handlers);
31806
- this.unsubscribers.push(() => {
31807
- unbindAutoInstrumentationSuppression?.();
31808
- channel2.unsubscribe(handlers);
31809
- });
33277
+ )
33278
+ );
31810
33279
  }
31811
33280
  };
33281
+ function finishPiPromptCall(state) {
33282
+ state.promptCallEnded = true;
33283
+ if (state.deferCompletionUntilTurnEnd && !state.turnEnded) {
33284
+ return;
33285
+ }
33286
+ finishPiPromptRun(state);
33287
+ }
31812
33288
  function startPiPromptRun(event, onFinalize) {
31813
33289
  const session = extractSession(event);
31814
33290
  const agent = session?.agent;
31815
33291
  if (!session || !isPiAgent(agent)) {
31816
33292
  return void 0;
31817
33293
  }
33294
+ installPiAgentInstrumentation(agent);
31818
33295
  const metadata = {
31819
33296
  ...extractSessionMetadata(session),
31820
33297
  ...extractPromptOptionsMetadata(event.arguments[1]),
@@ -31836,9 +33313,7 @@ function startPiPromptRun(event, onFinalize) {
31836
33313
  INSTRUMENTATION_NAMES.PI_CODING_AGENT
31837
33314
  )
31838
33315
  );
31839
- const streamPatchState = installPiStreamPatch(agent);
31840
33316
  const options = event.arguments[1];
31841
- const promptText = event.arguments[0];
31842
33317
  const state = {
31843
33318
  activeLlmSpans: /* @__PURE__ */ new Set(),
31844
33319
  activeToolSpans: /* @__PURE__ */ new Map(),
@@ -31850,29 +33325,10 @@ function startPiPromptRun(event, onFinalize) {
31850
33325
  metrics: {},
31851
33326
  onFinalize,
31852
33327
  promptCallEnded: false,
31853
- ...typeof promptText === "string" ? { promptText } : {},
31854
- queued: false,
31855
33328
  span,
31856
- sawStreamFn: false,
31857
33329
  startTime: getCurrentUnixTimestamp(),
31858
- streamPatchState,
31859
33330
  turnEnded: false
31860
33331
  };
31861
- state.restorePromptContext = enterPiPromptContext(state);
31862
- streamPatchState.activePromptStates.add(state);
31863
- try {
31864
- state.unsubscribeAgent = agent.subscribe(async (agentEvent) => {
31865
- try {
31866
- await runWithAutoInstrumentationSuppressed(
31867
- () => handlePiAgentEvent(state, agentEvent)
31868
- );
31869
- } catch (error) {
31870
- logInstrumentationError4("Pi Coding Agent event", error);
31871
- }
31872
- });
31873
- } catch (error) {
31874
- logInstrumentationError4("Pi Coding Agent event subscription", error);
31875
- }
31876
33332
  return state;
31877
33333
  }
31878
33334
  function extractSession(event) {
@@ -31886,111 +33342,55 @@ function promptContextStore() {
31886
33342
  piPromptContextStore ??= isomorph_default.newAsyncLocalStorage();
31887
33343
  return piPromptContextStore;
31888
33344
  }
31889
- function currentPromptContextFrames() {
31890
- return promptContextStore().getStore()?.frames ?? [];
31891
- }
31892
33345
  function currentPiPromptState() {
31893
- const frames = currentPromptContextFrames();
31894
- return frames[frames.length - 1]?.state;
31895
- }
31896
- function enterPiPromptContext(state) {
31897
- const frame = {
31898
- id: /* @__PURE__ */ Symbol("braintrust.pi-coding-agent.prompt"),
31899
- state
31900
- };
31901
- promptContextStore().enterWith({
31902
- frames: [...currentPromptContextFrames(), frame]
31903
- });
31904
- return () => {
31905
- const frames = currentPromptContextFrames().filter(
31906
- (candidate) => candidate.id !== frame.id
31907
- );
31908
- promptContextStore().enterWith(frames.length > 0 ? { frames } : void 0);
31909
- };
31910
- }
31911
- function installPiStreamPatch(agent) {
31912
- const existing = piStreamPatchStates.get(agent);
31913
- if (existing) {
31914
- if (agent.streamFn !== existing.wrappedStreamFn) {
31915
- debugLogger.debug(
31916
- "Pi Coding Agent streamFn changed while Braintrust instrumentation was active; preserving existing patch state."
31917
- );
31918
- }
31919
- return existing;
31920
- }
31921
- const patchState = {
31922
- activePromptStates: /* @__PURE__ */ new Set(),
31923
- agent,
31924
- originalStreamFn: agent.streamFn,
31925
- queuedPromptStates: [],
31926
- wrappedStreamFn: agent.streamFn
31927
- };
31928
- patchState.wrappedStreamFn = makeSharedInstrumentedStreamFn(patchState);
31929
- agent.streamFn = patchState.wrappedStreamFn;
31930
- piStreamPatchStates.set(agent, patchState);
31931
- return patchState;
31932
- }
31933
- function resolveStreamPromptState(patchState, context) {
31934
- let lastUserText;
31935
- if (Array.isArray(context.messages)) {
31936
- for (let i = context.messages.length - 1; i >= 0; i--) {
31937
- const message = context.messages[i];
31938
- if (isPiUserMessage(message)) {
31939
- if (typeof message.content === "string") {
31940
- lastUserText = message.content;
31941
- } else {
31942
- lastUserText = message.content.flatMap((part) => part.type === "text" ? [part.text] : []).join("");
31943
- }
31944
- break;
31945
- }
31946
- }
31947
- }
31948
- if (lastUserText !== void 0) {
31949
- const queuedMatch = patchState.queuedPromptStates.find(
31950
- (state) => state.promptText === lastUserText
31951
- );
31952
- if (queuedMatch) {
31953
- return queuedMatch;
31954
- }
31955
- const matches = [...patchState.activePromptStates].filter(
31956
- (state) => state.promptText === lastUserText
33346
+ return promptContextStore().getStore();
33347
+ }
33348
+ function installPiAgentInstrumentation(agent) {
33349
+ const existing = piAgentPatchStates.get(agent);
33350
+ if (!existing || agent.streamFn !== existing.wrappedStreamFn) {
33351
+ const patchState = {
33352
+ originalStreamFn: agent.streamFn,
33353
+ wrappedStreamFn: agent.streamFn
33354
+ };
33355
+ patchState.wrappedStreamFn = makeInstrumentedStreamFn(
33356
+ agent,
33357
+ patchState.originalStreamFn
31957
33358
  );
31958
- if (matches.length === 1) {
31959
- return matches[0];
31960
- }
33359
+ agent.streamFn = patchState.wrappedStreamFn;
33360
+ piAgentPatchStates.set(agent, patchState);
31961
33361
  }
31962
- const contextState = currentPiPromptState();
31963
- if (contextState && patchState.activePromptStates.has(contextState) && (!contextState.queued || lastUserText !== void 0 && contextState.promptText === lastUserText)) {
31964
- return contextState;
33362
+ if (piAgentEventSubscriptions.has(agent)) {
33363
+ return;
31965
33364
  }
31966
- if (patchState.activePromptStates.size === 1) {
31967
- return [...patchState.activePromptStates][0];
33365
+ try {
33366
+ agent.subscribe(async (event) => {
33367
+ const state = currentPiPromptState();
33368
+ if (!state || state.agent !== agent || state.finalized) {
33369
+ return;
33370
+ }
33371
+ try {
33372
+ await runWithAutoInstrumentationSuppressed(
33373
+ () => handlePiAgentEvent(state, event)
33374
+ );
33375
+ } catch (error) {
33376
+ logInstrumentationError4("Pi Coding Agent event", error);
33377
+ }
33378
+ });
33379
+ piAgentEventSubscriptions.add(agent);
33380
+ } catch (error) {
33381
+ logInstrumentationError4("Pi Coding Agent event subscription", error);
31968
33382
  }
31969
- return void 0;
31970
33383
  }
31971
- function makeSharedInstrumentedStreamFn(patchState) {
33384
+ function makeInstrumentedStreamFn(agent, originalStreamFn) {
31972
33385
  return async function instrumentedPiStreamFn(model, context, options) {
31973
- const state = resolveStreamPromptState(patchState, context);
31974
- if (!state) {
31975
- const invokeOriginal = () => Reflect.apply(patchState.originalStreamFn, this, [
31976
- model,
31977
- context,
31978
- options
31979
- ]);
31980
- return patchState.activePromptStates.size > 0 ? runWithAutoInstrumentationSuppressed(invokeOriginal) : invokeOriginal();
33386
+ const invokeOriginal = () => Reflect.apply(originalStreamFn, this, [model, context, options]);
33387
+ const state = currentPiPromptState();
33388
+ if (!state || state.agent !== agent || state.finalized) {
33389
+ return invokeOriginal();
31981
33390
  }
31982
- state.sawStreamFn = true;
31983
- removeQueuedPromptState(state);
31984
- state.streamPatchState.eventPromptState = state;
31985
33391
  const llmState = await startPiLlmSpan(state, model, context, options);
31986
33392
  try {
31987
- const stream = await runWithAutoInstrumentationSuppressed(
31988
- () => Reflect.apply(patchState.originalStreamFn, this, [
31989
- model,
31990
- context,
31991
- options
31992
- ])
31993
- );
33393
+ const stream = await runWithAutoInstrumentationSuppressed(invokeOriginal);
31994
33394
  return patchAssistantMessageStream(stream, state, llmState);
31995
33395
  } catch (error) {
31996
33396
  finishPiLlmSpan(state, llmState, void 0, error);
@@ -32137,13 +33537,6 @@ async function handlePiAgentEvent(state, event) {
32137
33537
  if (state.finalized) {
32138
33538
  return;
32139
33539
  }
32140
- const eventPromptState = state.streamPatchState.eventPromptState;
32141
- if (eventPromptState && eventPromptState !== state) {
32142
- return;
32143
- }
32144
- if (!eventPromptState && (state.queued || state.streamPatchState.activePromptStates.size > 1 && currentPiPromptState() !== state)) {
32145
- return;
32146
- }
32147
33540
  switch (event.type) {
32148
33541
  case "message_end":
32149
33542
  if (isPiAssistantMessage(event.message)) {
@@ -32158,11 +33551,8 @@ async function handlePiAgentEvent(state, event) {
32158
33551
  addMetrics(state.metrics, extractUsageMetrics2(event.message.usage));
32159
33552
  }
32160
33553
  }
32161
- if (state.streamPatchState.eventPromptState === state) {
32162
- state.streamPatchState.eventPromptState = void 0;
32163
- }
32164
33554
  if (state.promptCallEnded && state.deferCompletionUntilTurnEnd) {
32165
- await finalizePiPromptRun(state);
33555
+ finishPiPromptRun(state);
32166
33556
  }
32167
33557
  return;
32168
33558
  case "tool_execution_start":
@@ -32235,19 +33625,13 @@ function finishPiToolSpan(state, event) {
32235
33625
  }
32236
33626
  }
32237
33627
  }
32238
- async function finalizePiPromptRun(state, error) {
33628
+ function finishPiPromptRun(state, error) {
32239
33629
  if (state.finalized) {
32240
33630
  return;
32241
33631
  }
32242
33632
  state.finalized = true;
32243
33633
  state.onFinalize?.(state);
32244
- restorePiStreamFn(state);
32245
- try {
32246
- state.unsubscribeAgent?.();
32247
- } catch (unsubscribeError) {
32248
- logInstrumentationError4("Pi Coding Agent unsubscribe", unsubscribeError);
32249
- }
32250
- await finishOpenLlmSpans(state, error);
33634
+ finishOpenLlmSpans(state, error);
32251
33635
  finishOpenToolSpans(state, error);
32252
33636
  const metadata = {
32253
33637
  ...state.metadata,
@@ -32264,34 +33648,14 @@ async function finalizePiPromptRun(state, error) {
32264
33648
  output: state.output
32265
33649
  });
32266
33650
  } finally {
32267
- state.span.end();
32268
- }
32269
- }
32270
- function restorePiStreamFn(state) {
32271
- const patchState = state.streamPatchState;
32272
- patchState.activePromptStates.delete(state);
32273
- removeQueuedPromptState(state);
32274
- if (patchState.eventPromptState === state) {
32275
- patchState.eventPromptState = void 0;
32276
- }
32277
- state.restorePromptContext?.();
32278
- if (patchState.activePromptStates.size > 0) {
32279
- return;
32280
- }
32281
- if (patchState.agent.streamFn === patchState.wrappedStreamFn) {
32282
- patchState.agent.streamFn = patchState.originalStreamFn;
32283
- }
32284
- piStreamPatchStates.delete(patchState.agent);
32285
- }
32286
- function removeQueuedPromptState(state) {
32287
- state.queued = false;
32288
- const queuedPromptStates = state.streamPatchState.queuedPromptStates;
32289
- const index = queuedPromptStates.indexOf(state);
32290
- if (index >= 0) {
32291
- queuedPromptStates.splice(index, 1);
33651
+ try {
33652
+ state.span.end();
33653
+ } catch (endError) {
33654
+ logInstrumentationError4("Pi Coding Agent prompt end", endError);
33655
+ }
32292
33656
  }
32293
33657
  }
32294
- async function finishOpenLlmSpans(state, error) {
33658
+ function finishOpenLlmSpans(state, error) {
32295
33659
  for (const llmState of [...state.activeLlmSpans]) {
32296
33660
  finishPiLlmSpan(state, llmState, void 0, error);
32297
33661
  }
@@ -32372,7 +33736,7 @@ function normalizeAssistantMessage(message) {
32372
33736
  (part) => part.type === "thinking" && !part.redacted ? [part.thinking] : []
32373
33737
  ).join("");
32374
33738
  const toolCalls2 = message.content.flatMap(
32375
- (part) => part.type === "toolCall" ? [normalizeToolCall(part)] : []
33739
+ (part) => part.type === "toolCall" ? [normalizeToolCall2(part)] : []
32376
33740
  );
32377
33741
  return {
32378
33742
  role: "assistant",
@@ -32407,13 +33771,13 @@ function normalizeUserContent(content) {
32407
33771
  return part;
32408
33772
  });
32409
33773
  }
32410
- function normalizeToolCall(toolCall) {
33774
+ function normalizeToolCall2(toolCall) {
32411
33775
  return {
32412
33776
  id: toolCall.id,
32413
33777
  type: "function",
32414
33778
  function: {
32415
33779
  name: toolCall.name,
32416
- arguments: stringifyArguments(toolCall.arguments)
33780
+ arguments: stringifyArguments2(toolCall.arguments)
32417
33781
  }
32418
33782
  };
32419
33783
  }
@@ -32596,7 +33960,7 @@ function cleanMetrics5(metrics) {
32596
33960
  }
32597
33961
  return cleaned;
32598
33962
  }
32599
- function stringifyArguments(value) {
33963
+ function stringifyArguments2(value) {
32600
33964
  if (typeof value === "string") {
32601
33965
  return value;
32602
33966
  }
@@ -34187,6 +35551,7 @@ var BraintrustPlugin = class extends BasePlugin {
34187
35551
  anthropicPlugin = null;
34188
35552
  aiSDKPlugin = null;
34189
35553
  claudeAgentSDKPlugin = null;
35554
+ cloudflareThinkPlugin = null;
34190
35555
  cursorSDKPlugin = null;
34191
35556
  openAIAgentsPlugin = null;
34192
35557
  googleGenAIPlugin = null;
@@ -34195,6 +35560,7 @@ var BraintrustPlugin = class extends BasePlugin {
34195
35560
  openRouterPlugin = null;
34196
35561
  openRouterAgentPlugin = null;
34197
35562
  mistralPlugin = null;
35563
+ ollamaPlugin = null;
34198
35564
  googleADKPlugin = null;
34199
35565
  coherePlugin = null;
34200
35566
  groqPlugin = null;
@@ -34234,6 +35600,10 @@ var BraintrustPlugin = class extends BasePlugin {
34234
35600
  this.claudeAgentSDKPlugin = new ClaudeAgentSDKPlugin();
34235
35601
  this.claudeAgentSDKPlugin.enable();
34236
35602
  }
35603
+ if (integrations.cloudflareThink !== false) {
35604
+ this.cloudflareThinkPlugin = new CloudflareThinkPlugin();
35605
+ this.cloudflareThinkPlugin.enable();
35606
+ }
34237
35607
  if (integrations.cursorSDK !== false && integrations.cursor !== false) {
34238
35608
  this.cursorSDKPlugin = new CursorSDKPlugin();
34239
35609
  this.cursorSDKPlugin.enable();
@@ -34264,6 +35634,10 @@ var BraintrustPlugin = class extends BasePlugin {
34264
35634
  this.mistralPlugin = new MistralPlugin();
34265
35635
  this.mistralPlugin.enable();
34266
35636
  }
35637
+ if (integrations.ollama !== false) {
35638
+ this.ollamaPlugin = new OllamaPlugin();
35639
+ this.ollamaPlugin.enable();
35640
+ }
34267
35641
  if (integrations.googleADK !== false) {
34268
35642
  this.googleADKPlugin = new GoogleADKPlugin();
34269
35643
  this.googleADKPlugin.enable();
@@ -34340,6 +35714,10 @@ var BraintrustPlugin = class extends BasePlugin {
34340
35714
  this.claudeAgentSDKPlugin.disable();
34341
35715
  this.claudeAgentSDKPlugin = null;
34342
35716
  }
35717
+ if (this.cloudflareThinkPlugin) {
35718
+ this.cloudflareThinkPlugin.disable();
35719
+ this.cloudflareThinkPlugin = null;
35720
+ }
34343
35721
  if (this.cursorSDKPlugin) {
34344
35722
  this.cursorSDKPlugin.disable();
34345
35723
  this.cursorSDKPlugin = null;
@@ -34372,6 +35750,10 @@ var BraintrustPlugin = class extends BasePlugin {
34372
35750
  this.mistralPlugin.disable();
34373
35751
  this.mistralPlugin = null;
34374
35752
  }
35753
+ if (this.ollamaPlugin) {
35754
+ this.ollamaPlugin.disable();
35755
+ this.ollamaPlugin = null;
35756
+ }
34375
35757
  if (this.googleADKPlugin) {
34376
35758
  this.googleADKPlugin.disable();
34377
35759
  this.googleADKPlugin = null;
@@ -34457,6 +35839,7 @@ var envIntegrationAliases = {
34457
35839
  cloudflareaichat: "cloudflareAIChat",
34458
35840
  "cloudflare-ai-chat": "cloudflareAIChat",
34459
35841
  "@cloudflare/ai-chat": "cloudflareAIChat",
35842
+ cloudflarethink: "cloudflareThink",
34460
35843
  cursor: "cursor",
34461
35844
  "cursor-sdk": "cursorSDK",
34462
35845
  cursorsdk: "cursorSDK",
@@ -34477,6 +35860,7 @@ var envIntegrationAliases = {
34477
35860
  openrouteragent: "openrouterAgent",
34478
35861
  "openrouter-agent": "openrouterAgent",
34479
35862
  mistral: "mistral",
35863
+ ollama: "ollama",
34480
35864
  googleadk: "googleADK",
34481
35865
  "google-adk": "googleADK",
34482
35866
  cohere: "cohere",
@@ -34512,6 +35896,7 @@ function getDefaultInstrumentationIntegrations() {
34512
35896
  huggingface: true,
34513
35897
  claudeAgentSDK: true,
34514
35898
  cloudflareAIChat: true,
35899
+ cloudflareThink: true,
34515
35900
  cursor: true,
34516
35901
  cursorSDK: true,
34517
35902
  flue: true,
@@ -34520,6 +35905,7 @@ function getDefaultInstrumentationIntegrations() {
34520
35905
  openrouter: true,
34521
35906
  openrouterAgent: true,
34522
35907
  mistral: true,
35908
+ ollama: true,
34523
35909
  cohere: true,
34524
35910
  groq: true,
34525
35911
  bedrock: true,
@@ -34756,6 +36142,7 @@ __export(exports_exports, {
34756
36142
  braintrustFlueObserver: () => braintrustFlueObserver,
34757
36143
  braintrustStreamChunkSchema: () => braintrustStreamChunkSchema,
34758
36144
  buildLocalSummary: () => buildLocalSummary,
36145
+ collectAnthropicSession: () => collectAnthropicSession,
34759
36146
  configureInstrumentation: () => configureInstrumentation,
34760
36147
  constructLogs3OverflowRequest: () => constructLogs3OverflowRequest,
34761
36148
  createFinalValuePassThroughStream: () => createFinalValuePassThroughStream,
@@ -34835,6 +36222,7 @@ __export(exports_exports, {
34835
36222
  wrapClaudeAgentSDK: () => wrapClaudeAgentSDK,
34836
36223
  wrapCloudflareAIChat: () => wrapCloudflareAIChat,
34837
36224
  wrapCloudflareAgent: () => wrapCloudflareAgent,
36225
+ wrapCloudflareThink: () => wrapCloudflareThink,
34838
36226
  wrapCohere: () => wrapCohere,
34839
36227
  wrapCopilotClient: () => wrapCopilotClient,
34840
36228
  wrapCursorSDK: () => wrapCursorSDK,
@@ -34849,6 +36237,7 @@ __export(exports_exports, {
34849
36237
  wrapLangSmithTraceable: () => wrapLangSmithTraceable,
34850
36238
  wrapMastraAgent: () => wrapMastraAgent,
34851
36239
  wrapMistral: () => wrapMistral,
36240
+ wrapOllama: () => wrapOllama,
34852
36241
  wrapOpenAI: () => wrapOpenAI,
34853
36242
  wrapOpenAICodexSDK: () => wrapOpenAICodexSDK,
34854
36243
  wrapOpenAIv4: () => wrapOpenAIv4,
@@ -36123,7 +37512,7 @@ function normalizeUsageMetrics(usage, provider, providerMetadata) {
36123
37512
  }
36124
37513
  return metrics;
36125
37514
  }
36126
- function normalizeFinishReason(reason) {
37515
+ function normalizeFinishReason2(reason) {
36127
37516
  if (typeof reason !== "string") return void 0;
36128
37517
  return reason.replace(/-/g, "_");
36129
37518
  }
@@ -36132,7 +37521,7 @@ function buildAssistantOutputWithToolCalls(result, toolCalls2) {
36132
37521
  {
36133
37522
  index: 0,
36134
37523
  logprobs: null,
36135
- finish_reason: normalizeFinishReason(result?.finishReason) ?? (toolCalls2.length ? "tool_calls" : void 0),
37524
+ finish_reason: normalizeFinishReason2(result?.finishReason) ?? (toolCalls2.length ? "tool_calls" : void 0),
36136
37525
  message: {
36137
37526
  role: "assistant",
36138
37527
  tool_calls: toolCalls2.length > 0 ? toolCalls2 : void 0
@@ -38053,6 +39442,66 @@ function betaProxy(beta, anthropic) {
38053
39442
  if (prop === "messages") {
38054
39443
  return betaMessagesProxy(target.messages, anthropic);
38055
39444
  }
39445
+ if (prop === "sessions") {
39446
+ return target.sessions ? betaSessionsProxy(target.sessions) : target.sessions;
39447
+ }
39448
+ return Reflect.get(target, prop, receiver);
39449
+ }
39450
+ });
39451
+ }
39452
+ function betaSessionsProxy(sessions) {
39453
+ return new Proxy(sessions, {
39454
+ get(target, prop, receiver) {
39455
+ if (prop === "events") {
39456
+ return betaSessionEventsProxy(target.events);
39457
+ }
39458
+ if (prop === "threads") {
39459
+ return target.threads ? betaSessionThreadsProxy(target.threads) : target.threads;
39460
+ }
39461
+ return Reflect.get(target, prop, receiver);
39462
+ }
39463
+ });
39464
+ }
39465
+ function betaSessionEventsProxy(events) {
39466
+ return new Proxy(events, {
39467
+ get(target, prop, receiver) {
39468
+ if (prop === "stream") {
39469
+ return new TypedApplyProxy(target.stream, {
39470
+ apply(stream, thisArg, argArray) {
39471
+ return anthropicChannels.betaSessionsEventsStream.tracePromise(
39472
+ () => Reflect.apply(stream, thisArg, argArray),
39473
+ { arguments: argArray }
39474
+ );
39475
+ }
39476
+ });
39477
+ }
39478
+ return Reflect.get(target, prop, receiver);
39479
+ }
39480
+ });
39481
+ }
39482
+ function betaSessionThreadsProxy(threads) {
39483
+ return new Proxy(threads, {
39484
+ get(target, prop, receiver) {
39485
+ if (prop === "events") {
39486
+ return betaSessionThreadEventsProxy(target.events);
39487
+ }
39488
+ return Reflect.get(target, prop, receiver);
39489
+ }
39490
+ });
39491
+ }
39492
+ function betaSessionThreadEventsProxy(events) {
39493
+ return new Proxy(events, {
39494
+ get(target, prop, receiver) {
39495
+ if (prop === "stream") {
39496
+ return new TypedApplyProxy(target.stream, {
39497
+ apply(stream, thisArg, argArray) {
39498
+ return anthropicChannels.betaSessionsThreadsEventsStream.tracePromise(
39499
+ () => Reflect.apply(stream, thisArg, argArray),
39500
+ { arguments: argArray }
39501
+ );
39502
+ }
39503
+ });
39504
+ }
38056
39505
  return Reflect.get(target, prop, receiver);
38057
39506
  }
38058
39507
  });
@@ -38466,6 +39915,52 @@ function claudeAgentSDKProxy(sdk) {
38466
39915
  });
38467
39916
  }
38468
39917
 
39918
+ // src/wrappers/cloudflare-think.ts
39919
+ var WRAPPED_THINK = /* @__PURE__ */ Symbol.for("braintrust.cloudflare-think.wrapped");
39920
+ function wrapCloudflareThink(sdk) {
39921
+ if (!sdk || typeof sdk !== "object") {
39922
+ return sdk;
39923
+ }
39924
+ const thinkModule = sdk;
39925
+ if (typeof thinkModule.Think !== "function") {
39926
+ return sdk;
39927
+ }
39928
+ patchThinkClass(thinkModule.Think);
39929
+ return sdk;
39930
+ }
39931
+ function patchThinkClass(Think) {
39932
+ const prototype = Think.prototype;
39933
+ if (!prototype || prototype[WRAPPED_THINK]) {
39934
+ return;
39935
+ }
39936
+ const descriptor = Object.getOwnPropertyDescriptor(
39937
+ prototype,
39938
+ "_runInferenceLoop"
39939
+ );
39940
+ if (!descriptor || typeof descriptor.value !== "function") {
39941
+ return;
39942
+ }
39943
+ const original = descriptor.value;
39944
+ Object.defineProperty(prototype, "_runInferenceLoop", {
39945
+ ...descriptor,
39946
+ value: function wrappedCloudflareThinkRunInferenceLoop(input) {
39947
+ const args = [input];
39948
+ return cloudflareThinkChannels.runInferenceLoop.tracePromise(
39949
+ () => Reflect.apply(original, this, args),
39950
+ {
39951
+ arguments: args,
39952
+ self: this
39953
+ }
39954
+ );
39955
+ }
39956
+ });
39957
+ Object.defineProperty(prototype, WRAPPED_THINK, {
39958
+ configurable: false,
39959
+ enumerable: false,
39960
+ value: true
39961
+ });
39962
+ }
39963
+
38469
39964
  // src/wrappers/openai-codex.ts
38470
39965
  var WRAPPED_CLIENT = /* @__PURE__ */ Symbol.for("braintrust.openai-codex.wrapped-client");
38471
39966
  var WRAPPED_THREAD = /* @__PURE__ */ Symbol.for("braintrust.openai-codex.wrapped-thread");
@@ -38758,14 +40253,9 @@ function patchAgentSessionClass(AgentSession) {
38758
40253
  ...descriptor,
38759
40254
  value: function wrappedPiCodingAgentPrompt(text, options) {
38760
40255
  const args = [text, options];
38761
- return piCodingAgentChannels.prompt.tracePromise(
38762
- () => Reflect.apply(originalPrompt, this, args),
38763
- {
38764
- arguments: args,
38765
- self: this,
38766
- session: this
38767
- }
38768
- );
40256
+ return piCodingAgentChannels.prompt.invoke(originalPrompt, this, args, {
40257
+ session: this
40258
+ });
38769
40259
  }
38770
40260
  });
38771
40261
  Object.defineProperty(prototype, WRAPPED_PROMPT, {
@@ -40205,6 +41695,83 @@ function wrapAgentsStream(stream) {
40205
41695
  });
40206
41696
  }
40207
41697
 
41698
+ // src/wrappers/ollama.ts
41699
+ function wrapOllama(ollama) {
41700
+ if (isSupportedOllamaClient(ollama)) {
41701
+ return ollamaProxy(ollama);
41702
+ }
41703
+ debugLogger.warn("Unsupported Ollama library. Not wrapping.");
41704
+ return ollama;
41705
+ }
41706
+ var ollamaProxyCache = /* @__PURE__ */ new WeakMap();
41707
+ function isSupportedOllamaClient(value) {
41708
+ return isObject(value) && ["chat", "generate", "embed"].some(
41709
+ (name) => typeof value[name] === "function"
41710
+ );
41711
+ }
41712
+ function ollamaProxy(ollama) {
41713
+ const cached = ollamaProxyCache.get(ollama);
41714
+ if (cached) {
41715
+ return cached;
41716
+ }
41717
+ let chatSource;
41718
+ let wrappedChat;
41719
+ let generateSource;
41720
+ let wrappedGenerate;
41721
+ let embedSource;
41722
+ let wrappedEmbed;
41723
+ const proxy = new Proxy(ollama, {
41724
+ get(target, prop, receiver) {
41725
+ switch (prop) {
41726
+ case "chat": {
41727
+ const source = target.chat;
41728
+ if (source !== chatSource) {
41729
+ chatSource = source;
41730
+ wrappedChat = typeof source === "function" ? wrapChat(source.bind(target)) : source;
41731
+ }
41732
+ return wrappedChat;
41733
+ }
41734
+ case "generate": {
41735
+ const source = target.generate;
41736
+ if (source !== generateSource) {
41737
+ generateSource = source;
41738
+ wrappedGenerate = typeof source === "function" ? wrapGenerate2(source.bind(target)) : source;
41739
+ }
41740
+ return wrappedGenerate;
41741
+ }
41742
+ case "embed": {
41743
+ const source = target.embed;
41744
+ if (source !== embedSource) {
41745
+ embedSource = source;
41746
+ wrappedEmbed = typeof source === "function" ? wrapEmbed3(source.bind(target)) : source;
41747
+ }
41748
+ return wrappedEmbed;
41749
+ }
41750
+ default:
41751
+ return Reflect.get(target, prop, receiver);
41752
+ }
41753
+ }
41754
+ });
41755
+ ollamaProxyCache.set(ollama, proxy);
41756
+ ollamaProxyCache.set(proxy, proxy);
41757
+ return proxy;
41758
+ }
41759
+ function wrapChat(chat) {
41760
+ return (request) => ollamaChannels.chat.tracePromise(() => chat(request), {
41761
+ arguments: [request]
41762
+ });
41763
+ }
41764
+ function wrapGenerate2(generate) {
41765
+ return (request) => ollamaChannels.generate.tracePromise(() => generate(request), {
41766
+ arguments: [request]
41767
+ });
41768
+ }
41769
+ function wrapEmbed3(embed) {
41770
+ return (request) => ollamaChannels.embed.tracePromise(() => embed(request), {
41771
+ arguments: [request]
41772
+ });
41773
+ }
41774
+
40208
41775
  // src/wrappers/cohere.ts
40209
41776
  function wrapCohere(cohere) {
40210
41777
  if (isSupportedCohereClient(cohere)) {
@@ -40235,11 +41802,11 @@ function cohereProxy(cohere) {
40235
41802
  get(target, prop, receiver) {
40236
41803
  switch (prop) {
40237
41804
  case "chat":
40238
- return typeof target.chat === "function" ? wrapChat(target.chat.bind(target)) : target.chat;
41805
+ return typeof target.chat === "function" ? wrapChat2(target.chat.bind(target)) : target.chat;
40239
41806
  case "chatStream":
40240
41807
  return typeof target.chatStream === "function" ? wrapChatStream2(target.chatStream.bind(target)) : target.chatStream;
40241
41808
  case "embed":
40242
- return typeof target.embed === "function" ? wrapEmbed3(target.embed.bind(target)) : target.embed;
41809
+ return typeof target.embed === "function" ? wrapEmbed4(target.embed.bind(target)) : target.embed;
40243
41810
  case "rerank":
40244
41811
  return typeof target.rerank === "function" ? wrapRerank3(target.rerank.bind(target)) : target.rerank;
40245
41812
  default: {
@@ -40252,7 +41819,7 @@ function cohereProxy(cohere) {
40252
41819
  cohereProxyCache.set(cohere, proxy);
40253
41820
  return proxy;
40254
41821
  }
40255
- function wrapChat(chat) {
41822
+ function wrapChat2(chat) {
40256
41823
  return (request, options) => cohereChannels.chat.tracePromise(() => chat(request, options), {
40257
41824
  arguments: [request]
40258
41825
  });
@@ -40262,7 +41829,7 @@ function wrapChatStream2(chatStream) {
40262
41829
  arguments: [request]
40263
41830
  });
40264
41831
  }
40265
- function wrapEmbed3(embed) {
41832
+ function wrapEmbed4(embed) {
40266
41833
  return (request, options) => cohereChannels.embed.tracePromise(() => embed(request, options), {
40267
41834
  arguments: [request]
40268
41835
  });
@@ -45155,6 +46722,7 @@ export {
45155
46722
  braintrustFlueObserver,
45156
46723
  braintrustStreamChunkSchema,
45157
46724
  buildLocalSummary,
46725
+ collectAnthropicSession,
45158
46726
  configureInstrumentation,
45159
46727
  constructLogs3OverflowRequest,
45160
46728
  createFinalValuePassThroughStream,
@@ -45235,6 +46803,7 @@ export {
45235
46803
  wrapClaudeAgentSDK,
45236
46804
  wrapCloudflareAIChat,
45237
46805
  wrapCloudflareAgent,
46806
+ wrapCloudflareThink,
45238
46807
  wrapCohere,
45239
46808
  wrapCopilotClient,
45240
46809
  wrapCursorSDK,
@@ -45249,6 +46818,7 @@ export {
45249
46818
  wrapLangSmithTraceable,
45250
46819
  wrapMastraAgent,
45251
46820
  wrapMistral,
46821
+ wrapOllama,
45252
46822
  wrapOpenAI,
45253
46823
  wrapOpenAICodexSDK,
45254
46824
  wrapOpenAIv4,