braintrust 3.25.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 (79) hide show
  1. package/NOTICE +6 -0
  2. package/dev/dist/index.d.mts +130 -2
  3. package/dev/dist/index.d.ts +130 -2
  4. package/dev/dist/index.js +4133 -1421
  5. package/dev/dist/index.mjs +3242 -530
  6. package/dist/apply-auto-instrumentation.js +526 -426
  7. package/dist/apply-auto-instrumentation.mjs +329 -229
  8. package/dist/auto-instrumentations/bundler/esbuild.cjs +1198 -364
  9. package/dist/auto-instrumentations/bundler/esbuild.d.mts +4 -4
  10. package/dist/auto-instrumentations/bundler/esbuild.d.ts +4 -4
  11. package/dist/auto-instrumentations/bundler/esbuild.mjs +6 -8
  12. package/dist/auto-instrumentations/bundler/next.cjs +1227 -413
  13. package/dist/auto-instrumentations/bundler/next.mjs +7 -29
  14. package/dist/auto-instrumentations/bundler/rollup.cjs +1198 -364
  15. package/dist/auto-instrumentations/bundler/rollup.d.mts +4 -4
  16. package/dist/auto-instrumentations/bundler/rollup.d.ts +4 -4
  17. package/dist/auto-instrumentations/bundler/rollup.mjs +6 -8
  18. package/dist/auto-instrumentations/bundler/vite.cjs +1249 -387
  19. package/dist/auto-instrumentations/bundler/vite.d.mts +4 -4
  20. package/dist/auto-instrumentations/bundler/vite.d.ts +4 -4
  21. package/dist/auto-instrumentations/bundler/vite.mjs +34 -8
  22. package/dist/auto-instrumentations/bundler/webpack-loader.cjs +1368 -324
  23. package/dist/auto-instrumentations/bundler/webpack-loader.d.ts +20 -12
  24. package/dist/auto-instrumentations/bundler/webpack.cjs +1198 -364
  25. package/dist/auto-instrumentations/bundler/webpack.d.mts +4 -4
  26. package/dist/auto-instrumentations/bundler/webpack.d.ts +4 -4
  27. package/dist/auto-instrumentations/bundler/webpack.mjs +6 -4
  28. package/dist/auto-instrumentations/chunk-2AMDGD65.mjs +1396 -0
  29. package/dist/auto-instrumentations/{chunk-7P6563SW.mjs → chunk-BW33ULMW.mjs} +2 -6
  30. package/dist/auto-instrumentations/{chunk-M6DLIJ2Z.mjs → chunk-I55G56ZL.mjs} +114 -221
  31. package/dist/auto-instrumentations/chunk-JPUFNW7X.mjs +649 -0
  32. package/dist/auto-instrumentations/{chunk-JPVCUKTY.mjs → chunk-XEYKUBLY.mjs} +191 -73
  33. package/dist/auto-instrumentations/{chunk-CZ24KNHT.mjs → chunk-ZNHTSSGI.mjs} +231 -69
  34. package/dist/auto-instrumentations/hook.mjs +406 -183
  35. package/dist/auto-instrumentations/index.cjs +853 -49
  36. package/dist/auto-instrumentations/index.d.mts +10 -2
  37. package/dist/auto-instrumentations/index.d.ts +10 -2
  38. package/dist/auto-instrumentations/index.mjs +10 -1
  39. package/dist/auto-instrumentations/loader/cjs-patch.cjs +566 -221
  40. package/dist/auto-instrumentations/loader/cjs-patch.d.mts +2 -2
  41. package/dist/auto-instrumentations/loader/cjs-patch.d.ts +2 -2
  42. package/dist/auto-instrumentations/loader/cjs-patch.mjs +3 -2
  43. package/dist/auto-instrumentations/loader/esm-hook.mjs +1 -1
  44. package/dist/auto-instrumentations/plugin-B-aZh7EP.d.ts +30 -0
  45. package/dist/auto-instrumentations/plugin-Bnj4E_6B.d.mts +30 -0
  46. package/dist/auto-instrumentations/{types-RNPaKi9o.d.mts → types-C1fVeiCp.d.mts} +1 -1
  47. package/dist/auto-instrumentations/{types-RNPaKi9o.d.ts → types-C1fVeiCp.d.ts} +1 -1
  48. package/dist/browser.d.mts +871 -199
  49. package/dist/browser.d.ts +871 -199
  50. package/dist/browser.js +3737 -549
  51. package/dist/browser.mjs +3737 -549
  52. package/dist/{chunk-ABR2QWDP.mjs → chunk-CZM5JIQL.mjs} +788 -132
  53. package/dist/{chunk-P25IOOU4.js → chunk-MF7NU6BT.js} +795 -139
  54. package/dist/{chunk-GSIDVFE6.js → chunk-QRHGVBKU.js} +3580 -1463
  55. package/dist/{chunk-2SANLSWX.mjs → chunk-YKD22IMR.mjs} +2505 -388
  56. package/dist/cli.js +3244 -533
  57. package/dist/edge-light.d.mts +1 -1
  58. package/dist/edge-light.d.ts +1 -1
  59. package/dist/edge-light.js +3737 -552
  60. package/dist/edge-light.mjs +3737 -552
  61. package/dist/index.d.mts +871 -199
  62. package/dist/index.d.ts +871 -199
  63. package/dist/index.js +893 -446
  64. package/dist/index.mjs +463 -16
  65. package/dist/instrumentation/index.d.mts +138 -6
  66. package/dist/instrumentation/index.d.ts +138 -6
  67. package/dist/instrumentation/index.js +3362 -559
  68. package/dist/instrumentation/index.mjs +3362 -559
  69. package/dist/vitest-evals-reporter.js +45 -43
  70. package/dist/vitest-evals-reporter.mjs +5 -3
  71. package/dist/workerd.d.mts +1 -1
  72. package/dist/workerd.d.ts +1 -1
  73. package/dist/workerd.js +3737 -552
  74. package/dist/workerd.mjs +3737 -552
  75. package/licenses/node-diagnostics-channel/LICENSE +19 -0
  76. package/package.json +34 -35
  77. package/dist/auto-instrumentations/chunk-VT6DDNKM.mjs +0 -856
  78. package/dist/auto-instrumentations/plugin-D0KHwSJv.d.mts +0 -44
  79. package/dist/auto-instrumentations/plugin-G6fgxk1b.d.ts +0 -44
@@ -44,331 +44,688 @@ __export(index_exports, {
44
44
  });
45
45
  module.exports = __toCommonJS(index_exports);
46
46
 
47
- // src/isomorph.ts
48
- var DefaultAsyncLocalStorage = class {
49
- constructor() {
50
- }
51
- enterWith(_) {
52
- }
53
- run(_, callback) {
54
- return callback();
47
+ // src/global-instrumentation-hooks.ts
48
+ var GLOBAL_INSTRUMENTATION_HOOKS_KEY = "__braintrust_instrumentation_hooks";
49
+ var GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION = 1;
50
+ var GLOBAL_INSTRUMENTATION_HOOKS_REGISTRY_BRAND = "braintrust.global-instrumentation-hooks.registry";
51
+ var GLOBAL_INSTRUMENTATION_HOOK_BRAND = "braintrust.global-instrumentation-hooks.hook";
52
+ var GLOBAL_INVOCATION_HOOK_BRAND = "braintrust.global-instrumentation-hooks.invocation-hook";
53
+ var registryBrand = Symbol.for(GLOBAL_INSTRUMENTATION_HOOKS_REGISTRY_BRAND);
54
+ var hookBrand = Symbol.for(GLOBAL_INSTRUMENTATION_HOOK_BRAND);
55
+ var invocationHookBrand = Symbol.for(GLOBAL_INVOCATION_HOOK_BRAND);
56
+ var errorReporter;
57
+ function setGlobalHookErrorReporter(reporter) {
58
+ const previousReporter = errorReporter;
59
+ errorReporter = reporter;
60
+ return () => {
61
+ if (errorReporter === reporter) {
62
+ errorReporter = previousReporter;
63
+ }
64
+ };
65
+ }
66
+ function reportError(error) {
67
+ try {
68
+ errorReporter?.(error);
69
+ } catch {
55
70
  }
56
- getStore() {
57
- return void 0;
71
+ }
72
+ function setContextValue(context, key, value) {
73
+ try {
74
+ context[key] = value;
75
+ } catch (error) {
76
+ reportError(error);
58
77
  }
59
- };
60
- var DefaultChannel = class {
78
+ }
79
+ function wrapStoreRun(store, message, next, transform) {
80
+ return () => {
81
+ let context;
82
+ try {
83
+ context = transform ? transform(message) : message;
84
+ } catch (error) {
85
+ reportError(error);
86
+ return next();
87
+ }
88
+ let called = false;
89
+ let result;
90
+ let providerError;
91
+ let providerThrew = false;
92
+ const runNext = () => {
93
+ if (called) {
94
+ reportError(
95
+ new Error(
96
+ "Instrumentation store invoked its callback more than once"
97
+ )
98
+ );
99
+ if (providerThrew) {
100
+ throw providerError;
101
+ }
102
+ return result;
103
+ }
104
+ called = true;
105
+ try {
106
+ result = next();
107
+ return result;
108
+ } catch (error) {
109
+ providerThrew = true;
110
+ providerError = error;
111
+ throw error;
112
+ }
113
+ };
114
+ try {
115
+ store.run(context, runNext);
116
+ } catch (error) {
117
+ if (!providerThrew || error !== providerError) {
118
+ reportError(error);
119
+ }
120
+ }
121
+ if (!called) {
122
+ reportError(
123
+ new Error("Instrumentation store did not invoke its callback")
124
+ );
125
+ return runNext();
126
+ }
127
+ if (providerThrew) {
128
+ throw providerError;
129
+ }
130
+ return result;
131
+ };
132
+ }
133
+ var HookChannel = class {
61
134
  constructor(name) {
62
135
  this.name = name;
63
136
  }
64
137
  name;
65
- hasSubscribers = false;
66
- subscribe(_subscription) {
138
+ subscribers = [];
139
+ stores = /* @__PURE__ */ new Map();
140
+ get hasSubscribers() {
141
+ return this.subscribers.length > 0 || this.stores.size > 0;
67
142
  }
68
- unsubscribe(_subscription) {
69
- return false;
143
+ subscribe(subscription) {
144
+ if (typeof subscription !== "function") {
145
+ throw new TypeError("subscription must be a function");
146
+ }
147
+ this.subscribers = [...this.subscribers, subscription];
70
148
  }
71
- bindStore(_store, _transform) {
149
+ unsubscribe(subscription) {
150
+ const index = this.subscribers.indexOf(subscription);
151
+ if (index === -1) {
152
+ return false;
153
+ }
154
+ this.subscribers = [
155
+ ...this.subscribers.slice(0, index),
156
+ ...this.subscribers.slice(index + 1)
157
+ ];
158
+ return true;
72
159
  }
73
- unbindStore(_store) {
74
- return false;
160
+ bindStore(store, transform) {
161
+ if (!store || typeof store.run !== "function") {
162
+ throw new TypeError("store must have a run method");
163
+ }
164
+ this.stores.set(
165
+ store,
166
+ transform
167
+ );
75
168
  }
76
- publish(_message) {
169
+ unbindStore(store) {
170
+ return this.stores.delete(store);
77
171
  }
78
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
79
- runStores(_message, fn, thisArg, ...args) {
80
- return fn.apply(thisArg, args);
172
+ publish(message) {
173
+ const subscribers = this.subscribers;
174
+ for (const subscriber of subscribers) {
175
+ try {
176
+ subscriber(message, this.name);
177
+ } catch (error) {
178
+ reportError(error);
179
+ }
180
+ }
181
+ }
182
+ runStores(message, fn, thisArg, ...args) {
183
+ let run = () => {
184
+ this.publish(message);
185
+ return Reflect.apply(fn, thisArg, args);
186
+ };
187
+ for (const [store, transform] of this.stores.entries()) {
188
+ run = wrapStoreRun(store, message, run, transform);
189
+ }
190
+ return run();
81
191
  }
82
192
  };
83
- var DefaultTracingChannel = class {
193
+ var traceEvents = [
194
+ "start",
195
+ "end",
196
+ "asyncStart",
197
+ "asyncEnd",
198
+ "error"
199
+ ];
200
+ function traceInvocation(hook, operator, target, thisArg, args, additional, callbackIndex = -1) {
201
+ const context = {
202
+ ...additional,
203
+ arguments: args,
204
+ self: thisArg
205
+ };
206
+ const invoke = () => hook.invoke(target, thisArg, args, additional);
207
+ if (operator === "traceCallback") {
208
+ return hook.traceCallback(invoke, callbackIndex, context);
209
+ }
210
+ if (operator === "tracePromise") {
211
+ return hook.tracePromise(invoke, context);
212
+ }
213
+ return hook.traceSync(invoke, context);
214
+ }
215
+ var InvocationHook = class {
216
+ interceptors = [];
217
+ get hasInterceptors() {
218
+ return this.interceptors.length > 0;
219
+ }
220
+ intercept(interceptor) {
221
+ if (typeof interceptor !== "function") {
222
+ throw new TypeError("interceptor must be a function");
223
+ }
224
+ this.interceptors = [...this.interceptors, interceptor];
225
+ let active = true;
226
+ return () => {
227
+ if (!active) {
228
+ return;
229
+ }
230
+ active = false;
231
+ const index = this.interceptors.indexOf(interceptor);
232
+ if (index !== -1) {
233
+ this.interceptors = [
234
+ ...this.interceptors.slice(0, index),
235
+ ...this.interceptors.slice(index + 1)
236
+ ];
237
+ }
238
+ };
239
+ }
240
+ invoke(target, thisArg, args, additional) {
241
+ const interceptors = this.interceptors;
242
+ if (interceptors.length === 0) {
243
+ return Reflect.apply(target, thisArg, args);
244
+ }
245
+ let next = target;
246
+ for (let index = interceptors.length - 1; index >= 0; index -= 1) {
247
+ const interceptor = interceptors[index];
248
+ const downstream = next;
249
+ next = function(...nextArgs) {
250
+ return interceptor(downstream, this, nextArgs, additional);
251
+ };
252
+ }
253
+ return Reflect.apply(next, thisArg, args);
254
+ }
255
+ };
256
+ var TracingHook = class {
84
257
  start;
85
258
  end;
86
259
  asyncStart;
87
260
  asyncEnd;
88
261
  error;
262
+ invocationHook = new InvocationHook();
89
263
  constructor(nameOrChannels) {
264
+ Object.defineProperty(this, hookBrand, {
265
+ configurable: false,
266
+ enumerable: false,
267
+ value: GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION,
268
+ writable: false
269
+ });
270
+ Object.defineProperty(this, invocationHookBrand, {
271
+ configurable: false,
272
+ enumerable: false,
273
+ value: GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION,
274
+ writable: false
275
+ });
90
276
  if (typeof nameOrChannels === "string") {
91
- this.start = new DefaultChannel(`tracing:${nameOrChannels}:start`);
92
- this.end = new DefaultChannel(`tracing:${nameOrChannels}:end`);
93
- this.asyncStart = new DefaultChannel(
94
- `tracing:${nameOrChannels}:asyncStart`
95
- );
96
- this.asyncEnd = new DefaultChannel(`tracing:${nameOrChannels}:asyncEnd`);
97
- this.error = new DefaultChannel(`tracing:${nameOrChannels}:error`);
277
+ this.start = new HookChannel(`tracing:${nameOrChannels}:start`);
278
+ this.end = new HookChannel(`tracing:${nameOrChannels}:end`);
279
+ this.asyncStart = new HookChannel(`tracing:${nameOrChannels}:asyncStart`);
280
+ this.asyncEnd = new HookChannel(`tracing:${nameOrChannels}:asyncEnd`);
281
+ this.error = new HookChannel(`tracing:${nameOrChannels}:error`);
98
282
  return;
99
283
  }
100
- this.start = nameOrChannels.start ?? new DefaultChannel("tracing:start");
101
- this.end = nameOrChannels.end ?? new DefaultChannel("tracing:end");
102
- this.asyncStart = nameOrChannels.asyncStart ?? new DefaultChannel("tracing:asyncStart");
103
- this.asyncEnd = nameOrChannels.asyncEnd ?? new DefaultChannel("tracing:asyncEnd");
104
- this.error = nameOrChannels.error ?? new DefaultChannel("tracing:error");
284
+ this.start = nameOrChannels.start ?? new HookChannel("tracing:start");
285
+ this.end = nameOrChannels.end ?? new HookChannel("tracing:end");
286
+ this.asyncStart = nameOrChannels.asyncStart ?? new HookChannel("tracing:asyncStart");
287
+ this.asyncEnd = nameOrChannels.asyncEnd ?? new HookChannel("tracing:asyncEnd");
288
+ this.error = nameOrChannels.error ?? new HookChannel("tracing:error");
105
289
  }
106
290
  get hasSubscribers() {
107
291
  return this.start.hasSubscribers || this.end.hasSubscribers || this.asyncStart.hasSubscribers || this.asyncEnd.hasSubscribers || this.error.hasSubscribers;
108
292
  }
109
- subscribe(_handlers) {
110
- }
111
- unsubscribe(_handlers) {
112
- return false;
293
+ get hasInterceptors() {
294
+ return this.invocationHook.hasInterceptors;
113
295
  }
114
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
115
- traceSync(fn, _message, thisArg, ...args) {
116
- return fn.apply(thisArg, args);
296
+ intercept(interceptor) {
297
+ return this.invocationHook.intercept(interceptor);
117
298
  }
118
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
119
- tracePromise(fn, _message, thisArg, ...args) {
120
- return fn.apply(thisArg, args);
299
+ invoke(target, thisArg, args, additional) {
300
+ return this.invocationHook.invoke(target, thisArg, args, additional);
121
301
  }
122
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
123
- traceCallback(fn, _position, _message, thisArg, ...args) {
124
- return fn.apply(thisArg, args);
302
+ traceInvocation(operator, target, thisArg, args, additional, callbackIndex = -1) {
303
+ return traceInvocation(
304
+ this,
305
+ operator,
306
+ target,
307
+ thisArg,
308
+ args,
309
+ additional,
310
+ callbackIndex
311
+ );
125
312
  }
126
- };
127
- var iso = {
128
- buildType: "unknown",
129
- // Will be set by configureBrowser() or configureNode()
130
- getRepoInfo: async (_settings) => void 0,
131
- getPastNAncestors: async () => [],
132
- getEnv: (_name) => void 0,
133
- getBraintrustApiKey: async () => void 0,
134
- getCallerLocation: () => void 0,
135
- newAsyncLocalStorage: () => new DefaultAsyncLocalStorage(),
136
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
137
- newTracingChannel: (nameOrChannels) => new DefaultTracingChannel(nameOrChannels),
138
- processOn: (_0, _1) => {
139
- },
140
- basename: (filepath) => filepath.split(/[\\/]/).pop() || filepath,
141
- // eslint-disable-next-line no-restricted-properties -- preserving intentional console usage.
142
- writeln: (text) => console.log(text)
143
- };
144
- var isomorph_default = iso;
145
-
146
- // src/instrumentation/core/stream-patcher.ts
147
- function isAsyncIterable(value) {
148
- return value !== null && typeof value === "object" && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
149
- }
150
- function hasAsyncIteratorMethods(value) {
151
- return value !== null && typeof value === "object" && "next" in value && typeof value.next === "function";
152
- }
153
- function isSelfAsyncIterator(value) {
154
- try {
155
- return value[Symbol.asyncIterator]() === value;
156
- } catch {
157
- return false;
313
+ subscribe(handlers) {
314
+ for (const eventName of traceEvents) {
315
+ const handler = handlers[eventName];
316
+ if (handler) {
317
+ this[eventName].subscribe(handler);
318
+ }
319
+ }
158
320
  }
159
- }
160
- function patchStreamIfNeeded(stream, options) {
161
- if (!isAsyncIterable(stream)) {
162
- return stream;
321
+ unsubscribe(handlers) {
322
+ let done = true;
323
+ for (const eventName of traceEvents) {
324
+ const handler = handlers[eventName];
325
+ if (handler && !this[eventName].unsubscribe(handler)) {
326
+ done = false;
327
+ }
328
+ }
329
+ return done;
163
330
  }
164
- if (Object.isFrozen(stream) || Object.isSealed(stream)) {
165
- console.warn(
166
- "Cannot patch frozen/sealed stream. Stream output will not be collected."
167
- );
168
- return stream;
331
+ traceSync(fn, message = {}, thisArg, ...args) {
332
+ if (!this.hasSubscribers) {
333
+ return Reflect.apply(fn, thisArg, args);
334
+ }
335
+ const context = message;
336
+ return this.start.runStores(message, () => {
337
+ try {
338
+ const result = Reflect.apply(fn, thisArg, args);
339
+ setContextValue(context, "result", result);
340
+ return result;
341
+ } catch (error) {
342
+ setContextValue(context, "error", error);
343
+ this.error.publish(message);
344
+ throw error;
345
+ } finally {
346
+ this.end.publish(message);
347
+ }
348
+ });
169
349
  }
170
- if (hasAsyncIteratorMethods(stream) && isSelfAsyncIterator(stream)) {
171
- if ("__braintrust_patched_iterator_methods" in stream) {
172
- return stream;
350
+ tracePromise(fn, message = {}, thisArg, ...args) {
351
+ if (!this.hasSubscribers) {
352
+ return Reflect.apply(fn, thisArg, args);
173
353
  }
174
- try {
175
- const originalNext = stream.next.bind(stream);
176
- const originalReturn = typeof stream.return === "function" ? stream.return.bind(stream) : null;
177
- const originalThrow = typeof stream.throw === "function" ? stream.throw.bind(stream) : null;
178
- const chunks = [];
179
- let completed = false;
180
- stream.next = async (...args) => {
181
- try {
182
- const result = await runNextWithWrapper(
183
- options,
184
- () => originalNext(...args)
185
- );
186
- if (result.done) {
187
- if (!completed) {
188
- completed = true;
189
- try {
190
- await options.onComplete(chunks);
191
- } catch (error) {
192
- console.error("Error in stream onComplete handler:", error);
193
- }
194
- }
195
- } else {
196
- const chunk = result.value;
197
- const shouldCollect = options.shouldCollect ? options.shouldCollect(chunk) : true;
198
- if (shouldCollect) {
199
- chunks.push(chunk);
200
- if (options.onChunk) {
201
- try {
202
- await options.onChunk(chunk);
203
- } catch (error) {
204
- console.error("Error in stream onChunk handler:", error);
205
- }
206
- }
207
- }
208
- }
209
- return result;
210
- } catch (error) {
211
- if (!completed) {
212
- completed = true;
213
- if (options.onError) {
214
- try {
215
- await options.onError(
216
- error instanceof Error ? error : new Error(String(error)),
217
- chunks
218
- );
219
- } catch (handlerError) {
220
- console.error("Error in stream onError handler:", handlerError);
221
- }
222
- }
223
- }
224
- throw error;
354
+ const context = message;
355
+ return this.start.runStores(message, () => {
356
+ let result;
357
+ try {
358
+ result = Reflect.apply(fn, thisArg, args);
359
+ } catch (error) {
360
+ setContextValue(context, "error", error);
361
+ this.error.publish(message);
362
+ this.end.publish(message);
363
+ throw error;
364
+ }
365
+ this.end.publish(message);
366
+ if (!result || typeof result !== "object" && typeof result !== "function") {
367
+ setContextValue(context, "result", result);
368
+ this.asyncStart.publish(message);
369
+ this.asyncEnd.publish(message);
370
+ return result;
371
+ }
372
+ let terminalPublished = false;
373
+ const finishUnobservedResult = (error) => {
374
+ reportError(error);
375
+ if (!terminalPublished) {
376
+ terminalPublished = true;
377
+ setContextValue(context, "result", result);
378
+ this.asyncStart.publish(message);
379
+ this.asyncEnd.publish(message);
225
380
  }
381
+ return result;
226
382
  };
227
- if (originalReturn) {
228
- stream.return = async (...args) => {
229
- if (!completed) {
230
- completed = true;
383
+ let then;
384
+ try {
385
+ then = result.then;
386
+ } catch (error) {
387
+ return finishUnobservedResult(error);
388
+ }
389
+ if (typeof then !== "function") {
390
+ setContextValue(context, "result", result);
391
+ this.asyncStart.publish(message);
392
+ this.asyncEnd.publish(message);
393
+ return result;
394
+ }
395
+ const resolve = (resolved) => {
396
+ if (!terminalPublished) {
397
+ terminalPublished = true;
398
+ setContextValue(context, "result", resolved);
399
+ this.asyncStart.publish(message);
400
+ this.asyncEnd.publish(message);
401
+ }
402
+ return resolved;
403
+ };
404
+ let rejectionThrown = false;
405
+ let rejectionError;
406
+ const reject = (error) => {
407
+ if (!terminalPublished) {
408
+ terminalPublished = true;
409
+ setContextValue(context, "error", error);
410
+ this.error.publish(message);
411
+ this.asyncStart.publish(message);
412
+ this.asyncEnd.publish(message);
413
+ }
414
+ rejectionThrown = true;
415
+ rejectionError = error;
416
+ throw error;
417
+ };
418
+ let isPlainPromise;
419
+ try {
420
+ isPlainPromise = result instanceof Promise && result.constructor === Promise;
421
+ } catch (error) {
422
+ return finishUnobservedResult(error);
423
+ }
424
+ try {
425
+ if (isPlainPromise) {
426
+ return Reflect.apply(then, result, [resolve, reject]);
427
+ }
428
+ Reflect.apply(then, result, [
429
+ resolve,
430
+ (error) => {
231
431
  try {
232
- await options.onComplete(chunks);
233
- } catch (error) {
234
- console.error("Error in stream onComplete handler:", error);
432
+ reject(error);
433
+ } catch {
235
434
  }
236
435
  }
237
- return originalReturn(...args);
238
- };
436
+ ]);
437
+ } catch (error) {
438
+ if (rejectionThrown && error === rejectionError) {
439
+ return result;
440
+ }
441
+ return finishUnobservedResult(error);
239
442
  }
240
- if (originalThrow) {
241
- stream.throw = async (...args) => {
242
- if (!completed) {
243
- completed = true;
244
- const rawError = args[0];
245
- const error = rawError instanceof Error ? rawError : new Error(String(rawError));
246
- if (options.onError) {
247
- try {
248
- await options.onError(error, chunks);
249
- } catch (handlerError) {
250
- console.error("Error in stream onError handler:", handlerError);
251
- }
252
- }
253
- }
254
- return originalThrow(...args);
255
- };
443
+ return result;
444
+ });
445
+ }
446
+ traceCallback(fn, position = -1, message = {}, thisArg, ...args) {
447
+ if (!this.hasSubscribers) {
448
+ return Reflect.apply(fn, thisArg, args);
449
+ }
450
+ const context = message;
451
+ const callArgs = args.length > 0 ? args : context.arguments ?? args;
452
+ const callback = Array.prototype.at.call(callArgs, position);
453
+ if (typeof callback !== "function") {
454
+ return Reflect.apply(fn, thisArg, args);
455
+ }
456
+ const { asyncStart, asyncEnd, error: errorChannel } = this;
457
+ function wrappedCallback(error, result) {
458
+ if (error) {
459
+ setContextValue(context, "error", error);
460
+ errorChannel.publish(message);
461
+ } else {
462
+ setContextValue(context, "result", result);
256
463
  }
257
- Object.defineProperty(stream, "__braintrust_patched_iterator_methods", {
258
- value: true
464
+ return asyncStart.runStores(message, () => {
465
+ try {
466
+ return Reflect.apply(callback, this, arguments);
467
+ } finally {
468
+ asyncEnd.publish(message);
469
+ }
259
470
  });
260
- return stream;
261
- } catch (error) {
262
- console.warn("Failed to patch stream iterator methods:", error);
263
471
  }
472
+ Array.prototype.splice.call(callArgs, position, 1, wrappedCallback);
473
+ return this.start.runStores(message, () => {
474
+ try {
475
+ return Reflect.apply(fn, thisArg, args);
476
+ } catch (error) {
477
+ setContextValue(context, "error", error);
478
+ this.error.publish(message);
479
+ throw error;
480
+ } finally {
481
+ this.end.publish(message);
482
+ }
483
+ });
264
484
  }
265
- const originalIteratorFn = stream[Symbol.asyncIterator];
266
- if ("__braintrust_patched" in originalIteratorFn && originalIteratorFn["__braintrust_patched"]) {
267
- return stream;
485
+ };
486
+ var inertChannel = Object.freeze({
487
+ name: "braintrust:inert",
488
+ hasSubscribers: false,
489
+ subscribe() {
490
+ },
491
+ unsubscribe() {
492
+ return false;
493
+ },
494
+ bindStore() {
495
+ },
496
+ unbindStore() {
497
+ return false;
498
+ },
499
+ publish() {
500
+ },
501
+ runStores(_message, fn, thisArg, ...args) {
502
+ return Reflect.apply(fn, thisArg, args);
503
+ }
504
+ });
505
+ var inertTracingHook = new TracingHook({
506
+ start: inertChannel,
507
+ end: inertChannel,
508
+ asyncStart: inertChannel,
509
+ asyncEnd: inertChannel,
510
+ error: inertChannel
511
+ });
512
+ function isHookChannel(value) {
513
+ if (typeof value !== "object" && typeof value !== "function" || value === null) {
514
+ return false;
268
515
  }
269
516
  try {
270
- const patchedIteratorFn = function() {
271
- const iterator = originalIteratorFn.call(this);
272
- const originalNext = iterator.next.bind(iterator);
273
- const chunks = [];
274
- let completed = false;
275
- iterator.next = async function(...args) {
276
- try {
277
- const result = await runNextWithWrapper(
278
- options,
279
- () => originalNext(...args)
280
- );
281
- if (result.done) {
282
- if (!completed) {
283
- completed = true;
284
- try {
285
- await options.onComplete(chunks);
286
- } catch (error) {
287
- console.error("Error in stream onComplete handler:", error);
288
- }
289
- }
290
- } else {
291
- const chunk = result.value;
292
- const shouldCollect = options.shouldCollect ? options.shouldCollect(chunk) : true;
293
- if (shouldCollect) {
294
- chunks.push(chunk);
295
- if (options.onChunk) {
296
- try {
297
- await options.onChunk(chunk);
298
- } catch (error) {
299
- console.error("Error in stream onChunk handler:", error);
300
- }
301
- }
302
- }
303
- }
304
- return result;
305
- } catch (error) {
306
- if (!completed) {
307
- completed = true;
308
- if (options.onError) {
309
- try {
310
- await options.onError(
311
- error instanceof Error ? error : new Error(String(error)),
312
- chunks
313
- );
314
- } catch (handlerError) {
315
- console.error("Error in stream onError handler:", handlerError);
316
- }
317
- }
318
- }
319
- throw error;
517
+ const channel2 = value;
518
+ return typeof channel2.hasSubscribers === "boolean" && typeof channel2.subscribe === "function" && typeof channel2.unsubscribe === "function" && typeof channel2.bindStore === "function" && typeof channel2.unbindStore === "function" && typeof channel2.publish === "function" && typeof channel2.runStores === "function";
519
+ } catch {
520
+ return false;
521
+ }
522
+ }
523
+ function hasTracingHookShape(value) {
524
+ if (typeof value !== "object" && typeof value !== "function" || value === null) {
525
+ return false;
526
+ }
527
+ try {
528
+ const hook = value;
529
+ return typeof hook.hasSubscribers === "boolean" && typeof hook.subscribe === "function" && typeof hook.unsubscribe === "function" && typeof hook.traceSync === "function" && typeof hook.tracePromise === "function" && typeof hook.traceCallback === "function" && isHookChannel(hook.start) && isHookChannel(hook.end) && isHookChannel(hook.asyncStart) && isHookChannel(hook.asyncEnd) && isHookChannel(hook.error);
530
+ } catch {
531
+ return false;
532
+ }
533
+ }
534
+ function hasInvocationHookShape(value) {
535
+ if (typeof value !== "object" && typeof value !== "function" || value === null) {
536
+ return false;
537
+ }
538
+ try {
539
+ const hook = value;
540
+ return value[invocationHookBrand] === GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION && typeof hook.hasInterceptors === "boolean" && typeof hook.intercept === "function" && typeof hook.invoke === "function";
541
+ } catch {
542
+ return false;
543
+ }
544
+ }
545
+ function installInvocationHook(value) {
546
+ const hasInvocationHook = hasInvocationHookShape(value);
547
+ const invocationHook = new InvocationHook();
548
+ try {
549
+ if (!hasInvocationHook) {
550
+ Object.defineProperties(value, {
551
+ [invocationHookBrand]: {
552
+ configurable: false,
553
+ enumerable: false,
554
+ value: GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION,
555
+ writable: false
556
+ },
557
+ hasInterceptors: {
558
+ configurable: false,
559
+ enumerable: false,
560
+ get: () => invocationHook.hasInterceptors
561
+ },
562
+ intercept: {
563
+ configurable: false,
564
+ enumerable: false,
565
+ value: invocationHook.intercept.bind(invocationHook),
566
+ writable: false
567
+ },
568
+ invoke: {
569
+ configurable: false,
570
+ enumerable: false,
571
+ value: invocationHook.invoke.bind(invocationHook),
572
+ writable: false
320
573
  }
321
- };
322
- if (iterator.return) {
323
- const originalReturn = iterator.return.bind(iterator);
324
- iterator.return = async function(...args) {
325
- if (!completed) {
326
- completed = true;
327
- try {
328
- await options.onComplete(chunks);
329
- } catch (error) {
330
- console.error("Error in stream onComplete handler:", error);
331
- }
332
- }
333
- return originalReturn(...args);
334
- };
335
- }
336
- if (iterator.throw) {
337
- const originalThrow = iterator.throw.bind(iterator);
338
- iterator.throw = async function(...args) {
339
- if (!completed) {
340
- completed = true;
341
- const rawError = args[0];
342
- const error = rawError instanceof Error ? rawError : new Error(String(rawError));
343
- if (options.onError) {
344
- try {
345
- await options.onError(error, chunks);
346
- } catch (handlerError) {
347
- console.error("Error in stream onError handler:", handlerError);
348
- }
349
- }
350
- }
351
- return originalThrow(...args);
352
- };
574
+ });
575
+ }
576
+ if (typeof value.traceInvocation !== "function") {
577
+ Object.defineProperty(value, "traceInvocation", {
578
+ configurable: false,
579
+ enumerable: false,
580
+ value: traceInvocation.bind(void 0, value),
581
+ writable: false
582
+ });
583
+ }
584
+ } catch (error) {
585
+ reportError(error);
586
+ }
587
+ }
588
+ function isCompatibleTracingHook(value) {
589
+ try {
590
+ return value[hookBrand] === GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION && hasTracingHookShape(value);
591
+ } catch {
592
+ return false;
593
+ }
594
+ }
595
+ function isCompatibleHookRegistry(value) {
596
+ try {
597
+ return value instanceof Map && value[registryBrand] === GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION;
598
+ } catch {
599
+ return false;
600
+ }
601
+ }
602
+ function getHookRegistry() {
603
+ let descriptor;
604
+ try {
605
+ descriptor = Object.getOwnPropertyDescriptor(
606
+ globalThis,
607
+ GLOBAL_INSTRUMENTATION_HOOKS_KEY
608
+ );
609
+ } catch (error) {
610
+ reportError(error);
611
+ return void 0;
612
+ }
613
+ if (descriptor && "value" in descriptor && isCompatibleHookRegistry(descriptor.value) && (descriptor.configurable || descriptor.enumerable === false)) {
614
+ if (descriptor.configurable || descriptor.writable) {
615
+ try {
616
+ Object.defineProperty(globalThis, GLOBAL_INSTRUMENTATION_HOOKS_KEY, {
617
+ configurable: false,
618
+ enumerable: false,
619
+ value: descriptor.value,
620
+ writable: false
621
+ });
622
+ } catch (error) {
623
+ reportError(error);
624
+ return void 0;
353
625
  }
354
- return iterator;
355
- };
356
- Object.defineProperty(patchedIteratorFn, "__braintrust_patched", {
357
- value: true
626
+ }
627
+ return descriptor.value;
628
+ }
629
+ if (descriptor && !descriptor.configurable) {
630
+ reportError(new Error("Incompatible global instrumentation hook registry"));
631
+ return void 0;
632
+ }
633
+ const registry2 = /* @__PURE__ */ new Map();
634
+ try {
635
+ Object.defineProperty(registry2, registryBrand, {
636
+ configurable: false,
637
+ enumerable: false,
638
+ value: GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION,
639
+ writable: false
358
640
  });
359
- stream[Symbol.asyncIterator] = patchedIteratorFn;
360
- return stream;
361
641
  } catch (error) {
362
- console.warn("Failed to patch stream:", error);
363
- return stream;
642
+ reportError(error);
643
+ return void 0;
644
+ }
645
+ try {
646
+ Object.defineProperty(globalThis, GLOBAL_INSTRUMENTATION_HOOKS_KEY, {
647
+ configurable: false,
648
+ enumerable: false,
649
+ value: registry2,
650
+ writable: false
651
+ });
652
+ return registry2;
653
+ } catch (error) {
654
+ reportError(error);
655
+ return void 0;
364
656
  }
365
657
  }
366
- function runNextWithWrapper(options, callback) {
367
- return options.aroundNext ? options.aroundNext(callback) : callback();
658
+ function newGlobalTracingChannel(nameOrChannels) {
659
+ if (typeof nameOrChannels !== "string") {
660
+ return new TracingHook(nameOrChannels);
661
+ }
662
+ const registry2 = getHookRegistry();
663
+ if (!registry2) {
664
+ return inertTracingHook;
665
+ }
666
+ let existing;
667
+ try {
668
+ existing = Map.prototype.get.call(registry2, nameOrChannels);
669
+ } catch (error) {
670
+ reportError(error);
671
+ return inertTracingHook;
672
+ }
673
+ if (isCompatibleTracingHook(existing)) {
674
+ installInvocationHook(existing);
675
+ return existing;
676
+ }
677
+ if (existing !== void 0) {
678
+ reportError(
679
+ new Error(`Invalid global instrumentation hook: ${nameOrChannels}`)
680
+ );
681
+ try {
682
+ Map.prototype.delete.call(registry2, nameOrChannels);
683
+ } catch (error) {
684
+ reportError(error);
685
+ return inertTracingHook;
686
+ }
687
+ }
688
+ const hook = new TracingHook(nameOrChannels);
689
+ try {
690
+ Map.prototype.set.call(registry2, nameOrChannels, hook);
691
+ } catch (error) {
692
+ reportError(error);
693
+ return inertTracingHook;
694
+ }
695
+ return hook;
368
696
  }
369
697
 
370
- // src/logger.ts
371
- var import_uuid2 = require("uuid");
698
+ // src/isomorph.ts
699
+ var DefaultAsyncLocalStorage = class {
700
+ constructor() {
701
+ }
702
+ enterWith(_) {
703
+ }
704
+ run(_, callback) {
705
+ return callback();
706
+ }
707
+ getStore() {
708
+ return void 0;
709
+ }
710
+ };
711
+ var iso = {
712
+ buildType: "unknown",
713
+ // Will be set by configureBrowser() or configureNode()
714
+ getRepoInfo: async (_settings) => void 0,
715
+ getPastNAncestors: async () => [],
716
+ getEnv: (_name) => void 0,
717
+ getBraintrustApiKey: async () => void 0,
718
+ getCallerLocation: () => void 0,
719
+ newAsyncLocalStorage: () => new DefaultAsyncLocalStorage(),
720
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
721
+ newTracingChannel: (nameOrChannels) => newGlobalTracingChannel(nameOrChannels),
722
+ processOn: (_0, _1) => {
723
+ },
724
+ basename: (filepath) => filepath.split(/[\\/]/).pop() || filepath,
725
+ // eslint-disable-next-line no-restricted-properties -- preserving intentional console usage.
726
+ writeln: (text) => console.log(text)
727
+ };
728
+ var isomorph_default = iso;
372
729
 
373
730
  // src/debug-logger.ts
374
731
  var PREFIX = "[braintrust]";
@@ -474,6 +831,254 @@ var debugLogger = {
474
831
  return createDebugLogger(state);
475
832
  }
476
833
  };
834
+ setGlobalHookErrorReporter((error) => {
835
+ debugLogger.error("Global instrumentation hook error:", error);
836
+ });
837
+
838
+ // src/instrumentation/core/stream-patcher.ts
839
+ function isAsyncIterable(value) {
840
+ return value !== null && typeof value === "object" && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
841
+ }
842
+ function hasAsyncIteratorMethods(value) {
843
+ return value !== null && typeof value === "object" && "next" in value && typeof value.next === "function";
844
+ }
845
+ function isSelfAsyncIterator(value) {
846
+ try {
847
+ return value[Symbol.asyncIterator]() === value;
848
+ } catch {
849
+ return false;
850
+ }
851
+ }
852
+ function patchStreamIfNeeded(stream, options) {
853
+ if (!isAsyncIterable(stream)) {
854
+ return stream;
855
+ }
856
+ if (Object.isFrozen(stream) || Object.isSealed(stream)) {
857
+ console.warn(
858
+ "Cannot patch frozen/sealed stream. Stream output will not be collected."
859
+ );
860
+ return stream;
861
+ }
862
+ const chunks = [];
863
+ let completed = false;
864
+ const notifyCancellation = async () => {
865
+ try {
866
+ await (options.onCancel ?? options.onComplete)(chunks);
867
+ } catch (error) {
868
+ debugLogger.error("Error in stream cancellation handler:", error);
869
+ }
870
+ };
871
+ const patchAbortIfPresent = () => {
872
+ try {
873
+ if ("abort" in stream && typeof stream.abort === "function") {
874
+ const originalAbort = stream.abort.bind(stream);
875
+ stream.abort = (...args) => {
876
+ try {
877
+ return originalAbort(...args);
878
+ } finally {
879
+ if (!completed) {
880
+ completed = true;
881
+ void notifyCancellation();
882
+ }
883
+ }
884
+ };
885
+ }
886
+ } catch (error) {
887
+ debugLogger.warn("Failed to patch stream abort method:", error);
888
+ }
889
+ };
890
+ if (hasAsyncIteratorMethods(stream) && isSelfAsyncIterator(stream)) {
891
+ if ("__braintrust_patched_iterator_methods" in stream) {
892
+ return stream;
893
+ }
894
+ try {
895
+ const originalNext = stream.next.bind(stream);
896
+ const originalReturn = typeof stream.return === "function" ? stream.return.bind(stream) : null;
897
+ const originalThrow = typeof stream.throw === "function" ? stream.throw.bind(stream) : null;
898
+ stream.next = async (...args) => {
899
+ try {
900
+ const result = await runNextWithWrapper(
901
+ options,
902
+ () => originalNext(...args)
903
+ );
904
+ if (result.done) {
905
+ if (!completed) {
906
+ completed = true;
907
+ try {
908
+ await options.onComplete(chunks);
909
+ } catch (error) {
910
+ console.error("Error in stream onComplete handler:", error);
911
+ }
912
+ }
913
+ } else {
914
+ const chunk = result.value;
915
+ const shouldCollect = options.shouldCollect ? options.shouldCollect(chunk) : true;
916
+ if (shouldCollect) {
917
+ chunks.push(chunk);
918
+ if (options.onChunk) {
919
+ try {
920
+ await options.onChunk(chunk);
921
+ } catch (error) {
922
+ console.error("Error in stream onChunk handler:", error);
923
+ }
924
+ }
925
+ }
926
+ }
927
+ return result;
928
+ } catch (error) {
929
+ if (!completed) {
930
+ completed = true;
931
+ if (options.onError) {
932
+ try {
933
+ await options.onError(
934
+ error instanceof Error ? error : new Error(String(error)),
935
+ chunks
936
+ );
937
+ } catch (handlerError) {
938
+ console.error("Error in stream onError handler:", handlerError);
939
+ }
940
+ }
941
+ }
942
+ throw error;
943
+ }
944
+ };
945
+ if (originalReturn) {
946
+ stream.return = async (...args) => {
947
+ if (!completed) {
948
+ completed = true;
949
+ await notifyCancellation();
950
+ }
951
+ return originalReturn(...args);
952
+ };
953
+ }
954
+ if (originalThrow) {
955
+ stream.throw = async (...args) => {
956
+ if (!completed) {
957
+ completed = true;
958
+ const rawError = args[0];
959
+ const error = rawError instanceof Error ? rawError : new Error(String(rawError));
960
+ if (options.onError) {
961
+ try {
962
+ await options.onError(error, chunks);
963
+ } catch (handlerError) {
964
+ console.error("Error in stream onError handler:", handlerError);
965
+ }
966
+ }
967
+ }
968
+ return originalThrow(...args);
969
+ };
970
+ }
971
+ Object.defineProperty(stream, "__braintrust_patched_iterator_methods", {
972
+ value: true
973
+ });
974
+ patchAbortIfPresent();
975
+ return stream;
976
+ } catch (error) {
977
+ console.warn("Failed to patch stream iterator methods:", error);
978
+ }
979
+ }
980
+ const originalIteratorFn = stream[Symbol.asyncIterator];
981
+ if ("__braintrust_patched" in originalIteratorFn && originalIteratorFn["__braintrust_patched"]) {
982
+ return stream;
983
+ }
984
+ try {
985
+ const patchedIteratorFn = function() {
986
+ const iterator = originalIteratorFn.call(this);
987
+ const originalNext = iterator.next.bind(iterator);
988
+ iterator.next = async function(...args) {
989
+ try {
990
+ const result = await runNextWithWrapper(
991
+ options,
992
+ () => originalNext(...args)
993
+ );
994
+ if (result.done) {
995
+ if (!completed) {
996
+ completed = true;
997
+ try {
998
+ await options.onComplete(chunks);
999
+ } catch (error) {
1000
+ console.error("Error in stream onComplete handler:", error);
1001
+ }
1002
+ }
1003
+ } else {
1004
+ const chunk = result.value;
1005
+ const shouldCollect = options.shouldCollect ? options.shouldCollect(chunk) : true;
1006
+ if (shouldCollect) {
1007
+ chunks.push(chunk);
1008
+ if (options.onChunk) {
1009
+ try {
1010
+ await options.onChunk(chunk);
1011
+ } catch (error) {
1012
+ console.error("Error in stream onChunk handler:", error);
1013
+ }
1014
+ }
1015
+ }
1016
+ }
1017
+ return result;
1018
+ } catch (error) {
1019
+ if (!completed) {
1020
+ completed = true;
1021
+ if (options.onError) {
1022
+ try {
1023
+ await options.onError(
1024
+ error instanceof Error ? error : new Error(String(error)),
1025
+ chunks
1026
+ );
1027
+ } catch (handlerError) {
1028
+ console.error("Error in stream onError handler:", handlerError);
1029
+ }
1030
+ }
1031
+ }
1032
+ throw error;
1033
+ }
1034
+ };
1035
+ if (iterator.return) {
1036
+ const originalReturn = iterator.return.bind(iterator);
1037
+ iterator.return = async function(...args) {
1038
+ if (!completed) {
1039
+ completed = true;
1040
+ await notifyCancellation();
1041
+ }
1042
+ return originalReturn(...args);
1043
+ };
1044
+ }
1045
+ if (iterator.throw) {
1046
+ const originalThrow = iterator.throw.bind(iterator);
1047
+ iterator.throw = async function(...args) {
1048
+ if (!completed) {
1049
+ completed = true;
1050
+ const rawError = args[0];
1051
+ const error = rawError instanceof Error ? rawError : new Error(String(rawError));
1052
+ if (options.onError) {
1053
+ try {
1054
+ await options.onError(error, chunks);
1055
+ } catch (handlerError) {
1056
+ console.error("Error in stream onError handler:", handlerError);
1057
+ }
1058
+ }
1059
+ }
1060
+ return originalThrow(...args);
1061
+ };
1062
+ }
1063
+ return iterator;
1064
+ };
1065
+ Object.defineProperty(patchedIteratorFn, "__braintrust_patched", {
1066
+ value: true
1067
+ });
1068
+ stream[Symbol.asyncIterator] = patchedIteratorFn;
1069
+ patchAbortIfPresent();
1070
+ return stream;
1071
+ } catch (error) {
1072
+ console.warn("Failed to patch stream:", error);
1073
+ return stream;
1074
+ }
1075
+ }
1076
+ function runNextWithWrapper(options, callback) {
1077
+ return options.aroundNext ? options.aroundNext(callback) : callback();
1078
+ }
1079
+
1080
+ // src/logger.ts
1081
+ var import_uuid2 = require("uuid");
477
1082
 
478
1083
  // src/queue.ts
479
1084
  var DEFAULT_QUEUE_SIZE = 15e3;
@@ -2125,7 +2730,8 @@ var ApiKey = import_v36.z.object({
2125
2730
  user_email: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2126
2731
  user_given_name: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2127
2732
  user_family_name: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2128
- org_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional()
2733
+ org_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2734
+ expires_at: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional()
2129
2735
  });
2130
2736
  var TriggeredFunctionState = import_v36.z.object({
2131
2737
  triggered_xact_id: import_v36.z.string(),
@@ -2245,6 +2851,7 @@ var TopicMapData = import_v36.z.object({
2245
2851
  topic_names: import_v36.z.record(import_v36.z.string()).optional(),
2246
2852
  generation_settings: TopicMapGenerationSettings.optional(),
2247
2853
  disable_reconciliation: import_v36.z.boolean().optional(),
2854
+ reconcile_mode: import_v36.z.enum(["evolve", "names_only"]).optional(),
2248
2855
  distance_threshold: import_v36.z.number().optional(),
2249
2856
  btql_filter: import_v36.z.string().optional(),
2250
2857
  automation_btql_filter: import_v36.z.string().optional()
@@ -2825,7 +3432,12 @@ var ModelParams = import_v36.z.union([
2825
3432
  }).partial().passthrough()
2826
3433
  ]);
2827
3434
  var PromptOptionsNullish = import_v36.z.union([
2828
- import_v36.z.object({ model: import_v36.z.string(), params: ModelParams, position: import_v36.z.string() }).partial(),
3435
+ import_v36.z.object({
3436
+ model: import_v36.z.string(),
3437
+ params: ModelParams,
3438
+ position: import_v36.z.string(),
3439
+ endpoint_name: import_v36.z.union([import_v36.z.string(), import_v36.z.null()])
3440
+ }).partial(),
2829
3441
  import_v36.z.null()
2830
3442
  ]);
2831
3443
  var PromptParserNullish = import_v36.z.union([
@@ -2839,11 +3451,25 @@ var PromptParserNullish = import_v36.z.union([
2839
3451
  }),
2840
3452
  import_v36.z.null()
2841
3453
  ]);
3454
+ var PreprocessorSavedFunctionId = import_v36.z.union([
3455
+ import_v36.z.object({
3456
+ type: import_v36.z.literal("function"),
3457
+ id: import_v36.z.string(),
3458
+ version: import_v36.z.string().optional()
3459
+ }),
3460
+ import_v36.z.object({
3461
+ type: import_v36.z.literal("global"),
3462
+ name: import_v36.z.string(),
3463
+ function_type: import_v36.z.literal("preprocessor").optional().default("preprocessor")
3464
+ }),
3465
+ import_v36.z.null()
3466
+ ]);
2842
3467
  var PromptDataNullish = import_v36.z.union([
2843
3468
  import_v36.z.object({
2844
3469
  prompt: PromptBlockDataNullish,
2845
3470
  options: PromptOptionsNullish,
2846
3471
  parser: PromptParserNullish,
3472
+ preprocessor: PreprocessorSavedFunctionId,
2847
3473
  tool_functions: import_v36.z.union([import_v36.z.array(SavedFunctionId), import_v36.z.null()]),
2848
3474
  template_format: import_v36.z.union([
2849
3475
  import_v36.z.enum(["mustache", "nunjucks", "none"]),
@@ -3045,6 +3671,7 @@ var PromptData = import_v36.z.object({
3045
3671
  prompt: PromptBlockDataNullish,
3046
3672
  options: PromptOptionsNullish,
3047
3673
  parser: PromptParserNullish,
3674
+ preprocessor: PreprocessorSavedFunctionId,
3048
3675
  tool_functions: import_v36.z.union([import_v36.z.array(SavedFunctionId), import_v36.z.null()]),
3049
3676
  template_format: import_v36.z.union([
3050
3677
  import_v36.z.enum(["mustache", "nunjucks", "none"]),
@@ -3207,7 +3834,8 @@ var InvokeFunction = FunctionId.and(
3207
3834
  mode: StreamingMode,
3208
3835
  strict: import_v36.z.union([import_v36.z.boolean(), import_v36.z.null()]),
3209
3836
  mcp_auth: import_v36.z.record(import_v36.z.object({ oauth_token: import_v36.z.string() }).partial()),
3210
- overrides: import_v36.z.union([import_v36.z.object({}).partial().passthrough(), import_v36.z.null()])
3837
+ overrides: import_v36.z.union([import_v36.z.object({}).partial().passthrough(), import_v36.z.null()]),
3838
+ endpoint_name: import_v36.z.union([import_v36.z.string(), import_v36.z.null()])
3211
3839
  }).partial()
3212
3840
  );
3213
3841
  var MCPServer = import_v36.z.object({
@@ -3271,6 +3899,24 @@ var Organization = import_v36.z.object({
3271
3899
  created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3272
3900
  image_rendering_mode: ImageRenderingMode.optional()
3273
3901
  });
3902
+ var RetentionObjectType = import_v36.z.enum([
3903
+ "project_logs",
3904
+ "experiment",
3905
+ "dataset"
3906
+ ]);
3907
+ var OrgAutomation = import_v36.z.object({
3908
+ id: import_v36.z.string().uuid(),
3909
+ org_id: import_v36.z.string().uuid(),
3910
+ user_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3911
+ created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3912
+ name: import_v36.z.string(),
3913
+ description: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3914
+ config: import_v36.z.object({
3915
+ event_type: import_v36.z.literal("retention"),
3916
+ object_type: RetentionObjectType,
3917
+ retention_days: import_v36.z.number().int().gte(0)
3918
+ })
3919
+ });
3274
3920
  var ProjectSettings = import_v36.z.union([
3275
3921
  import_v36.z.object({
3276
3922
  comparison_key: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
@@ -3297,6 +3943,7 @@ var ProjectSettings = import_v36.z.union([
3297
3943
  import_v36.z.null()
3298
3944
  ]),
3299
3945
  disable_realtime_queries: import_v36.z.union([import_v36.z.boolean(), import_v36.z.null()]),
3946
+ monitor_charts_use_metrics_start: import_v36.z.union([import_v36.z.boolean(), import_v36.z.null()]),
3300
3947
  default_preprocessor: NullableSavedFunctionId
3301
3948
  }).partial(),
3302
3949
  import_v36.z.null()
@@ -3311,11 +3958,6 @@ var Project = import_v36.z.object({
3311
3958
  user_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3312
3959
  settings: ProjectSettings.optional()
3313
3960
  });
3314
- var RetentionObjectType = import_v36.z.enum([
3315
- "project_logs",
3316
- "experiment",
3317
- "dataset"
3318
- ]);
3319
3961
  var TopicAutomationFacetModel = import_v36.z.union([
3320
3962
  import_v36.z.enum(["brain-facet-latest", "brain-facet-1", "brain-facet-2"]),
3321
3963
  import_v36.z.null()
@@ -3426,7 +4068,7 @@ var ProjectAutomation = import_v36.z.object({
3426
4068
  import_v36.z.object({
3427
4069
  event_type: import_v36.z.literal("retention"),
3428
4070
  object_type: RetentionObjectType,
3429
- retention_days: import_v36.z.number().gte(0)
4071
+ retention_days: import_v36.z.number().int().gte(0)
3430
4072
  }),
3431
4073
  import_v36.z.object({
3432
4074
  event_type: import_v36.z.literal("environment_update"),
@@ -3598,7 +4240,12 @@ var Prompt = import_v36.z.object({
3598
4240
  metadata: import_v36.z.union([import_v36.z.object({}).partial().passthrough(), import_v36.z.null()]).optional(),
3599
4241
  function_type: FunctionTypeEnumNullish.optional()
3600
4242
  });
3601
- var PromptOptions = import_v36.z.object({ model: import_v36.z.string(), params: ModelParams, position: import_v36.z.string() }).partial();
4243
+ var PromptOptions = import_v36.z.object({
4244
+ model: import_v36.z.string(),
4245
+ params: ModelParams,
4246
+ position: import_v36.z.string(),
4247
+ endpoint_name: import_v36.z.union([import_v36.z.string(), import_v36.z.null()])
4248
+ }).partial();
3602
4249
  var PromptSessionEvent = import_v36.z.object({
3603
4250
  id: import_v36.z.string(),
3604
4251
  _xact_id: import_v36.z.string(),
@@ -3681,7 +4328,8 @@ var RunEval = import_v36.z.object({
3681
4328
  stop_token: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3682
4329
  extra_messages: import_v36.z.string().optional(),
3683
4330
  tags: import_v36.z.array(import_v36.z.string()).optional(),
3684
- mcp_auth: import_v36.z.record(import_v36.z.object({ oauth_token: import_v36.z.string() }).partial()).optional()
4331
+ mcp_auth: import_v36.z.record(import_v36.z.object({ oauth_token: import_v36.z.string() }).partial()).optional(),
4332
+ endpoint_name: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional()
3685
4333
  });
3686
4334
  var ServiceToken = import_v36.z.object({
3687
4335
  id: import_v36.z.string().uuid(),
@@ -3691,7 +4339,8 @@ var ServiceToken = import_v36.z.object({
3691
4339
  service_account_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3692
4340
  service_account_email: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3693
4341
  service_account_name: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3694
- org_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional()
4342
+ org_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
4343
+ expires_at: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional()
3695
4344
  });
3696
4345
  var SpanIFrame = import_v36.z.object({
3697
4346
  id: import_v36.z.string().uuid(),
@@ -3813,6 +4462,13 @@ var ViewOptions = import_v36.z.union([
3813
4462
  }),
3814
4463
  import_v36.z.null()
3815
4464
  ]),
4465
+ pointSizeMetric: import_v36.z.union([
4466
+ import_v36.z.object({
4467
+ type: import_v36.z.enum(["none", "score", "metric", "metadata"]),
4468
+ value: import_v36.z.string()
4469
+ }),
4470
+ import_v36.z.null()
4471
+ ]),
3816
4472
  xAxisAggregation: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
3817
4473
  chartAnnotations: import_v36.z.union([
3818
4474
  import_v36.z.array(import_v36.z.object({ id: import_v36.z.string(), text: import_v36.z.string() })),
@@ -4926,6 +5582,9 @@ var INSTRUMENTATION_NAMES = {
4926
5582
  BEDROCK_RUNTIME: "bedrock-runtime",
4927
5583
  BRAINTRUST_JS_LOGGER: "braintrust-js-logger",
4928
5584
  CLAUDE_AGENT_SDK: "claude-agent-sdk",
5585
+ CLOUDFLARE_AI_CHAT: "cloudflare-ai-chat",
5586
+ CLOUDFLARE_AGENTS: "cloudflare-agents",
5587
+ CLOUDFLARE_THINK: "cloudflare-think",
4929
5588
  COHERE: "cohere",
4930
5589
  CURSOR_SDK: "cursor-sdk",
4931
5590
  EVE: "eve",
@@ -4940,6 +5599,7 @@ var INSTRUMENTATION_NAMES = {
4940
5599
  LANGSMITH: "langsmith",
4941
5600
  MASTRA: "mastra",
4942
5601
  MISTRAL: "mistral",
5602
+ OLLAMA: "ollama",
4943
5603
  OPENAI: "openai",
4944
5604
  OPENAI_AGENTS: "openai-agents",
4945
5605
  OPENAI_CODEX: "openai-codex",
@@ -4951,7 +5611,7 @@ var INSTRUMENTATION_NAMES = {
4951
5611
  var INTERNAL_SPAN_INSTRUMENTATION_NAME = /* @__PURE__ */ Symbol.for(
4952
5612
  "braintrust.spanInstrumentationName"
4953
5613
  );
4954
- var SDK_VERSION = true ? "3.25.0" : "0.0.0";
5614
+ var SDK_VERSION = true ? "3.27.0" : "0.0.0";
4955
5615
  function withSpanInstrumentationName(args, instrumentationName) {
4956
5616
  return {
4957
5617
  ...args,
@@ -5146,12 +5806,13 @@ function applyMaskingToField(maskingFunction, data, fieldName) {
5146
5806
  var INITIAL_SPAN_WRITE_AS_MERGE = /* @__PURE__ */ Symbol(
5147
5807
  "braintrust.initial-span-write-as-merge"
5148
5808
  );
5809
+ var INTERNAL_SPAN_CONTEXT = /* @__PURE__ */ Symbol("braintrust.internal-span-context");
5149
5810
  var BRAINTRUST_CURRENT_SPAN_STORE = /* @__PURE__ */ Symbol.for(
5150
5811
  "braintrust.currentSpanStore"
5151
5812
  );
5152
5813
  var ContextManager = class {
5153
5814
  /**
5154
- * Returns the value to store in the ALS bound to a TracingChannel's start event.
5815
+ * Returns the value to store in the ALS bound to a global hook's start event.
5155
5816
  * In default mode this is the Span itself; in OTEL mode it is the OTEL Context
5156
5817
  * containing the span so that OTEL's own ALS stores a proper Context object.
5157
5818
  */
@@ -7695,6 +8356,12 @@ function _internalStartSpanWithInitialMerge(args) {
7695
8356
  [INITIAL_SPAN_WRITE_AS_MERGE]: true
7696
8357
  }).span;
7697
8358
  }
8359
+ function _internalStartSpanWithContext(args, context) {
8360
+ return startSpanAndIsLogger({
8361
+ ...args,
8362
+ [INTERNAL_SPAN_CONTEXT]: context
8363
+ }).span;
8364
+ }
7698
8365
  async function flush(options) {
7699
8366
  const state = options?.state ?? _globalState;
7700
8367
  return await state.bgLogger().flush();
@@ -8488,7 +9155,7 @@ var SpanImpl = class _SpanImpl {
8488
9155
  start: args.startTime ?? getCurrentUnixTimestamp()
8489
9156
  },
8490
9157
  context: mergeSpanOriginContext(
8491
- { ...callerLocation },
9158
+ { ...callerLocation, ...args[INTERNAL_SPAN_CONTEXT] },
8492
9159
  instrumentationName,
8493
9160
  this._state.spanOriginEnvironment
8494
9161
  ),
@@ -9965,6 +10632,33 @@ function traceStreamingChannel(channel2, config) {
9965
10632
  const { span, startTime } = spanData;
9966
10633
  if (isAsyncIterable(asyncEndEvent.result)) {
9967
10634
  let firstChunkTime;
10635
+ const handleStreamError = (error) => {
10636
+ try {
10637
+ span.log({ error });
10638
+ } catch (loggingError) {
10639
+ debugLogger.error(
10640
+ `Error logging failure for ${channelName}:`,
10641
+ loggingError
10642
+ );
10643
+ }
10644
+ try {
10645
+ span.end();
10646
+ } catch (endingError) {
10647
+ debugLogger.error(
10648
+ `Error ending span for ${channelName}:`,
10649
+ endingError
10650
+ );
10651
+ }
10652
+ states.delete(event);
10653
+ runStreamingErrorHook({
10654
+ channelName,
10655
+ config,
10656
+ error,
10657
+ event: asyncEndEvent,
10658
+ span,
10659
+ startTime
10660
+ });
10661
+ };
9968
10662
  patchStreamIfNeeded(asyncEndEvent.result, {
9969
10663
  onChunk: () => {
9970
10664
  if (firstChunkTime === void 0) {
@@ -10044,33 +10738,12 @@ function traceStreamingChannel(channel2, config) {
10044
10738
  });
10045
10739
  }
10046
10740
  },
10047
- onError: (error) => {
10048
- try {
10049
- span.log({ error });
10050
- } catch (loggingError) {
10051
- debugLogger.error(
10052
- `Error logging failure for ${channelName}:`,
10053
- loggingError
10054
- );
10055
- }
10056
- try {
10057
- span.end();
10058
- } catch (endingError) {
10059
- debugLogger.error(
10060
- `Error ending span for ${channelName}:`,
10061
- endingError
10062
- );
10063
- }
10064
- states.delete(event);
10065
- runStreamingErrorHook({
10066
- channelName,
10067
- config,
10068
- error,
10069
- event: asyncEndEvent,
10070
- span,
10071
- startTime
10072
- });
10073
- }
10741
+ onCancel: () => {
10742
+ const error = new Error("Stream cancelled before completion");
10743
+ error.name = "AbortError";
10744
+ handleStreamError(error);
10745
+ },
10746
+ onError: handleStreamError
10074
10747
  });
10075
10748
  return;
10076
10749
  }
@@ -10458,11 +11131,21 @@ function defineChannels(pkg, channels, options) {
10458
11131
  const tracingChannel2 = () => isomorph_default.newTracingChannel(
10459
11132
  fullChannelName
10460
11133
  );
11134
+ const intercept2 = (interceptor) => {
11135
+ const hook = tracingChannel2();
11136
+ return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
11137
+ };
11138
+ };
10461
11139
  return [
10462
11140
  key,
10463
11141
  {
10464
11142
  ...asyncSpec,
10465
11143
  instrumentationName,
11144
+ intercept: intercept2,
11145
+ invoke: (target, thisArg, args, additional) => {
11146
+ const hook = tracingChannel2();
11147
+ return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
11148
+ },
10466
11149
  tracingChannel: tracingChannel2,
10467
11150
  tracePromise: (fn, context) => tracingChannel2().tracePromise(
10468
11151
  fn,
@@ -10476,11 +11159,21 @@ function defineChannels(pkg, channels, options) {
10476
11159
  const tracingChannel = () => isomorph_default.newTracingChannel(
10477
11160
  fullChannelName
10478
11161
  );
11162
+ const intercept = (interceptor) => {
11163
+ const hook = tracingChannel();
11164
+ return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
11165
+ };
11166
+ };
10479
11167
  return [
10480
11168
  key,
10481
11169
  {
10482
11170
  ...syncSpec,
10483
11171
  instrumentationName,
11172
+ intercept,
11173
+ invoke: (target, thisArg, args, additional) => {
11174
+ const hook = tracingChannel();
11175
+ return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
11176
+ },
10484
11177
  tracingChannel,
10485
11178
  traceSync: (fn, context) => tracingChannel().traceSync(
10486
11179
  fn,
@@ -11731,6 +12424,12 @@ function extractAnthropicCacheTokens(cacheReadTokens = 0, cacheCreationTokens =
11731
12424
  return cacheTokens;
11732
12425
  }
11733
12426
 
12427
+ // src/wrappers/anthropic-session-collector.ts
12428
+ var sessionStreamCollectors = /* @__PURE__ */ new WeakMap();
12429
+ function registerAnthropicSessionStreamCollector(stream, collector) {
12430
+ sessionStreamCollectors.set(stream, collector);
12431
+ }
12432
+
11734
12433
  // src/instrumentation/plugins/anthropic-channels.ts
11735
12434
  var anthropicChannels = defineChannels(
11736
12435
  "@anthropic-ai/sdk",
@@ -11746,6 +12445,14 @@ var anthropicChannels = defineChannels(
11746
12445
  betaMessagesToolRunner: channel({
11747
12446
  channelName: "beta.messages.toolRunner",
11748
12447
  kind: "sync-stream"
12448
+ }),
12449
+ betaSessionsEventsStream: channel({
12450
+ channelName: "beta.sessions.events.stream",
12451
+ kind: "async"
12452
+ }),
12453
+ betaSessionsThreadsEventsStream: channel({
12454
+ channelName: "beta.sessions.threads.events.stream",
12455
+ kind: "async"
11749
12456
  })
11750
12457
  },
11751
12458
  { instrumentationName: INSTRUMENTATION_NAMES.ANTHROPIC }
@@ -11759,6 +12466,7 @@ var AnthropicPlugin = class extends BasePlugin {
11759
12466
  onEnable() {
11760
12467
  this.subscribeToAnthropicChannels();
11761
12468
  this.subscribeToAnthropicToolRunner();
12469
+ this.subscribeToAnthropicSessionStreams();
11762
12470
  }
11763
12471
  onDisable() {
11764
12472
  this.unsubscribers = unsubscribeAll(this.unsubscribers);
@@ -11876,7 +12584,411 @@ var AnthropicPlugin = class extends BasePlugin {
11876
12584
  tracingChannel.unsubscribe(handlers);
11877
12585
  });
11878
12586
  }
12587
+ subscribeToAnthropicSessionStreams() {
12588
+ this.subscribeToAnthropicSessionStream(
12589
+ anthropicChannels.betaSessionsEventsStream,
12590
+ false
12591
+ );
12592
+ this.subscribeToAnthropicSessionStream(
12593
+ anthropicChannels.betaSessionsThreadsEventsStream,
12594
+ true
12595
+ );
12596
+ }
12597
+ subscribeToAnthropicSessionStream(channel2, isThread) {
12598
+ const tracingChannel = channel2.tracingChannel();
12599
+ const pending = /* @__PURE__ */ new WeakSet();
12600
+ const handlers = {
12601
+ start: (event) => {
12602
+ if (isAutoInstrumentationSuppressed()) {
12603
+ return;
12604
+ }
12605
+ pending.add(event);
12606
+ },
12607
+ asyncEnd: (event) => {
12608
+ if (!pending.delete(event)) {
12609
+ return;
12610
+ }
12611
+ const stream = event.result;
12612
+ if (!isAsyncIterable(stream)) {
12613
+ return;
12614
+ }
12615
+ registerAnthropicSessionStreamCollector(stream, () => {
12616
+ wrapAnthropicSessionEventStream(stream, isThread);
12617
+ });
12618
+ },
12619
+ error: (event) => {
12620
+ pending.delete(event);
12621
+ }
12622
+ };
12623
+ tracingChannel.subscribe(handlers);
12624
+ this.unsubscribers.push(() => tracingChannel.unsubscribe(handlers));
12625
+ }
11879
12626
  };
12627
+ function wrapAnthropicSessionEventStream(stream, isThread) {
12628
+ const state = {
12629
+ history: [],
12630
+ isThread,
12631
+ pendingInput: [],
12632
+ seenEventIds: /* @__PURE__ */ new Set()
12633
+ };
12634
+ patchStreamIfNeeded(stream, {
12635
+ onChunk: (event) => handleAnthropicSessionEvent(state, event),
12636
+ onComplete: () => finalizeAnthropicSessionTurn(state),
12637
+ onError: (error) => finalizeAnthropicSessionTurn(state, error)
12638
+ });
12639
+ return stream;
12640
+ }
12641
+ function handleAnthropicSessionEvent(state, event) {
12642
+ try {
12643
+ if (typeof event.id === "string" && event.type !== "event_delta" && state.seenEventIds.has(event.id)) {
12644
+ return;
12645
+ }
12646
+ if (typeof event.id === "string" && event.type !== "event_delta") {
12647
+ state.seenEventIds.add(event.id);
12648
+ }
12649
+ switch (event.type) {
12650
+ case "user.message":
12651
+ case "system.message":
12652
+ recordAnthropicSessionInput(
12653
+ state,
12654
+ event
12655
+ );
12656
+ break;
12657
+ case "session.status_running":
12658
+ if (!state.isThread) {
12659
+ ensureAnthropicSessionTurn(state);
12660
+ }
12661
+ break;
12662
+ case "session.thread_status_running":
12663
+ if (state.isThread) {
12664
+ ensureAnthropicSessionTurn(state);
12665
+ }
12666
+ break;
12667
+ case "span.model_request_start":
12668
+ if (typeof event.id === "string") {
12669
+ startAnthropicSessionModel(state, event.id);
12670
+ }
12671
+ break;
12672
+ case "event_delta":
12673
+ recordAnthropicSessionFirstToken(state, event);
12674
+ break;
12675
+ case "agent.message":
12676
+ recordAnthropicSessionMessage(
12677
+ state,
12678
+ event
12679
+ );
12680
+ break;
12681
+ case "agent.custom_tool_use":
12682
+ case "agent.mcp_tool_use":
12683
+ case "agent.tool_use":
12684
+ startAnthropicSessionTool(state, event);
12685
+ break;
12686
+ case "user.tool_confirmation":
12687
+ recordAnthropicSessionToolConfirmation(state, event);
12688
+ break;
12689
+ case "agent.mcp_tool_result":
12690
+ case "agent.tool_result":
12691
+ case "user.custom_tool_result":
12692
+ case "user.tool_result":
12693
+ finalizeAnthropicSessionTool(
12694
+ state,
12695
+ event
12696
+ );
12697
+ break;
12698
+ case "span.model_request_end":
12699
+ finalizeAnthropicSessionModel(
12700
+ state,
12701
+ event
12702
+ );
12703
+ break;
12704
+ case "session.status_idle":
12705
+ case "session.thread_status_idle": {
12706
+ if (event.type === "session.status_idle" && state.isThread || event.type === "session.thread_status_idle" && !state.isThread) {
12707
+ break;
12708
+ }
12709
+ const stopReason = isObject(event.stop_reason) ? event.stop_reason.type : void 0;
12710
+ if (stopReason === "end_turn") {
12711
+ finalizeAnthropicSessionTurn(state);
12712
+ } else if (stopReason === "retries_exhausted") {
12713
+ finalizeAnthropicSessionTurn(
12714
+ state,
12715
+ "Anthropic session retries exhausted"
12716
+ );
12717
+ }
12718
+ break;
12719
+ }
12720
+ case "session.error":
12721
+ finalizeAnthropicSessionTurn(state, event.error);
12722
+ break;
12723
+ case "session.deleted":
12724
+ case "session.status_terminated":
12725
+ case "session.thread_status_terminated":
12726
+ if (event.type === "session.deleted" || event.type === "session.status_terminated" && !state.isThread || event.type === "session.thread_status_terminated" && state.isThread) {
12727
+ finalizeAnthropicSessionTurn(state);
12728
+ }
12729
+ break;
12730
+ default:
12731
+ break;
12732
+ }
12733
+ } catch (error) {
12734
+ debugLogger.debug("Error processing Anthropic Sessions event:", error);
12735
+ }
12736
+ }
12737
+ function ensureAnthropicSessionTurn(state) {
12738
+ if (state.activeTurn) {
12739
+ return state.activeTurn;
12740
+ }
12741
+ const input = state.pendingInput;
12742
+ state.pendingInput = [];
12743
+ const span = startSpan(
12744
+ withSpanInstrumentationName(
12745
+ {
12746
+ event: {
12747
+ ...input.length > 0 ? { input } : {},
12748
+ metadata: { provider: "anthropic" }
12749
+ },
12750
+ name: state.isThread ? "anthropic.beta.sessions.thread.turn" : "anthropic.beta.sessions.turn",
12751
+ spanAttributes: { type: "task" /* TASK */ }
12752
+ },
12753
+ INSTRUMENTATION_NAMES.ANTHROPIC
12754
+ )
12755
+ );
12756
+ state.activeTurn = {
12757
+ activeTools: /* @__PURE__ */ new Map(),
12758
+ input: input.slice(),
12759
+ metrics: {},
12760
+ span
12761
+ };
12762
+ return state.activeTurn;
12763
+ }
12764
+ function recordAnthropicSessionInput(state, event) {
12765
+ const content = processAttachmentsInInput(event.content);
12766
+ const message = {
12767
+ role: event.type === "system.message" ? "system" : "user",
12768
+ content
12769
+ };
12770
+ state.history.push(message);
12771
+ if (state.activeTurn) {
12772
+ state.activeTurn.input.push(message);
12773
+ } else {
12774
+ state.pendingInput.push(message);
12775
+ }
12776
+ }
12777
+ function startAnthropicSessionModel(state, startEventId) {
12778
+ const turn = ensureAnthropicSessionTurn(state);
12779
+ if (turn.activeModel) {
12780
+ finalizeAnthropicSessionModelState(state, turn);
12781
+ }
12782
+ const span = withCurrent(
12783
+ turn.span,
12784
+ () => startSpan(
12785
+ withSpanInstrumentationName(
12786
+ {
12787
+ event: {
12788
+ ...state.history.length > 0 ? { input: state.history.slice() } : {},
12789
+ metadata: { provider: "anthropic" }
12790
+ },
12791
+ name: "anthropic.messages.create",
12792
+ spanAttributes: { type: "llm" /* LLM */ }
12793
+ },
12794
+ INSTRUMENTATION_NAMES.ANTHROPIC
12795
+ )
12796
+ )
12797
+ );
12798
+ turn.activeModel = {
12799
+ output: [],
12800
+ span,
12801
+ startEventId,
12802
+ startTime: getCurrentUnixTimestamp()
12803
+ };
12804
+ }
12805
+ function recordAnthropicSessionFirstToken(state, event) {
12806
+ const model = state.activeTurn?.activeModel;
12807
+ if (!model || model.firstTokenTime !== void 0 || !isObject(event.delta) || !isObject(event.delta.content) || typeof event.delta.content.text !== "string") {
12808
+ return;
12809
+ }
12810
+ model.firstTokenTime = getCurrentUnixTimestamp();
12811
+ }
12812
+ function recordAnthropicSessionMessage(state, event) {
12813
+ const turn = ensureAnthropicSessionTurn(state);
12814
+ const content = processAttachmentsInInput(
12815
+ event.content
12816
+ );
12817
+ if (turn.activeModel) {
12818
+ turn.activeModel.output.push(...content);
12819
+ } else {
12820
+ const output = { role: "assistant", content };
12821
+ turn.lastOutput = output;
12822
+ state.history.push(output);
12823
+ }
12824
+ }
12825
+ function startAnthropicSessionTool(state, event) {
12826
+ const turn = ensureAnthropicSessionTurn(state);
12827
+ if (turn.activeModel) {
12828
+ turn.activeModel.output.push({
12829
+ type: "tool_use",
12830
+ id: event.id,
12831
+ name: event.name,
12832
+ input: event.input
12833
+ });
12834
+ }
12835
+ const existing = turn.activeTools.get(event.id);
12836
+ if (existing) {
12837
+ existing.span.end();
12838
+ turn.activeTools.delete(event.id);
12839
+ }
12840
+ const span = withCurrent(
12841
+ turn.span,
12842
+ () => startSpan(
12843
+ withSpanInstrumentationName(
12844
+ {
12845
+ event: { input: event.input },
12846
+ name: event.name,
12847
+ spanAttributes: { type: "tool" /* TOOL */ }
12848
+ },
12849
+ INSTRUMENTATION_NAMES.ANTHROPIC
12850
+ )
12851
+ )
12852
+ );
12853
+ const toolState = {
12854
+ approval: event.evaluated_permission === "allow" ? "approved" : event.evaluated_permission === "deny" ? "denied" : void 0,
12855
+ span
12856
+ };
12857
+ turn.activeTools.set(event.id, toolState);
12858
+ if (toolState.approval === "denied") {
12859
+ finalizeAnthropicSessionToolState(toolState);
12860
+ turn.activeTools.delete(event.id);
12861
+ }
12862
+ }
12863
+ function recordAnthropicSessionToolConfirmation(state, event) {
12864
+ if (typeof event.tool_use_id !== "string" || event.result !== "allow" && event.result !== "deny") {
12865
+ return;
12866
+ }
12867
+ const turn = state.activeTurn;
12868
+ const tool = turn?.activeTools.get(event.tool_use_id);
12869
+ if (!turn || !tool) {
12870
+ return;
12871
+ }
12872
+ tool.approval = event.result === "allow" ? "approved" : "denied";
12873
+ if (tool.approval === "denied") {
12874
+ finalizeAnthropicSessionToolState(tool);
12875
+ turn.activeTools.delete(event.tool_use_id);
12876
+ }
12877
+ }
12878
+ function finalizeAnthropicSessionTool(state, event) {
12879
+ const toolUseId = event.tool_use_id ?? event.mcp_tool_use_id ?? event.custom_tool_use_id;
12880
+ if (!toolUseId) {
12881
+ return;
12882
+ }
12883
+ const content = processAttachmentsInInput(event.content);
12884
+ const turn = state.activeTurn;
12885
+ const tool = turn?.activeTools.get(toolUseId);
12886
+ if (turn && tool) {
12887
+ finalizeAnthropicSessionToolState(tool, event, content);
12888
+ turn.activeTools.delete(toolUseId);
12889
+ }
12890
+ const toolResult = {
12891
+ type: "tool_result",
12892
+ tool_use_id: toolUseId,
12893
+ ...content !== void 0 ? { content } : {},
12894
+ ...event.is_error === true ? { is_error: true } : {}
12895
+ };
12896
+ state.history.push({
12897
+ role: "user",
12898
+ content: [toolResult]
12899
+ });
12900
+ }
12901
+ function finalizeAnthropicSessionToolState(state, event, content = event?.content) {
12902
+ safeAnthropicSessionLog(state.span, {
12903
+ ...event?.is_error === true ? {
12904
+ error: content ?? "Anthropic session tool execution failed"
12905
+ } : {},
12906
+ ...state.approval ? { metadata: { tool_approval: state.approval } } : {},
12907
+ ...content !== void 0 ? { output: content } : {}
12908
+ });
12909
+ state.span.end();
12910
+ }
12911
+ function finalizeAnthropicSessionModel(state, event) {
12912
+ const turn = state.activeTurn;
12913
+ const model = turn?.activeModel;
12914
+ if (!turn || !model || model.startEventId !== event.model_request_start_id) {
12915
+ return;
12916
+ }
12917
+ finalizeAnthropicSessionModelState(state, turn, event);
12918
+ }
12919
+ function finalizeAnthropicSessionModelState(state, turn, event) {
12920
+ const model = turn.activeModel;
12921
+ if (!model) {
12922
+ return;
12923
+ }
12924
+ turn.activeModel = void 0;
12925
+ const metrics = event ? parseAnthropicSessionModelUsage(event.model_usage) : {};
12926
+ if (model.firstTokenTime !== void 0) {
12927
+ metrics.time_to_first_token = model.firstTokenTime - model.startTime;
12928
+ }
12929
+ const output = model.output.length > 0 ? { role: "assistant", content: model.output } : void 0;
12930
+ safeAnthropicSessionLog(model.span, {
12931
+ ...event?.is_error ? { error: "Anthropic session model request failed" } : {},
12932
+ ...Object.keys(metrics).length > 0 ? { metrics } : {},
12933
+ ...output ? { output } : {}
12934
+ });
12935
+ model.span.end();
12936
+ if (output) {
12937
+ turn.lastOutput = output;
12938
+ state.history.push(output);
12939
+ }
12940
+ for (const key of [
12941
+ "prompt_tokens",
12942
+ "completion_tokens",
12943
+ "tokens",
12944
+ "prompt_cached_tokens",
12945
+ "prompt_cache_creation_tokens"
12946
+ ]) {
12947
+ const value = metrics[key];
12948
+ if (typeof value === "number") {
12949
+ turn.metrics[key] = (turn.metrics[key] ?? 0) + value;
12950
+ }
12951
+ }
12952
+ }
12953
+ function parseAnthropicSessionModelUsage(usage) {
12954
+ const finalized = finalizeAnthropicTokens({
12955
+ completion_tokens: usage.output_tokens,
12956
+ prompt_cache_creation_tokens: usage.cache_creation_input_tokens,
12957
+ prompt_cached_tokens: usage.cache_read_input_tokens,
12958
+ prompt_tokens: usage.input_tokens
12959
+ });
12960
+ return Object.fromEntries(
12961
+ Object.entries(finalized).filter(
12962
+ (entry) => entry[1] !== void 0
12963
+ )
12964
+ );
12965
+ }
12966
+ function finalizeAnthropicSessionTurn(state, error) {
12967
+ const turn = state.activeTurn;
12968
+ if (!turn) {
12969
+ return;
12970
+ }
12971
+ state.activeTurn = void 0;
12972
+ finalizeAnthropicSessionModelState(state, turn);
12973
+ for (const tool of turn.activeTools.values()) {
12974
+ finalizeAnthropicSessionToolState(tool);
12975
+ }
12976
+ turn.activeTools.clear();
12977
+ safeAnthropicSessionLog(turn.span, {
12978
+ ...error !== void 0 ? { error: error instanceof Error ? error : toLoggedError(error) } : {},
12979
+ ...turn.input.length > 0 ? { input: turn.input } : {},
12980
+ ...turn.lastOutput ? { output: turn.lastOutput } : {},
12981
+ ...Object.keys(turn.metrics).length > 0 ? { metrics: turn.metrics } : {}
12982
+ });
12983
+ turn.span.end();
12984
+ }
12985
+ function safeAnthropicSessionLog(span, event) {
12986
+ try {
12987
+ span.log(event);
12988
+ } catch (error) {
12989
+ debugLogger.debug("Error logging Anthropic Sessions span:", error);
12990
+ }
12991
+ }
11880
12992
  function parseMetricsFromUsage2(usage) {
11881
12993
  if (!usage) {
11882
12994
  return {};
@@ -13750,6 +14862,29 @@ var harnessAgentChannels = defineChannels(
13750
14862
  { instrumentationName: INSTRUMENTATION_NAMES.AI_SDK }
13751
14863
  );
13752
14864
 
14865
+ // src/instrumentation/plugins/cloudflare-think-context.ts
14866
+ var cloudflareThinkSpans = /* @__PURE__ */ new Map();
14867
+ function registerCloudflareThinkSpan(span) {
14868
+ if (span.spanId) {
14869
+ cloudflareThinkSpans.set(span.spanId, span);
14870
+ }
14871
+ }
14872
+ function unregisterCloudflareThinkSpan(span) {
14873
+ if (span.spanId) {
14874
+ cloudflareThinkSpans.delete(span.spanId);
14875
+ }
14876
+ }
14877
+ function currentCloudflareThinkSpan() {
14878
+ const parentSpanIds = _internalGetGlobalState()?.contextManager.getParentSpanIds()?.spanParents ?? [];
14879
+ for (const parentSpanId of parentSpanIds) {
14880
+ const span = cloudflareThinkSpans.get(parentSpanId);
14881
+ if (span) {
14882
+ return span;
14883
+ }
14884
+ }
14885
+ return void 0;
14886
+ }
14887
+
13753
14888
  // src/instrumentation/plugins/ai-sdk-plugin.ts
13754
14889
  var DEFAULT_DENY_OUTPUT_PATHS = [
13755
14890
  // v3
@@ -13856,6 +14991,7 @@ var AISDKPlugin = class extends BasePlugin {
13856
14991
  traceStreamingChannel(aiSDKChannels.streamText, {
13857
14992
  name: "streamText",
13858
14993
  type: "function" /* FUNCTION */,
14994
+ shouldTrace: () => currentCloudflareThinkSpan() === void 0,
13859
14995
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
13860
14996
  extractOutput: (result, endEvent) => processAISDKOutput(
13861
14997
  result,
@@ -13876,6 +15012,7 @@ var AISDKPlugin = class extends BasePlugin {
13876
15012
  traceSyncStreamChannel(aiSDKChannels.streamTextSync, {
13877
15013
  name: "streamText",
13878
15014
  type: "function" /* FUNCTION */,
15015
+ shouldTrace: () => currentCloudflareThinkSpan() === void 0,
13879
15016
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
13880
15017
  patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
13881
15018
  defaultDenyOutputPaths: denyOutputPaths,
@@ -14861,6 +15998,23 @@ function prepareAISDKWorkflowAgentStreamInput(params, event, span, defaultDenyOu
14861
15998
  metadata
14862
15999
  };
14863
16000
  }
16001
+ function prepareAISDKAgentCallInput(params, event, span, defaultDenyOutputPaths = DEFAULT_DENY_OUTPUT_PATHS) {
16002
+ const { input } = processAISDKWorkflowAgentCallInput(params);
16003
+ const metadata = extractMetadataFromCallParams(params, event.self);
16004
+ const childTracing = prepareAISDKChildTracing(
16005
+ params,
16006
+ event.self,
16007
+ span,
16008
+ defaultDenyOutputPaths,
16009
+ event.aiSDK,
16010
+ { agentOwner: true }
16011
+ );
16012
+ event.modelWrapped = childTracing.modelWrapped;
16013
+ if (childTracing.cleanup) {
16014
+ event.__braintrust_ai_sdk_cleanup = childTracing.cleanup;
16015
+ }
16016
+ return { input, metadata };
16017
+ }
14864
16018
  function prepareAISDKEmbedInput(params, self) {
14865
16019
  return {
14866
16020
  input: { ...params },
@@ -14884,6 +16038,18 @@ function extractTopLevelAISDKMetrics(result, event, startTime) {
14884
16038
  }
14885
16039
  return metrics;
14886
16040
  }
16041
+ async function extractResolvedAISDKTokenMetrics(result) {
16042
+ for (const field of ["totalUsage", "usage"]) {
16043
+ try {
16044
+ const usage = await Promise.resolve(result[field]);
16045
+ if (usage !== void 0) {
16046
+ return extractTokenMetrics({ [field]: usage });
16047
+ }
16048
+ } catch {
16049
+ }
16050
+ }
16051
+ return extractTokenMetrics(result);
16052
+ }
14887
16053
  function hasModelChildTracing(event) {
14888
16054
  return event?.modelWrapped === true || event?.__braintrust_ai_sdk_model_wrapped === true;
14889
16055
  }
@@ -15701,13 +16867,15 @@ function patchAISDKStreamingResult(args) {
15701
16867
  const {
15702
16868
  defaultDenyOutputPaths,
15703
16869
  endEvent,
16870
+ forceTopLevelMetrics,
15704
16871
  onComplete,
15705
16872
  onCancel,
15706
16873
  onError,
15707
16874
  result,
15708
16875
  resolvePromiseUsage,
15709
16876
  span,
15710
- startTime
16877
+ startTime,
16878
+ transformOutput
15711
16879
  } = args;
15712
16880
  if (!result || typeof result !== "object") {
15713
16881
  return false;
@@ -15760,8 +16928,8 @@ function patchAISDKStreamingResult(args) {
15760
16928
  }
15761
16929
  outputLogged = true;
15762
16930
  try {
15763
- const metrics = extractTopLevelAISDKMetrics(result, endEvent);
15764
- if (resolvePromiseUsage) {
16931
+ const metrics = forceTopLevelMetrics ? await extractResolvedAISDKTokenMetrics(result) : extractTopLevelAISDKMetrics(result, endEvent);
16932
+ if (resolvePromiseUsage && !forceTopLevelMetrics) {
15765
16933
  try {
15766
16934
  const resultRecord2 = result;
15767
16935
  const pendingUsage = resultRecord2.totalUsage ?? resultRecord2.usage;
@@ -15780,10 +16948,11 @@ function patchAISDKStreamingResult(args) {
15780
16948
  if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
15781
16949
  metrics.time_to_first_token = firstChunkTime - startTime;
15782
16950
  }
15783
- const output = await processAISDKStreamingOutput(
16951
+ const processedOutput = await processAISDKStreamingOutput(
15784
16952
  result,
15785
16953
  resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
15786
16954
  );
16955
+ const output = transformOutput ? transformOutput(processedOutput) : processedOutput;
15787
16956
  const metadata = buildResolvedMetadataPayload(result).metadata;
15788
16957
  try {
15789
16958
  span.log({
@@ -18205,6 +19374,295 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
18205
19374
  }
18206
19375
  };
18207
19376
 
19377
+ // src/instrumentation/plugins/cloudflare-think-channels.ts
19378
+ var cloudflareThinkChannels = defineChannels(
19379
+ "@cloudflare/think",
19380
+ {
19381
+ runInferenceLoop: channel({
19382
+ channelName: "Think.runInferenceLoop",
19383
+ kind: "async"
19384
+ })
19385
+ },
19386
+ { instrumentationName: INSTRUMENTATION_NAMES.CLOUDFLARE_THINK }
19387
+ );
19388
+
19389
+ // src/instrumentation/plugins/cloudflare-think-plugin.ts
19390
+ var THINK_STATE_ID = /* @__PURE__ */ Symbol.for("braintrust.cloudflare-think.state-id");
19391
+ var CloudflareThinkPlugin = class extends BasePlugin {
19392
+ statesBySpanId = /* @__PURE__ */ new Map();
19393
+ onEnable() {
19394
+ this.subscribeToThinkRuns();
19395
+ this.subscribeToAISDKStreamTextSync();
19396
+ this.subscribeToAISDKStreamTextAsync();
19397
+ }
19398
+ onDisable() {
19399
+ for (const unsubscribe of this.unsubscribers) {
19400
+ unsubscribe();
19401
+ }
19402
+ this.unsubscribers = [];
19403
+ for (const state of this.statesBySpanId.values()) {
19404
+ this.finishState(state);
19405
+ }
19406
+ this.statesBySpanId.clear();
19407
+ }
19408
+ subscribeToThinkRuns() {
19409
+ const channel2 = cloudflareThinkChannels.runInferenceLoop.tracingChannel();
19410
+ const states = /* @__PURE__ */ new WeakMap();
19411
+ const state = _internalGetGlobalState();
19412
+ const contextManager = state?.contextManager;
19413
+ const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
19414
+ const ensureState2 = (event) => {
19415
+ if (isAutoInstrumentationSuppressed()) {
19416
+ return void 0;
19417
+ }
19418
+ const existing = states.get(event);
19419
+ if (existing) {
19420
+ return existing;
19421
+ }
19422
+ const span = startSpan(
19423
+ withSpanInstrumentationName(
19424
+ {
19425
+ name: "Think.runTurn",
19426
+ spanAttributes: { type: "task" /* TASK */ }
19427
+ },
19428
+ INSTRUMENTATION_NAMES.CLOUDFLARE_THINK
19429
+ )
19430
+ );
19431
+ const runState = {
19432
+ aiResultPatched: false,
19433
+ fallbackInput: extractFallbackInput(event.self?.messages),
19434
+ finalized: false,
19435
+ inputLogged: false,
19436
+ span,
19437
+ startTime: getCurrentUnixTimestamp()
19438
+ };
19439
+ const metadata = {
19440
+ braintrust: {
19441
+ integration_name: "cloudflare-think",
19442
+ sdk_language: "typescript"
19443
+ }
19444
+ };
19445
+ if (typeof event.moduleVersion === "string") {
19446
+ metadata["cloudflare_think.version"] = event.moduleVersion;
19447
+ }
19448
+ span.log({ metadata });
19449
+ states.set(event, runState);
19450
+ if (span.spanId) {
19451
+ this.statesBySpanId.set(span.spanId, runState);
19452
+ }
19453
+ registerCloudflareThinkSpan(span);
19454
+ return runState;
19455
+ };
19456
+ if (contextManager && currentSpanStore && channel2.start) {
19457
+ channel2.start.bindStore(currentSpanStore, (event) => {
19458
+ const runState = ensureState2(event);
19459
+ return runState ? contextManager.wrapSpanForStore(runState.span) : currentSpanStore.getStore();
19460
+ });
19461
+ this.unsubscribers.push(
19462
+ () => channel2.start?.unbindStore(currentSpanStore)
19463
+ );
19464
+ }
19465
+ const handlers = {
19466
+ start: (event) => {
19467
+ ensureState2(event);
19468
+ },
19469
+ asyncEnd: (event) => {
19470
+ const runState = states.get(event);
19471
+ states.delete(event);
19472
+ if (!runState || runState.finalized || runState.aiResultPatched) {
19473
+ return;
19474
+ }
19475
+ this.finishState(runState, void 0, event.result);
19476
+ },
19477
+ error: (event) => {
19478
+ const runState = states.get(event);
19479
+ states.delete(event);
19480
+ if (runState) {
19481
+ this.finishState(runState, event.error);
19482
+ }
19483
+ }
19484
+ };
19485
+ channel2.subscribe(handlers);
19486
+ this.unsubscribers.push(() => channel2.unsubscribe(handlers));
19487
+ }
19488
+ subscribeToAISDKStreamTextSync() {
19489
+ const channel2 = aiSDKChannels.streamTextSync.tracingChannel();
19490
+ const handlers = {
19491
+ start: (event) => {
19492
+ this.startAISDKStream(event);
19493
+ },
19494
+ end: (event) => {
19495
+ this.endAISDKStream(event);
19496
+ },
19497
+ error: (event) => {
19498
+ this.errorAISDKStream(event);
19499
+ }
19500
+ };
19501
+ channel2.subscribe(handlers);
19502
+ this.unsubscribers.push(() => channel2.unsubscribe(handlers));
19503
+ }
19504
+ subscribeToAISDKStreamTextAsync() {
19505
+ const channel2 = aiSDKChannels.streamText.tracingChannel();
19506
+ const handlers = {
19507
+ start: (event) => {
19508
+ this.startAISDKStream(event);
19509
+ },
19510
+ asyncEnd: (event) => {
19511
+ this.endAISDKStream(event);
19512
+ },
19513
+ error: (event) => {
19514
+ this.errorAISDKStream(event);
19515
+ }
19516
+ };
19517
+ channel2.subscribe(handlers);
19518
+ this.unsubscribers.push(() => channel2.unsubscribe(handlers));
19519
+ }
19520
+ startAISDKStream(event) {
19521
+ const runState = this.currentState();
19522
+ if (!runState || runState.finalized) {
19523
+ return;
19524
+ }
19525
+ try {
19526
+ const prepared = prepareAISDKAgentCallInput(
19527
+ event.arguments[0],
19528
+ event,
19529
+ runState.span
19530
+ );
19531
+ runState.span.log({
19532
+ input: extractThinkTaskInput(prepared.input),
19533
+ metadata: {
19534
+ ...prepared.metadata,
19535
+ braintrust: {
19536
+ integration_name: "cloudflare-think",
19537
+ sdk_language: "typescript"
19538
+ }
19539
+ }
19540
+ });
19541
+ runState.inputLogged = true;
19542
+ runState.aiEvent = event;
19543
+ Reflect.set(event, THINK_STATE_ID, runState.span.spanId);
19544
+ } catch (error) {
19545
+ debugLogger.error(
19546
+ "Error preparing @cloudflare/think AI SDK tracing:",
19547
+ error
19548
+ );
19549
+ }
19550
+ }
19551
+ endAISDKStream(event) {
19552
+ const runState = this.stateForAISDKEvent(event);
19553
+ if (!runState || runState.finalized) {
19554
+ return;
19555
+ }
19556
+ const patched = patchAISDKStreamingResult({
19557
+ defaultDenyOutputPaths: DEFAULT_DENY_OUTPUT_PATHS,
19558
+ endEvent: event,
19559
+ forceTopLevelMetrics: true,
19560
+ onComplete: () => this.releaseState(runState),
19561
+ result: event.result,
19562
+ span: runState.span,
19563
+ startTime: runState.startTime,
19564
+ transformOutput: extractThinkTaskOutput
19565
+ });
19566
+ runState.aiResultPatched = patched;
19567
+ if (!patched) {
19568
+ this.finishState(runState, void 0, event.result);
19569
+ }
19570
+ }
19571
+ errorAISDKStream(event) {
19572
+ const runState = this.stateForAISDKEvent(event);
19573
+ if (runState) {
19574
+ this.finishState(runState, event.error);
19575
+ }
19576
+ }
19577
+ currentState() {
19578
+ const parentIds = _internalGetGlobalState()?.contextManager.getParentSpanIds()?.spanParents ?? [];
19579
+ for (const parentId of parentIds) {
19580
+ const state = this.statesBySpanId.get(parentId);
19581
+ if (state) {
19582
+ return state;
19583
+ }
19584
+ }
19585
+ return void 0;
19586
+ }
19587
+ stateForAISDKEvent(event) {
19588
+ const spanId = Reflect.get(event, THINK_STATE_ID);
19589
+ return typeof spanId === "string" ? this.statesBySpanId.get(spanId) : void 0;
19590
+ }
19591
+ finishState(state, error, output) {
19592
+ if (state.finalized) {
19593
+ return;
19594
+ }
19595
+ state.finalized = true;
19596
+ try {
19597
+ if (!state.inputLogged && state.fallbackInput !== void 0) {
19598
+ state.span.log({ input: state.fallbackInput });
19599
+ }
19600
+ if (error !== void 0) {
19601
+ state.span.log({ error });
19602
+ } else if (output !== void 0) {
19603
+ state.span.log({ output: extractThinkTaskOutput(output) });
19604
+ }
19605
+ finalizeAISDKChildTracing(state.aiEvent);
19606
+ state.span.end();
19607
+ } finally {
19608
+ this.releaseState(state);
19609
+ }
19610
+ }
19611
+ releaseState(state) {
19612
+ state.finalized = true;
19613
+ unregisterCloudflareThinkSpan(state.span);
19614
+ if (state.span.spanId) {
19615
+ this.statesBySpanId.delete(state.span.spanId);
19616
+ }
19617
+ }
19618
+ };
19619
+ function extractFallbackInput(messages) {
19620
+ if (!Array.isArray(messages) || messages.length === 0) {
19621
+ return void 0;
19622
+ }
19623
+ let latestUserIndex = -1;
19624
+ for (let index = messages.length - 1; index >= 0; index--) {
19625
+ if (messages[index]?.role === "user") {
19626
+ latestUserIndex = index;
19627
+ break;
19628
+ }
19629
+ }
19630
+ const selected = latestUserIndex >= 0 ? messages.slice(latestUserIndex) : [];
19631
+ return selected.map((message) => ({
19632
+ role: message.role,
19633
+ content: message.content ?? message.parts
19634
+ }));
19635
+ }
19636
+ function extractThinkTaskOutput(output) {
19637
+ if (!isObject(output)) {
19638
+ return output;
19639
+ }
19640
+ if (typeof output.text === "string") {
19641
+ return { role: "assistant", content: output.text };
19642
+ }
19643
+ if (output.object !== void 0) {
19644
+ return output.object;
19645
+ }
19646
+ return output;
19647
+ }
19648
+ function extractThinkTaskInput(input) {
19649
+ if (!isObject(input)) {
19650
+ return input;
19651
+ }
19652
+ const system = input.instructions ?? input.system;
19653
+ if (Array.isArray(input.messages)) {
19654
+ return system === void 0 ? input.messages : [{ role: "system", content: system }, ...input.messages];
19655
+ }
19656
+ if (Array.isArray(input.prompt)) {
19657
+ return system === void 0 ? input.prompt : [{ role: "system", content: system }, ...input.prompt];
19658
+ }
19659
+ if (typeof input.prompt === "string") {
19660
+ const messages = [{ role: "user", content: input.prompt }];
19661
+ return system === void 0 ? messages : [{ role: "system", content: system }, ...messages];
19662
+ }
19663
+ return input;
19664
+ }
19665
+
18208
19666
  // src/instrumentation/plugins/cursor-sdk-channels.ts
18209
19667
  var cursorSDKChannels = defineChannels(
18210
19668
  "@cursor/sdk",
@@ -20347,11 +21805,11 @@ function summarizeEmbedContentOutput(response) {
20347
21805
  };
20348
21806
  }
20349
21807
  function populateUsageMetrics(metrics, usage) {
20350
- if (usage.promptTokenCount !== void 0) {
20351
- metrics.prompt_tokens = usage.promptTokenCount;
21808
+ if (usage.promptTokenCount !== void 0 || usage.toolUsePromptTokenCount !== void 0) {
21809
+ metrics.prompt_tokens = (usage.promptTokenCount ?? 0) + (usage.toolUsePromptTokenCount ?? 0);
20352
21810
  }
20353
- if (usage.candidatesTokenCount !== void 0) {
20354
- metrics.completion_tokens = usage.candidatesTokenCount;
21811
+ if (usage.candidatesTokenCount !== void 0 || usage.thoughtsTokenCount !== void 0) {
21812
+ metrics.completion_tokens = (usage.candidatesTokenCount ?? 0) + (usage.thoughtsTokenCount ?? 0);
20355
21813
  }
20356
21814
  if (usage.totalTokenCount !== void 0) {
20357
21815
  metrics.tokens = usage.totalTokenCount;
@@ -20362,13 +21820,26 @@ function populateUsageMetrics(metrics, usage) {
20362
21820
  if (usage.thoughtsTokenCount !== void 0) {
20363
21821
  metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
20364
21822
  }
21823
+ for (const detail of usage.promptTokensDetails ?? []) {
21824
+ if (detail.modality === "AUDIO" && detail.tokenCount !== void 0) {
21825
+ metrics.prompt_audio_tokens = (metrics.prompt_audio_tokens ?? 0) + detail.tokenCount;
21826
+ }
21827
+ }
21828
+ for (const detail of usage.candidatesTokensDetails ?? []) {
21829
+ if (detail.modality === "AUDIO" && detail.tokenCount !== void 0) {
21830
+ metrics.completion_audio_tokens = (metrics.completion_audio_tokens ?? 0) + detail.tokenCount;
21831
+ }
21832
+ if (detail.modality === "IMAGE" && detail.tokenCount !== void 0) {
21833
+ metrics.completion_image_tokens = (metrics.completion_image_tokens ?? 0) + detail.tokenCount;
21834
+ }
21835
+ }
20365
21836
  }
20366
21837
  function populateInteractionUsageMetrics(metrics, usage) {
20367
21838
  if (typeof usage.total_input_tokens === "number") {
20368
21839
  metrics.prompt_tokens = usage.total_input_tokens;
20369
21840
  }
20370
21841
  if (typeof usage.total_output_tokens === "number") {
20371
- metrics.completion_tokens = usage.total_output_tokens;
21842
+ metrics.completion_tokens = usage.total_output_tokens + (typeof usage.total_thought_tokens === "number" ? usage.total_thought_tokens : 0);
20372
21843
  }
20373
21844
  if (typeof usage.total_tokens === "number") {
20374
21845
  metrics.tokens = usage.total_tokens;
@@ -20379,6 +21850,24 @@ function populateInteractionUsageMetrics(metrics, usage) {
20379
21850
  if (typeof usage.total_thought_tokens === "number") {
20380
21851
  metrics.completion_reasoning_tokens = usage.total_thought_tokens;
20381
21852
  }
21853
+ for (const detail of Array.isArray(usage.input_tokens_by_modality) ? usage.input_tokens_by_modality : []) {
21854
+ if (typeof detail?.modality === "string" && detail.modality.toLowerCase() === "audio" && typeof detail.tokens === "number") {
21855
+ metrics.prompt_audio_tokens = (metrics.prompt_audio_tokens ?? 0) + detail.tokens;
21856
+ }
21857
+ }
21858
+ for (const detail of Array.isArray(usage.output_tokens_by_modality) ? usage.output_tokens_by_modality : []) {
21859
+ if (typeof detail?.modality !== "string" || typeof detail.tokens !== "number") {
21860
+ continue;
21861
+ }
21862
+ switch (detail.modality.toLowerCase()) {
21863
+ case "audio":
21864
+ metrics.completion_audio_tokens = (metrics.completion_audio_tokens ?? 0) + detail.tokens;
21865
+ break;
21866
+ case "image":
21867
+ metrics.completion_image_tokens = (metrics.completion_image_tokens ?? 0) + detail.tokens;
21868
+ break;
21869
+ }
21870
+ }
20382
21871
  }
20383
21872
  function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
20384
21873
  const end = getCurrentUnixTimestamp();
@@ -21117,6 +22606,299 @@ function extractTextGenerationStreamMetadata(chunks) {
21117
22606
  return void 0;
21118
22607
  }
21119
22608
 
22609
+ // src/instrumentation/plugins/huggingface-transformers-channels.ts
22610
+ var SUPPORTED_TASKS = /* @__PURE__ */ new Set([
22611
+ "text-generation",
22612
+ "text2text-generation",
22613
+ "summarization",
22614
+ "feature-extraction",
22615
+ "question-answering"
22616
+ ]);
22617
+ var pipelineInfo = /* @__PURE__ */ new WeakMap();
22618
+ function isSupportedHuggingFaceTransformersTask(task) {
22619
+ return typeof task === "string" && SUPPORTED_TASKS.has(task);
22620
+ }
22621
+ function registerHuggingFaceTransformersPipeline(pipeline, task, model) {
22622
+ if (typeof task !== "string") {
22623
+ return;
22624
+ }
22625
+ const info = { task };
22626
+ if (typeof model === "string") {
22627
+ info.model = model;
22628
+ }
22629
+ pipelineInfo.set(pipeline, info);
22630
+ }
22631
+ function getHuggingFaceTransformersPipelineInfo(pipeline) {
22632
+ return pipeline ? pipelineInfo.get(pipeline) : void 0;
22633
+ }
22634
+ var huggingFaceTransformersChannels = defineChannels(
22635
+ "@huggingface/transformers",
22636
+ {
22637
+ pipeline: channel({
22638
+ channelName: "pipeline",
22639
+ kind: "async"
22640
+ }),
22641
+ pipelineCall: channel({
22642
+ channelName: "pipeline.call",
22643
+ kind: "async"
22644
+ })
22645
+ },
22646
+ { instrumentationName: INSTRUMENTATION_NAMES.HUGGINGFACE }
22647
+ );
22648
+
22649
+ // src/instrumentation/plugins/huggingface-transformers-plugin.ts
22650
+ var REQUEST_METADATA_KEYS = [
22651
+ "temperature",
22652
+ "top_p",
22653
+ "max_tokens",
22654
+ "stop"
22655
+ ];
22656
+ var HuggingFaceTransformersPlugin = class extends BasePlugin {
22657
+ onEnable() {
22658
+ this.subscribeToPipelineFactory();
22659
+ this.unsubscribers.push(
22660
+ traceAsyncChannel(huggingFaceTransformersChannels.pipelineCall, {
22661
+ name: (_args, event) => {
22662
+ const task = getTask(event);
22663
+ const operation = task?.replaceAll("-", "_") ?? "unknown";
22664
+ return `huggingface.transformers.${operation}`;
22665
+ },
22666
+ type: "llm" /* LLM */,
22667
+ shouldTrace: (_args, event) => isSupportedHuggingFaceTransformersTask(
22668
+ getTask(event)
22669
+ ),
22670
+ extractInput: (args, event) => ({
22671
+ input: extractInput(
22672
+ getTask(event),
22673
+ args
22674
+ ),
22675
+ metadata: extractMetadata(
22676
+ event,
22677
+ args
22678
+ )
22679
+ }),
22680
+ extractOutput: (result, event) => extractOutput(
22681
+ getTask(event),
22682
+ result
22683
+ ),
22684
+ extractMetrics: () => ({})
22685
+ })
22686
+ );
22687
+ }
22688
+ onDisable() {
22689
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
22690
+ }
22691
+ subscribeToPipelineFactory() {
22692
+ const channel2 = huggingFaceTransformersChannels.pipeline.tracingChannel();
22693
+ const handlers = {
22694
+ asyncEnd: (event) => {
22695
+ if (typeof event.result !== "function") {
22696
+ return;
22697
+ }
22698
+ registerHuggingFaceTransformersPipeline(
22699
+ event.result,
22700
+ event.arguments?.[0],
22701
+ event.arguments?.[1]
22702
+ );
22703
+ }
22704
+ };
22705
+ channel2.subscribe(handlers);
22706
+ this.unsubscribers.push(() => channel2.unsubscribe(handlers));
22707
+ }
22708
+ };
22709
+ function getTask(event) {
22710
+ const self = event.self;
22711
+ const registeredTask = getHuggingFaceTransformersPipelineInfo(self)?.task;
22712
+ if (registeredTask !== void 0) {
22713
+ return registeredTask;
22714
+ }
22715
+ if (typeof self?.task === "string") {
22716
+ return self.task;
22717
+ }
22718
+ return void 0;
22719
+ }
22720
+ function extractMetadata(event, args) {
22721
+ const metadata = {
22722
+ provider: "huggingface"
22723
+ };
22724
+ const registeredModel = getHuggingFaceTransformersPipelineInfo(
22725
+ event.self
22726
+ )?.model;
22727
+ const model = registeredModel ?? modelIdentifier(event.self);
22728
+ if (model) {
22729
+ metadata.model = model;
22730
+ }
22731
+ const task = getTask(event);
22732
+ const options = task === "question-answering" ? args[2] : args[1];
22733
+ if (isObject(options)) {
22734
+ for (const key of REQUEST_METADATA_KEYS) {
22735
+ if (options[key] !== void 0) {
22736
+ metadata[key] = options[key];
22737
+ }
22738
+ }
22739
+ }
22740
+ return metadata;
22741
+ }
22742
+ function modelIdentifier(pipeline) {
22743
+ const model = pipeline?.model;
22744
+ if (!isObject(model)) {
22745
+ return void 0;
22746
+ }
22747
+ const config = isObject(model.config) ? model.config : void 0;
22748
+ for (const value of [
22749
+ config?._name_or_path,
22750
+ config?.name_or_path,
22751
+ config?.model_id,
22752
+ config?.modelId,
22753
+ model.name
22754
+ ]) {
22755
+ if (typeof value === "string" && value.length > 0) {
22756
+ return value;
22757
+ }
22758
+ }
22759
+ return void 0;
22760
+ }
22761
+ function extractInput(task, args) {
22762
+ switch (task) {
22763
+ case "feature-extraction":
22764
+ return args[0];
22765
+ case "question-answering": {
22766
+ const question = args[0];
22767
+ const context = args[1];
22768
+ if (Array.isArray(question) && Array.isArray(context) && question.every((value) => typeof value === "string") && context.every((value) => typeof value === "string")) {
22769
+ return question.map((value, index) => [
22770
+ {
22771
+ role: "user",
22772
+ content: `Context:
22773
+ ${context[index] ?? ""}
22774
+
22775
+ Question:
22776
+ ${value}`
22777
+ }
22778
+ ]);
22779
+ }
22780
+ if (typeof question === "string" && typeof context === "string") {
22781
+ return [
22782
+ {
22783
+ role: "user",
22784
+ content: `Context:
22785
+ ${context}
22786
+
22787
+ Question:
22788
+ ${question}`
22789
+ }
22790
+ ];
22791
+ }
22792
+ return { context, question };
22793
+ }
22794
+ }
22795
+ const input = args[0];
22796
+ if (task === "text-generation" && isChat(input)) {
22797
+ return input;
22798
+ }
22799
+ if (task === "text-generation" && Array.isArray(input) && input.every(isChat)) {
22800
+ return input;
22801
+ }
22802
+ if (typeof input === "string") {
22803
+ return [{ role: "user", content: input }];
22804
+ }
22805
+ if (Array.isArray(input) && input.every((value) => typeof value === "string")) {
22806
+ return input.map((value) => [
22807
+ {
22808
+ role: "user",
22809
+ content: value
22810
+ }
22811
+ ]);
22812
+ }
22813
+ return input;
22814
+ }
22815
+ function isChat(value) {
22816
+ return Array.isArray(value) && value.length > 0 && value.every(
22817
+ (message) => isObject(message) && typeof message.role === "string" && "content" in message
22818
+ );
22819
+ }
22820
+ function extractOutput(task, result) {
22821
+ switch (task) {
22822
+ case "feature-extraction":
22823
+ return summarizeEmbedding(result);
22824
+ case "question-answering":
22825
+ return choicesFromAnswers(result);
22826
+ default:
22827
+ return choicesFromGenerations(result);
22828
+ }
22829
+ }
22830
+ function summarizeEmbedding(result) {
22831
+ if (!isObject(result) || !Array.isArray(result.dims)) {
22832
+ return void 0;
22833
+ }
22834
+ const { dims } = result;
22835
+ if (dims.length === 0 || !dims.every((dimension) => typeof dimension === "number")) {
22836
+ return void 0;
22837
+ }
22838
+ if (dims.length === 1) {
22839
+ return { embedding_length: dims[0] };
22840
+ }
22841
+ if (dims.length === 2) {
22842
+ return {
22843
+ embedding_count: dims[0],
22844
+ embedding_length: dims[1]
22845
+ };
22846
+ }
22847
+ return {
22848
+ embedding_batch_count: dims[0],
22849
+ embedding_count: dims[1],
22850
+ embedding_length: dims.at(-1) ?? 0
22851
+ };
22852
+ }
22853
+ function choicesFromAnswers(result) {
22854
+ const answers = Array.isArray(result) ? result.flat() : [result];
22855
+ const choices = answers.flatMap((answer, index) => {
22856
+ if (!isObject(answer) || typeof answer.answer !== "string") {
22857
+ return [];
22858
+ }
22859
+ return [
22860
+ {
22861
+ index,
22862
+ finish_reason: "stop",
22863
+ message: {
22864
+ role: "assistant",
22865
+ content: answer.answer
22866
+ }
22867
+ }
22868
+ ];
22869
+ });
22870
+ return choices.length > 0 ? choices : void 0;
22871
+ }
22872
+ function choicesFromGenerations(result) {
22873
+ const generations = Array.isArray(result) ? result.flat() : [result];
22874
+ const choices = generations.flatMap((generation, index) => {
22875
+ if (!isObject(generation)) {
22876
+ return [];
22877
+ }
22878
+ const generated = generation.generated_text ?? generation.summary_text;
22879
+ let content;
22880
+ if (typeof generated === "string") {
22881
+ content = generated;
22882
+ } else if (isChat(generated)) {
22883
+ content = generated.at(-1)?.content;
22884
+ }
22885
+ if (typeof content !== "string") {
22886
+ return [];
22887
+ }
22888
+ return [
22889
+ {
22890
+ index,
22891
+ finish_reason: "stop",
22892
+ message: {
22893
+ role: "assistant",
22894
+ content
22895
+ }
22896
+ }
22897
+ ];
22898
+ });
22899
+ return choices.length > 0 ? choices : void 0;
22900
+ }
22901
+
21120
22902
  // src/instrumentation/plugins/openrouter-agent-channels.ts
21121
22903
  var openRouterAgentChannels = defineChannels(
21122
22904
  "@openrouter/agent",
@@ -23646,6 +25428,470 @@ function aggregateMistralStreamChunks(chunks) {
23646
25428
  };
23647
25429
  }
23648
25430
 
25431
+ // src/instrumentation/plugins/ollama-channels.ts
25432
+ var ollamaChannels = defineChannels(
25433
+ "ollama",
25434
+ {
25435
+ chat: channel({
25436
+ channelName: "chat",
25437
+ kind: "async"
25438
+ }),
25439
+ generate: channel({
25440
+ channelName: "generate",
25441
+ kind: "async"
25442
+ }),
25443
+ embed: channel({
25444
+ channelName: "embed",
25445
+ kind: "async"
25446
+ })
25447
+ },
25448
+ { instrumentationName: INSTRUMENTATION_NAMES.OLLAMA }
25449
+ );
25450
+
25451
+ // src/instrumentation/plugins/ollama-plugin.ts
25452
+ var OllamaPlugin = class extends BasePlugin {
25453
+ onEnable() {
25454
+ this.unsubscribers.push(
25455
+ traceStreamingChannel(ollamaChannels.chat, {
25456
+ name: "ollama.chat",
25457
+ type: "llm" /* LLM */,
25458
+ extractInput: extractOllamaChatInput,
25459
+ extractOutput: (result, event) => extractOllamaChatOutput(
25460
+ result,
25461
+ countOllamaToolCalls(event?.arguments?.[0]?.messages)
25462
+ ),
25463
+ extractMetadata: extractOllamaResponseMetadata,
25464
+ extractMetrics: extractOllamaMetrics,
25465
+ aggregateChunks: aggregateOllamaChatChunks
25466
+ }),
25467
+ traceStreamingChannel(ollamaChannels.generate, {
25468
+ name: "ollama.generate",
25469
+ type: "llm" /* LLM */,
25470
+ extractInput: extractOllamaGenerateInput,
25471
+ extractOutput: extractOllamaGenerateOutput,
25472
+ extractMetadata: extractOllamaResponseMetadata,
25473
+ extractMetrics: extractOllamaMetrics,
25474
+ aggregateChunks: aggregateOllamaGenerateChunks
25475
+ }),
25476
+ traceAsyncChannel(ollamaChannels.embed, {
25477
+ name: "ollama.embed",
25478
+ type: "llm" /* LLM */,
25479
+ extractInput: extractOllamaEmbedInput,
25480
+ extractOutput: extractOllamaEmbedOutput,
25481
+ extractMetadata: extractOllamaResponseMetadata,
25482
+ extractMetrics: extractOllamaMetrics
25483
+ })
25484
+ );
25485
+ }
25486
+ onDisable() {
25487
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
25488
+ }
25489
+ };
25490
+ function isNonNegativeNumber(value) {
25491
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
25492
+ }
25493
+ function normalizeFinishReason(response, hasToolCalls = false) {
25494
+ if (hasToolCalls) {
25495
+ return "tool_calls";
25496
+ }
25497
+ return response?.done_reason || "stop";
25498
+ }
25499
+ function stringifyArguments(value) {
25500
+ if (typeof value === "string") {
25501
+ return value;
25502
+ }
25503
+ try {
25504
+ return JSON.stringify(value ?? {});
25505
+ } catch {
25506
+ return String(value);
25507
+ }
25508
+ }
25509
+ function syntheticToolCallId(name, index) {
25510
+ const normalizedName = name.replace(/[^a-zA-Z0-9_-]/g, "_") || "tool";
25511
+ return `ollama_call_${normalizedName}_${index}`;
25512
+ }
25513
+ function normalizeToolCall(toolCall, index) {
25514
+ const name = toolCall.function?.name;
25515
+ if (typeof name !== "string" || name.length === 0) {
25516
+ return void 0;
25517
+ }
25518
+ return {
25519
+ id: typeof toolCall.id === "string" && toolCall.id.length > 0 ? toolCall.id : syntheticToolCallId(name, index),
25520
+ type: "function",
25521
+ function: {
25522
+ name,
25523
+ arguments: stringifyArguments(toolCall.function?.arguments)
25524
+ }
25525
+ };
25526
+ }
25527
+ function normalizeToolCalls(toolCalls, syntheticIdOffset = 0) {
25528
+ if (!Array.isArray(toolCalls)) {
25529
+ return [];
25530
+ }
25531
+ return toolCalls.flatMap((toolCall, index) => {
25532
+ const normalized = normalizeToolCall(toolCall, syntheticIdOffset + index);
25533
+ return normalized ? [normalized] : [];
25534
+ });
25535
+ }
25536
+ function countOllamaToolCalls(messages) {
25537
+ if (!Array.isArray(messages)) {
25538
+ return 0;
25539
+ }
25540
+ return messages.reduce(
25541
+ (count, message) => count + (isObject(message) && Array.isArray(message.tool_calls) ? message.tool_calls.length : 0),
25542
+ 0
25543
+ );
25544
+ }
25545
+ function imageBytes(value) {
25546
+ if (value instanceof Uint8Array) {
25547
+ return value;
25548
+ }
25549
+ if (value instanceof ArrayBuffer) {
25550
+ return new Uint8Array(value);
25551
+ }
25552
+ if (typeof value !== "string" || value.startsWith("data:")) {
25553
+ return void 0;
25554
+ }
25555
+ try {
25556
+ const decoded = atob(value.slice(0, 24));
25557
+ return Uint8Array.from(decoded, (character) => character.charCodeAt(0));
25558
+ } catch {
25559
+ return void 0;
25560
+ }
25561
+ }
25562
+ function inferImageMediaType(value) {
25563
+ if (typeof value === "string") {
25564
+ const dataUrlType = value.match(/^data:(image\/[^;]+);base64,/i)?.[1];
25565
+ if (dataUrlType) {
25566
+ return dataUrlType;
25567
+ }
25568
+ }
25569
+ const bytes = imageBytes(value);
25570
+ if (!bytes) {
25571
+ return void 0;
25572
+ }
25573
+ if (bytes[0] === 137 && bytes[1] === 80 && bytes[2] === 78 && bytes[3] === 71) {
25574
+ return "image/png";
25575
+ }
25576
+ if (bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255) {
25577
+ return "image/jpeg";
25578
+ }
25579
+ const signature = String.fromCharCode(...bytes.slice(0, 12));
25580
+ if (signature.startsWith("GIF87a") || signature.startsWith("GIF89a")) {
25581
+ return "image/gif";
25582
+ }
25583
+ if (signature.startsWith("RIFF") && signature.slice(8, 12) === "WEBP") {
25584
+ return "image/webp";
25585
+ }
25586
+ return void 0;
25587
+ }
25588
+ function normalizeTextAndImages(content, images) {
25589
+ if (!images || images.length === 0) {
25590
+ return { content };
25591
+ }
25592
+ const imageParts = [];
25593
+ const unrecognizedImages = [];
25594
+ for (const image of images) {
25595
+ let localImagePath;
25596
+ let localPathMediaType;
25597
+ if (typeof image === "string" && !/^data:/i.test(image) && !/^https?:\/\//i.test(image)) {
25598
+ const extension = image.match(/\.([a-z0-9]+)$/i)?.[1]?.toLowerCase();
25599
+ const extensionMediaType = {
25600
+ png: "image/png",
25601
+ jpg: "image/jpeg",
25602
+ jpeg: "image/jpeg",
25603
+ gif: "image/gif",
25604
+ webp: "image/webp"
25605
+ }[extension ?? ""];
25606
+ if (extensionMediaType && isomorph_default.statSync) {
25607
+ try {
25608
+ if (isomorph_default.statSync(image).isFile()) {
25609
+ localImagePath = image;
25610
+ localPathMediaType = extensionMediaType;
25611
+ }
25612
+ } catch {
25613
+ }
25614
+ }
25615
+ }
25616
+ const mediaType = localPathMediaType ?? inferImageMediaType(image);
25617
+ if (!mediaType) {
25618
+ unrecognizedImages.push(image);
25619
+ continue;
25620
+ }
25621
+ const processedImage = localImagePath ? new Attachment({
25622
+ data: localImagePath,
25623
+ filename: localImagePath.split(/[\\/]/).at(-1) ?? "image",
25624
+ contentType: mediaType
25625
+ }) : processInputAttachments({
25626
+ type: "image",
25627
+ image,
25628
+ mediaType
25629
+ }).image;
25630
+ imageParts.push({
25631
+ type: "image_url",
25632
+ image_url: { url: processedImage }
25633
+ });
25634
+ }
25635
+ return {
25636
+ content: imageParts.length > 0 ? [...content ? [{ type: "text", text: content }] : [], ...imageParts] : content,
25637
+ ...unrecognizedImages.length > 0 ? { unrecognizedImages } : {}
25638
+ };
25639
+ }
25640
+ function normalizeMessage(message, toolCallId, syntheticToolCallIdOffset = 0) {
25641
+ if (typeof message.role !== "string") {
25642
+ return void 0;
25643
+ }
25644
+ const toolCalls = normalizeToolCalls(
25645
+ message.tool_calls,
25646
+ syntheticToolCallIdOffset
25647
+ );
25648
+ if (message.role === "tool") {
25649
+ const toolName = typeof message.tool_name === "string" && message.tool_name.length > 0 ? message.tool_name : "tool";
25650
+ return {
25651
+ role: "tool",
25652
+ tool_call_id: toolCallId ?? syntheticToolCallId(toolName, 0),
25653
+ content: typeof message.content === "string" ? message.content : ""
25654
+ };
25655
+ }
25656
+ const normalizedContent = normalizeTextAndImages(
25657
+ typeof message.content === "string" ? message.content || (toolCalls.length > 0 ? null : "") : toolCalls.length > 0 ? null : "",
25658
+ message.images
25659
+ );
25660
+ return {
25661
+ role: message.role,
25662
+ content: normalizedContent.content,
25663
+ ...typeof message.thinking === "string" && message.thinking.length > 0 ? { reasoning: message.thinking } : {},
25664
+ ...toolCalls.length > 0 ? { tool_calls: toolCalls } : {},
25665
+ ...normalizedContent.unrecognizedImages ? { images: normalizedContent.unrecognizedImages } : {}
25666
+ };
25667
+ }
25668
+ function normalizeMessages(messages) {
25669
+ if (!Array.isArray(messages)) {
25670
+ return [];
25671
+ }
25672
+ const pendingToolCallIds = /* @__PURE__ */ new Map();
25673
+ let syntheticToolCallIdOffset = 0;
25674
+ return messages.flatMap((message) => {
25675
+ if (!isObject(message)) {
25676
+ return [];
25677
+ }
25678
+ const ollamaMessage = message;
25679
+ let toolCallId;
25680
+ if (ollamaMessage.role === "tool") {
25681
+ const toolName = ollamaMessage.tool_name;
25682
+ if (typeof toolName === "string") {
25683
+ toolCallId = pendingToolCallIds.get(toolName)?.shift();
25684
+ }
25685
+ }
25686
+ const normalized = normalizeMessage(
25687
+ ollamaMessage,
25688
+ toolCallId,
25689
+ syntheticToolCallIdOffset
25690
+ );
25691
+ if (Array.isArray(ollamaMessage.tool_calls)) {
25692
+ syntheticToolCallIdOffset += ollamaMessage.tool_calls.length;
25693
+ }
25694
+ if (ollamaMessage.role === "assistant" && normalized) {
25695
+ const toolCalls = Array.isArray(normalized.tool_calls) ? normalized.tool_calls : [];
25696
+ for (const toolCall of toolCalls) {
25697
+ if (!isObject(toolCall) || !isObject(toolCall.function)) {
25698
+ continue;
25699
+ }
25700
+ const name = toolCall.function.name;
25701
+ const id = toolCall.id;
25702
+ if (typeof name === "string" && typeof id === "string") {
25703
+ const ids = pendingToolCallIds.get(name) ?? [];
25704
+ ids.push(id);
25705
+ pendingToolCallIds.set(name, ids);
25706
+ }
25707
+ }
25708
+ }
25709
+ return normalized ? [normalized] : [];
25710
+ });
25711
+ }
25712
+ function normalizeToolDefinition(tool) {
25713
+ const fn = tool.function;
25714
+ if (!fn || typeof fn.name !== "string" || fn.name.length === 0) {
25715
+ return void 0;
25716
+ }
25717
+ return {
25718
+ type: "function",
25719
+ function: {
25720
+ name: fn.name,
25721
+ ...typeof fn.description === "string" ? { description: fn.description } : {},
25722
+ ...isObject(fn.parameters) ? { parameters: fn.parameters } : {}
25723
+ }
25724
+ };
25725
+ }
25726
+ function extractToolsMetadata(tools) {
25727
+ if (!Array.isArray(tools)) {
25728
+ return {};
25729
+ }
25730
+ const normalized = tools.flatMap((tool) => {
25731
+ if (!isObject(tool)) {
25732
+ return [];
25733
+ }
25734
+ const definition = normalizeToolDefinition(tool);
25735
+ return definition ? [definition] : [];
25736
+ });
25737
+ return normalized.length > 0 ? { tools: normalized } : {};
25738
+ }
25739
+ function extractOptionsMetadata(options) {
25740
+ if (!isObject(options)) {
25741
+ return {};
25742
+ }
25743
+ const metadata = {};
25744
+ const mappings = [
25745
+ ["temperature", "temperature"],
25746
+ ["top_p", "top_p"],
25747
+ ["num_predict", "max_tokens"],
25748
+ ["frequency_penalty", "frequency_penalty"],
25749
+ ["presence_penalty", "presence_penalty"],
25750
+ ["stop", "stop"]
25751
+ ];
25752
+ for (const [source, target] of mappings) {
25753
+ if (options[source] !== void 0) {
25754
+ metadata[target] = options[source];
25755
+ }
25756
+ }
25757
+ return metadata;
25758
+ }
25759
+ function extractRequestMetadata(request) {
25760
+ return {
25761
+ provider: "ollama",
25762
+ ...typeof request?.model === "string" ? { model: request.model } : {},
25763
+ ...extractOptionsMetadata(request?.options),
25764
+ ...request?.format !== void 0 ? { response_format: request.format } : {}
25765
+ };
25766
+ }
25767
+ function extractOllamaChatInput([request]) {
25768
+ return {
25769
+ input: normalizeMessages(request.messages),
25770
+ metadata: {
25771
+ ...extractRequestMetadata(request),
25772
+ ...extractToolsMetadata(request.tools)
25773
+ }
25774
+ };
25775
+ }
25776
+ function extractOllamaGenerateInput([request]) {
25777
+ const normalizedPrompt = normalizeTextAndImages(
25778
+ typeof request.prompt === "string" ? request.prompt : "",
25779
+ Array.isArray(request.images) ? request.images : void 0
25780
+ );
25781
+ const input = [
25782
+ ...typeof request.system === "string" ? [{ role: "system", content: request.system }] : [],
25783
+ {
25784
+ role: "user",
25785
+ content: normalizedPrompt.content,
25786
+ ...typeof request.suffix === "string" ? { suffix: request.suffix } : {},
25787
+ ...normalizedPrompt.unrecognizedImages ? { images: normalizedPrompt.unrecognizedImages } : {}
25788
+ }
25789
+ ];
25790
+ return {
25791
+ input,
25792
+ metadata: extractRequestMetadata(request)
25793
+ };
25794
+ }
25795
+ function extractOllamaEmbedInput([request]) {
25796
+ return {
25797
+ input: request.input,
25798
+ metadata: extractRequestMetadata(request)
25799
+ };
25800
+ }
25801
+ function extractOllamaChatOutput(result, syntheticToolCallIdOffset = 0) {
25802
+ if (!isObject(result) || !isObject(result.message)) {
25803
+ return void 0;
25804
+ }
25805
+ const message = normalizeMessage(
25806
+ result.message,
25807
+ void 0,
25808
+ syntheticToolCallIdOffset
25809
+ );
25810
+ if (!message) {
25811
+ return void 0;
25812
+ }
25813
+ const toolCalls = Array.isArray(message.tool_calls) ? message.tool_calls : [];
25814
+ return [
25815
+ {
25816
+ index: 0,
25817
+ finish_reason: normalizeFinishReason(result, toolCalls.length > 0),
25818
+ message
25819
+ }
25820
+ ];
25821
+ }
25822
+ function extractOllamaGenerateOutput(result) {
25823
+ if (!isObject(result) || typeof result.response !== "string") {
25824
+ return void 0;
25825
+ }
25826
+ return [
25827
+ {
25828
+ index: 0,
25829
+ finish_reason: normalizeFinishReason(result),
25830
+ message: {
25831
+ role: "assistant",
25832
+ content: result.response,
25833
+ ...typeof result.thinking === "string" && result.thinking.length > 0 ? { reasoning: result.thinking } : {}
25834
+ }
25835
+ }
25836
+ ];
25837
+ }
25838
+ function extractOllamaEmbedOutput(result) {
25839
+ const embedding = Array.isArray(result?.embeddings) ? result.embeddings[0] : void 0;
25840
+ return Array.isArray(embedding) ? { embedding_length: embedding.length } : void 0;
25841
+ }
25842
+ function extractOllamaResponseMetadata(result) {
25843
+ return typeof result?.model === "string" ? { model: result.model } : void 0;
25844
+ }
25845
+ function extractOllamaMetrics(result) {
25846
+ const metrics = {};
25847
+ const promptTokens = result?.prompt_eval_count;
25848
+ const completionTokens = result?.eval_count;
25849
+ if (isNonNegativeNumber(promptTokens)) {
25850
+ metrics.prompt_tokens = promptTokens;
25851
+ }
25852
+ if (isNonNegativeNumber(completionTokens)) {
25853
+ metrics.completion_tokens = completionTokens;
25854
+ }
25855
+ if (isNonNegativeNumber(promptTokens) || isNonNegativeNumber(completionTokens)) {
25856
+ metrics.tokens = (isNonNegativeNumber(promptTokens) ? promptTokens : 0) + (isNonNegativeNumber(completionTokens) ? completionTokens : 0);
25857
+ }
25858
+ return metrics;
25859
+ }
25860
+ function aggregateOllamaChatChunks(chunks, _result, event, _startTime) {
25861
+ const last = chunks.at(-1);
25862
+ const message = {
25863
+ role: "assistant",
25864
+ content: chunks.map((chunk) => chunk.message?.content ?? "").join(""),
25865
+ thinking: chunks.map((chunk) => chunk.message?.thinking ?? "").join(""),
25866
+ tool_calls: chunks.flatMap((chunk) => chunk.message?.tool_calls ?? [])
25867
+ };
25868
+ const response = {
25869
+ ...last,
25870
+ message
25871
+ };
25872
+ return {
25873
+ output: extractOllamaChatOutput(
25874
+ response,
25875
+ countOllamaToolCalls(event?.arguments?.[0]?.messages)
25876
+ ),
25877
+ metrics: extractOllamaMetrics(last ?? {}),
25878
+ metadata: extractOllamaResponseMetadata(last ?? {})
25879
+ };
25880
+ }
25881
+ function aggregateOllamaGenerateChunks(chunks, _result, _event, _startTime) {
25882
+ const last = chunks.at(-1);
25883
+ const response = {
25884
+ ...last,
25885
+ response: chunks.map((chunk) => chunk.response ?? "").join(""),
25886
+ thinking: chunks.map((chunk) => chunk.thinking ?? "").join("")
25887
+ };
25888
+ return {
25889
+ output: extractOllamaGenerateOutput(response),
25890
+ metrics: extractOllamaMetrics(last ?? {}),
25891
+ metadata: extractOllamaResponseMetadata(last ?? {})
25892
+ };
25893
+ }
25894
+
23649
25895
  // src/instrumentation/plugins/google-adk-channels.ts
23650
25896
  var googleADKChannels = defineChannels(
23651
25897
  "@google/adk",
@@ -24282,15 +26528,32 @@ function aggregateUsageFromEvents(events) {
24282
26528
  if (usage.thoughtsTokenCount !== void 0) {
24283
26529
  aggregated.thoughtsTokenCount = (aggregated.thoughtsTokenCount ?? 0) + usage.thoughtsTokenCount;
24284
26530
  }
26531
+ if (usage.toolUsePromptTokenCount !== void 0) {
26532
+ aggregated.toolUsePromptTokenCount = (aggregated.toolUsePromptTokenCount ?? 0) + usage.toolUsePromptTokenCount;
26533
+ }
26534
+ for (const detailsField of [
26535
+ "promptTokensDetails",
26536
+ "cacheTokensDetails",
26537
+ "candidatesTokensDetails",
26538
+ "toolUsePromptTokensDetails"
26539
+ ]) {
26540
+ const details = usage[detailsField];
26541
+ if (details !== void 0) {
26542
+ aggregated[detailsField] = [
26543
+ ...aggregated[detailsField] ?? [],
26544
+ ...details
26545
+ ];
26546
+ }
26547
+ }
24285
26548
  }
24286
26549
  return hasUsage ? aggregated : void 0;
24287
26550
  }
24288
26551
  function populateUsageMetrics2(metrics, usage) {
24289
- if (usage.promptTokenCount !== void 0) {
24290
- metrics.prompt_tokens = usage.promptTokenCount;
26552
+ if (usage.promptTokenCount !== void 0 || usage.toolUsePromptTokenCount !== void 0) {
26553
+ metrics.prompt_tokens = (usage.promptTokenCount ?? 0) + (usage.toolUsePromptTokenCount ?? 0);
24291
26554
  }
24292
- if (usage.candidatesTokenCount !== void 0) {
24293
- metrics.completion_tokens = usage.candidatesTokenCount;
26555
+ if (usage.candidatesTokenCount !== void 0 || usage.thoughtsTokenCount !== void 0) {
26556
+ metrics.completion_tokens = (usage.candidatesTokenCount ?? 0) + (usage.thoughtsTokenCount ?? 0);
24294
26557
  }
24295
26558
  if (usage.totalTokenCount !== void 0) {
24296
26559
  metrics.tokens = usage.totalTokenCount;
@@ -24301,6 +26564,19 @@ function populateUsageMetrics2(metrics, usage) {
24301
26564
  if (usage.thoughtsTokenCount !== void 0) {
24302
26565
  metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
24303
26566
  }
26567
+ for (const detail of usage.promptTokensDetails ?? []) {
26568
+ if (detail.modality === "AUDIO" && detail.tokenCount !== void 0) {
26569
+ metrics.prompt_audio_tokens = (metrics.prompt_audio_tokens ?? 0) + detail.tokenCount;
26570
+ }
26571
+ }
26572
+ for (const detail of usage.candidatesTokensDetails ?? []) {
26573
+ if (detail.modality === "AUDIO" && detail.tokenCount !== void 0) {
26574
+ metrics.completion_audio_tokens = (metrics.completion_audio_tokens ?? 0) + detail.tokenCount;
26575
+ }
26576
+ if (detail.modality === "IMAGE" && detail.tokenCount !== void 0) {
26577
+ metrics.completion_image_tokens = (metrics.completion_image_tokens ?? 0) + detail.tokenCount;
26578
+ }
26579
+ }
24304
26580
  }
24305
26581
  function cleanMetrics4(metrics) {
24306
26582
  const cleaned = {};
@@ -27369,7 +29645,7 @@ var FlueObserveBridge = class {
27369
29645
  return;
27370
29646
  }
27371
29647
  const state = this.operationsById.get(event.operationId) ?? this.startSyntheticOperation(event);
27372
- const output = operationOutput(event);
29648
+ const output = operationOutput(event) ?? outputFromAgentTurn(state.latestAgentOutput);
27373
29649
  const metadata = {
27374
29650
  ...state.metadata,
27375
29651
  ...extractEventMetadata(event),
@@ -27378,7 +29654,7 @@ var FlueObserveBridge = class {
27378
29654
  };
27379
29655
  this.finishPendingChildrenForOperation(event, output);
27380
29656
  safeLog3(state.span, {
27381
- ...event.isError ? { error: toLoggedError(event.error) } : {},
29657
+ ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.error) } : {},
27382
29658
  metadata,
27383
29659
  metrics: durationMetrics2(event.durationMs),
27384
29660
  output
@@ -27409,7 +29685,7 @@ var FlueObserveBridge = class {
27409
29685
  };
27410
29686
  const parent = this.parentSpanForTurn(event);
27411
29687
  const span = startFlueSpan(parent, {
27412
- name: `llm:${model ?? event.purpose ?? "unknown"}`,
29688
+ name: "flue.turn",
27413
29689
  spanAttributes: { type: "llm" /* LLM */ },
27414
29690
  startTime: eventTime(event.timestamp),
27415
29691
  event: {
@@ -27453,6 +29729,12 @@ var FlueObserveBridge = class {
27453
29729
  },
27454
29730
  output
27455
29731
  });
29732
+ if (event.purpose === "agent" && event.operationId) {
29733
+ const operation = this.operationsById.get(event.operationId);
29734
+ if (operation) {
29735
+ operation.latestAgentOutput = output;
29736
+ }
29737
+ }
27456
29738
  safeEnd(state.span, eventTime(event.timestamp));
27457
29739
  this.turnsByKey.delete(key);
27458
29740
  }
@@ -27532,7 +29814,7 @@ var FlueObserveBridge = class {
27532
29814
  return;
27533
29815
  }
27534
29816
  safeLog3(state.span, {
27535
- ...event.isError ? { error: toLoggedError(event.result) } : {},
29817
+ ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.result) } : {},
27536
29818
  metadata: {
27537
29819
  ...state.metadata,
27538
29820
  ...extractEventMetadata(event),
@@ -27578,6 +29860,7 @@ var FlueObserveBridge = class {
27578
29860
  ...event.usage ? { "flue.usage": event.usage } : {}
27579
29861
  };
27580
29862
  safeLog3(state.span, {
29863
+ ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.error) } : {},
27581
29864
  metadata,
27582
29865
  metrics: {
27583
29866
  ...durationMetrics2(event.durationMs),
@@ -27682,7 +29965,7 @@ var FlueObserveBridge = class {
27682
29965
  ...event.purpose ? { "flue.turn_purpose": event.purpose } : {}
27683
29966
  };
27684
29967
  const span = startFlueSpan(this.parentSpanForEvent(event), {
27685
- name: `llm:${model ?? event.purpose ?? "unknown"}`,
29968
+ name: "flue.turn",
27686
29969
  spanAttributes: { type: "llm" /* LLM */ },
27687
29970
  startTime: eventTime(event.timestamp),
27688
29971
  event: { metadata }
@@ -27814,7 +30097,10 @@ function extractEventMetadata(event, ctx) {
27814
30097
  return {
27815
30098
  ...event.runId ? { "flue.run_id": event.runId } : {},
27816
30099
  ...event.instanceId ? { "flue.instance_id": event.instanceId } : {},
30100
+ ...event.submissionId ? { "flue.submission_id": event.submissionId } : {},
27817
30101
  ...event.dispatchId ? { "flue.dispatch_id": event.dispatchId } : {},
30102
+ ...event.agentName ? { "flue.agent_name": event.agentName } : {},
30103
+ ...event.conversationId ? { "flue.conversation_id": event.conversationId } : {},
27818
30104
  ...typeof event.eventIndex === "number" ? { "flue.event_index": event.eventIndex } : {},
27819
30105
  ...event.session ? { "flue.session": event.session } : {},
27820
30106
  ...event.parentSession ? { "flue.parent_session": event.parentSession } : {},
@@ -27843,7 +30129,7 @@ function flueTurnRequestInput(event) {
27843
30129
  return event.request?.input ?? event.input;
27844
30130
  }
27845
30131
  function flueTurnRequestModel(event) {
27846
- return event.request?.model ?? event.model;
30132
+ return event.request?.requestedModel ?? event.request?.model ?? event.model;
27847
30133
  }
27848
30134
  function flueTurnRequestProvider(event) {
27849
30135
  return event.request?.providerName ?? event.provider ?? event.request?.providerId;
@@ -27852,10 +30138,10 @@ function flueTurnRequestApi(event) {
27852
30138
  return event.request?.api ?? event.api;
27853
30139
  }
27854
30140
  function flueTurnRequestReasoning(event) {
27855
- return event.request?.reasoning ?? event.reasoning;
30141
+ return event.request?.reasoningLevel ?? event.request?.reasoning ?? event.reasoning;
27856
30142
  }
27857
30143
  function flueTurnModel(event) {
27858
- return event.request?.model ?? event.model;
30144
+ return event.response?.responseModel ?? event.request?.requestedModel ?? event.request?.model ?? event.model;
27859
30145
  }
27860
30146
  function flueTurnProvider(event) {
27861
30147
  return event.request?.providerName ?? event.provider ?? event.request?.providerId;
@@ -27870,7 +30156,7 @@ function flueTurnOutput(event) {
27870
30156
  return event.response?.output ?? event.output;
27871
30157
  }
27872
30158
  function flueTurnStopReason(event) {
27873
- return event.response?.stopReason ?? event.stopReason;
30159
+ return event.response?.finishReason ?? event.response?.stopReason ?? event.stopReason;
27874
30160
  }
27875
30161
  function flueTurnError(event) {
27876
30162
  return event.response?.error ?? event.response?.errorInfo?.message ?? event.error;
@@ -27885,6 +30171,9 @@ function flueToolInput(event) {
27885
30171
  return event.input;
27886
30172
  }
27887
30173
  function flueToolOutput(event) {
30174
+ if (Object.hasOwn(event, "effectiveResult")) {
30175
+ return event.effectiveResult;
30176
+ }
27888
30177
  return event.output !== void 0 ? event.output : event.result;
27889
30178
  }
27890
30179
  function flueToolError(event) {
@@ -27892,10 +30181,36 @@ function flueToolError(event) {
27892
30181
  }
27893
30182
  function operationOutput(event) {
27894
30183
  if (event.operationKind === "prompt" || event.operationKind === "skill") {
27895
- return llmResultFromOperationResult(event.result);
30184
+ return outputFromAgentInvocation(event.agentOutput) ?? llmResultFromOperationResult(event.result);
27896
30185
  }
27897
30186
  return event.result ?? (event.operationKind === "compact" ? { completed: true } : void 0);
27898
30187
  }
30188
+ function outputFromAgentInvocation(output) {
30189
+ if (output?.type === "text") {
30190
+ return output.text;
30191
+ }
30192
+ if (output?.type === "data") {
30193
+ return output.data;
30194
+ }
30195
+ return void 0;
30196
+ }
30197
+ function outputFromAgentTurn(output) {
30198
+ if (!isObjectLike(output)) {
30199
+ return output;
30200
+ }
30201
+ const content = Reflect.get(output, "content");
30202
+ if (!Array.isArray(content)) {
30203
+ return output;
30204
+ }
30205
+ const text = content.flatMap((part) => {
30206
+ if (!isObjectLike(part) || Reflect.get(part, "type") !== "text") {
30207
+ return [];
30208
+ }
30209
+ const value = Reflect.get(part, "text");
30210
+ return typeof value === "string" ? [value] : [];
30211
+ });
30212
+ return text.length > 0 ? text.join("") : output;
30213
+ }
27899
30214
  function llmResultFromOperationResult(result) {
27900
30215
  if (!isObjectLike(result)) {
27901
30216
  return result;
@@ -27994,7 +30309,7 @@ function safeEnd(span, endTime) {
27994
30309
  }
27995
30310
  }
27996
30311
  function logInstrumentationError3(label, error) {
27997
- console.error(`Error in ${label} instrumentation:`, error);
30312
+ debugLogger.debug(`Error in ${label} instrumentation:`, error);
27998
30313
  }
27999
30314
 
28000
30315
  // src/wrappers/langchain/callback-handler.ts
@@ -28666,7 +30981,7 @@ var LangSmithPlugin = class extends BasePlugin {
28666
30981
  const inputs = preferOwnValue(run, previous, "inputs");
28667
30982
  const outputs = preferOwnValue(run, previous, "outputs");
28668
30983
  const error = errorMessage(preferOwnValue(run, previous, "error"));
28669
- const metadata = extractMetadata(run, previous);
30984
+ const metadata = extractMetadata2(run, previous);
28670
30985
  const tags = extractTags(preferOwnValue(run, previous, "tags"));
28671
30986
  const metrics = extractMetrics(run, previous);
28672
30987
  span.log({
@@ -28771,7 +31086,7 @@ function mapRunType(runType) {
28771
31086
  return "task" /* TASK */;
28772
31087
  }
28773
31088
  }
28774
- function extractMetadata(run, previous) {
31089
+ function extractMetadata2(run, previous) {
28775
31090
  const extra = preferOwnValue(run, previous, "extra");
28776
31091
  const rawMetadata = ownValue(extra, "metadata");
28777
31092
  if (!isRecord2(rawMetadata)) {
@@ -28923,12 +31238,13 @@ var piCodingAgentChannels = defineChannels(
28923
31238
  );
28924
31239
 
28925
31240
  // src/instrumentation/plugins/pi-coding-agent-plugin.ts
28926
- var piStreamPatchStates = /* @__PURE__ */ new WeakMap();
31241
+ var piAgentPatchStates = /* @__PURE__ */ new WeakMap();
31242
+ var piAgentEventSubscriptions = /* @__PURE__ */ new WeakSet();
28927
31243
  var piPromptContextStore;
28928
31244
  var PiCodingAgentPlugin = class extends BasePlugin {
28929
31245
  activePromptStates = /* @__PURE__ */ new Set();
28930
31246
  onEnable() {
28931
- this.subscribeToPrompt();
31247
+ this.interceptPrompt();
28932
31248
  }
28933
31249
  onDisable() {
28934
31250
  for (const unsubscribe of this.unsubscribers) {
@@ -28936,65 +31252,74 @@ var PiCodingAgentPlugin = class extends BasePlugin {
28936
31252
  }
28937
31253
  this.unsubscribers = [];
28938
31254
  for (const state of [...this.activePromptStates]) {
28939
- void finalizePiPromptRun(state).catch((error) => {
28940
- logInstrumentationError4("Pi Coding Agent disable cleanup", error);
28941
- });
31255
+ finishPiPromptRun(state);
28942
31256
  }
28943
31257
  }
28944
- subscribeToPrompt() {
28945
- const channel2 = piCodingAgentChannels.prompt.tracingChannel();
28946
- const states = /* @__PURE__ */ new WeakMap();
28947
- const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(channel2);
28948
- const handlers = {
28949
- start: (event) => {
28950
- const state = startPiPromptRun(event, (state2) => {
28951
- this.activePromptStates.delete(state2);
28952
- });
28953
- if (state) {
28954
- this.activePromptStates.add(state);
28955
- states.set(event, state);
28956
- }
28957
- },
28958
- asyncEnd: async (event) => {
28959
- const state = states.get(event);
28960
- if (!state) {
28961
- return;
28962
- }
28963
- states.delete(event);
28964
- state.promptCallEnded = true;
28965
- if (!state.finalized && state.deferCompletionUntilTurnEnd && !state.turnEnded) {
28966
- if (!state.sawStreamFn) {
28967
- state.queued = true;
28968
- if (!state.streamPatchState.queuedPromptStates.includes(state)) {
28969
- state.streamPatchState.queuedPromptStates.push(state);
28970
- }
31258
+ interceptPrompt() {
31259
+ this.unsubscribers.push(
31260
+ piCodingAgentChannels.prompt.intercept(
31261
+ (target, thisArg, args, additional) => {
31262
+ const invokeTarget = () => Reflect.apply(target, thisArg, args);
31263
+ let state;
31264
+ try {
31265
+ state = startPiPromptRun(
31266
+ {
31267
+ ...additional,
31268
+ arguments: args,
31269
+ self: thisArg
31270
+ },
31271
+ (finalizedState) => {
31272
+ this.activePromptStates.delete(finalizedState);
31273
+ }
31274
+ );
31275
+ } catch (error) {
31276
+ logInstrumentationError4("Pi Coding Agent prompt start", error);
28971
31277
  }
28972
- return;
28973
- }
28974
- await finalizePiPromptRun(state);
28975
- },
28976
- error: async (event) => {
28977
- const state = states.get(event);
28978
- if (!state) {
28979
- return;
31278
+ if (!state) {
31279
+ return runWithAutoInstrumentationSuppressed(invokeTarget);
31280
+ }
31281
+ this.activePromptStates.add(state);
31282
+ return promptContextStore().run(
31283
+ state,
31284
+ () => runWithAutoInstrumentationSuppressed(() => {
31285
+ let result;
31286
+ try {
31287
+ result = invokeTarget();
31288
+ } catch (error) {
31289
+ finishPiPromptRun(state, error);
31290
+ throw error;
31291
+ }
31292
+ return Promise.resolve(result).then(
31293
+ (value) => {
31294
+ finishPiPromptCall(state);
31295
+ return value;
31296
+ },
31297
+ (error) => {
31298
+ finishPiPromptRun(state, error);
31299
+ throw error;
31300
+ }
31301
+ );
31302
+ })
31303
+ );
28980
31304
  }
28981
- states.delete(event);
28982
- await finalizePiPromptRun(state, event.error);
28983
- }
28984
- };
28985
- channel2.subscribe(handlers);
28986
- this.unsubscribers.push(() => {
28987
- unbindAutoInstrumentationSuppression?.();
28988
- channel2.unsubscribe(handlers);
28989
- });
31305
+ )
31306
+ );
28990
31307
  }
28991
31308
  };
31309
+ function finishPiPromptCall(state) {
31310
+ state.promptCallEnded = true;
31311
+ if (state.deferCompletionUntilTurnEnd && !state.turnEnded) {
31312
+ return;
31313
+ }
31314
+ finishPiPromptRun(state);
31315
+ }
28992
31316
  function startPiPromptRun(event, onFinalize) {
28993
31317
  const session = extractSession(event);
28994
31318
  const agent = session?.agent;
28995
31319
  if (!session || !isPiAgent(agent)) {
28996
31320
  return void 0;
28997
31321
  }
31322
+ installPiAgentInstrumentation(agent);
28998
31323
  const metadata = {
28999
31324
  ...extractSessionMetadata(session),
29000
31325
  ...extractPromptOptionsMetadata(event.arguments[1]),
@@ -29016,9 +31341,7 @@ function startPiPromptRun(event, onFinalize) {
29016
31341
  INSTRUMENTATION_NAMES.PI_CODING_AGENT
29017
31342
  )
29018
31343
  );
29019
- const streamPatchState = installPiStreamPatch(agent);
29020
31344
  const options = event.arguments[1];
29021
- const promptText = event.arguments[0];
29022
31345
  const state = {
29023
31346
  activeLlmSpans: /* @__PURE__ */ new Set(),
29024
31347
  activeToolSpans: /* @__PURE__ */ new Map(),
@@ -29030,29 +31353,10 @@ function startPiPromptRun(event, onFinalize) {
29030
31353
  metrics: {},
29031
31354
  onFinalize,
29032
31355
  promptCallEnded: false,
29033
- ...typeof promptText === "string" ? { promptText } : {},
29034
- queued: false,
29035
31356
  span,
29036
- sawStreamFn: false,
29037
31357
  startTime: getCurrentUnixTimestamp(),
29038
- streamPatchState,
29039
31358
  turnEnded: false
29040
31359
  };
29041
- state.restorePromptContext = enterPiPromptContext(state);
29042
- streamPatchState.activePromptStates.add(state);
29043
- try {
29044
- state.unsubscribeAgent = agent.subscribe(async (agentEvent) => {
29045
- try {
29046
- await runWithAutoInstrumentationSuppressed(
29047
- () => handlePiAgentEvent(state, agentEvent)
29048
- );
29049
- } catch (error) {
29050
- logInstrumentationError4("Pi Coding Agent event", error);
29051
- }
29052
- });
29053
- } catch (error) {
29054
- logInstrumentationError4("Pi Coding Agent event subscription", error);
29055
- }
29056
31360
  return state;
29057
31361
  }
29058
31362
  function extractSession(event) {
@@ -29066,111 +31370,55 @@ function promptContextStore() {
29066
31370
  piPromptContextStore ??= isomorph_default.newAsyncLocalStorage();
29067
31371
  return piPromptContextStore;
29068
31372
  }
29069
- function currentPromptContextFrames() {
29070
- return promptContextStore().getStore()?.frames ?? [];
29071
- }
29072
31373
  function currentPiPromptState() {
29073
- const frames = currentPromptContextFrames();
29074
- return frames[frames.length - 1]?.state;
29075
- }
29076
- function enterPiPromptContext(state) {
29077
- const frame = {
29078
- id: /* @__PURE__ */ Symbol("braintrust.pi-coding-agent.prompt"),
29079
- state
29080
- };
29081
- promptContextStore().enterWith({
29082
- frames: [...currentPromptContextFrames(), frame]
29083
- });
29084
- return () => {
29085
- const frames = currentPromptContextFrames().filter(
29086
- (candidate) => candidate.id !== frame.id
29087
- );
29088
- promptContextStore().enterWith(frames.length > 0 ? { frames } : void 0);
29089
- };
29090
- }
29091
- function installPiStreamPatch(agent) {
29092
- const existing = piStreamPatchStates.get(agent);
29093
- if (existing) {
29094
- if (agent.streamFn !== existing.wrappedStreamFn) {
29095
- debugLogger.debug(
29096
- "Pi Coding Agent streamFn changed while Braintrust instrumentation was active; preserving existing patch state."
29097
- );
29098
- }
29099
- return existing;
29100
- }
29101
- const patchState = {
29102
- activePromptStates: /* @__PURE__ */ new Set(),
29103
- agent,
29104
- originalStreamFn: agent.streamFn,
29105
- queuedPromptStates: [],
29106
- wrappedStreamFn: agent.streamFn
29107
- };
29108
- patchState.wrappedStreamFn = makeSharedInstrumentedStreamFn(patchState);
29109
- agent.streamFn = patchState.wrappedStreamFn;
29110
- piStreamPatchStates.set(agent, patchState);
29111
- return patchState;
29112
- }
29113
- function resolveStreamPromptState(patchState, context) {
29114
- let lastUserText;
29115
- if (Array.isArray(context.messages)) {
29116
- for (let i = context.messages.length - 1; i >= 0; i--) {
29117
- const message = context.messages[i];
29118
- if (isPiUserMessage(message)) {
29119
- if (typeof message.content === "string") {
29120
- lastUserText = message.content;
29121
- } else {
29122
- lastUserText = message.content.flatMap((part) => part.type === "text" ? [part.text] : []).join("");
29123
- }
29124
- break;
29125
- }
29126
- }
29127
- }
29128
- if (lastUserText !== void 0) {
29129
- const queuedMatch = patchState.queuedPromptStates.find(
29130
- (state) => state.promptText === lastUserText
29131
- );
29132
- if (queuedMatch) {
29133
- return queuedMatch;
29134
- }
29135
- const matches = [...patchState.activePromptStates].filter(
29136
- (state) => state.promptText === lastUserText
31374
+ return promptContextStore().getStore();
31375
+ }
31376
+ function installPiAgentInstrumentation(agent) {
31377
+ const existing = piAgentPatchStates.get(agent);
31378
+ if (!existing || agent.streamFn !== existing.wrappedStreamFn) {
31379
+ const patchState = {
31380
+ originalStreamFn: agent.streamFn,
31381
+ wrappedStreamFn: agent.streamFn
31382
+ };
31383
+ patchState.wrappedStreamFn = makeInstrumentedStreamFn(
31384
+ agent,
31385
+ patchState.originalStreamFn
29137
31386
  );
29138
- if (matches.length === 1) {
29139
- return matches[0];
29140
- }
31387
+ agent.streamFn = patchState.wrappedStreamFn;
31388
+ piAgentPatchStates.set(agent, patchState);
29141
31389
  }
29142
- const contextState = currentPiPromptState();
29143
- if (contextState && patchState.activePromptStates.has(contextState) && (!contextState.queued || lastUserText !== void 0 && contextState.promptText === lastUserText)) {
29144
- return contextState;
31390
+ if (piAgentEventSubscriptions.has(agent)) {
31391
+ return;
29145
31392
  }
29146
- if (patchState.activePromptStates.size === 1) {
29147
- return [...patchState.activePromptStates][0];
31393
+ try {
31394
+ agent.subscribe(async (event) => {
31395
+ const state = currentPiPromptState();
31396
+ if (!state || state.agent !== agent || state.finalized) {
31397
+ return;
31398
+ }
31399
+ try {
31400
+ await runWithAutoInstrumentationSuppressed(
31401
+ () => handlePiAgentEvent(state, event)
31402
+ );
31403
+ } catch (error) {
31404
+ logInstrumentationError4("Pi Coding Agent event", error);
31405
+ }
31406
+ });
31407
+ piAgentEventSubscriptions.add(agent);
31408
+ } catch (error) {
31409
+ logInstrumentationError4("Pi Coding Agent event subscription", error);
29148
31410
  }
29149
- return void 0;
29150
31411
  }
29151
- function makeSharedInstrumentedStreamFn(patchState) {
31412
+ function makeInstrumentedStreamFn(agent, originalStreamFn) {
29152
31413
  return async function instrumentedPiStreamFn(model, context, options) {
29153
- const state = resolveStreamPromptState(patchState, context);
29154
- if (!state) {
29155
- const invokeOriginal = () => Reflect.apply(patchState.originalStreamFn, this, [
29156
- model,
29157
- context,
29158
- options
29159
- ]);
29160
- return patchState.activePromptStates.size > 0 ? runWithAutoInstrumentationSuppressed(invokeOriginal) : invokeOriginal();
31414
+ const invokeOriginal = () => Reflect.apply(originalStreamFn, this, [model, context, options]);
31415
+ const state = currentPiPromptState();
31416
+ if (!state || state.agent !== agent || state.finalized) {
31417
+ return invokeOriginal();
29161
31418
  }
29162
- state.sawStreamFn = true;
29163
- removeQueuedPromptState(state);
29164
- state.streamPatchState.eventPromptState = state;
29165
31419
  const llmState = await startPiLlmSpan(state, model, context, options);
29166
31420
  try {
29167
- const stream = await runWithAutoInstrumentationSuppressed(
29168
- () => Reflect.apply(patchState.originalStreamFn, this, [
29169
- model,
29170
- context,
29171
- options
29172
- ])
29173
- );
31421
+ const stream = await runWithAutoInstrumentationSuppressed(invokeOriginal);
29174
31422
  return patchAssistantMessageStream(stream, state, llmState);
29175
31423
  } catch (error) {
29176
31424
  finishPiLlmSpan(state, llmState, void 0, error);
@@ -29317,13 +31565,6 @@ async function handlePiAgentEvent(state, event) {
29317
31565
  if (state.finalized) {
29318
31566
  return;
29319
31567
  }
29320
- const eventPromptState = state.streamPatchState.eventPromptState;
29321
- if (eventPromptState && eventPromptState !== state) {
29322
- return;
29323
- }
29324
- if (!eventPromptState && (state.queued || state.streamPatchState.activePromptStates.size > 1 && currentPiPromptState() !== state)) {
29325
- return;
29326
- }
29327
31568
  switch (event.type) {
29328
31569
  case "message_end":
29329
31570
  if (isPiAssistantMessage(event.message)) {
@@ -29338,11 +31579,8 @@ async function handlePiAgentEvent(state, event) {
29338
31579
  addMetrics(state.metrics, extractUsageMetrics2(event.message.usage));
29339
31580
  }
29340
31581
  }
29341
- if (state.streamPatchState.eventPromptState === state) {
29342
- state.streamPatchState.eventPromptState = void 0;
29343
- }
29344
31582
  if (state.promptCallEnded && state.deferCompletionUntilTurnEnd) {
29345
- await finalizePiPromptRun(state);
31583
+ finishPiPromptRun(state);
29346
31584
  }
29347
31585
  return;
29348
31586
  case "tool_execution_start":
@@ -29415,19 +31653,13 @@ function finishPiToolSpan(state, event) {
29415
31653
  }
29416
31654
  }
29417
31655
  }
29418
- async function finalizePiPromptRun(state, error) {
31656
+ function finishPiPromptRun(state, error) {
29419
31657
  if (state.finalized) {
29420
31658
  return;
29421
31659
  }
29422
31660
  state.finalized = true;
29423
31661
  state.onFinalize?.(state);
29424
- restorePiStreamFn(state);
29425
- try {
29426
- state.unsubscribeAgent?.();
29427
- } catch (unsubscribeError) {
29428
- logInstrumentationError4("Pi Coding Agent unsubscribe", unsubscribeError);
29429
- }
29430
- await finishOpenLlmSpans(state, error);
31662
+ finishOpenLlmSpans(state, error);
29431
31663
  finishOpenToolSpans(state, error);
29432
31664
  const metadata = {
29433
31665
  ...state.metadata,
@@ -29444,34 +31676,14 @@ async function finalizePiPromptRun(state, error) {
29444
31676
  output: state.output
29445
31677
  });
29446
31678
  } finally {
29447
- state.span.end();
29448
- }
29449
- }
29450
- function restorePiStreamFn(state) {
29451
- const patchState = state.streamPatchState;
29452
- patchState.activePromptStates.delete(state);
29453
- removeQueuedPromptState(state);
29454
- if (patchState.eventPromptState === state) {
29455
- patchState.eventPromptState = void 0;
29456
- }
29457
- state.restorePromptContext?.();
29458
- if (patchState.activePromptStates.size > 0) {
29459
- return;
29460
- }
29461
- if (patchState.agent.streamFn === patchState.wrappedStreamFn) {
29462
- patchState.agent.streamFn = patchState.originalStreamFn;
29463
- }
29464
- piStreamPatchStates.delete(patchState.agent);
29465
- }
29466
- function removeQueuedPromptState(state) {
29467
- state.queued = false;
29468
- const queuedPromptStates = state.streamPatchState.queuedPromptStates;
29469
- const index = queuedPromptStates.indexOf(state);
29470
- if (index >= 0) {
29471
- queuedPromptStates.splice(index, 1);
31679
+ try {
31680
+ state.span.end();
31681
+ } catch (endError) {
31682
+ logInstrumentationError4("Pi Coding Agent prompt end", endError);
31683
+ }
29472
31684
  }
29473
31685
  }
29474
- async function finishOpenLlmSpans(state, error) {
31686
+ function finishOpenLlmSpans(state, error) {
29475
31687
  for (const llmState of [...state.activeLlmSpans]) {
29476
31688
  finishPiLlmSpan(state, llmState, void 0, error);
29477
31689
  }
@@ -29552,7 +31764,7 @@ function normalizeAssistantMessage(message) {
29552
31764
  (part) => part.type === "thinking" && !part.redacted ? [part.thinking] : []
29553
31765
  ).join("");
29554
31766
  const toolCalls = message.content.flatMap(
29555
- (part) => part.type === "toolCall" ? [normalizeToolCall(part)] : []
31767
+ (part) => part.type === "toolCall" ? [normalizeToolCall2(part)] : []
29556
31768
  );
29557
31769
  return {
29558
31770
  role: "assistant",
@@ -29587,13 +31799,13 @@ function normalizeUserContent(content) {
29587
31799
  return part;
29588
31800
  });
29589
31801
  }
29590
- function normalizeToolCall(toolCall) {
31802
+ function normalizeToolCall2(toolCall) {
29591
31803
  return {
29592
31804
  id: toolCall.id,
29593
31805
  type: "function",
29594
31806
  function: {
29595
31807
  name: toolCall.name,
29596
- arguments: stringifyArguments(toolCall.arguments)
31808
+ arguments: stringifyArguments2(toolCall.arguments)
29597
31809
  }
29598
31810
  };
29599
31811
  }
@@ -29776,7 +31988,7 @@ function cleanMetrics5(metrics) {
29776
31988
  }
29777
31989
  return cleaned;
29778
31990
  }
29779
- function stringifyArguments(value) {
31991
+ function stringifyArguments2(value) {
29780
31992
  if (typeof value === "string") {
29781
31993
  return value;
29782
31994
  }
@@ -30144,6 +32356,15 @@ function handleMultiAgentStreamEvent(state, event, activeChildParents) {
30144
32356
  logInstrumentationError5("Strands Agent SDK multi-agent event", error);
30145
32357
  }
30146
32358
  }
32359
+ function buildModelSpanInput(event, attachmentCache) {
32360
+ const systemPrompt = typeof event.agent?.systemPrompt === "string" && event.agent.systemPrompt.length > 0 ? event.agent.systemPrompt : void 0;
32361
+ const processedMessages = Array.isArray(event.agent?.messages) ? processStrandsInputAttachments(event.agent.messages, attachmentCache) : void 0;
32362
+ if (!systemPrompt) {
32363
+ return processedMessages;
32364
+ }
32365
+ const systemMessage = { role: "system", content: systemPrompt };
32366
+ return Array.isArray(processedMessages) ? [systemMessage, ...processedMessages] : [systemMessage];
32367
+ }
30147
32368
  function startModelSpan(state, event) {
30148
32369
  if (state.activeModel) {
30149
32370
  finalizeModelSpan(state);
@@ -30161,10 +32382,7 @@ function startModelSpan(state, event) {
30161
32382
  withSpanInstrumentationName(
30162
32383
  {
30163
32384
  event: {
30164
- input: Array.isArray(event.agent?.messages) ? processStrandsInputAttachments(
30165
- event.agent.messages,
30166
- state.attachmentCache
30167
- ) : void 0,
32385
+ input: buildModelSpanInput(event, state.attachmentCache),
30168
32386
  metadata
30169
32387
  },
30170
32388
  name: formatModelSpanName(model),
@@ -30804,6 +33022,532 @@ function logInstrumentationError5(context, error) {
30804
33022
  debugLogger.debug(`${context}:`, error);
30805
33023
  }
30806
33024
 
33025
+ // src/instrumentation/plugins/cloudflare-ai-chat-channels.ts
33026
+ var cloudflareAIChatChannels = defineChannels(
33027
+ "@cloudflare/ai-chat",
33028
+ {
33029
+ runExclusiveChatTurn: channel({
33030
+ channelName: "AIChatAgent._runExclusiveChatTurn",
33031
+ kind: "async"
33032
+ }),
33033
+ onChatResponse: channel({
33034
+ channelName: "AIChatAgent.onChatResponse",
33035
+ kind: "sync-stream"
33036
+ })
33037
+ },
33038
+ { instrumentationName: INSTRUMENTATION_NAMES.CLOUDFLARE_AI_CHAT }
33039
+ );
33040
+
33041
+ // src/instrumentation/plugins/cloudflare-ai-chat-instrumentation.ts
33042
+ var wrappedResponseHooks = /* @__PURE__ */ new WeakSet();
33043
+ function instrumentCloudflareAIChatResponseHook(agent) {
33044
+ try {
33045
+ const original = Reflect.get(agent, "onChatResponse");
33046
+ if (typeof original !== "function" || wrappedResponseHooks.has(original)) {
33047
+ return;
33048
+ }
33049
+ const wrapped = function(result) {
33050
+ const args = [result];
33051
+ return cloudflareAIChatChannels.onChatResponse.traceSync(
33052
+ () => Reflect.apply(original, this, args),
33053
+ {
33054
+ arguments: args,
33055
+ self: this
33056
+ }
33057
+ );
33058
+ };
33059
+ wrappedResponseHooks.add(wrapped);
33060
+ defineWrappedMethod(agent, "onChatResponse", original, wrapped);
33061
+ } catch (error) {
33062
+ debugLogger.debug(
33063
+ "Failed to wrap @cloudflare/ai-chat response hook:",
33064
+ error
33065
+ );
33066
+ }
33067
+ }
33068
+ function defineWrappedMethod(target, property, original, wrapped) {
33069
+ const ownDescriptor = Object.getOwnPropertyDescriptor(target, property);
33070
+ Object.defineProperty(target, property, {
33071
+ configurable: ownDescriptor?.configurable ?? true,
33072
+ enumerable: ownDescriptor?.enumerable ?? false,
33073
+ value: wrapped,
33074
+ writable: ownDescriptor && "writable" in ownDescriptor ? ownDescriptor.writable : true
33075
+ });
33076
+ try {
33077
+ Object.defineProperty(wrapped, "name", {
33078
+ configurable: true,
33079
+ value: original.name
33080
+ });
33081
+ } catch {
33082
+ }
33083
+ }
33084
+
33085
+ // src/instrumentation/plugins/cloudflare-ai-chat-plugin.ts
33086
+ var BLOCKED_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
33087
+ var RESPONSE_STATE_RETENTION_MS = 6e4;
33088
+ var CloudflareAIChatPlugin = class extends BasePlugin {
33089
+ activeStates = /* @__PURE__ */ new Set();
33090
+ activeTurns = /* @__PURE__ */ new WeakMap();
33091
+ eventStates = /* @__PURE__ */ new WeakMap();
33092
+ onEnable() {
33093
+ this.subscribeToResponseHook();
33094
+ this.subscribeToTurnRunner();
33095
+ }
33096
+ onDisable() {
33097
+ for (const unsubscribe of this.unsubscribers) {
33098
+ unsubscribe();
33099
+ }
33100
+ this.unsubscribers = [];
33101
+ for (const state of this.activeStates) {
33102
+ this.cleanupState(state);
33103
+ }
33104
+ this.activeStates.clear();
33105
+ }
33106
+ subscribeToTurnRunner() {
33107
+ const tracingChannel = cloudflareAIChatChannels.runExclusiveChatTurn.tracingChannel();
33108
+ const unbindCurrentSpanStore = this.bindCurrentSpanStore(tracingChannel);
33109
+ const handlers = {
33110
+ start: (event) => {
33111
+ this.ensureEventState(event);
33112
+ },
33113
+ asyncEnd: (event) => {
33114
+ this.finishEvent(event);
33115
+ },
33116
+ error: (event) => {
33117
+ this.finishEvent(event, event.error);
33118
+ }
33119
+ };
33120
+ tracingChannel.subscribe(handlers);
33121
+ this.unsubscribers.push(() => {
33122
+ unbindCurrentSpanStore?.();
33123
+ tracingChannel.unsubscribe(handlers);
33124
+ });
33125
+ }
33126
+ subscribeToResponseHook() {
33127
+ const tracingChannel = cloudflareAIChatChannels.onChatResponse.tracingChannel();
33128
+ const handlers = {
33129
+ start: (event) => {
33130
+ let state;
33131
+ try {
33132
+ const agent = asObject(event.self);
33133
+ const result = event.arguments[0];
33134
+ state = agent ? this.findResponseState(
33135
+ agent,
33136
+ stringValue3(ownValue2(result, "requestId"))
33137
+ ) : void 0;
33138
+ if (!state) {
33139
+ return;
33140
+ }
33141
+ state.responseObserved = true;
33142
+ const output = serializeMessage(ownValue2(result, "message"));
33143
+ const status = stringValue3(ownValue2(result, "status"));
33144
+ const error = ownValue2(result, "error");
33145
+ const input = ownValue2(result, "continuation") === true ? state.input : serializeMessages(readProperty(agent, "messages"))?.filter(
33146
+ (message) => typeof output?.id !== "string" || message.id !== output.id
33147
+ );
33148
+ state.span.log({
33149
+ ...input !== void 0 ? { input } : {},
33150
+ ...output !== void 0 ? { output } : {},
33151
+ ...status === "error" && error !== void 0 ? { error } : {}
33152
+ });
33153
+ } catch (error) {
33154
+ debugLogger.debug(
33155
+ "Failed to process @cloudflare/ai-chat response hook:",
33156
+ error
33157
+ );
33158
+ } finally {
33159
+ if (state?.settled) {
33160
+ this.cleanupState(state);
33161
+ }
33162
+ }
33163
+ }
33164
+ };
33165
+ tracingChannel.subscribe(handlers);
33166
+ this.unsubscribers.push(() => tracingChannel.unsubscribe(handlers));
33167
+ }
33168
+ bindCurrentSpanStore(tracingChannel) {
33169
+ const globalState = _internalGetGlobalState();
33170
+ const contextManager = globalState?.contextManager;
33171
+ const startChannel = tracingChannel.start;
33172
+ const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
33173
+ if (!startChannel || !currentSpanStore || !contextManager) {
33174
+ return void 0;
33175
+ }
33176
+ startChannel.bindStore(currentSpanStore, (event) => {
33177
+ const state = this.ensureEventState(event);
33178
+ return state ? contextManager.wrapSpanForStore(state.span) : currentSpanStore.getStore();
33179
+ });
33180
+ return () => startChannel.unbindStore(currentSpanStore);
33181
+ }
33182
+ ensureEventState(event) {
33183
+ const eventKey = event;
33184
+ const known = this.eventStates.get(eventKey);
33185
+ if (known) {
33186
+ return known;
33187
+ }
33188
+ try {
33189
+ const agent = asObject(event.self);
33190
+ const requestId = stringValue3(event.arguments[0]);
33191
+ const key = requestId ?? /* @__PURE__ */ Symbol("cloudflare-ai-chat-turn");
33192
+ const activeForAgent = agent ? this.getActiveTurns(agent) : void 0;
33193
+ const existing = activeForAgent?.get(key);
33194
+ const state = existing && !existing.settled ? existing : this.createTurnState(agent, key);
33195
+ if (existing && !existing.settled) {
33196
+ state.depth += 1;
33197
+ }
33198
+ this.eventStates.set(eventKey, state);
33199
+ this.bindTurnCallback(event, agent, state);
33200
+ if (agent) {
33201
+ instrumentCloudflareAIChatResponseHook(agent);
33202
+ }
33203
+ return state;
33204
+ } catch (error) {
33205
+ debugLogger.debug(
33206
+ "Failed to start @cloudflare/ai-chat instrumentation:",
33207
+ error
33208
+ );
33209
+ return void 0;
33210
+ }
33211
+ }
33212
+ createTurnState(agent, key) {
33213
+ const span = startSpan(
33214
+ withSpanInstrumentationName(
33215
+ {
33216
+ name: "AIChatAgent.onChatMessage",
33217
+ spanAttributes: { type: "task" /* TASK */ }
33218
+ },
33219
+ INSTRUMENTATION_NAMES.CLOUDFLARE_AI_CHAT
33220
+ )
33221
+ );
33222
+ const state = {
33223
+ agent,
33224
+ depth: 1,
33225
+ ended: false,
33226
+ key,
33227
+ responseObserved: false,
33228
+ settled: false,
33229
+ span
33230
+ };
33231
+ this.activeStates.add(state);
33232
+ if (agent) {
33233
+ this.getActiveTurns(agent).set(key, state);
33234
+ }
33235
+ return state;
33236
+ }
33237
+ bindTurnCallback(event, agent, state) {
33238
+ const callback = event.arguments[1];
33239
+ if (typeof callback !== "function") {
33240
+ return;
33241
+ }
33242
+ try {
33243
+ event.arguments[1] = function(...args) {
33244
+ return withCurrent(state.span, () => {
33245
+ try {
33246
+ const input = serializeMessages(readProperty(agent, "messages"));
33247
+ if (input !== void 0 && state.input === void 0) {
33248
+ state.input = input;
33249
+ state.span.log({ input });
33250
+ }
33251
+ } catch (error) {
33252
+ debugLogger.debug(
33253
+ "Failed to capture @cloudflare/ai-chat messages:",
33254
+ error
33255
+ );
33256
+ }
33257
+ return Reflect.apply(callback, this, args);
33258
+ });
33259
+ };
33260
+ } catch (error) {
33261
+ debugLogger.debug(
33262
+ "Failed to bind @cloudflare/ai-chat turn callback context:",
33263
+ error
33264
+ );
33265
+ }
33266
+ }
33267
+ finishEvent(event, error) {
33268
+ const eventKey = event;
33269
+ const state = this.eventStates.get(eventKey);
33270
+ if (!state || state.ended) {
33271
+ return;
33272
+ }
33273
+ this.eventStates.delete(eventKey);
33274
+ if (error !== void 0 && state.pendingError === void 0) {
33275
+ state.pendingError = error;
33276
+ }
33277
+ state.depth -= 1;
33278
+ if (state.depth === 0) {
33279
+ state.settled = true;
33280
+ this.endState(state);
33281
+ if (state.responseObserved || error !== void 0) {
33282
+ this.cleanupState(state);
33283
+ } else {
33284
+ state.cleanupTimer = setTimeout(
33285
+ () => this.cleanupState(state),
33286
+ RESPONSE_STATE_RETENTION_MS
33287
+ );
33288
+ if (typeof state.cleanupTimer === "object" && state.cleanupTimer !== null && "unref" in state.cleanupTimer && typeof state.cleanupTimer.unref === "function") {
33289
+ state.cleanupTimer.unref();
33290
+ }
33291
+ }
33292
+ }
33293
+ }
33294
+ endState(state) {
33295
+ if (state.ended) {
33296
+ return;
33297
+ }
33298
+ state.ended = true;
33299
+ try {
33300
+ if (state.pendingError !== void 0) {
33301
+ state.span.log({ error: state.pendingError });
33302
+ }
33303
+ } finally {
33304
+ state.span.end();
33305
+ }
33306
+ }
33307
+ cleanupState(state) {
33308
+ if (state.cleanupTimer !== void 0) {
33309
+ clearTimeout(state.cleanupTimer);
33310
+ state.cleanupTimer = void 0;
33311
+ }
33312
+ try {
33313
+ this.endState(state);
33314
+ } finally {
33315
+ this.activeStates.delete(state);
33316
+ if (state.agent) {
33317
+ const activeForAgent = this.activeTurns.get(state.agent);
33318
+ if (activeForAgent?.get(state.key) === state) {
33319
+ activeForAgent.delete(state.key);
33320
+ }
33321
+ }
33322
+ }
33323
+ }
33324
+ getActiveTurns(agent) {
33325
+ let turns = this.activeTurns.get(agent);
33326
+ if (!turns) {
33327
+ turns = /* @__PURE__ */ new Map();
33328
+ this.activeTurns.set(agent, turns);
33329
+ }
33330
+ return turns;
33331
+ }
33332
+ findResponseState(agent, requestId) {
33333
+ const turns = this.activeTurns.get(agent);
33334
+ if (!turns) {
33335
+ return void 0;
33336
+ }
33337
+ if (requestId !== void 0) {
33338
+ return turns.get(requestId);
33339
+ }
33340
+ const active = [...turns.values()];
33341
+ return active.length === 1 ? active[0] : void 0;
33342
+ }
33343
+ };
33344
+ function asObject(value) {
33345
+ return value !== null && (typeof value === "object" || typeof value === "function") ? value : void 0;
33346
+ }
33347
+ function readProperty(value, key) {
33348
+ const object = asObject(value);
33349
+ return object ? Reflect.get(object, key) : void 0;
33350
+ }
33351
+ function ownValue2(value, key) {
33352
+ const object = asObject(value);
33353
+ if (!object) {
33354
+ return void 0;
33355
+ }
33356
+ const descriptor = Object.getOwnPropertyDescriptor(object, key);
33357
+ return descriptor && "value" in descriptor ? descriptor.value : void 0;
33358
+ }
33359
+ function stringValue3(value) {
33360
+ return typeof value === "string" ? value : void 0;
33361
+ }
33362
+ function serializeMessages(value) {
33363
+ if (!Array.isArray(value)) {
33364
+ return void 0;
33365
+ }
33366
+ return value.flatMap((message) => {
33367
+ const serialized = serializeMessage(message);
33368
+ return serialized === void 0 ? [] : [serialized];
33369
+ });
33370
+ }
33371
+ function serializeMessage(value) {
33372
+ const message = asObject(value);
33373
+ if (!message) {
33374
+ return void 0;
33375
+ }
33376
+ const serialized = [];
33377
+ const id = ownValue2(message, "id");
33378
+ const role = ownValue2(message, "role");
33379
+ const parts = ownValue2(message, "parts");
33380
+ if (typeof id === "string") {
33381
+ serialized.push(["id", id]);
33382
+ }
33383
+ if (typeof role === "string") {
33384
+ serialized.push(["role", role]);
33385
+ }
33386
+ const sanitizedParts = sanitizeLoggedValue2(parts);
33387
+ if (sanitizedParts !== void 0) {
33388
+ serialized.push(["parts", sanitizedParts]);
33389
+ }
33390
+ return serialized.length > 0 ? Object.fromEntries(serialized) : void 0;
33391
+ }
33392
+ function sanitizeLoggedValue2(value, seen = /* @__PURE__ */ new WeakSet(), depth = 0) {
33393
+ if (value === null || typeof value === "string" || typeof value === "boolean") {
33394
+ return value;
33395
+ }
33396
+ if (typeof value === "number") {
33397
+ return Number.isFinite(value) ? value : void 0;
33398
+ }
33399
+ const object = asObject(value);
33400
+ if (!object || depth >= 20 || typeof value === "function") {
33401
+ return void 0;
33402
+ }
33403
+ if (seen.has(object)) {
33404
+ return "[Circular]";
33405
+ }
33406
+ seen.add(object);
33407
+ if (Array.isArray(value)) {
33408
+ return value.map((entry) => sanitizeLoggedValue2(entry, seen, depth + 1));
33409
+ }
33410
+ const entries = [];
33411
+ for (const [key, descriptor] of Object.entries(
33412
+ Object.getOwnPropertyDescriptors(object)
33413
+ )) {
33414
+ if (BLOCKED_KEYS.has(key) || !descriptor.enumerable || !("value" in descriptor)) {
33415
+ continue;
33416
+ }
33417
+ const sanitized = sanitizeLoggedValue2(descriptor.value, seen, depth + 1);
33418
+ if (sanitized !== void 0) {
33419
+ entries.push([key, sanitized]);
33420
+ }
33421
+ }
33422
+ return Object.fromEntries(entries);
33423
+ }
33424
+
33425
+ // src/instrumentation/plugins/cloudflare-agents-channels.ts
33426
+ var cloudflareAgentsChannels = defineChannels(
33427
+ "agents",
33428
+ {
33429
+ runAgentTool: channel({
33430
+ channelName: "Agent.runAgentTool",
33431
+ kind: "async"
33432
+ })
33433
+ },
33434
+ { instrumentationName: INSTRUMENTATION_NAMES.CLOUDFLARE_AGENTS }
33435
+ );
33436
+
33437
+ // src/instrumentation/plugins/cloudflare-agents-plugin.ts
33438
+ var CLOUDFLARE_WORKERS_CONTEXT = {
33439
+ span_origin: {
33440
+ environment: { type: "server", name: "cloudflare_workers" }
33441
+ }
33442
+ };
33443
+ var CloudflareAgentsPlugin = class extends BasePlugin {
33444
+ onEnable() {
33445
+ const channel2 = cloudflareAgentsChannels.runAgentTool.tracingChannel();
33446
+ const spans = /* @__PURE__ */ new WeakMap();
33447
+ const handlers = {
33448
+ start: (event) => {
33449
+ try {
33450
+ const agentClass = event.arguments[0];
33451
+ const options = event.arguments[1];
33452
+ if (ownValue3(options, "detached")) {
33453
+ return;
33454
+ }
33455
+ const name = ownValue3(agentClass, "name");
33456
+ if (typeof name !== "string" || name.length === 0) {
33457
+ debugLogger.warn(
33458
+ "Skipping Cloudflare Agents runAgentTool span because the child agent class has no name."
33459
+ );
33460
+ return;
33461
+ }
33462
+ const span = _internalStartSpanWithContext(
33463
+ withSpanInstrumentationName(
33464
+ {
33465
+ name,
33466
+ spanAttributes: { type: "tool" /* TOOL */ },
33467
+ event: {
33468
+ input: ownValue3(options, "input")
33469
+ }
33470
+ },
33471
+ INSTRUMENTATION_NAMES.CLOUDFLARE_AGENTS
33472
+ ),
33473
+ CLOUDFLARE_WORKERS_CONTEXT
33474
+ );
33475
+ spans.set(event, span);
33476
+ } catch (error) {
33477
+ logInstrumentationError6("start", error);
33478
+ }
33479
+ },
33480
+ asyncEnd: (event) => {
33481
+ const span = spans.get(event);
33482
+ if (!span) {
33483
+ return;
33484
+ }
33485
+ spans.delete(event);
33486
+ try {
33487
+ const status = ownValue3(event.result, "status");
33488
+ if (status === "completed") {
33489
+ span.log({ output: ownValue3(event.result, "output") });
33490
+ } else {
33491
+ const error = ownValue3(event.result, "error");
33492
+ if (typeof error === "string") {
33493
+ span.log({ error });
33494
+ }
33495
+ }
33496
+ } catch (error) {
33497
+ logInstrumentationError6("completion", error);
33498
+ } finally {
33499
+ safelyEndSpan(span);
33500
+ }
33501
+ },
33502
+ error: (event) => {
33503
+ const span = spans.get(event);
33504
+ if (!span) {
33505
+ return;
33506
+ }
33507
+ spans.delete(event);
33508
+ try {
33509
+ span.log({ error: event.error });
33510
+ } catch (error) {
33511
+ logInstrumentationError6("rejection", error);
33512
+ } finally {
33513
+ safelyEndSpan(span);
33514
+ }
33515
+ }
33516
+ };
33517
+ channel2.subscribe(handlers);
33518
+ this.unsubscribers.push(() => channel2.unsubscribe(handlers));
33519
+ }
33520
+ onDisable() {
33521
+ for (const unsubscribe of this.unsubscribers) {
33522
+ unsubscribe();
33523
+ }
33524
+ this.unsubscribers = [];
33525
+ }
33526
+ };
33527
+ function ownValue3(value, key) {
33528
+ if (!isObjectLike2(value)) {
33529
+ return void 0;
33530
+ }
33531
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
33532
+ return descriptor && "value" in descriptor ? descriptor.value : void 0;
33533
+ }
33534
+ function isObjectLike2(value) {
33535
+ return typeof value === "object" && value !== null || typeof value === "function";
33536
+ }
33537
+ function safelyEndSpan(span) {
33538
+ try {
33539
+ span.end();
33540
+ } catch (error) {
33541
+ logInstrumentationError6("span end", error);
33542
+ }
33543
+ }
33544
+ function logInstrumentationError6(operation, error) {
33545
+ debugLogger.error(
33546
+ `Failed to process Cloudflare Agents ${operation} instrumentation:`,
33547
+ error
33548
+ );
33549
+ }
33550
+
30807
33551
  // src/instrumentation/braintrust-plugin.ts
30808
33552
  var BraintrustPlugin = class extends BasePlugin {
30809
33553
  config;
@@ -30812,13 +33556,16 @@ var BraintrustPlugin = class extends BasePlugin {
30812
33556
  anthropicPlugin = null;
30813
33557
  aiSDKPlugin = null;
30814
33558
  claudeAgentSDKPlugin = null;
33559
+ cloudflareThinkPlugin = null;
30815
33560
  cursorSDKPlugin = null;
30816
33561
  openAIAgentsPlugin = null;
30817
33562
  googleGenAIPlugin = null;
30818
33563
  huggingFacePlugin = null;
33564
+ huggingFaceTransformersPlugin = null;
30819
33565
  openRouterPlugin = null;
30820
33566
  openRouterAgentPlugin = null;
30821
33567
  mistralPlugin = null;
33568
+ ollamaPlugin = null;
30822
33569
  googleADKPlugin = null;
30823
33570
  coherePlugin = null;
30824
33571
  groqPlugin = null;
@@ -30830,6 +33577,8 @@ var BraintrustPlugin = class extends BasePlugin {
30830
33577
  langSmithPlugin = null;
30831
33578
  piCodingAgentPlugin = null;
30832
33579
  strandsAgentSDKPlugin = null;
33580
+ cloudflareAIChatPlugin = null;
33581
+ cloudflareAgentsPlugin = null;
30833
33582
  constructor(config = {}) {
30834
33583
  super();
30835
33584
  this.config = config;
@@ -30856,6 +33605,10 @@ var BraintrustPlugin = class extends BasePlugin {
30856
33605
  this.claudeAgentSDKPlugin = new ClaudeAgentSDKPlugin();
30857
33606
  this.claudeAgentSDKPlugin.enable();
30858
33607
  }
33608
+ if (integrations.cloudflareThink !== false) {
33609
+ this.cloudflareThinkPlugin = new CloudflareThinkPlugin();
33610
+ this.cloudflareThinkPlugin.enable();
33611
+ }
30859
33612
  if (integrations.cursorSDK !== false && integrations.cursor !== false) {
30860
33613
  this.cursorSDKPlugin = new CursorSDKPlugin();
30861
33614
  this.cursorSDKPlugin.enable();
@@ -30871,6 +33624,8 @@ var BraintrustPlugin = class extends BasePlugin {
30871
33624
  if (integrations.huggingface !== false) {
30872
33625
  this.huggingFacePlugin = new HuggingFacePlugin();
30873
33626
  this.huggingFacePlugin.enable();
33627
+ this.huggingFaceTransformersPlugin = new HuggingFaceTransformersPlugin();
33628
+ this.huggingFaceTransformersPlugin.enable();
30874
33629
  }
30875
33630
  if (integrations.openrouter !== false) {
30876
33631
  this.openRouterPlugin = new OpenRouterPlugin();
@@ -30884,6 +33639,10 @@ var BraintrustPlugin = class extends BasePlugin {
30884
33639
  this.mistralPlugin = new MistralPlugin();
30885
33640
  this.mistralPlugin.enable();
30886
33641
  }
33642
+ if (integrations.ollama !== false) {
33643
+ this.ollamaPlugin = new OllamaPlugin();
33644
+ this.ollamaPlugin.enable();
33645
+ }
30887
33646
  if (integrations.googleADK !== false) {
30888
33647
  this.googleADKPlugin = new GoogleADKPlugin();
30889
33648
  this.googleADKPlugin.enable();
@@ -30916,6 +33675,14 @@ var BraintrustPlugin = class extends BasePlugin {
30916
33675
  this.strandsAgentSDKPlugin = new StrandsAgentSDKPlugin();
30917
33676
  this.strandsAgentSDKPlugin.enable();
30918
33677
  }
33678
+ if (integrations.cloudflareAIChat !== false) {
33679
+ this.cloudflareAIChatPlugin = new CloudflareAIChatPlugin();
33680
+ this.cloudflareAIChatPlugin.enable();
33681
+ }
33682
+ if (integrations.cloudflareAgents !== false) {
33683
+ this.cloudflareAgentsPlugin = new CloudflareAgentsPlugin();
33684
+ this.cloudflareAgentsPlugin.enable();
33685
+ }
30919
33686
  if (integrations.flue !== false) {
30920
33687
  this.fluePlugin = new FluePlugin();
30921
33688
  this.fluePlugin.enable();
@@ -30952,6 +33719,10 @@ var BraintrustPlugin = class extends BasePlugin {
30952
33719
  this.claudeAgentSDKPlugin.disable();
30953
33720
  this.claudeAgentSDKPlugin = null;
30954
33721
  }
33722
+ if (this.cloudflareThinkPlugin) {
33723
+ this.cloudflareThinkPlugin.disable();
33724
+ this.cloudflareThinkPlugin = null;
33725
+ }
30955
33726
  if (this.cursorSDKPlugin) {
30956
33727
  this.cursorSDKPlugin.disable();
30957
33728
  this.cursorSDKPlugin = null;
@@ -30968,6 +33739,10 @@ var BraintrustPlugin = class extends BasePlugin {
30968
33739
  this.huggingFacePlugin.disable();
30969
33740
  this.huggingFacePlugin = null;
30970
33741
  }
33742
+ if (this.huggingFaceTransformersPlugin) {
33743
+ this.huggingFaceTransformersPlugin.disable();
33744
+ this.huggingFaceTransformersPlugin = null;
33745
+ }
30971
33746
  if (this.openRouterPlugin) {
30972
33747
  this.openRouterPlugin.disable();
30973
33748
  this.openRouterPlugin = null;
@@ -30980,6 +33755,10 @@ var BraintrustPlugin = class extends BasePlugin {
30980
33755
  this.mistralPlugin.disable();
30981
33756
  this.mistralPlugin = null;
30982
33757
  }
33758
+ if (this.ollamaPlugin) {
33759
+ this.ollamaPlugin.disable();
33760
+ this.ollamaPlugin = null;
33761
+ }
30983
33762
  if (this.googleADKPlugin) {
30984
33763
  this.googleADKPlugin.disable();
30985
33764
  this.googleADKPlugin = null;
@@ -31012,6 +33791,14 @@ var BraintrustPlugin = class extends BasePlugin {
31012
33791
  this.strandsAgentSDKPlugin.disable();
31013
33792
  this.strandsAgentSDKPlugin = null;
31014
33793
  }
33794
+ if (this.cloudflareAIChatPlugin) {
33795
+ this.cloudflareAIChatPlugin.disable();
33796
+ this.cloudflareAIChatPlugin = null;
33797
+ }
33798
+ if (this.cloudflareAgentsPlugin) {
33799
+ this.cloudflareAgentsPlugin.disable();
33800
+ this.cloudflareAgentsPlugin = null;
33801
+ }
31015
33802
  if (this.fluePlugin) {
31016
33803
  this.fluePlugin.disable();
31017
33804
  this.fluePlugin = null;
@@ -32695,6 +35482,9 @@ var envIntegrationAliases = {
32695
35482
  strandsagentsdk: "strandsAgentSDK",
32696
35483
  "strands-agent-sdk": "strandsAgentSDK",
32697
35484
  "@strands-agents/sdk": "strandsAgentSDK",
35485
+ agents: "cloudflareAgents",
35486
+ "cloudflare-agents": "cloudflareAgents",
35487
+ cloudflareagents: "cloudflareAgents",
32698
35488
  anthropic: "anthropic",
32699
35489
  aisdk: "aisdk",
32700
35490
  "ai-sdk": "aisdk",
@@ -32702,6 +35492,10 @@ var envIntegrationAliases = {
32702
35492
  vercel: "vercel",
32703
35493
  claudeagentsdk: "claudeAgentSDK",
32704
35494
  "claude-agent-sdk": "claudeAgentSDK",
35495
+ cloudflareaichat: "cloudflareAIChat",
35496
+ "cloudflare-ai-chat": "cloudflareAIChat",
35497
+ "@cloudflare/ai-chat": "cloudflareAIChat",
35498
+ cloudflarethink: "cloudflareThink",
32705
35499
  cursor: "cursor",
32706
35500
  "cursor-sdk": "cursorSDK",
32707
35501
  cursorsdk: "cursorSDK",
@@ -32716,10 +35510,13 @@ var envIntegrationAliases = {
32716
35510
  "google-genai": "googleGenAI",
32717
35511
  googlegenai: "googleGenAI",
32718
35512
  huggingface: "huggingface",
35513
+ "@huggingface/transformers": "huggingface",
35514
+ transformers: "huggingface",
32719
35515
  openrouter: "openrouter",
32720
35516
  openrouteragent: "openrouterAgent",
32721
35517
  "openrouter-agent": "openrouterAgent",
32722
35518
  mistral: "mistral",
35519
+ ollama: "ollama",
32723
35520
  googleadk: "googleADK",
32724
35521
  "google-adk": "googleADK",
32725
35522
  cohere: "cohere",
@@ -32754,6 +35551,8 @@ function getDefaultInstrumentationIntegrations() {
32754
35551
  googleADK: true,
32755
35552
  huggingface: true,
32756
35553
  claudeAgentSDK: true,
35554
+ cloudflareAIChat: true,
35555
+ cloudflareThink: true,
32757
35556
  cursor: true,
32758
35557
  cursorSDK: true,
32759
35558
  flue: true,
@@ -32762,6 +35561,7 @@ function getDefaultInstrumentationIntegrations() {
32762
35561
  openrouter: true,
32763
35562
  openrouterAgent: true,
32764
35563
  mistral: true,
35564
+ ollama: true,
32765
35565
  cohere: true,
32766
35566
  groq: true,
32767
35567
  bedrock: true,
@@ -32773,7 +35573,8 @@ function getDefaultInstrumentationIntegrations() {
32773
35573
  langgraph: true,
32774
35574
  langsmith: true,
32775
35575
  piCodingAgent: true,
32776
- strandsAgentSDK: true
35576
+ strandsAgentSDK: true,
35577
+ cloudflareAgents: true
32777
35578
  };
32778
35579
  }
32779
35580
  function readDisabledInstrumentationEnvConfig(disabledList) {
@@ -32791,7 +35592,9 @@ function readDisabledInstrumentationEnvConfig(disabledList) {
32791
35592
  }
32792
35593
 
32793
35594
  // src/instrumentation/registry.ts
32794
- var REGISTRY_STATE_KEY = /* @__PURE__ */ Symbol.for("braintrust.registry");
35595
+ var REGISTRY_STATE_KEY = /* @__PURE__ */ Symbol.for(
35596
+ `braintrust.registry.global-hooks.v${GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION}`
35597
+ );
32795
35598
  function getSharedState() {
32796
35599
  const state = globalThis[/* @__PURE__ */ Symbol.for("braintrust-state")];
32797
35600
  return state && typeof state === "object" ? state : void 0;