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
@@ -1,328 +1,685 @@
1
- // src/isomorph.ts
2
- var DefaultAsyncLocalStorage = class {
3
- constructor() {
4
- }
5
- enterWith(_) {
6
- }
7
- run(_, callback) {
8
- return callback();
1
+ // src/global-instrumentation-hooks.ts
2
+ var GLOBAL_INSTRUMENTATION_HOOKS_KEY = "__braintrust_instrumentation_hooks";
3
+ var GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION = 1;
4
+ var GLOBAL_INSTRUMENTATION_HOOKS_REGISTRY_BRAND = "braintrust.global-instrumentation-hooks.registry";
5
+ var GLOBAL_INSTRUMENTATION_HOOK_BRAND = "braintrust.global-instrumentation-hooks.hook";
6
+ var GLOBAL_INVOCATION_HOOK_BRAND = "braintrust.global-instrumentation-hooks.invocation-hook";
7
+ var registryBrand = Symbol.for(GLOBAL_INSTRUMENTATION_HOOKS_REGISTRY_BRAND);
8
+ var hookBrand = Symbol.for(GLOBAL_INSTRUMENTATION_HOOK_BRAND);
9
+ var invocationHookBrand = Symbol.for(GLOBAL_INVOCATION_HOOK_BRAND);
10
+ var errorReporter;
11
+ function setGlobalHookErrorReporter(reporter) {
12
+ const previousReporter = errorReporter;
13
+ errorReporter = reporter;
14
+ return () => {
15
+ if (errorReporter === reporter) {
16
+ errorReporter = previousReporter;
17
+ }
18
+ };
19
+ }
20
+ function reportError(error) {
21
+ try {
22
+ errorReporter?.(error);
23
+ } catch {
9
24
  }
10
- getStore() {
11
- return void 0;
25
+ }
26
+ function setContextValue(context, key, value) {
27
+ try {
28
+ context[key] = value;
29
+ } catch (error) {
30
+ reportError(error);
12
31
  }
13
- };
14
- var DefaultChannel = class {
32
+ }
33
+ function wrapStoreRun(store, message, next, transform) {
34
+ return () => {
35
+ let context;
36
+ try {
37
+ context = transform ? transform(message) : message;
38
+ } catch (error) {
39
+ reportError(error);
40
+ return next();
41
+ }
42
+ let called = false;
43
+ let result;
44
+ let providerError;
45
+ let providerThrew = false;
46
+ const runNext = () => {
47
+ if (called) {
48
+ reportError(
49
+ new Error(
50
+ "Instrumentation store invoked its callback more than once"
51
+ )
52
+ );
53
+ if (providerThrew) {
54
+ throw providerError;
55
+ }
56
+ return result;
57
+ }
58
+ called = true;
59
+ try {
60
+ result = next();
61
+ return result;
62
+ } catch (error) {
63
+ providerThrew = true;
64
+ providerError = error;
65
+ throw error;
66
+ }
67
+ };
68
+ try {
69
+ store.run(context, runNext);
70
+ } catch (error) {
71
+ if (!providerThrew || error !== providerError) {
72
+ reportError(error);
73
+ }
74
+ }
75
+ if (!called) {
76
+ reportError(
77
+ new Error("Instrumentation store did not invoke its callback")
78
+ );
79
+ return runNext();
80
+ }
81
+ if (providerThrew) {
82
+ throw providerError;
83
+ }
84
+ return result;
85
+ };
86
+ }
87
+ var HookChannel = class {
15
88
  constructor(name) {
16
89
  this.name = name;
17
90
  }
18
91
  name;
19
- hasSubscribers = false;
20
- subscribe(_subscription) {
92
+ subscribers = [];
93
+ stores = /* @__PURE__ */ new Map();
94
+ get hasSubscribers() {
95
+ return this.subscribers.length > 0 || this.stores.size > 0;
21
96
  }
22
- unsubscribe(_subscription) {
23
- return false;
97
+ subscribe(subscription) {
98
+ if (typeof subscription !== "function") {
99
+ throw new TypeError("subscription must be a function");
100
+ }
101
+ this.subscribers = [...this.subscribers, subscription];
24
102
  }
25
- bindStore(_store, _transform) {
103
+ unsubscribe(subscription) {
104
+ const index = this.subscribers.indexOf(subscription);
105
+ if (index === -1) {
106
+ return false;
107
+ }
108
+ this.subscribers = [
109
+ ...this.subscribers.slice(0, index),
110
+ ...this.subscribers.slice(index + 1)
111
+ ];
112
+ return true;
26
113
  }
27
- unbindStore(_store) {
28
- return false;
114
+ bindStore(store, transform) {
115
+ if (!store || typeof store.run !== "function") {
116
+ throw new TypeError("store must have a run method");
117
+ }
118
+ this.stores.set(
119
+ store,
120
+ transform
121
+ );
29
122
  }
30
- publish(_message) {
123
+ unbindStore(store) {
124
+ return this.stores.delete(store);
31
125
  }
32
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
33
- runStores(_message, fn, thisArg, ...args) {
34
- return fn.apply(thisArg, args);
126
+ publish(message) {
127
+ const subscribers = this.subscribers;
128
+ for (const subscriber of subscribers) {
129
+ try {
130
+ subscriber(message, this.name);
131
+ } catch (error) {
132
+ reportError(error);
133
+ }
134
+ }
135
+ }
136
+ runStores(message, fn, thisArg, ...args) {
137
+ let run = () => {
138
+ this.publish(message);
139
+ return Reflect.apply(fn, thisArg, args);
140
+ };
141
+ for (const [store, transform] of this.stores.entries()) {
142
+ run = wrapStoreRun(store, message, run, transform);
143
+ }
144
+ return run();
35
145
  }
36
146
  };
37
- var DefaultTracingChannel = class {
147
+ var traceEvents = [
148
+ "start",
149
+ "end",
150
+ "asyncStart",
151
+ "asyncEnd",
152
+ "error"
153
+ ];
154
+ function traceInvocation(hook, operator, target, thisArg, args, additional, callbackIndex = -1) {
155
+ const context = {
156
+ ...additional,
157
+ arguments: args,
158
+ self: thisArg
159
+ };
160
+ const invoke = () => hook.invoke(target, thisArg, args, additional);
161
+ if (operator === "traceCallback") {
162
+ return hook.traceCallback(invoke, callbackIndex, context);
163
+ }
164
+ if (operator === "tracePromise") {
165
+ return hook.tracePromise(invoke, context);
166
+ }
167
+ return hook.traceSync(invoke, context);
168
+ }
169
+ var InvocationHook = class {
170
+ interceptors = [];
171
+ get hasInterceptors() {
172
+ return this.interceptors.length > 0;
173
+ }
174
+ intercept(interceptor) {
175
+ if (typeof interceptor !== "function") {
176
+ throw new TypeError("interceptor must be a function");
177
+ }
178
+ this.interceptors = [...this.interceptors, interceptor];
179
+ let active = true;
180
+ return () => {
181
+ if (!active) {
182
+ return;
183
+ }
184
+ active = false;
185
+ const index = this.interceptors.indexOf(interceptor);
186
+ if (index !== -1) {
187
+ this.interceptors = [
188
+ ...this.interceptors.slice(0, index),
189
+ ...this.interceptors.slice(index + 1)
190
+ ];
191
+ }
192
+ };
193
+ }
194
+ invoke(target, thisArg, args, additional) {
195
+ const interceptors = this.interceptors;
196
+ if (interceptors.length === 0) {
197
+ return Reflect.apply(target, thisArg, args);
198
+ }
199
+ let next = target;
200
+ for (let index = interceptors.length - 1; index >= 0; index -= 1) {
201
+ const interceptor = interceptors[index];
202
+ const downstream = next;
203
+ next = function(...nextArgs) {
204
+ return interceptor(downstream, this, nextArgs, additional);
205
+ };
206
+ }
207
+ return Reflect.apply(next, thisArg, args);
208
+ }
209
+ };
210
+ var TracingHook = class {
38
211
  start;
39
212
  end;
40
213
  asyncStart;
41
214
  asyncEnd;
42
215
  error;
216
+ invocationHook = new InvocationHook();
43
217
  constructor(nameOrChannels) {
218
+ Object.defineProperty(this, hookBrand, {
219
+ configurable: false,
220
+ enumerable: false,
221
+ value: GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION,
222
+ writable: false
223
+ });
224
+ Object.defineProperty(this, invocationHookBrand, {
225
+ configurable: false,
226
+ enumerable: false,
227
+ value: GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION,
228
+ writable: false
229
+ });
44
230
  if (typeof nameOrChannels === "string") {
45
- this.start = new DefaultChannel(`tracing:${nameOrChannels}:start`);
46
- this.end = new DefaultChannel(`tracing:${nameOrChannels}:end`);
47
- this.asyncStart = new DefaultChannel(
48
- `tracing:${nameOrChannels}:asyncStart`
49
- );
50
- this.asyncEnd = new DefaultChannel(`tracing:${nameOrChannels}:asyncEnd`);
51
- this.error = new DefaultChannel(`tracing:${nameOrChannels}:error`);
231
+ this.start = new HookChannel(`tracing:${nameOrChannels}:start`);
232
+ this.end = new HookChannel(`tracing:${nameOrChannels}:end`);
233
+ this.asyncStart = new HookChannel(`tracing:${nameOrChannels}:asyncStart`);
234
+ this.asyncEnd = new HookChannel(`tracing:${nameOrChannels}:asyncEnd`);
235
+ this.error = new HookChannel(`tracing:${nameOrChannels}:error`);
52
236
  return;
53
237
  }
54
- this.start = nameOrChannels.start ?? new DefaultChannel("tracing:start");
55
- this.end = nameOrChannels.end ?? new DefaultChannel("tracing:end");
56
- this.asyncStart = nameOrChannels.asyncStart ?? new DefaultChannel("tracing:asyncStart");
57
- this.asyncEnd = nameOrChannels.asyncEnd ?? new DefaultChannel("tracing:asyncEnd");
58
- this.error = nameOrChannels.error ?? new DefaultChannel("tracing:error");
238
+ this.start = nameOrChannels.start ?? new HookChannel("tracing:start");
239
+ this.end = nameOrChannels.end ?? new HookChannel("tracing:end");
240
+ this.asyncStart = nameOrChannels.asyncStart ?? new HookChannel("tracing:asyncStart");
241
+ this.asyncEnd = nameOrChannels.asyncEnd ?? new HookChannel("tracing:asyncEnd");
242
+ this.error = nameOrChannels.error ?? new HookChannel("tracing:error");
59
243
  }
60
244
  get hasSubscribers() {
61
245
  return this.start.hasSubscribers || this.end.hasSubscribers || this.asyncStart.hasSubscribers || this.asyncEnd.hasSubscribers || this.error.hasSubscribers;
62
246
  }
63
- subscribe(_handlers) {
64
- }
65
- unsubscribe(_handlers) {
66
- return false;
247
+ get hasInterceptors() {
248
+ return this.invocationHook.hasInterceptors;
67
249
  }
68
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
69
- traceSync(fn, _message, thisArg, ...args) {
70
- return fn.apply(thisArg, args);
250
+ intercept(interceptor) {
251
+ return this.invocationHook.intercept(interceptor);
71
252
  }
72
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
73
- tracePromise(fn, _message, thisArg, ...args) {
74
- return fn.apply(thisArg, args);
253
+ invoke(target, thisArg, args, additional) {
254
+ return this.invocationHook.invoke(target, thisArg, args, additional);
75
255
  }
76
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
77
- traceCallback(fn, _position, _message, thisArg, ...args) {
78
- return fn.apply(thisArg, args);
256
+ traceInvocation(operator, target, thisArg, args, additional, callbackIndex = -1) {
257
+ return traceInvocation(
258
+ this,
259
+ operator,
260
+ target,
261
+ thisArg,
262
+ args,
263
+ additional,
264
+ callbackIndex
265
+ );
79
266
  }
80
- };
81
- var iso = {
82
- buildType: "unknown",
83
- // Will be set by configureBrowser() or configureNode()
84
- getRepoInfo: async (_settings) => void 0,
85
- getPastNAncestors: async () => [],
86
- getEnv: (_name) => void 0,
87
- getBraintrustApiKey: async () => void 0,
88
- getCallerLocation: () => void 0,
89
- newAsyncLocalStorage: () => new DefaultAsyncLocalStorage(),
90
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
91
- newTracingChannel: (nameOrChannels) => new DefaultTracingChannel(nameOrChannels),
92
- processOn: (_0, _1) => {
93
- },
94
- basename: (filepath) => filepath.split(/[\\/]/).pop() || filepath,
95
- // eslint-disable-next-line no-restricted-properties -- preserving intentional console usage.
96
- writeln: (text) => console.log(text)
97
- };
98
- var isomorph_default = iso;
99
-
100
- // src/instrumentation/core/stream-patcher.ts
101
- function isAsyncIterable(value) {
102
- return value !== null && typeof value === "object" && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
103
- }
104
- function hasAsyncIteratorMethods(value) {
105
- return value !== null && typeof value === "object" && "next" in value && typeof value.next === "function";
106
- }
107
- function isSelfAsyncIterator(value) {
108
- try {
109
- return value[Symbol.asyncIterator]() === value;
110
- } catch {
111
- return false;
267
+ subscribe(handlers) {
268
+ for (const eventName of traceEvents) {
269
+ const handler = handlers[eventName];
270
+ if (handler) {
271
+ this[eventName].subscribe(handler);
272
+ }
273
+ }
112
274
  }
113
- }
114
- function patchStreamIfNeeded(stream, options) {
115
- if (!isAsyncIterable(stream)) {
116
- return stream;
275
+ unsubscribe(handlers) {
276
+ let done = true;
277
+ for (const eventName of traceEvents) {
278
+ const handler = handlers[eventName];
279
+ if (handler && !this[eventName].unsubscribe(handler)) {
280
+ done = false;
281
+ }
282
+ }
283
+ return done;
117
284
  }
118
- if (Object.isFrozen(stream) || Object.isSealed(stream)) {
119
- console.warn(
120
- "Cannot patch frozen/sealed stream. Stream output will not be collected."
121
- );
122
- return stream;
285
+ traceSync(fn, message = {}, thisArg, ...args) {
286
+ if (!this.hasSubscribers) {
287
+ return Reflect.apply(fn, thisArg, args);
288
+ }
289
+ const context = message;
290
+ return this.start.runStores(message, () => {
291
+ try {
292
+ const result = Reflect.apply(fn, thisArg, args);
293
+ setContextValue(context, "result", result);
294
+ return result;
295
+ } catch (error) {
296
+ setContextValue(context, "error", error);
297
+ this.error.publish(message);
298
+ throw error;
299
+ } finally {
300
+ this.end.publish(message);
301
+ }
302
+ });
123
303
  }
124
- if (hasAsyncIteratorMethods(stream) && isSelfAsyncIterator(stream)) {
125
- if ("__braintrust_patched_iterator_methods" in stream) {
126
- return stream;
304
+ tracePromise(fn, message = {}, thisArg, ...args) {
305
+ if (!this.hasSubscribers) {
306
+ return Reflect.apply(fn, thisArg, args);
127
307
  }
128
- try {
129
- const originalNext = stream.next.bind(stream);
130
- const originalReturn = typeof stream.return === "function" ? stream.return.bind(stream) : null;
131
- const originalThrow = typeof stream.throw === "function" ? stream.throw.bind(stream) : null;
132
- const chunks = [];
133
- let completed = false;
134
- stream.next = async (...args) => {
135
- try {
136
- const result = await runNextWithWrapper(
137
- options,
138
- () => originalNext(...args)
139
- );
140
- if (result.done) {
141
- if (!completed) {
142
- completed = true;
143
- try {
144
- await options.onComplete(chunks);
145
- } catch (error) {
146
- console.error("Error in stream onComplete handler:", error);
147
- }
148
- }
149
- } else {
150
- const chunk = result.value;
151
- const shouldCollect = options.shouldCollect ? options.shouldCollect(chunk) : true;
152
- if (shouldCollect) {
153
- chunks.push(chunk);
154
- if (options.onChunk) {
155
- try {
156
- await options.onChunk(chunk);
157
- } catch (error) {
158
- console.error("Error in stream onChunk handler:", error);
159
- }
160
- }
161
- }
162
- }
163
- return result;
164
- } catch (error) {
165
- if (!completed) {
166
- completed = true;
167
- if (options.onError) {
168
- try {
169
- await options.onError(
170
- error instanceof Error ? error : new Error(String(error)),
171
- chunks
172
- );
173
- } catch (handlerError) {
174
- console.error("Error in stream onError handler:", handlerError);
175
- }
176
- }
177
- }
178
- throw error;
308
+ const context = message;
309
+ return this.start.runStores(message, () => {
310
+ let result;
311
+ try {
312
+ result = Reflect.apply(fn, thisArg, args);
313
+ } catch (error) {
314
+ setContextValue(context, "error", error);
315
+ this.error.publish(message);
316
+ this.end.publish(message);
317
+ throw error;
318
+ }
319
+ this.end.publish(message);
320
+ if (!result || typeof result !== "object" && typeof result !== "function") {
321
+ setContextValue(context, "result", result);
322
+ this.asyncStart.publish(message);
323
+ this.asyncEnd.publish(message);
324
+ return result;
325
+ }
326
+ let terminalPublished = false;
327
+ const finishUnobservedResult = (error) => {
328
+ reportError(error);
329
+ if (!terminalPublished) {
330
+ terminalPublished = true;
331
+ setContextValue(context, "result", result);
332
+ this.asyncStart.publish(message);
333
+ this.asyncEnd.publish(message);
179
334
  }
335
+ return result;
180
336
  };
181
- if (originalReturn) {
182
- stream.return = async (...args) => {
183
- if (!completed) {
184
- completed = true;
337
+ let then;
338
+ try {
339
+ then = result.then;
340
+ } catch (error) {
341
+ return finishUnobservedResult(error);
342
+ }
343
+ if (typeof then !== "function") {
344
+ setContextValue(context, "result", result);
345
+ this.asyncStart.publish(message);
346
+ this.asyncEnd.publish(message);
347
+ return result;
348
+ }
349
+ const resolve = (resolved) => {
350
+ if (!terminalPublished) {
351
+ terminalPublished = true;
352
+ setContextValue(context, "result", resolved);
353
+ this.asyncStart.publish(message);
354
+ this.asyncEnd.publish(message);
355
+ }
356
+ return resolved;
357
+ };
358
+ let rejectionThrown = false;
359
+ let rejectionError;
360
+ const reject = (error) => {
361
+ if (!terminalPublished) {
362
+ terminalPublished = true;
363
+ setContextValue(context, "error", error);
364
+ this.error.publish(message);
365
+ this.asyncStart.publish(message);
366
+ this.asyncEnd.publish(message);
367
+ }
368
+ rejectionThrown = true;
369
+ rejectionError = error;
370
+ throw error;
371
+ };
372
+ let isPlainPromise;
373
+ try {
374
+ isPlainPromise = result instanceof Promise && result.constructor === Promise;
375
+ } catch (error) {
376
+ return finishUnobservedResult(error);
377
+ }
378
+ try {
379
+ if (isPlainPromise) {
380
+ return Reflect.apply(then, result, [resolve, reject]);
381
+ }
382
+ Reflect.apply(then, result, [
383
+ resolve,
384
+ (error) => {
185
385
  try {
186
- await options.onComplete(chunks);
187
- } catch (error) {
188
- console.error("Error in stream onComplete handler:", error);
386
+ reject(error);
387
+ } catch {
189
388
  }
190
389
  }
191
- return originalReturn(...args);
192
- };
390
+ ]);
391
+ } catch (error) {
392
+ if (rejectionThrown && error === rejectionError) {
393
+ return result;
394
+ }
395
+ return finishUnobservedResult(error);
193
396
  }
194
- if (originalThrow) {
195
- stream.throw = async (...args) => {
196
- if (!completed) {
197
- completed = true;
198
- const rawError = args[0];
199
- const error = rawError instanceof Error ? rawError : new Error(String(rawError));
200
- if (options.onError) {
201
- try {
202
- await options.onError(error, chunks);
203
- } catch (handlerError) {
204
- console.error("Error in stream onError handler:", handlerError);
205
- }
206
- }
207
- }
208
- return originalThrow(...args);
209
- };
397
+ return result;
398
+ });
399
+ }
400
+ traceCallback(fn, position = -1, message = {}, thisArg, ...args) {
401
+ if (!this.hasSubscribers) {
402
+ return Reflect.apply(fn, thisArg, args);
403
+ }
404
+ const context = message;
405
+ const callArgs = args.length > 0 ? args : context.arguments ?? args;
406
+ const callback = Array.prototype.at.call(callArgs, position);
407
+ if (typeof callback !== "function") {
408
+ return Reflect.apply(fn, thisArg, args);
409
+ }
410
+ const { asyncStart, asyncEnd, error: errorChannel } = this;
411
+ function wrappedCallback(error, result) {
412
+ if (error) {
413
+ setContextValue(context, "error", error);
414
+ errorChannel.publish(message);
415
+ } else {
416
+ setContextValue(context, "result", result);
210
417
  }
211
- Object.defineProperty(stream, "__braintrust_patched_iterator_methods", {
212
- value: true
418
+ return asyncStart.runStores(message, () => {
419
+ try {
420
+ return Reflect.apply(callback, this, arguments);
421
+ } finally {
422
+ asyncEnd.publish(message);
423
+ }
213
424
  });
214
- return stream;
215
- } catch (error) {
216
- console.warn("Failed to patch stream iterator methods:", error);
217
425
  }
426
+ Array.prototype.splice.call(callArgs, position, 1, wrappedCallback);
427
+ return this.start.runStores(message, () => {
428
+ try {
429
+ return Reflect.apply(fn, thisArg, args);
430
+ } catch (error) {
431
+ setContextValue(context, "error", error);
432
+ this.error.publish(message);
433
+ throw error;
434
+ } finally {
435
+ this.end.publish(message);
436
+ }
437
+ });
218
438
  }
219
- const originalIteratorFn = stream[Symbol.asyncIterator];
220
- if ("__braintrust_patched" in originalIteratorFn && originalIteratorFn["__braintrust_patched"]) {
221
- return stream;
439
+ };
440
+ var inertChannel = Object.freeze({
441
+ name: "braintrust:inert",
442
+ hasSubscribers: false,
443
+ subscribe() {
444
+ },
445
+ unsubscribe() {
446
+ return false;
447
+ },
448
+ bindStore() {
449
+ },
450
+ unbindStore() {
451
+ return false;
452
+ },
453
+ publish() {
454
+ },
455
+ runStores(_message, fn, thisArg, ...args) {
456
+ return Reflect.apply(fn, thisArg, args);
457
+ }
458
+ });
459
+ var inertTracingHook = new TracingHook({
460
+ start: inertChannel,
461
+ end: inertChannel,
462
+ asyncStart: inertChannel,
463
+ asyncEnd: inertChannel,
464
+ error: inertChannel
465
+ });
466
+ function isHookChannel(value) {
467
+ if (typeof value !== "object" && typeof value !== "function" || value === null) {
468
+ return false;
222
469
  }
223
470
  try {
224
- const patchedIteratorFn = function() {
225
- const iterator = originalIteratorFn.call(this);
226
- const originalNext = iterator.next.bind(iterator);
227
- const chunks = [];
228
- let completed = false;
229
- iterator.next = async function(...args) {
230
- try {
231
- const result = await runNextWithWrapper(
232
- options,
233
- () => originalNext(...args)
234
- );
235
- if (result.done) {
236
- if (!completed) {
237
- completed = true;
238
- try {
239
- await options.onComplete(chunks);
240
- } catch (error) {
241
- console.error("Error in stream onComplete handler:", error);
242
- }
243
- }
244
- } else {
245
- const chunk = result.value;
246
- const shouldCollect = options.shouldCollect ? options.shouldCollect(chunk) : true;
247
- if (shouldCollect) {
248
- chunks.push(chunk);
249
- if (options.onChunk) {
250
- try {
251
- await options.onChunk(chunk);
252
- } catch (error) {
253
- console.error("Error in stream onChunk handler:", error);
254
- }
255
- }
256
- }
257
- }
258
- return result;
259
- } catch (error) {
260
- if (!completed) {
261
- completed = true;
262
- if (options.onError) {
263
- try {
264
- await options.onError(
265
- error instanceof Error ? error : new Error(String(error)),
266
- chunks
267
- );
268
- } catch (handlerError) {
269
- console.error("Error in stream onError handler:", handlerError);
270
- }
271
- }
272
- }
273
- throw error;
471
+ const channel2 = value;
472
+ 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";
473
+ } catch {
474
+ return false;
475
+ }
476
+ }
477
+ function hasTracingHookShape(value) {
478
+ if (typeof value !== "object" && typeof value !== "function" || value === null) {
479
+ return false;
480
+ }
481
+ try {
482
+ const hook = value;
483
+ 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);
484
+ } catch {
485
+ return false;
486
+ }
487
+ }
488
+ function hasInvocationHookShape(value) {
489
+ if (typeof value !== "object" && typeof value !== "function" || value === null) {
490
+ return false;
491
+ }
492
+ try {
493
+ const hook = value;
494
+ return value[invocationHookBrand] === GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION && typeof hook.hasInterceptors === "boolean" && typeof hook.intercept === "function" && typeof hook.invoke === "function";
495
+ } catch {
496
+ return false;
497
+ }
498
+ }
499
+ function installInvocationHook(value) {
500
+ const hasInvocationHook = hasInvocationHookShape(value);
501
+ const invocationHook = new InvocationHook();
502
+ try {
503
+ if (!hasInvocationHook) {
504
+ Object.defineProperties(value, {
505
+ [invocationHookBrand]: {
506
+ configurable: false,
507
+ enumerable: false,
508
+ value: GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION,
509
+ writable: false
510
+ },
511
+ hasInterceptors: {
512
+ configurable: false,
513
+ enumerable: false,
514
+ get: () => invocationHook.hasInterceptors
515
+ },
516
+ intercept: {
517
+ configurable: false,
518
+ enumerable: false,
519
+ value: invocationHook.intercept.bind(invocationHook),
520
+ writable: false
521
+ },
522
+ invoke: {
523
+ configurable: false,
524
+ enumerable: false,
525
+ value: invocationHook.invoke.bind(invocationHook),
526
+ writable: false
274
527
  }
275
- };
276
- if (iterator.return) {
277
- const originalReturn = iterator.return.bind(iterator);
278
- iterator.return = async function(...args) {
279
- if (!completed) {
280
- completed = true;
281
- try {
282
- await options.onComplete(chunks);
283
- } catch (error) {
284
- console.error("Error in stream onComplete handler:", error);
285
- }
286
- }
287
- return originalReturn(...args);
288
- };
289
- }
290
- if (iterator.throw) {
291
- const originalThrow = iterator.throw.bind(iterator);
292
- iterator.throw = async function(...args) {
293
- if (!completed) {
294
- completed = true;
295
- const rawError = args[0];
296
- const error = rawError instanceof Error ? rawError : new Error(String(rawError));
297
- if (options.onError) {
298
- try {
299
- await options.onError(error, chunks);
300
- } catch (handlerError) {
301
- console.error("Error in stream onError handler:", handlerError);
302
- }
303
- }
304
- }
305
- return originalThrow(...args);
306
- };
528
+ });
529
+ }
530
+ if (typeof value.traceInvocation !== "function") {
531
+ Object.defineProperty(value, "traceInvocation", {
532
+ configurable: false,
533
+ enumerable: false,
534
+ value: traceInvocation.bind(void 0, value),
535
+ writable: false
536
+ });
537
+ }
538
+ } catch (error) {
539
+ reportError(error);
540
+ }
541
+ }
542
+ function isCompatibleTracingHook(value) {
543
+ try {
544
+ return value[hookBrand] === GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION && hasTracingHookShape(value);
545
+ } catch {
546
+ return false;
547
+ }
548
+ }
549
+ function isCompatibleHookRegistry(value) {
550
+ try {
551
+ return value instanceof Map && value[registryBrand] === GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION;
552
+ } catch {
553
+ return false;
554
+ }
555
+ }
556
+ function getHookRegistry() {
557
+ let descriptor;
558
+ try {
559
+ descriptor = Object.getOwnPropertyDescriptor(
560
+ globalThis,
561
+ GLOBAL_INSTRUMENTATION_HOOKS_KEY
562
+ );
563
+ } catch (error) {
564
+ reportError(error);
565
+ return void 0;
566
+ }
567
+ if (descriptor && "value" in descriptor && isCompatibleHookRegistry(descriptor.value) && (descriptor.configurable || descriptor.enumerable === false)) {
568
+ if (descriptor.configurable || descriptor.writable) {
569
+ try {
570
+ Object.defineProperty(globalThis, GLOBAL_INSTRUMENTATION_HOOKS_KEY, {
571
+ configurable: false,
572
+ enumerable: false,
573
+ value: descriptor.value,
574
+ writable: false
575
+ });
576
+ } catch (error) {
577
+ reportError(error);
578
+ return void 0;
307
579
  }
308
- return iterator;
309
- };
310
- Object.defineProperty(patchedIteratorFn, "__braintrust_patched", {
311
- value: true
580
+ }
581
+ return descriptor.value;
582
+ }
583
+ if (descriptor && !descriptor.configurable) {
584
+ reportError(new Error("Incompatible global instrumentation hook registry"));
585
+ return void 0;
586
+ }
587
+ const registry2 = /* @__PURE__ */ new Map();
588
+ try {
589
+ Object.defineProperty(registry2, registryBrand, {
590
+ configurable: false,
591
+ enumerable: false,
592
+ value: GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION,
593
+ writable: false
312
594
  });
313
- stream[Symbol.asyncIterator] = patchedIteratorFn;
314
- return stream;
315
595
  } catch (error) {
316
- console.warn("Failed to patch stream:", error);
317
- return stream;
596
+ reportError(error);
597
+ return void 0;
598
+ }
599
+ try {
600
+ Object.defineProperty(globalThis, GLOBAL_INSTRUMENTATION_HOOKS_KEY, {
601
+ configurable: false,
602
+ enumerable: false,
603
+ value: registry2,
604
+ writable: false
605
+ });
606
+ return registry2;
607
+ } catch (error) {
608
+ reportError(error);
609
+ return void 0;
318
610
  }
319
611
  }
320
- function runNextWithWrapper(options, callback) {
321
- return options.aroundNext ? options.aroundNext(callback) : callback();
612
+ function newGlobalTracingChannel(nameOrChannels) {
613
+ if (typeof nameOrChannels !== "string") {
614
+ return new TracingHook(nameOrChannels);
615
+ }
616
+ const registry2 = getHookRegistry();
617
+ if (!registry2) {
618
+ return inertTracingHook;
619
+ }
620
+ let existing;
621
+ try {
622
+ existing = Map.prototype.get.call(registry2, nameOrChannels);
623
+ } catch (error) {
624
+ reportError(error);
625
+ return inertTracingHook;
626
+ }
627
+ if (isCompatibleTracingHook(existing)) {
628
+ installInvocationHook(existing);
629
+ return existing;
630
+ }
631
+ if (existing !== void 0) {
632
+ reportError(
633
+ new Error(`Invalid global instrumentation hook: ${nameOrChannels}`)
634
+ );
635
+ try {
636
+ Map.prototype.delete.call(registry2, nameOrChannels);
637
+ } catch (error) {
638
+ reportError(error);
639
+ return inertTracingHook;
640
+ }
641
+ }
642
+ const hook = new TracingHook(nameOrChannels);
643
+ try {
644
+ Map.prototype.set.call(registry2, nameOrChannels, hook);
645
+ } catch (error) {
646
+ reportError(error);
647
+ return inertTracingHook;
648
+ }
649
+ return hook;
322
650
  }
323
651
 
324
- // src/logger.ts
325
- import { v4 as uuidv42 } from "uuid";
652
+ // src/isomorph.ts
653
+ var DefaultAsyncLocalStorage = class {
654
+ constructor() {
655
+ }
656
+ enterWith(_) {
657
+ }
658
+ run(_, callback) {
659
+ return callback();
660
+ }
661
+ getStore() {
662
+ return void 0;
663
+ }
664
+ };
665
+ var iso = {
666
+ buildType: "unknown",
667
+ // Will be set by configureBrowser() or configureNode()
668
+ getRepoInfo: async (_settings) => void 0,
669
+ getPastNAncestors: async () => [],
670
+ getEnv: (_name) => void 0,
671
+ getBraintrustApiKey: async () => void 0,
672
+ getCallerLocation: () => void 0,
673
+ newAsyncLocalStorage: () => new DefaultAsyncLocalStorage(),
674
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
675
+ newTracingChannel: (nameOrChannels) => newGlobalTracingChannel(nameOrChannels),
676
+ processOn: (_0, _1) => {
677
+ },
678
+ basename: (filepath) => filepath.split(/[\\/]/).pop() || filepath,
679
+ // eslint-disable-next-line no-restricted-properties -- preserving intentional console usage.
680
+ writeln: (text) => console.log(text)
681
+ };
682
+ var isomorph_default = iso;
326
683
 
327
684
  // src/debug-logger.ts
328
685
  var PREFIX = "[braintrust]";
@@ -428,6 +785,254 @@ var debugLogger = {
428
785
  return createDebugLogger(state);
429
786
  }
430
787
  };
788
+ setGlobalHookErrorReporter((error) => {
789
+ debugLogger.error("Global instrumentation hook error:", error);
790
+ });
791
+
792
+ // src/instrumentation/core/stream-patcher.ts
793
+ function isAsyncIterable(value) {
794
+ return value !== null && typeof value === "object" && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
795
+ }
796
+ function hasAsyncIteratorMethods(value) {
797
+ return value !== null && typeof value === "object" && "next" in value && typeof value.next === "function";
798
+ }
799
+ function isSelfAsyncIterator(value) {
800
+ try {
801
+ return value[Symbol.asyncIterator]() === value;
802
+ } catch {
803
+ return false;
804
+ }
805
+ }
806
+ function patchStreamIfNeeded(stream, options) {
807
+ if (!isAsyncIterable(stream)) {
808
+ return stream;
809
+ }
810
+ if (Object.isFrozen(stream) || Object.isSealed(stream)) {
811
+ console.warn(
812
+ "Cannot patch frozen/sealed stream. Stream output will not be collected."
813
+ );
814
+ return stream;
815
+ }
816
+ const chunks = [];
817
+ let completed = false;
818
+ const notifyCancellation = async () => {
819
+ try {
820
+ await (options.onCancel ?? options.onComplete)(chunks);
821
+ } catch (error) {
822
+ debugLogger.error("Error in stream cancellation handler:", error);
823
+ }
824
+ };
825
+ const patchAbortIfPresent = () => {
826
+ try {
827
+ if ("abort" in stream && typeof stream.abort === "function") {
828
+ const originalAbort = stream.abort.bind(stream);
829
+ stream.abort = (...args) => {
830
+ try {
831
+ return originalAbort(...args);
832
+ } finally {
833
+ if (!completed) {
834
+ completed = true;
835
+ void notifyCancellation();
836
+ }
837
+ }
838
+ };
839
+ }
840
+ } catch (error) {
841
+ debugLogger.warn("Failed to patch stream abort method:", error);
842
+ }
843
+ };
844
+ if (hasAsyncIteratorMethods(stream) && isSelfAsyncIterator(stream)) {
845
+ if ("__braintrust_patched_iterator_methods" in stream) {
846
+ return stream;
847
+ }
848
+ try {
849
+ const originalNext = stream.next.bind(stream);
850
+ const originalReturn = typeof stream.return === "function" ? stream.return.bind(stream) : null;
851
+ const originalThrow = typeof stream.throw === "function" ? stream.throw.bind(stream) : null;
852
+ stream.next = async (...args) => {
853
+ try {
854
+ const result = await runNextWithWrapper(
855
+ options,
856
+ () => originalNext(...args)
857
+ );
858
+ if (result.done) {
859
+ if (!completed) {
860
+ completed = true;
861
+ try {
862
+ await options.onComplete(chunks);
863
+ } catch (error) {
864
+ console.error("Error in stream onComplete handler:", error);
865
+ }
866
+ }
867
+ } else {
868
+ const chunk = result.value;
869
+ const shouldCollect = options.shouldCollect ? options.shouldCollect(chunk) : true;
870
+ if (shouldCollect) {
871
+ chunks.push(chunk);
872
+ if (options.onChunk) {
873
+ try {
874
+ await options.onChunk(chunk);
875
+ } catch (error) {
876
+ console.error("Error in stream onChunk handler:", error);
877
+ }
878
+ }
879
+ }
880
+ }
881
+ return result;
882
+ } catch (error) {
883
+ if (!completed) {
884
+ completed = true;
885
+ if (options.onError) {
886
+ try {
887
+ await options.onError(
888
+ error instanceof Error ? error : new Error(String(error)),
889
+ chunks
890
+ );
891
+ } catch (handlerError) {
892
+ console.error("Error in stream onError handler:", handlerError);
893
+ }
894
+ }
895
+ }
896
+ throw error;
897
+ }
898
+ };
899
+ if (originalReturn) {
900
+ stream.return = async (...args) => {
901
+ if (!completed) {
902
+ completed = true;
903
+ await notifyCancellation();
904
+ }
905
+ return originalReturn(...args);
906
+ };
907
+ }
908
+ if (originalThrow) {
909
+ stream.throw = async (...args) => {
910
+ if (!completed) {
911
+ completed = true;
912
+ const rawError = args[0];
913
+ const error = rawError instanceof Error ? rawError : new Error(String(rawError));
914
+ if (options.onError) {
915
+ try {
916
+ await options.onError(error, chunks);
917
+ } catch (handlerError) {
918
+ console.error("Error in stream onError handler:", handlerError);
919
+ }
920
+ }
921
+ }
922
+ return originalThrow(...args);
923
+ };
924
+ }
925
+ Object.defineProperty(stream, "__braintrust_patched_iterator_methods", {
926
+ value: true
927
+ });
928
+ patchAbortIfPresent();
929
+ return stream;
930
+ } catch (error) {
931
+ console.warn("Failed to patch stream iterator methods:", error);
932
+ }
933
+ }
934
+ const originalIteratorFn = stream[Symbol.asyncIterator];
935
+ if ("__braintrust_patched" in originalIteratorFn && originalIteratorFn["__braintrust_patched"]) {
936
+ return stream;
937
+ }
938
+ try {
939
+ const patchedIteratorFn = function() {
940
+ const iterator = originalIteratorFn.call(this);
941
+ const originalNext = iterator.next.bind(iterator);
942
+ iterator.next = async function(...args) {
943
+ try {
944
+ const result = await runNextWithWrapper(
945
+ options,
946
+ () => originalNext(...args)
947
+ );
948
+ if (result.done) {
949
+ if (!completed) {
950
+ completed = true;
951
+ try {
952
+ await options.onComplete(chunks);
953
+ } catch (error) {
954
+ console.error("Error in stream onComplete handler:", error);
955
+ }
956
+ }
957
+ } else {
958
+ const chunk = result.value;
959
+ const shouldCollect = options.shouldCollect ? options.shouldCollect(chunk) : true;
960
+ if (shouldCollect) {
961
+ chunks.push(chunk);
962
+ if (options.onChunk) {
963
+ try {
964
+ await options.onChunk(chunk);
965
+ } catch (error) {
966
+ console.error("Error in stream onChunk handler:", error);
967
+ }
968
+ }
969
+ }
970
+ }
971
+ return result;
972
+ } catch (error) {
973
+ if (!completed) {
974
+ completed = true;
975
+ if (options.onError) {
976
+ try {
977
+ await options.onError(
978
+ error instanceof Error ? error : new Error(String(error)),
979
+ chunks
980
+ );
981
+ } catch (handlerError) {
982
+ console.error("Error in stream onError handler:", handlerError);
983
+ }
984
+ }
985
+ }
986
+ throw error;
987
+ }
988
+ };
989
+ if (iterator.return) {
990
+ const originalReturn = iterator.return.bind(iterator);
991
+ iterator.return = async function(...args) {
992
+ if (!completed) {
993
+ completed = true;
994
+ await notifyCancellation();
995
+ }
996
+ return originalReturn(...args);
997
+ };
998
+ }
999
+ if (iterator.throw) {
1000
+ const originalThrow = iterator.throw.bind(iterator);
1001
+ iterator.throw = async function(...args) {
1002
+ if (!completed) {
1003
+ completed = true;
1004
+ const rawError = args[0];
1005
+ const error = rawError instanceof Error ? rawError : new Error(String(rawError));
1006
+ if (options.onError) {
1007
+ try {
1008
+ await options.onError(error, chunks);
1009
+ } catch (handlerError) {
1010
+ console.error("Error in stream onError handler:", handlerError);
1011
+ }
1012
+ }
1013
+ }
1014
+ return originalThrow(...args);
1015
+ };
1016
+ }
1017
+ return iterator;
1018
+ };
1019
+ Object.defineProperty(patchedIteratorFn, "__braintrust_patched", {
1020
+ value: true
1021
+ });
1022
+ stream[Symbol.asyncIterator] = patchedIteratorFn;
1023
+ patchAbortIfPresent();
1024
+ return stream;
1025
+ } catch (error) {
1026
+ console.warn("Failed to patch stream:", error);
1027
+ return stream;
1028
+ }
1029
+ }
1030
+ function runNextWithWrapper(options, callback) {
1031
+ return options.aroundNext ? options.aroundNext(callback) : callback();
1032
+ }
1033
+
1034
+ // src/logger.ts
1035
+ import { v4 as uuidv42 } from "uuid";
431
1036
 
432
1037
  // src/queue.ts
433
1038
  var DEFAULT_QUEUE_SIZE = 15e3;
@@ -2079,7 +2684,8 @@ var ApiKey = z6.object({
2079
2684
  user_email: z6.union([z6.string(), z6.null()]).optional(),
2080
2685
  user_given_name: z6.union([z6.string(), z6.null()]).optional(),
2081
2686
  user_family_name: z6.union([z6.string(), z6.null()]).optional(),
2082
- org_id: z6.union([z6.string(), z6.null()]).optional()
2687
+ org_id: z6.union([z6.string(), z6.null()]).optional(),
2688
+ expires_at: z6.union([z6.string(), z6.null()]).optional()
2083
2689
  });
2084
2690
  var TriggeredFunctionState = z6.object({
2085
2691
  triggered_xact_id: z6.string(),
@@ -2199,6 +2805,7 @@ var TopicMapData = z6.object({
2199
2805
  topic_names: z6.record(z6.string()).optional(),
2200
2806
  generation_settings: TopicMapGenerationSettings.optional(),
2201
2807
  disable_reconciliation: z6.boolean().optional(),
2808
+ reconcile_mode: z6.enum(["evolve", "names_only"]).optional(),
2202
2809
  distance_threshold: z6.number().optional(),
2203
2810
  btql_filter: z6.string().optional(),
2204
2811
  automation_btql_filter: z6.string().optional()
@@ -2779,7 +3386,12 @@ var ModelParams = z6.union([
2779
3386
  }).partial().passthrough()
2780
3387
  ]);
2781
3388
  var PromptOptionsNullish = z6.union([
2782
- z6.object({ model: z6.string(), params: ModelParams, position: z6.string() }).partial(),
3389
+ z6.object({
3390
+ model: z6.string(),
3391
+ params: ModelParams,
3392
+ position: z6.string(),
3393
+ endpoint_name: z6.union([z6.string(), z6.null()])
3394
+ }).partial(),
2783
3395
  z6.null()
2784
3396
  ]);
2785
3397
  var PromptParserNullish = z6.union([
@@ -2793,11 +3405,25 @@ var PromptParserNullish = z6.union([
2793
3405
  }),
2794
3406
  z6.null()
2795
3407
  ]);
3408
+ var PreprocessorSavedFunctionId = z6.union([
3409
+ z6.object({
3410
+ type: z6.literal("function"),
3411
+ id: z6.string(),
3412
+ version: z6.string().optional()
3413
+ }),
3414
+ z6.object({
3415
+ type: z6.literal("global"),
3416
+ name: z6.string(),
3417
+ function_type: z6.literal("preprocessor").optional().default("preprocessor")
3418
+ }),
3419
+ z6.null()
3420
+ ]);
2796
3421
  var PromptDataNullish = z6.union([
2797
3422
  z6.object({
2798
3423
  prompt: PromptBlockDataNullish,
2799
3424
  options: PromptOptionsNullish,
2800
3425
  parser: PromptParserNullish,
3426
+ preprocessor: PreprocessorSavedFunctionId,
2801
3427
  tool_functions: z6.union([z6.array(SavedFunctionId), z6.null()]),
2802
3428
  template_format: z6.union([
2803
3429
  z6.enum(["mustache", "nunjucks", "none"]),
@@ -2999,6 +3625,7 @@ var PromptData = z6.object({
2999
3625
  prompt: PromptBlockDataNullish,
3000
3626
  options: PromptOptionsNullish,
3001
3627
  parser: PromptParserNullish,
3628
+ preprocessor: PreprocessorSavedFunctionId,
3002
3629
  tool_functions: z6.union([z6.array(SavedFunctionId), z6.null()]),
3003
3630
  template_format: z6.union([
3004
3631
  z6.enum(["mustache", "nunjucks", "none"]),
@@ -3161,7 +3788,8 @@ var InvokeFunction = FunctionId.and(
3161
3788
  mode: StreamingMode,
3162
3789
  strict: z6.union([z6.boolean(), z6.null()]),
3163
3790
  mcp_auth: z6.record(z6.object({ oauth_token: z6.string() }).partial()),
3164
- overrides: z6.union([z6.object({}).partial().passthrough(), z6.null()])
3791
+ overrides: z6.union([z6.object({}).partial().passthrough(), z6.null()]),
3792
+ endpoint_name: z6.union([z6.string(), z6.null()])
3165
3793
  }).partial()
3166
3794
  );
3167
3795
  var MCPServer = z6.object({
@@ -3225,6 +3853,24 @@ var Organization = z6.object({
3225
3853
  created: z6.union([z6.string(), z6.null()]).optional(),
3226
3854
  image_rendering_mode: ImageRenderingMode.optional()
3227
3855
  });
3856
+ var RetentionObjectType = z6.enum([
3857
+ "project_logs",
3858
+ "experiment",
3859
+ "dataset"
3860
+ ]);
3861
+ var OrgAutomation = z6.object({
3862
+ id: z6.string().uuid(),
3863
+ org_id: z6.string().uuid(),
3864
+ user_id: z6.union([z6.string(), z6.null()]).optional(),
3865
+ created: z6.union([z6.string(), z6.null()]).optional(),
3866
+ name: z6.string(),
3867
+ description: z6.union([z6.string(), z6.null()]).optional(),
3868
+ config: z6.object({
3869
+ event_type: z6.literal("retention"),
3870
+ object_type: RetentionObjectType,
3871
+ retention_days: z6.number().int().gte(0)
3872
+ })
3873
+ });
3228
3874
  var ProjectSettings = z6.union([
3229
3875
  z6.object({
3230
3876
  comparison_key: z6.union([z6.string(), z6.null()]),
@@ -3251,6 +3897,7 @@ var ProjectSettings = z6.union([
3251
3897
  z6.null()
3252
3898
  ]),
3253
3899
  disable_realtime_queries: z6.union([z6.boolean(), z6.null()]),
3900
+ monitor_charts_use_metrics_start: z6.union([z6.boolean(), z6.null()]),
3254
3901
  default_preprocessor: NullableSavedFunctionId
3255
3902
  }).partial(),
3256
3903
  z6.null()
@@ -3265,11 +3912,6 @@ var Project = z6.object({
3265
3912
  user_id: z6.union([z6.string(), z6.null()]).optional(),
3266
3913
  settings: ProjectSettings.optional()
3267
3914
  });
3268
- var RetentionObjectType = z6.enum([
3269
- "project_logs",
3270
- "experiment",
3271
- "dataset"
3272
- ]);
3273
3915
  var TopicAutomationFacetModel = z6.union([
3274
3916
  z6.enum(["brain-facet-latest", "brain-facet-1", "brain-facet-2"]),
3275
3917
  z6.null()
@@ -3380,7 +4022,7 @@ var ProjectAutomation = z6.object({
3380
4022
  z6.object({
3381
4023
  event_type: z6.literal("retention"),
3382
4024
  object_type: RetentionObjectType,
3383
- retention_days: z6.number().gte(0)
4025
+ retention_days: z6.number().int().gte(0)
3384
4026
  }),
3385
4027
  z6.object({
3386
4028
  event_type: z6.literal("environment_update"),
@@ -3552,7 +4194,12 @@ var Prompt = z6.object({
3552
4194
  metadata: z6.union([z6.object({}).partial().passthrough(), z6.null()]).optional(),
3553
4195
  function_type: FunctionTypeEnumNullish.optional()
3554
4196
  });
3555
- var PromptOptions = z6.object({ model: z6.string(), params: ModelParams, position: z6.string() }).partial();
4197
+ var PromptOptions = z6.object({
4198
+ model: z6.string(),
4199
+ params: ModelParams,
4200
+ position: z6.string(),
4201
+ endpoint_name: z6.union([z6.string(), z6.null()])
4202
+ }).partial();
3556
4203
  var PromptSessionEvent = z6.object({
3557
4204
  id: z6.string(),
3558
4205
  _xact_id: z6.string(),
@@ -3635,7 +4282,8 @@ var RunEval = z6.object({
3635
4282
  stop_token: z6.union([z6.string(), z6.null()]).optional(),
3636
4283
  extra_messages: z6.string().optional(),
3637
4284
  tags: z6.array(z6.string()).optional(),
3638
- mcp_auth: z6.record(z6.object({ oauth_token: z6.string() }).partial()).optional()
4285
+ mcp_auth: z6.record(z6.object({ oauth_token: z6.string() }).partial()).optional(),
4286
+ endpoint_name: z6.union([z6.string(), z6.null()]).optional()
3639
4287
  });
3640
4288
  var ServiceToken = z6.object({
3641
4289
  id: z6.string().uuid(),
@@ -3645,7 +4293,8 @@ var ServiceToken = z6.object({
3645
4293
  service_account_id: z6.union([z6.string(), z6.null()]).optional(),
3646
4294
  service_account_email: z6.union([z6.string(), z6.null()]).optional(),
3647
4295
  service_account_name: z6.union([z6.string(), z6.null()]).optional(),
3648
- org_id: z6.union([z6.string(), z6.null()]).optional()
4296
+ org_id: z6.union([z6.string(), z6.null()]).optional(),
4297
+ expires_at: z6.union([z6.string(), z6.null()]).optional()
3649
4298
  });
3650
4299
  var SpanIFrame = z6.object({
3651
4300
  id: z6.string().uuid(),
@@ -3767,6 +4416,13 @@ var ViewOptions = z6.union([
3767
4416
  }),
3768
4417
  z6.null()
3769
4418
  ]),
4419
+ pointSizeMetric: z6.union([
4420
+ z6.object({
4421
+ type: z6.enum(["none", "score", "metric", "metadata"]),
4422
+ value: z6.string()
4423
+ }),
4424
+ z6.null()
4425
+ ]),
3770
4426
  xAxisAggregation: z6.union([z6.string(), z6.null()]),
3771
4427
  chartAnnotations: z6.union([
3772
4428
  z6.array(z6.object({ id: z6.string(), text: z6.string() })),
@@ -4882,6 +5538,9 @@ var INSTRUMENTATION_NAMES = {
4882
5538
  BEDROCK_RUNTIME: "bedrock-runtime",
4883
5539
  BRAINTRUST_JS_LOGGER: "braintrust-js-logger",
4884
5540
  CLAUDE_AGENT_SDK: "claude-agent-sdk",
5541
+ CLOUDFLARE_AI_CHAT: "cloudflare-ai-chat",
5542
+ CLOUDFLARE_AGENTS: "cloudflare-agents",
5543
+ CLOUDFLARE_THINK: "cloudflare-think",
4885
5544
  COHERE: "cohere",
4886
5545
  CURSOR_SDK: "cursor-sdk",
4887
5546
  EVE: "eve",
@@ -4896,6 +5555,7 @@ var INSTRUMENTATION_NAMES = {
4896
5555
  LANGSMITH: "langsmith",
4897
5556
  MASTRA: "mastra",
4898
5557
  MISTRAL: "mistral",
5558
+ OLLAMA: "ollama",
4899
5559
  OPENAI: "openai",
4900
5560
  OPENAI_AGENTS: "openai-agents",
4901
5561
  OPENAI_CODEX: "openai-codex",
@@ -4907,7 +5567,7 @@ var INSTRUMENTATION_NAMES = {
4907
5567
  var INTERNAL_SPAN_INSTRUMENTATION_NAME = /* @__PURE__ */ Symbol.for(
4908
5568
  "braintrust.spanInstrumentationName"
4909
5569
  );
4910
- var SDK_VERSION = true ? "3.25.0" : "0.0.0";
5570
+ var SDK_VERSION = true ? "3.27.0" : "0.0.0";
4911
5571
  function withSpanInstrumentationName(args, instrumentationName) {
4912
5572
  return {
4913
5573
  ...args,
@@ -5102,12 +5762,13 @@ function applyMaskingToField(maskingFunction, data, fieldName) {
5102
5762
  var INITIAL_SPAN_WRITE_AS_MERGE = /* @__PURE__ */ Symbol(
5103
5763
  "braintrust.initial-span-write-as-merge"
5104
5764
  );
5765
+ var INTERNAL_SPAN_CONTEXT = /* @__PURE__ */ Symbol("braintrust.internal-span-context");
5105
5766
  var BRAINTRUST_CURRENT_SPAN_STORE = /* @__PURE__ */ Symbol.for(
5106
5767
  "braintrust.currentSpanStore"
5107
5768
  );
5108
5769
  var ContextManager = class {
5109
5770
  /**
5110
- * Returns the value to store in the ALS bound to a TracingChannel's start event.
5771
+ * Returns the value to store in the ALS bound to a global hook's start event.
5111
5772
  * In default mode this is the Span itself; in OTEL mode it is the OTEL Context
5112
5773
  * containing the span so that OTEL's own ALS stores a proper Context object.
5113
5774
  */
@@ -7651,6 +8312,12 @@ function _internalStartSpanWithInitialMerge(args) {
7651
8312
  [INITIAL_SPAN_WRITE_AS_MERGE]: true
7652
8313
  }).span;
7653
8314
  }
8315
+ function _internalStartSpanWithContext(args, context) {
8316
+ return startSpanAndIsLogger({
8317
+ ...args,
8318
+ [INTERNAL_SPAN_CONTEXT]: context
8319
+ }).span;
8320
+ }
7654
8321
  async function flush(options) {
7655
8322
  const state = options?.state ?? _globalState;
7656
8323
  return await state.bgLogger().flush();
@@ -8444,7 +9111,7 @@ var SpanImpl = class _SpanImpl {
8444
9111
  start: args.startTime ?? getCurrentUnixTimestamp()
8445
9112
  },
8446
9113
  context: mergeSpanOriginContext(
8447
- { ...callerLocation },
9114
+ { ...callerLocation, ...args[INTERNAL_SPAN_CONTEXT] },
8448
9115
  instrumentationName,
8449
9116
  this._state.spanOriginEnvironment
8450
9117
  ),
@@ -9921,6 +10588,33 @@ function traceStreamingChannel(channel2, config) {
9921
10588
  const { span, startTime } = spanData;
9922
10589
  if (isAsyncIterable(asyncEndEvent.result)) {
9923
10590
  let firstChunkTime;
10591
+ const handleStreamError = (error) => {
10592
+ try {
10593
+ span.log({ error });
10594
+ } catch (loggingError) {
10595
+ debugLogger.error(
10596
+ `Error logging failure for ${channelName}:`,
10597
+ loggingError
10598
+ );
10599
+ }
10600
+ try {
10601
+ span.end();
10602
+ } catch (endingError) {
10603
+ debugLogger.error(
10604
+ `Error ending span for ${channelName}:`,
10605
+ endingError
10606
+ );
10607
+ }
10608
+ states.delete(event);
10609
+ runStreamingErrorHook({
10610
+ channelName,
10611
+ config,
10612
+ error,
10613
+ event: asyncEndEvent,
10614
+ span,
10615
+ startTime
10616
+ });
10617
+ };
9924
10618
  patchStreamIfNeeded(asyncEndEvent.result, {
9925
10619
  onChunk: () => {
9926
10620
  if (firstChunkTime === void 0) {
@@ -10000,33 +10694,12 @@ function traceStreamingChannel(channel2, config) {
10000
10694
  });
10001
10695
  }
10002
10696
  },
10003
- onError: (error) => {
10004
- try {
10005
- span.log({ error });
10006
- } catch (loggingError) {
10007
- debugLogger.error(
10008
- `Error logging failure for ${channelName}:`,
10009
- loggingError
10010
- );
10011
- }
10012
- try {
10013
- span.end();
10014
- } catch (endingError) {
10015
- debugLogger.error(
10016
- `Error ending span for ${channelName}:`,
10017
- endingError
10018
- );
10019
- }
10020
- states.delete(event);
10021
- runStreamingErrorHook({
10022
- channelName,
10023
- config,
10024
- error,
10025
- event: asyncEndEvent,
10026
- span,
10027
- startTime
10028
- });
10029
- }
10697
+ onCancel: () => {
10698
+ const error = new Error("Stream cancelled before completion");
10699
+ error.name = "AbortError";
10700
+ handleStreamError(error);
10701
+ },
10702
+ onError: handleStreamError
10030
10703
  });
10031
10704
  return;
10032
10705
  }
@@ -10414,11 +11087,21 @@ function defineChannels(pkg, channels, options) {
10414
11087
  const tracingChannel2 = () => isomorph_default.newTracingChannel(
10415
11088
  fullChannelName
10416
11089
  );
11090
+ const intercept2 = (interceptor) => {
11091
+ const hook = tracingChannel2();
11092
+ return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
11093
+ };
11094
+ };
10417
11095
  return [
10418
11096
  key,
10419
11097
  {
10420
11098
  ...asyncSpec,
10421
11099
  instrumentationName,
11100
+ intercept: intercept2,
11101
+ invoke: (target, thisArg, args, additional) => {
11102
+ const hook = tracingChannel2();
11103
+ return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
11104
+ },
10422
11105
  tracingChannel: tracingChannel2,
10423
11106
  tracePromise: (fn, context) => tracingChannel2().tracePromise(
10424
11107
  fn,
@@ -10432,11 +11115,21 @@ function defineChannels(pkg, channels, options) {
10432
11115
  const tracingChannel = () => isomorph_default.newTracingChannel(
10433
11116
  fullChannelName
10434
11117
  );
11118
+ const intercept = (interceptor) => {
11119
+ const hook = tracingChannel();
11120
+ return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
11121
+ };
11122
+ };
10435
11123
  return [
10436
11124
  key,
10437
11125
  {
10438
11126
  ...syncSpec,
10439
11127
  instrumentationName,
11128
+ intercept,
11129
+ invoke: (target, thisArg, args, additional) => {
11130
+ const hook = tracingChannel();
11131
+ return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
11132
+ },
10440
11133
  tracingChannel,
10441
11134
  traceSync: (fn, context) => tracingChannel().traceSync(
10442
11135
  fn,
@@ -11687,6 +12380,12 @@ function extractAnthropicCacheTokens(cacheReadTokens = 0, cacheCreationTokens =
11687
12380
  return cacheTokens;
11688
12381
  }
11689
12382
 
12383
+ // src/wrappers/anthropic-session-collector.ts
12384
+ var sessionStreamCollectors = /* @__PURE__ */ new WeakMap();
12385
+ function registerAnthropicSessionStreamCollector(stream, collector) {
12386
+ sessionStreamCollectors.set(stream, collector);
12387
+ }
12388
+
11690
12389
  // src/instrumentation/plugins/anthropic-channels.ts
11691
12390
  var anthropicChannels = defineChannels(
11692
12391
  "@anthropic-ai/sdk",
@@ -11702,6 +12401,14 @@ var anthropicChannels = defineChannels(
11702
12401
  betaMessagesToolRunner: channel({
11703
12402
  channelName: "beta.messages.toolRunner",
11704
12403
  kind: "sync-stream"
12404
+ }),
12405
+ betaSessionsEventsStream: channel({
12406
+ channelName: "beta.sessions.events.stream",
12407
+ kind: "async"
12408
+ }),
12409
+ betaSessionsThreadsEventsStream: channel({
12410
+ channelName: "beta.sessions.threads.events.stream",
12411
+ kind: "async"
11705
12412
  })
11706
12413
  },
11707
12414
  { instrumentationName: INSTRUMENTATION_NAMES.ANTHROPIC }
@@ -11715,6 +12422,7 @@ var AnthropicPlugin = class extends BasePlugin {
11715
12422
  onEnable() {
11716
12423
  this.subscribeToAnthropicChannels();
11717
12424
  this.subscribeToAnthropicToolRunner();
12425
+ this.subscribeToAnthropicSessionStreams();
11718
12426
  }
11719
12427
  onDisable() {
11720
12428
  this.unsubscribers = unsubscribeAll(this.unsubscribers);
@@ -11832,7 +12540,411 @@ var AnthropicPlugin = class extends BasePlugin {
11832
12540
  tracingChannel.unsubscribe(handlers);
11833
12541
  });
11834
12542
  }
12543
+ subscribeToAnthropicSessionStreams() {
12544
+ this.subscribeToAnthropicSessionStream(
12545
+ anthropicChannels.betaSessionsEventsStream,
12546
+ false
12547
+ );
12548
+ this.subscribeToAnthropicSessionStream(
12549
+ anthropicChannels.betaSessionsThreadsEventsStream,
12550
+ true
12551
+ );
12552
+ }
12553
+ subscribeToAnthropicSessionStream(channel2, isThread) {
12554
+ const tracingChannel = channel2.tracingChannel();
12555
+ const pending = /* @__PURE__ */ new WeakSet();
12556
+ const handlers = {
12557
+ start: (event) => {
12558
+ if (isAutoInstrumentationSuppressed()) {
12559
+ return;
12560
+ }
12561
+ pending.add(event);
12562
+ },
12563
+ asyncEnd: (event) => {
12564
+ if (!pending.delete(event)) {
12565
+ return;
12566
+ }
12567
+ const stream = event.result;
12568
+ if (!isAsyncIterable(stream)) {
12569
+ return;
12570
+ }
12571
+ registerAnthropicSessionStreamCollector(stream, () => {
12572
+ wrapAnthropicSessionEventStream(stream, isThread);
12573
+ });
12574
+ },
12575
+ error: (event) => {
12576
+ pending.delete(event);
12577
+ }
12578
+ };
12579
+ tracingChannel.subscribe(handlers);
12580
+ this.unsubscribers.push(() => tracingChannel.unsubscribe(handlers));
12581
+ }
11835
12582
  };
12583
+ function wrapAnthropicSessionEventStream(stream, isThread) {
12584
+ const state = {
12585
+ history: [],
12586
+ isThread,
12587
+ pendingInput: [],
12588
+ seenEventIds: /* @__PURE__ */ new Set()
12589
+ };
12590
+ patchStreamIfNeeded(stream, {
12591
+ onChunk: (event) => handleAnthropicSessionEvent(state, event),
12592
+ onComplete: () => finalizeAnthropicSessionTurn(state),
12593
+ onError: (error) => finalizeAnthropicSessionTurn(state, error)
12594
+ });
12595
+ return stream;
12596
+ }
12597
+ function handleAnthropicSessionEvent(state, event) {
12598
+ try {
12599
+ if (typeof event.id === "string" && event.type !== "event_delta" && state.seenEventIds.has(event.id)) {
12600
+ return;
12601
+ }
12602
+ if (typeof event.id === "string" && event.type !== "event_delta") {
12603
+ state.seenEventIds.add(event.id);
12604
+ }
12605
+ switch (event.type) {
12606
+ case "user.message":
12607
+ case "system.message":
12608
+ recordAnthropicSessionInput(
12609
+ state,
12610
+ event
12611
+ );
12612
+ break;
12613
+ case "session.status_running":
12614
+ if (!state.isThread) {
12615
+ ensureAnthropicSessionTurn(state);
12616
+ }
12617
+ break;
12618
+ case "session.thread_status_running":
12619
+ if (state.isThread) {
12620
+ ensureAnthropicSessionTurn(state);
12621
+ }
12622
+ break;
12623
+ case "span.model_request_start":
12624
+ if (typeof event.id === "string") {
12625
+ startAnthropicSessionModel(state, event.id);
12626
+ }
12627
+ break;
12628
+ case "event_delta":
12629
+ recordAnthropicSessionFirstToken(state, event);
12630
+ break;
12631
+ case "agent.message":
12632
+ recordAnthropicSessionMessage(
12633
+ state,
12634
+ event
12635
+ );
12636
+ break;
12637
+ case "agent.custom_tool_use":
12638
+ case "agent.mcp_tool_use":
12639
+ case "agent.tool_use":
12640
+ startAnthropicSessionTool(state, event);
12641
+ break;
12642
+ case "user.tool_confirmation":
12643
+ recordAnthropicSessionToolConfirmation(state, event);
12644
+ break;
12645
+ case "agent.mcp_tool_result":
12646
+ case "agent.tool_result":
12647
+ case "user.custom_tool_result":
12648
+ case "user.tool_result":
12649
+ finalizeAnthropicSessionTool(
12650
+ state,
12651
+ event
12652
+ );
12653
+ break;
12654
+ case "span.model_request_end":
12655
+ finalizeAnthropicSessionModel(
12656
+ state,
12657
+ event
12658
+ );
12659
+ break;
12660
+ case "session.status_idle":
12661
+ case "session.thread_status_idle": {
12662
+ if (event.type === "session.status_idle" && state.isThread || event.type === "session.thread_status_idle" && !state.isThread) {
12663
+ break;
12664
+ }
12665
+ const stopReason = isObject(event.stop_reason) ? event.stop_reason.type : void 0;
12666
+ if (stopReason === "end_turn") {
12667
+ finalizeAnthropicSessionTurn(state);
12668
+ } else if (stopReason === "retries_exhausted") {
12669
+ finalizeAnthropicSessionTurn(
12670
+ state,
12671
+ "Anthropic session retries exhausted"
12672
+ );
12673
+ }
12674
+ break;
12675
+ }
12676
+ case "session.error":
12677
+ finalizeAnthropicSessionTurn(state, event.error);
12678
+ break;
12679
+ case "session.deleted":
12680
+ case "session.status_terminated":
12681
+ case "session.thread_status_terminated":
12682
+ if (event.type === "session.deleted" || event.type === "session.status_terminated" && !state.isThread || event.type === "session.thread_status_terminated" && state.isThread) {
12683
+ finalizeAnthropicSessionTurn(state);
12684
+ }
12685
+ break;
12686
+ default:
12687
+ break;
12688
+ }
12689
+ } catch (error) {
12690
+ debugLogger.debug("Error processing Anthropic Sessions event:", error);
12691
+ }
12692
+ }
12693
+ function ensureAnthropicSessionTurn(state) {
12694
+ if (state.activeTurn) {
12695
+ return state.activeTurn;
12696
+ }
12697
+ const input = state.pendingInput;
12698
+ state.pendingInput = [];
12699
+ const span = startSpan(
12700
+ withSpanInstrumentationName(
12701
+ {
12702
+ event: {
12703
+ ...input.length > 0 ? { input } : {},
12704
+ metadata: { provider: "anthropic" }
12705
+ },
12706
+ name: state.isThread ? "anthropic.beta.sessions.thread.turn" : "anthropic.beta.sessions.turn",
12707
+ spanAttributes: { type: "task" /* TASK */ }
12708
+ },
12709
+ INSTRUMENTATION_NAMES.ANTHROPIC
12710
+ )
12711
+ );
12712
+ state.activeTurn = {
12713
+ activeTools: /* @__PURE__ */ new Map(),
12714
+ input: input.slice(),
12715
+ metrics: {},
12716
+ span
12717
+ };
12718
+ return state.activeTurn;
12719
+ }
12720
+ function recordAnthropicSessionInput(state, event) {
12721
+ const content = processAttachmentsInInput(event.content);
12722
+ const message = {
12723
+ role: event.type === "system.message" ? "system" : "user",
12724
+ content
12725
+ };
12726
+ state.history.push(message);
12727
+ if (state.activeTurn) {
12728
+ state.activeTurn.input.push(message);
12729
+ } else {
12730
+ state.pendingInput.push(message);
12731
+ }
12732
+ }
12733
+ function startAnthropicSessionModel(state, startEventId) {
12734
+ const turn = ensureAnthropicSessionTurn(state);
12735
+ if (turn.activeModel) {
12736
+ finalizeAnthropicSessionModelState(state, turn);
12737
+ }
12738
+ const span = withCurrent(
12739
+ turn.span,
12740
+ () => startSpan(
12741
+ withSpanInstrumentationName(
12742
+ {
12743
+ event: {
12744
+ ...state.history.length > 0 ? { input: state.history.slice() } : {},
12745
+ metadata: { provider: "anthropic" }
12746
+ },
12747
+ name: "anthropic.messages.create",
12748
+ spanAttributes: { type: "llm" /* LLM */ }
12749
+ },
12750
+ INSTRUMENTATION_NAMES.ANTHROPIC
12751
+ )
12752
+ )
12753
+ );
12754
+ turn.activeModel = {
12755
+ output: [],
12756
+ span,
12757
+ startEventId,
12758
+ startTime: getCurrentUnixTimestamp()
12759
+ };
12760
+ }
12761
+ function recordAnthropicSessionFirstToken(state, event) {
12762
+ const model = state.activeTurn?.activeModel;
12763
+ if (!model || model.firstTokenTime !== void 0 || !isObject(event.delta) || !isObject(event.delta.content) || typeof event.delta.content.text !== "string") {
12764
+ return;
12765
+ }
12766
+ model.firstTokenTime = getCurrentUnixTimestamp();
12767
+ }
12768
+ function recordAnthropicSessionMessage(state, event) {
12769
+ const turn = ensureAnthropicSessionTurn(state);
12770
+ const content = processAttachmentsInInput(
12771
+ event.content
12772
+ );
12773
+ if (turn.activeModel) {
12774
+ turn.activeModel.output.push(...content);
12775
+ } else {
12776
+ const output = { role: "assistant", content };
12777
+ turn.lastOutput = output;
12778
+ state.history.push(output);
12779
+ }
12780
+ }
12781
+ function startAnthropicSessionTool(state, event) {
12782
+ const turn = ensureAnthropicSessionTurn(state);
12783
+ if (turn.activeModel) {
12784
+ turn.activeModel.output.push({
12785
+ type: "tool_use",
12786
+ id: event.id,
12787
+ name: event.name,
12788
+ input: event.input
12789
+ });
12790
+ }
12791
+ const existing = turn.activeTools.get(event.id);
12792
+ if (existing) {
12793
+ existing.span.end();
12794
+ turn.activeTools.delete(event.id);
12795
+ }
12796
+ const span = withCurrent(
12797
+ turn.span,
12798
+ () => startSpan(
12799
+ withSpanInstrumentationName(
12800
+ {
12801
+ event: { input: event.input },
12802
+ name: event.name,
12803
+ spanAttributes: { type: "tool" /* TOOL */ }
12804
+ },
12805
+ INSTRUMENTATION_NAMES.ANTHROPIC
12806
+ )
12807
+ )
12808
+ );
12809
+ const toolState = {
12810
+ approval: event.evaluated_permission === "allow" ? "approved" : event.evaluated_permission === "deny" ? "denied" : void 0,
12811
+ span
12812
+ };
12813
+ turn.activeTools.set(event.id, toolState);
12814
+ if (toolState.approval === "denied") {
12815
+ finalizeAnthropicSessionToolState(toolState);
12816
+ turn.activeTools.delete(event.id);
12817
+ }
12818
+ }
12819
+ function recordAnthropicSessionToolConfirmation(state, event) {
12820
+ if (typeof event.tool_use_id !== "string" || event.result !== "allow" && event.result !== "deny") {
12821
+ return;
12822
+ }
12823
+ const turn = state.activeTurn;
12824
+ const tool = turn?.activeTools.get(event.tool_use_id);
12825
+ if (!turn || !tool) {
12826
+ return;
12827
+ }
12828
+ tool.approval = event.result === "allow" ? "approved" : "denied";
12829
+ if (tool.approval === "denied") {
12830
+ finalizeAnthropicSessionToolState(tool);
12831
+ turn.activeTools.delete(event.tool_use_id);
12832
+ }
12833
+ }
12834
+ function finalizeAnthropicSessionTool(state, event) {
12835
+ const toolUseId = event.tool_use_id ?? event.mcp_tool_use_id ?? event.custom_tool_use_id;
12836
+ if (!toolUseId) {
12837
+ return;
12838
+ }
12839
+ const content = processAttachmentsInInput(event.content);
12840
+ const turn = state.activeTurn;
12841
+ const tool = turn?.activeTools.get(toolUseId);
12842
+ if (turn && tool) {
12843
+ finalizeAnthropicSessionToolState(tool, event, content);
12844
+ turn.activeTools.delete(toolUseId);
12845
+ }
12846
+ const toolResult = {
12847
+ type: "tool_result",
12848
+ tool_use_id: toolUseId,
12849
+ ...content !== void 0 ? { content } : {},
12850
+ ...event.is_error === true ? { is_error: true } : {}
12851
+ };
12852
+ state.history.push({
12853
+ role: "user",
12854
+ content: [toolResult]
12855
+ });
12856
+ }
12857
+ function finalizeAnthropicSessionToolState(state, event, content = event?.content) {
12858
+ safeAnthropicSessionLog(state.span, {
12859
+ ...event?.is_error === true ? {
12860
+ error: content ?? "Anthropic session tool execution failed"
12861
+ } : {},
12862
+ ...state.approval ? { metadata: { tool_approval: state.approval } } : {},
12863
+ ...content !== void 0 ? { output: content } : {}
12864
+ });
12865
+ state.span.end();
12866
+ }
12867
+ function finalizeAnthropicSessionModel(state, event) {
12868
+ const turn = state.activeTurn;
12869
+ const model = turn?.activeModel;
12870
+ if (!turn || !model || model.startEventId !== event.model_request_start_id) {
12871
+ return;
12872
+ }
12873
+ finalizeAnthropicSessionModelState(state, turn, event);
12874
+ }
12875
+ function finalizeAnthropicSessionModelState(state, turn, event) {
12876
+ const model = turn.activeModel;
12877
+ if (!model) {
12878
+ return;
12879
+ }
12880
+ turn.activeModel = void 0;
12881
+ const metrics = event ? parseAnthropicSessionModelUsage(event.model_usage) : {};
12882
+ if (model.firstTokenTime !== void 0) {
12883
+ metrics.time_to_first_token = model.firstTokenTime - model.startTime;
12884
+ }
12885
+ const output = model.output.length > 0 ? { role: "assistant", content: model.output } : void 0;
12886
+ safeAnthropicSessionLog(model.span, {
12887
+ ...event?.is_error ? { error: "Anthropic session model request failed" } : {},
12888
+ ...Object.keys(metrics).length > 0 ? { metrics } : {},
12889
+ ...output ? { output } : {}
12890
+ });
12891
+ model.span.end();
12892
+ if (output) {
12893
+ turn.lastOutput = output;
12894
+ state.history.push(output);
12895
+ }
12896
+ for (const key of [
12897
+ "prompt_tokens",
12898
+ "completion_tokens",
12899
+ "tokens",
12900
+ "prompt_cached_tokens",
12901
+ "prompt_cache_creation_tokens"
12902
+ ]) {
12903
+ const value = metrics[key];
12904
+ if (typeof value === "number") {
12905
+ turn.metrics[key] = (turn.metrics[key] ?? 0) + value;
12906
+ }
12907
+ }
12908
+ }
12909
+ function parseAnthropicSessionModelUsage(usage) {
12910
+ const finalized = finalizeAnthropicTokens({
12911
+ completion_tokens: usage.output_tokens,
12912
+ prompt_cache_creation_tokens: usage.cache_creation_input_tokens,
12913
+ prompt_cached_tokens: usage.cache_read_input_tokens,
12914
+ prompt_tokens: usage.input_tokens
12915
+ });
12916
+ return Object.fromEntries(
12917
+ Object.entries(finalized).filter(
12918
+ (entry) => entry[1] !== void 0
12919
+ )
12920
+ );
12921
+ }
12922
+ function finalizeAnthropicSessionTurn(state, error) {
12923
+ const turn = state.activeTurn;
12924
+ if (!turn) {
12925
+ return;
12926
+ }
12927
+ state.activeTurn = void 0;
12928
+ finalizeAnthropicSessionModelState(state, turn);
12929
+ for (const tool of turn.activeTools.values()) {
12930
+ finalizeAnthropicSessionToolState(tool);
12931
+ }
12932
+ turn.activeTools.clear();
12933
+ safeAnthropicSessionLog(turn.span, {
12934
+ ...error !== void 0 ? { error: error instanceof Error ? error : toLoggedError(error) } : {},
12935
+ ...turn.input.length > 0 ? { input: turn.input } : {},
12936
+ ...turn.lastOutput ? { output: turn.lastOutput } : {},
12937
+ ...Object.keys(turn.metrics).length > 0 ? { metrics: turn.metrics } : {}
12938
+ });
12939
+ turn.span.end();
12940
+ }
12941
+ function safeAnthropicSessionLog(span, event) {
12942
+ try {
12943
+ span.log(event);
12944
+ } catch (error) {
12945
+ debugLogger.debug("Error logging Anthropic Sessions span:", error);
12946
+ }
12947
+ }
11836
12948
  function parseMetricsFromUsage2(usage) {
11837
12949
  if (!usage) {
11838
12950
  return {};
@@ -13706,6 +14818,29 @@ var harnessAgentChannels = defineChannels(
13706
14818
  { instrumentationName: INSTRUMENTATION_NAMES.AI_SDK }
13707
14819
  );
13708
14820
 
14821
+ // src/instrumentation/plugins/cloudflare-think-context.ts
14822
+ var cloudflareThinkSpans = /* @__PURE__ */ new Map();
14823
+ function registerCloudflareThinkSpan(span) {
14824
+ if (span.spanId) {
14825
+ cloudflareThinkSpans.set(span.spanId, span);
14826
+ }
14827
+ }
14828
+ function unregisterCloudflareThinkSpan(span) {
14829
+ if (span.spanId) {
14830
+ cloudflareThinkSpans.delete(span.spanId);
14831
+ }
14832
+ }
14833
+ function currentCloudflareThinkSpan() {
14834
+ const parentSpanIds = _internalGetGlobalState()?.contextManager.getParentSpanIds()?.spanParents ?? [];
14835
+ for (const parentSpanId of parentSpanIds) {
14836
+ const span = cloudflareThinkSpans.get(parentSpanId);
14837
+ if (span) {
14838
+ return span;
14839
+ }
14840
+ }
14841
+ return void 0;
14842
+ }
14843
+
13709
14844
  // src/instrumentation/plugins/ai-sdk-plugin.ts
13710
14845
  var DEFAULT_DENY_OUTPUT_PATHS = [
13711
14846
  // v3
@@ -13812,6 +14947,7 @@ var AISDKPlugin = class extends BasePlugin {
13812
14947
  traceStreamingChannel(aiSDKChannels.streamText, {
13813
14948
  name: "streamText",
13814
14949
  type: "function" /* FUNCTION */,
14950
+ shouldTrace: () => currentCloudflareThinkSpan() === void 0,
13815
14951
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
13816
14952
  extractOutput: (result, endEvent) => processAISDKOutput(
13817
14953
  result,
@@ -13832,6 +14968,7 @@ var AISDKPlugin = class extends BasePlugin {
13832
14968
  traceSyncStreamChannel(aiSDKChannels.streamTextSync, {
13833
14969
  name: "streamText",
13834
14970
  type: "function" /* FUNCTION */,
14971
+ shouldTrace: () => currentCloudflareThinkSpan() === void 0,
13835
14972
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
13836
14973
  patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
13837
14974
  defaultDenyOutputPaths: denyOutputPaths,
@@ -14817,6 +15954,23 @@ function prepareAISDKWorkflowAgentStreamInput(params, event, span, defaultDenyOu
14817
15954
  metadata
14818
15955
  };
14819
15956
  }
15957
+ function prepareAISDKAgentCallInput(params, event, span, defaultDenyOutputPaths = DEFAULT_DENY_OUTPUT_PATHS) {
15958
+ const { input } = processAISDKWorkflowAgentCallInput(params);
15959
+ const metadata = extractMetadataFromCallParams(params, event.self);
15960
+ const childTracing = prepareAISDKChildTracing(
15961
+ params,
15962
+ event.self,
15963
+ span,
15964
+ defaultDenyOutputPaths,
15965
+ event.aiSDK,
15966
+ { agentOwner: true }
15967
+ );
15968
+ event.modelWrapped = childTracing.modelWrapped;
15969
+ if (childTracing.cleanup) {
15970
+ event.__braintrust_ai_sdk_cleanup = childTracing.cleanup;
15971
+ }
15972
+ return { input, metadata };
15973
+ }
14820
15974
  function prepareAISDKEmbedInput(params, self) {
14821
15975
  return {
14822
15976
  input: { ...params },
@@ -14840,6 +15994,18 @@ function extractTopLevelAISDKMetrics(result, event, startTime) {
14840
15994
  }
14841
15995
  return metrics;
14842
15996
  }
15997
+ async function extractResolvedAISDKTokenMetrics(result) {
15998
+ for (const field of ["totalUsage", "usage"]) {
15999
+ try {
16000
+ const usage = await Promise.resolve(result[field]);
16001
+ if (usage !== void 0) {
16002
+ return extractTokenMetrics({ [field]: usage });
16003
+ }
16004
+ } catch {
16005
+ }
16006
+ }
16007
+ return extractTokenMetrics(result);
16008
+ }
14843
16009
  function hasModelChildTracing(event) {
14844
16010
  return event?.modelWrapped === true || event?.__braintrust_ai_sdk_model_wrapped === true;
14845
16011
  }
@@ -15657,13 +16823,15 @@ function patchAISDKStreamingResult(args) {
15657
16823
  const {
15658
16824
  defaultDenyOutputPaths,
15659
16825
  endEvent,
16826
+ forceTopLevelMetrics,
15660
16827
  onComplete,
15661
16828
  onCancel,
15662
16829
  onError,
15663
16830
  result,
15664
16831
  resolvePromiseUsage,
15665
16832
  span,
15666
- startTime
16833
+ startTime,
16834
+ transformOutput
15667
16835
  } = args;
15668
16836
  if (!result || typeof result !== "object") {
15669
16837
  return false;
@@ -15716,8 +16884,8 @@ function patchAISDKStreamingResult(args) {
15716
16884
  }
15717
16885
  outputLogged = true;
15718
16886
  try {
15719
- const metrics = extractTopLevelAISDKMetrics(result, endEvent);
15720
- if (resolvePromiseUsage) {
16887
+ const metrics = forceTopLevelMetrics ? await extractResolvedAISDKTokenMetrics(result) : extractTopLevelAISDKMetrics(result, endEvent);
16888
+ if (resolvePromiseUsage && !forceTopLevelMetrics) {
15721
16889
  try {
15722
16890
  const resultRecord2 = result;
15723
16891
  const pendingUsage = resultRecord2.totalUsage ?? resultRecord2.usage;
@@ -15736,10 +16904,11 @@ function patchAISDKStreamingResult(args) {
15736
16904
  if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
15737
16905
  metrics.time_to_first_token = firstChunkTime - startTime;
15738
16906
  }
15739
- const output = await processAISDKStreamingOutput(
16907
+ const processedOutput = await processAISDKStreamingOutput(
15740
16908
  result,
15741
16909
  resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
15742
16910
  );
16911
+ const output = transformOutput ? transformOutput(processedOutput) : processedOutput;
15743
16912
  const metadata = buildResolvedMetadataPayload(result).metadata;
15744
16913
  try {
15745
16914
  span.log({
@@ -18161,6 +19330,295 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
18161
19330
  }
18162
19331
  };
18163
19332
 
19333
+ // src/instrumentation/plugins/cloudflare-think-channels.ts
19334
+ var cloudflareThinkChannels = defineChannels(
19335
+ "@cloudflare/think",
19336
+ {
19337
+ runInferenceLoop: channel({
19338
+ channelName: "Think.runInferenceLoop",
19339
+ kind: "async"
19340
+ })
19341
+ },
19342
+ { instrumentationName: INSTRUMENTATION_NAMES.CLOUDFLARE_THINK }
19343
+ );
19344
+
19345
+ // src/instrumentation/plugins/cloudflare-think-plugin.ts
19346
+ var THINK_STATE_ID = /* @__PURE__ */ Symbol.for("braintrust.cloudflare-think.state-id");
19347
+ var CloudflareThinkPlugin = class extends BasePlugin {
19348
+ statesBySpanId = /* @__PURE__ */ new Map();
19349
+ onEnable() {
19350
+ this.subscribeToThinkRuns();
19351
+ this.subscribeToAISDKStreamTextSync();
19352
+ this.subscribeToAISDKStreamTextAsync();
19353
+ }
19354
+ onDisable() {
19355
+ for (const unsubscribe of this.unsubscribers) {
19356
+ unsubscribe();
19357
+ }
19358
+ this.unsubscribers = [];
19359
+ for (const state of this.statesBySpanId.values()) {
19360
+ this.finishState(state);
19361
+ }
19362
+ this.statesBySpanId.clear();
19363
+ }
19364
+ subscribeToThinkRuns() {
19365
+ const channel2 = cloudflareThinkChannels.runInferenceLoop.tracingChannel();
19366
+ const states = /* @__PURE__ */ new WeakMap();
19367
+ const state = _internalGetGlobalState();
19368
+ const contextManager = state?.contextManager;
19369
+ const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
19370
+ const ensureState2 = (event) => {
19371
+ if (isAutoInstrumentationSuppressed()) {
19372
+ return void 0;
19373
+ }
19374
+ const existing = states.get(event);
19375
+ if (existing) {
19376
+ return existing;
19377
+ }
19378
+ const span = startSpan(
19379
+ withSpanInstrumentationName(
19380
+ {
19381
+ name: "Think.runTurn",
19382
+ spanAttributes: { type: "task" /* TASK */ }
19383
+ },
19384
+ INSTRUMENTATION_NAMES.CLOUDFLARE_THINK
19385
+ )
19386
+ );
19387
+ const runState = {
19388
+ aiResultPatched: false,
19389
+ fallbackInput: extractFallbackInput(event.self?.messages),
19390
+ finalized: false,
19391
+ inputLogged: false,
19392
+ span,
19393
+ startTime: getCurrentUnixTimestamp()
19394
+ };
19395
+ const metadata = {
19396
+ braintrust: {
19397
+ integration_name: "cloudflare-think",
19398
+ sdk_language: "typescript"
19399
+ }
19400
+ };
19401
+ if (typeof event.moduleVersion === "string") {
19402
+ metadata["cloudflare_think.version"] = event.moduleVersion;
19403
+ }
19404
+ span.log({ metadata });
19405
+ states.set(event, runState);
19406
+ if (span.spanId) {
19407
+ this.statesBySpanId.set(span.spanId, runState);
19408
+ }
19409
+ registerCloudflareThinkSpan(span);
19410
+ return runState;
19411
+ };
19412
+ if (contextManager && currentSpanStore && channel2.start) {
19413
+ channel2.start.bindStore(currentSpanStore, (event) => {
19414
+ const runState = ensureState2(event);
19415
+ return runState ? contextManager.wrapSpanForStore(runState.span) : currentSpanStore.getStore();
19416
+ });
19417
+ this.unsubscribers.push(
19418
+ () => channel2.start?.unbindStore(currentSpanStore)
19419
+ );
19420
+ }
19421
+ const handlers = {
19422
+ start: (event) => {
19423
+ ensureState2(event);
19424
+ },
19425
+ asyncEnd: (event) => {
19426
+ const runState = states.get(event);
19427
+ states.delete(event);
19428
+ if (!runState || runState.finalized || runState.aiResultPatched) {
19429
+ return;
19430
+ }
19431
+ this.finishState(runState, void 0, event.result);
19432
+ },
19433
+ error: (event) => {
19434
+ const runState = states.get(event);
19435
+ states.delete(event);
19436
+ if (runState) {
19437
+ this.finishState(runState, event.error);
19438
+ }
19439
+ }
19440
+ };
19441
+ channel2.subscribe(handlers);
19442
+ this.unsubscribers.push(() => channel2.unsubscribe(handlers));
19443
+ }
19444
+ subscribeToAISDKStreamTextSync() {
19445
+ const channel2 = aiSDKChannels.streamTextSync.tracingChannel();
19446
+ const handlers = {
19447
+ start: (event) => {
19448
+ this.startAISDKStream(event);
19449
+ },
19450
+ end: (event) => {
19451
+ this.endAISDKStream(event);
19452
+ },
19453
+ error: (event) => {
19454
+ this.errorAISDKStream(event);
19455
+ }
19456
+ };
19457
+ channel2.subscribe(handlers);
19458
+ this.unsubscribers.push(() => channel2.unsubscribe(handlers));
19459
+ }
19460
+ subscribeToAISDKStreamTextAsync() {
19461
+ const channel2 = aiSDKChannels.streamText.tracingChannel();
19462
+ const handlers = {
19463
+ start: (event) => {
19464
+ this.startAISDKStream(event);
19465
+ },
19466
+ asyncEnd: (event) => {
19467
+ this.endAISDKStream(event);
19468
+ },
19469
+ error: (event) => {
19470
+ this.errorAISDKStream(event);
19471
+ }
19472
+ };
19473
+ channel2.subscribe(handlers);
19474
+ this.unsubscribers.push(() => channel2.unsubscribe(handlers));
19475
+ }
19476
+ startAISDKStream(event) {
19477
+ const runState = this.currentState();
19478
+ if (!runState || runState.finalized) {
19479
+ return;
19480
+ }
19481
+ try {
19482
+ const prepared = prepareAISDKAgentCallInput(
19483
+ event.arguments[0],
19484
+ event,
19485
+ runState.span
19486
+ );
19487
+ runState.span.log({
19488
+ input: extractThinkTaskInput(prepared.input),
19489
+ metadata: {
19490
+ ...prepared.metadata,
19491
+ braintrust: {
19492
+ integration_name: "cloudflare-think",
19493
+ sdk_language: "typescript"
19494
+ }
19495
+ }
19496
+ });
19497
+ runState.inputLogged = true;
19498
+ runState.aiEvent = event;
19499
+ Reflect.set(event, THINK_STATE_ID, runState.span.spanId);
19500
+ } catch (error) {
19501
+ debugLogger.error(
19502
+ "Error preparing @cloudflare/think AI SDK tracing:",
19503
+ error
19504
+ );
19505
+ }
19506
+ }
19507
+ endAISDKStream(event) {
19508
+ const runState = this.stateForAISDKEvent(event);
19509
+ if (!runState || runState.finalized) {
19510
+ return;
19511
+ }
19512
+ const patched = patchAISDKStreamingResult({
19513
+ defaultDenyOutputPaths: DEFAULT_DENY_OUTPUT_PATHS,
19514
+ endEvent: event,
19515
+ forceTopLevelMetrics: true,
19516
+ onComplete: () => this.releaseState(runState),
19517
+ result: event.result,
19518
+ span: runState.span,
19519
+ startTime: runState.startTime,
19520
+ transformOutput: extractThinkTaskOutput
19521
+ });
19522
+ runState.aiResultPatched = patched;
19523
+ if (!patched) {
19524
+ this.finishState(runState, void 0, event.result);
19525
+ }
19526
+ }
19527
+ errorAISDKStream(event) {
19528
+ const runState = this.stateForAISDKEvent(event);
19529
+ if (runState) {
19530
+ this.finishState(runState, event.error);
19531
+ }
19532
+ }
19533
+ currentState() {
19534
+ const parentIds = _internalGetGlobalState()?.contextManager.getParentSpanIds()?.spanParents ?? [];
19535
+ for (const parentId of parentIds) {
19536
+ const state = this.statesBySpanId.get(parentId);
19537
+ if (state) {
19538
+ return state;
19539
+ }
19540
+ }
19541
+ return void 0;
19542
+ }
19543
+ stateForAISDKEvent(event) {
19544
+ const spanId = Reflect.get(event, THINK_STATE_ID);
19545
+ return typeof spanId === "string" ? this.statesBySpanId.get(spanId) : void 0;
19546
+ }
19547
+ finishState(state, error, output) {
19548
+ if (state.finalized) {
19549
+ return;
19550
+ }
19551
+ state.finalized = true;
19552
+ try {
19553
+ if (!state.inputLogged && state.fallbackInput !== void 0) {
19554
+ state.span.log({ input: state.fallbackInput });
19555
+ }
19556
+ if (error !== void 0) {
19557
+ state.span.log({ error });
19558
+ } else if (output !== void 0) {
19559
+ state.span.log({ output: extractThinkTaskOutput(output) });
19560
+ }
19561
+ finalizeAISDKChildTracing(state.aiEvent);
19562
+ state.span.end();
19563
+ } finally {
19564
+ this.releaseState(state);
19565
+ }
19566
+ }
19567
+ releaseState(state) {
19568
+ state.finalized = true;
19569
+ unregisterCloudflareThinkSpan(state.span);
19570
+ if (state.span.spanId) {
19571
+ this.statesBySpanId.delete(state.span.spanId);
19572
+ }
19573
+ }
19574
+ };
19575
+ function extractFallbackInput(messages) {
19576
+ if (!Array.isArray(messages) || messages.length === 0) {
19577
+ return void 0;
19578
+ }
19579
+ let latestUserIndex = -1;
19580
+ for (let index = messages.length - 1; index >= 0; index--) {
19581
+ if (messages[index]?.role === "user") {
19582
+ latestUserIndex = index;
19583
+ break;
19584
+ }
19585
+ }
19586
+ const selected = latestUserIndex >= 0 ? messages.slice(latestUserIndex) : [];
19587
+ return selected.map((message) => ({
19588
+ role: message.role,
19589
+ content: message.content ?? message.parts
19590
+ }));
19591
+ }
19592
+ function extractThinkTaskOutput(output) {
19593
+ if (!isObject(output)) {
19594
+ return output;
19595
+ }
19596
+ if (typeof output.text === "string") {
19597
+ return { role: "assistant", content: output.text };
19598
+ }
19599
+ if (output.object !== void 0) {
19600
+ return output.object;
19601
+ }
19602
+ return output;
19603
+ }
19604
+ function extractThinkTaskInput(input) {
19605
+ if (!isObject(input)) {
19606
+ return input;
19607
+ }
19608
+ const system = input.instructions ?? input.system;
19609
+ if (Array.isArray(input.messages)) {
19610
+ return system === void 0 ? input.messages : [{ role: "system", content: system }, ...input.messages];
19611
+ }
19612
+ if (Array.isArray(input.prompt)) {
19613
+ return system === void 0 ? input.prompt : [{ role: "system", content: system }, ...input.prompt];
19614
+ }
19615
+ if (typeof input.prompt === "string") {
19616
+ const messages = [{ role: "user", content: input.prompt }];
19617
+ return system === void 0 ? messages : [{ role: "system", content: system }, ...messages];
19618
+ }
19619
+ return input;
19620
+ }
19621
+
18164
19622
  // src/instrumentation/plugins/cursor-sdk-channels.ts
18165
19623
  var cursorSDKChannels = defineChannels(
18166
19624
  "@cursor/sdk",
@@ -20303,11 +21761,11 @@ function summarizeEmbedContentOutput(response) {
20303
21761
  };
20304
21762
  }
20305
21763
  function populateUsageMetrics(metrics, usage) {
20306
- if (usage.promptTokenCount !== void 0) {
20307
- metrics.prompt_tokens = usage.promptTokenCount;
21764
+ if (usage.promptTokenCount !== void 0 || usage.toolUsePromptTokenCount !== void 0) {
21765
+ metrics.prompt_tokens = (usage.promptTokenCount ?? 0) + (usage.toolUsePromptTokenCount ?? 0);
20308
21766
  }
20309
- if (usage.candidatesTokenCount !== void 0) {
20310
- metrics.completion_tokens = usage.candidatesTokenCount;
21767
+ if (usage.candidatesTokenCount !== void 0 || usage.thoughtsTokenCount !== void 0) {
21768
+ metrics.completion_tokens = (usage.candidatesTokenCount ?? 0) + (usage.thoughtsTokenCount ?? 0);
20311
21769
  }
20312
21770
  if (usage.totalTokenCount !== void 0) {
20313
21771
  metrics.tokens = usage.totalTokenCount;
@@ -20318,13 +21776,26 @@ function populateUsageMetrics(metrics, usage) {
20318
21776
  if (usage.thoughtsTokenCount !== void 0) {
20319
21777
  metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
20320
21778
  }
21779
+ for (const detail of usage.promptTokensDetails ?? []) {
21780
+ if (detail.modality === "AUDIO" && detail.tokenCount !== void 0) {
21781
+ metrics.prompt_audio_tokens = (metrics.prompt_audio_tokens ?? 0) + detail.tokenCount;
21782
+ }
21783
+ }
21784
+ for (const detail of usage.candidatesTokensDetails ?? []) {
21785
+ if (detail.modality === "AUDIO" && detail.tokenCount !== void 0) {
21786
+ metrics.completion_audio_tokens = (metrics.completion_audio_tokens ?? 0) + detail.tokenCount;
21787
+ }
21788
+ if (detail.modality === "IMAGE" && detail.tokenCount !== void 0) {
21789
+ metrics.completion_image_tokens = (metrics.completion_image_tokens ?? 0) + detail.tokenCount;
21790
+ }
21791
+ }
20321
21792
  }
20322
21793
  function populateInteractionUsageMetrics(metrics, usage) {
20323
21794
  if (typeof usage.total_input_tokens === "number") {
20324
21795
  metrics.prompt_tokens = usage.total_input_tokens;
20325
21796
  }
20326
21797
  if (typeof usage.total_output_tokens === "number") {
20327
- metrics.completion_tokens = usage.total_output_tokens;
21798
+ metrics.completion_tokens = usage.total_output_tokens + (typeof usage.total_thought_tokens === "number" ? usage.total_thought_tokens : 0);
20328
21799
  }
20329
21800
  if (typeof usage.total_tokens === "number") {
20330
21801
  metrics.tokens = usage.total_tokens;
@@ -20335,6 +21806,24 @@ function populateInteractionUsageMetrics(metrics, usage) {
20335
21806
  if (typeof usage.total_thought_tokens === "number") {
20336
21807
  metrics.completion_reasoning_tokens = usage.total_thought_tokens;
20337
21808
  }
21809
+ for (const detail of Array.isArray(usage.input_tokens_by_modality) ? usage.input_tokens_by_modality : []) {
21810
+ if (typeof detail?.modality === "string" && detail.modality.toLowerCase() === "audio" && typeof detail.tokens === "number") {
21811
+ metrics.prompt_audio_tokens = (metrics.prompt_audio_tokens ?? 0) + detail.tokens;
21812
+ }
21813
+ }
21814
+ for (const detail of Array.isArray(usage.output_tokens_by_modality) ? usage.output_tokens_by_modality : []) {
21815
+ if (typeof detail?.modality !== "string" || typeof detail.tokens !== "number") {
21816
+ continue;
21817
+ }
21818
+ switch (detail.modality.toLowerCase()) {
21819
+ case "audio":
21820
+ metrics.completion_audio_tokens = (metrics.completion_audio_tokens ?? 0) + detail.tokens;
21821
+ break;
21822
+ case "image":
21823
+ metrics.completion_image_tokens = (metrics.completion_image_tokens ?? 0) + detail.tokens;
21824
+ break;
21825
+ }
21826
+ }
20338
21827
  }
20339
21828
  function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
20340
21829
  const end = getCurrentUnixTimestamp();
@@ -21073,6 +22562,299 @@ function extractTextGenerationStreamMetadata(chunks) {
21073
22562
  return void 0;
21074
22563
  }
21075
22564
 
22565
+ // src/instrumentation/plugins/huggingface-transformers-channels.ts
22566
+ var SUPPORTED_TASKS = /* @__PURE__ */ new Set([
22567
+ "text-generation",
22568
+ "text2text-generation",
22569
+ "summarization",
22570
+ "feature-extraction",
22571
+ "question-answering"
22572
+ ]);
22573
+ var pipelineInfo = /* @__PURE__ */ new WeakMap();
22574
+ function isSupportedHuggingFaceTransformersTask(task) {
22575
+ return typeof task === "string" && SUPPORTED_TASKS.has(task);
22576
+ }
22577
+ function registerHuggingFaceTransformersPipeline(pipeline, task, model) {
22578
+ if (typeof task !== "string") {
22579
+ return;
22580
+ }
22581
+ const info = { task };
22582
+ if (typeof model === "string") {
22583
+ info.model = model;
22584
+ }
22585
+ pipelineInfo.set(pipeline, info);
22586
+ }
22587
+ function getHuggingFaceTransformersPipelineInfo(pipeline) {
22588
+ return pipeline ? pipelineInfo.get(pipeline) : void 0;
22589
+ }
22590
+ var huggingFaceTransformersChannels = defineChannels(
22591
+ "@huggingface/transformers",
22592
+ {
22593
+ pipeline: channel({
22594
+ channelName: "pipeline",
22595
+ kind: "async"
22596
+ }),
22597
+ pipelineCall: channel({
22598
+ channelName: "pipeline.call",
22599
+ kind: "async"
22600
+ })
22601
+ },
22602
+ { instrumentationName: INSTRUMENTATION_NAMES.HUGGINGFACE }
22603
+ );
22604
+
22605
+ // src/instrumentation/plugins/huggingface-transformers-plugin.ts
22606
+ var REQUEST_METADATA_KEYS = [
22607
+ "temperature",
22608
+ "top_p",
22609
+ "max_tokens",
22610
+ "stop"
22611
+ ];
22612
+ var HuggingFaceTransformersPlugin = class extends BasePlugin {
22613
+ onEnable() {
22614
+ this.subscribeToPipelineFactory();
22615
+ this.unsubscribers.push(
22616
+ traceAsyncChannel(huggingFaceTransformersChannels.pipelineCall, {
22617
+ name: (_args, event) => {
22618
+ const task = getTask(event);
22619
+ const operation = task?.replaceAll("-", "_") ?? "unknown";
22620
+ return `huggingface.transformers.${operation}`;
22621
+ },
22622
+ type: "llm" /* LLM */,
22623
+ shouldTrace: (_args, event) => isSupportedHuggingFaceTransformersTask(
22624
+ getTask(event)
22625
+ ),
22626
+ extractInput: (args, event) => ({
22627
+ input: extractInput(
22628
+ getTask(event),
22629
+ args
22630
+ ),
22631
+ metadata: extractMetadata(
22632
+ event,
22633
+ args
22634
+ )
22635
+ }),
22636
+ extractOutput: (result, event) => extractOutput(
22637
+ getTask(event),
22638
+ result
22639
+ ),
22640
+ extractMetrics: () => ({})
22641
+ })
22642
+ );
22643
+ }
22644
+ onDisable() {
22645
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
22646
+ }
22647
+ subscribeToPipelineFactory() {
22648
+ const channel2 = huggingFaceTransformersChannels.pipeline.tracingChannel();
22649
+ const handlers = {
22650
+ asyncEnd: (event) => {
22651
+ if (typeof event.result !== "function") {
22652
+ return;
22653
+ }
22654
+ registerHuggingFaceTransformersPipeline(
22655
+ event.result,
22656
+ event.arguments?.[0],
22657
+ event.arguments?.[1]
22658
+ );
22659
+ }
22660
+ };
22661
+ channel2.subscribe(handlers);
22662
+ this.unsubscribers.push(() => channel2.unsubscribe(handlers));
22663
+ }
22664
+ };
22665
+ function getTask(event) {
22666
+ const self = event.self;
22667
+ const registeredTask = getHuggingFaceTransformersPipelineInfo(self)?.task;
22668
+ if (registeredTask !== void 0) {
22669
+ return registeredTask;
22670
+ }
22671
+ if (typeof self?.task === "string") {
22672
+ return self.task;
22673
+ }
22674
+ return void 0;
22675
+ }
22676
+ function extractMetadata(event, args) {
22677
+ const metadata = {
22678
+ provider: "huggingface"
22679
+ };
22680
+ const registeredModel = getHuggingFaceTransformersPipelineInfo(
22681
+ event.self
22682
+ )?.model;
22683
+ const model = registeredModel ?? modelIdentifier(event.self);
22684
+ if (model) {
22685
+ metadata.model = model;
22686
+ }
22687
+ const task = getTask(event);
22688
+ const options = task === "question-answering" ? args[2] : args[1];
22689
+ if (isObject(options)) {
22690
+ for (const key of REQUEST_METADATA_KEYS) {
22691
+ if (options[key] !== void 0) {
22692
+ metadata[key] = options[key];
22693
+ }
22694
+ }
22695
+ }
22696
+ return metadata;
22697
+ }
22698
+ function modelIdentifier(pipeline) {
22699
+ const model = pipeline?.model;
22700
+ if (!isObject(model)) {
22701
+ return void 0;
22702
+ }
22703
+ const config = isObject(model.config) ? model.config : void 0;
22704
+ for (const value of [
22705
+ config?._name_or_path,
22706
+ config?.name_or_path,
22707
+ config?.model_id,
22708
+ config?.modelId,
22709
+ model.name
22710
+ ]) {
22711
+ if (typeof value === "string" && value.length > 0) {
22712
+ return value;
22713
+ }
22714
+ }
22715
+ return void 0;
22716
+ }
22717
+ function extractInput(task, args) {
22718
+ switch (task) {
22719
+ case "feature-extraction":
22720
+ return args[0];
22721
+ case "question-answering": {
22722
+ const question = args[0];
22723
+ const context = args[1];
22724
+ if (Array.isArray(question) && Array.isArray(context) && question.every((value) => typeof value === "string") && context.every((value) => typeof value === "string")) {
22725
+ return question.map((value, index) => [
22726
+ {
22727
+ role: "user",
22728
+ content: `Context:
22729
+ ${context[index] ?? ""}
22730
+
22731
+ Question:
22732
+ ${value}`
22733
+ }
22734
+ ]);
22735
+ }
22736
+ if (typeof question === "string" && typeof context === "string") {
22737
+ return [
22738
+ {
22739
+ role: "user",
22740
+ content: `Context:
22741
+ ${context}
22742
+
22743
+ Question:
22744
+ ${question}`
22745
+ }
22746
+ ];
22747
+ }
22748
+ return { context, question };
22749
+ }
22750
+ }
22751
+ const input = args[0];
22752
+ if (task === "text-generation" && isChat(input)) {
22753
+ return input;
22754
+ }
22755
+ if (task === "text-generation" && Array.isArray(input) && input.every(isChat)) {
22756
+ return input;
22757
+ }
22758
+ if (typeof input === "string") {
22759
+ return [{ role: "user", content: input }];
22760
+ }
22761
+ if (Array.isArray(input) && input.every((value) => typeof value === "string")) {
22762
+ return input.map((value) => [
22763
+ {
22764
+ role: "user",
22765
+ content: value
22766
+ }
22767
+ ]);
22768
+ }
22769
+ return input;
22770
+ }
22771
+ function isChat(value) {
22772
+ return Array.isArray(value) && value.length > 0 && value.every(
22773
+ (message) => isObject(message) && typeof message.role === "string" && "content" in message
22774
+ );
22775
+ }
22776
+ function extractOutput(task, result) {
22777
+ switch (task) {
22778
+ case "feature-extraction":
22779
+ return summarizeEmbedding(result);
22780
+ case "question-answering":
22781
+ return choicesFromAnswers(result);
22782
+ default:
22783
+ return choicesFromGenerations(result);
22784
+ }
22785
+ }
22786
+ function summarizeEmbedding(result) {
22787
+ if (!isObject(result) || !Array.isArray(result.dims)) {
22788
+ return void 0;
22789
+ }
22790
+ const { dims } = result;
22791
+ if (dims.length === 0 || !dims.every((dimension) => typeof dimension === "number")) {
22792
+ return void 0;
22793
+ }
22794
+ if (dims.length === 1) {
22795
+ return { embedding_length: dims[0] };
22796
+ }
22797
+ if (dims.length === 2) {
22798
+ return {
22799
+ embedding_count: dims[0],
22800
+ embedding_length: dims[1]
22801
+ };
22802
+ }
22803
+ return {
22804
+ embedding_batch_count: dims[0],
22805
+ embedding_count: dims[1],
22806
+ embedding_length: dims.at(-1) ?? 0
22807
+ };
22808
+ }
22809
+ function choicesFromAnswers(result) {
22810
+ const answers = Array.isArray(result) ? result.flat() : [result];
22811
+ const choices = answers.flatMap((answer, index) => {
22812
+ if (!isObject(answer) || typeof answer.answer !== "string") {
22813
+ return [];
22814
+ }
22815
+ return [
22816
+ {
22817
+ index,
22818
+ finish_reason: "stop",
22819
+ message: {
22820
+ role: "assistant",
22821
+ content: answer.answer
22822
+ }
22823
+ }
22824
+ ];
22825
+ });
22826
+ return choices.length > 0 ? choices : void 0;
22827
+ }
22828
+ function choicesFromGenerations(result) {
22829
+ const generations = Array.isArray(result) ? result.flat() : [result];
22830
+ const choices = generations.flatMap((generation, index) => {
22831
+ if (!isObject(generation)) {
22832
+ return [];
22833
+ }
22834
+ const generated = generation.generated_text ?? generation.summary_text;
22835
+ let content;
22836
+ if (typeof generated === "string") {
22837
+ content = generated;
22838
+ } else if (isChat(generated)) {
22839
+ content = generated.at(-1)?.content;
22840
+ }
22841
+ if (typeof content !== "string") {
22842
+ return [];
22843
+ }
22844
+ return [
22845
+ {
22846
+ index,
22847
+ finish_reason: "stop",
22848
+ message: {
22849
+ role: "assistant",
22850
+ content
22851
+ }
22852
+ }
22853
+ ];
22854
+ });
22855
+ return choices.length > 0 ? choices : void 0;
22856
+ }
22857
+
21076
22858
  // src/instrumentation/plugins/openrouter-agent-channels.ts
21077
22859
  var openRouterAgentChannels = defineChannels(
21078
22860
  "@openrouter/agent",
@@ -23602,6 +25384,470 @@ function aggregateMistralStreamChunks(chunks) {
23602
25384
  };
23603
25385
  }
23604
25386
 
25387
+ // src/instrumentation/plugins/ollama-channels.ts
25388
+ var ollamaChannels = defineChannels(
25389
+ "ollama",
25390
+ {
25391
+ chat: channel({
25392
+ channelName: "chat",
25393
+ kind: "async"
25394
+ }),
25395
+ generate: channel({
25396
+ channelName: "generate",
25397
+ kind: "async"
25398
+ }),
25399
+ embed: channel({
25400
+ channelName: "embed",
25401
+ kind: "async"
25402
+ })
25403
+ },
25404
+ { instrumentationName: INSTRUMENTATION_NAMES.OLLAMA }
25405
+ );
25406
+
25407
+ // src/instrumentation/plugins/ollama-plugin.ts
25408
+ var OllamaPlugin = class extends BasePlugin {
25409
+ onEnable() {
25410
+ this.unsubscribers.push(
25411
+ traceStreamingChannel(ollamaChannels.chat, {
25412
+ name: "ollama.chat",
25413
+ type: "llm" /* LLM */,
25414
+ extractInput: extractOllamaChatInput,
25415
+ extractOutput: (result, event) => extractOllamaChatOutput(
25416
+ result,
25417
+ countOllamaToolCalls(event?.arguments?.[0]?.messages)
25418
+ ),
25419
+ extractMetadata: extractOllamaResponseMetadata,
25420
+ extractMetrics: extractOllamaMetrics,
25421
+ aggregateChunks: aggregateOllamaChatChunks
25422
+ }),
25423
+ traceStreamingChannel(ollamaChannels.generate, {
25424
+ name: "ollama.generate",
25425
+ type: "llm" /* LLM */,
25426
+ extractInput: extractOllamaGenerateInput,
25427
+ extractOutput: extractOllamaGenerateOutput,
25428
+ extractMetadata: extractOllamaResponseMetadata,
25429
+ extractMetrics: extractOllamaMetrics,
25430
+ aggregateChunks: aggregateOllamaGenerateChunks
25431
+ }),
25432
+ traceAsyncChannel(ollamaChannels.embed, {
25433
+ name: "ollama.embed",
25434
+ type: "llm" /* LLM */,
25435
+ extractInput: extractOllamaEmbedInput,
25436
+ extractOutput: extractOllamaEmbedOutput,
25437
+ extractMetadata: extractOllamaResponseMetadata,
25438
+ extractMetrics: extractOllamaMetrics
25439
+ })
25440
+ );
25441
+ }
25442
+ onDisable() {
25443
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
25444
+ }
25445
+ };
25446
+ function isNonNegativeNumber(value) {
25447
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
25448
+ }
25449
+ function normalizeFinishReason(response, hasToolCalls = false) {
25450
+ if (hasToolCalls) {
25451
+ return "tool_calls";
25452
+ }
25453
+ return response?.done_reason || "stop";
25454
+ }
25455
+ function stringifyArguments(value) {
25456
+ if (typeof value === "string") {
25457
+ return value;
25458
+ }
25459
+ try {
25460
+ return JSON.stringify(value ?? {});
25461
+ } catch {
25462
+ return String(value);
25463
+ }
25464
+ }
25465
+ function syntheticToolCallId(name, index) {
25466
+ const normalizedName = name.replace(/[^a-zA-Z0-9_-]/g, "_") || "tool";
25467
+ return `ollama_call_${normalizedName}_${index}`;
25468
+ }
25469
+ function normalizeToolCall(toolCall, index) {
25470
+ const name = toolCall.function?.name;
25471
+ if (typeof name !== "string" || name.length === 0) {
25472
+ return void 0;
25473
+ }
25474
+ return {
25475
+ id: typeof toolCall.id === "string" && toolCall.id.length > 0 ? toolCall.id : syntheticToolCallId(name, index),
25476
+ type: "function",
25477
+ function: {
25478
+ name,
25479
+ arguments: stringifyArguments(toolCall.function?.arguments)
25480
+ }
25481
+ };
25482
+ }
25483
+ function normalizeToolCalls(toolCalls, syntheticIdOffset = 0) {
25484
+ if (!Array.isArray(toolCalls)) {
25485
+ return [];
25486
+ }
25487
+ return toolCalls.flatMap((toolCall, index) => {
25488
+ const normalized = normalizeToolCall(toolCall, syntheticIdOffset + index);
25489
+ return normalized ? [normalized] : [];
25490
+ });
25491
+ }
25492
+ function countOllamaToolCalls(messages) {
25493
+ if (!Array.isArray(messages)) {
25494
+ return 0;
25495
+ }
25496
+ return messages.reduce(
25497
+ (count, message) => count + (isObject(message) && Array.isArray(message.tool_calls) ? message.tool_calls.length : 0),
25498
+ 0
25499
+ );
25500
+ }
25501
+ function imageBytes(value) {
25502
+ if (value instanceof Uint8Array) {
25503
+ return value;
25504
+ }
25505
+ if (value instanceof ArrayBuffer) {
25506
+ return new Uint8Array(value);
25507
+ }
25508
+ if (typeof value !== "string" || value.startsWith("data:")) {
25509
+ return void 0;
25510
+ }
25511
+ try {
25512
+ const decoded = atob(value.slice(0, 24));
25513
+ return Uint8Array.from(decoded, (character) => character.charCodeAt(0));
25514
+ } catch {
25515
+ return void 0;
25516
+ }
25517
+ }
25518
+ function inferImageMediaType(value) {
25519
+ if (typeof value === "string") {
25520
+ const dataUrlType = value.match(/^data:(image\/[^;]+);base64,/i)?.[1];
25521
+ if (dataUrlType) {
25522
+ return dataUrlType;
25523
+ }
25524
+ }
25525
+ const bytes = imageBytes(value);
25526
+ if (!bytes) {
25527
+ return void 0;
25528
+ }
25529
+ if (bytes[0] === 137 && bytes[1] === 80 && bytes[2] === 78 && bytes[3] === 71) {
25530
+ return "image/png";
25531
+ }
25532
+ if (bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255) {
25533
+ return "image/jpeg";
25534
+ }
25535
+ const signature = String.fromCharCode(...bytes.slice(0, 12));
25536
+ if (signature.startsWith("GIF87a") || signature.startsWith("GIF89a")) {
25537
+ return "image/gif";
25538
+ }
25539
+ if (signature.startsWith("RIFF") && signature.slice(8, 12) === "WEBP") {
25540
+ return "image/webp";
25541
+ }
25542
+ return void 0;
25543
+ }
25544
+ function normalizeTextAndImages(content, images) {
25545
+ if (!images || images.length === 0) {
25546
+ return { content };
25547
+ }
25548
+ const imageParts = [];
25549
+ const unrecognizedImages = [];
25550
+ for (const image of images) {
25551
+ let localImagePath;
25552
+ let localPathMediaType;
25553
+ if (typeof image === "string" && !/^data:/i.test(image) && !/^https?:\/\//i.test(image)) {
25554
+ const extension = image.match(/\.([a-z0-9]+)$/i)?.[1]?.toLowerCase();
25555
+ const extensionMediaType = {
25556
+ png: "image/png",
25557
+ jpg: "image/jpeg",
25558
+ jpeg: "image/jpeg",
25559
+ gif: "image/gif",
25560
+ webp: "image/webp"
25561
+ }[extension ?? ""];
25562
+ if (extensionMediaType && isomorph_default.statSync) {
25563
+ try {
25564
+ if (isomorph_default.statSync(image).isFile()) {
25565
+ localImagePath = image;
25566
+ localPathMediaType = extensionMediaType;
25567
+ }
25568
+ } catch {
25569
+ }
25570
+ }
25571
+ }
25572
+ const mediaType = localPathMediaType ?? inferImageMediaType(image);
25573
+ if (!mediaType) {
25574
+ unrecognizedImages.push(image);
25575
+ continue;
25576
+ }
25577
+ const processedImage = localImagePath ? new Attachment({
25578
+ data: localImagePath,
25579
+ filename: localImagePath.split(/[\\/]/).at(-1) ?? "image",
25580
+ contentType: mediaType
25581
+ }) : processInputAttachments({
25582
+ type: "image",
25583
+ image,
25584
+ mediaType
25585
+ }).image;
25586
+ imageParts.push({
25587
+ type: "image_url",
25588
+ image_url: { url: processedImage }
25589
+ });
25590
+ }
25591
+ return {
25592
+ content: imageParts.length > 0 ? [...content ? [{ type: "text", text: content }] : [], ...imageParts] : content,
25593
+ ...unrecognizedImages.length > 0 ? { unrecognizedImages } : {}
25594
+ };
25595
+ }
25596
+ function normalizeMessage(message, toolCallId, syntheticToolCallIdOffset = 0) {
25597
+ if (typeof message.role !== "string") {
25598
+ return void 0;
25599
+ }
25600
+ const toolCalls = normalizeToolCalls(
25601
+ message.tool_calls,
25602
+ syntheticToolCallIdOffset
25603
+ );
25604
+ if (message.role === "tool") {
25605
+ const toolName = typeof message.tool_name === "string" && message.tool_name.length > 0 ? message.tool_name : "tool";
25606
+ return {
25607
+ role: "tool",
25608
+ tool_call_id: toolCallId ?? syntheticToolCallId(toolName, 0),
25609
+ content: typeof message.content === "string" ? message.content : ""
25610
+ };
25611
+ }
25612
+ const normalizedContent = normalizeTextAndImages(
25613
+ typeof message.content === "string" ? message.content || (toolCalls.length > 0 ? null : "") : toolCalls.length > 0 ? null : "",
25614
+ message.images
25615
+ );
25616
+ return {
25617
+ role: message.role,
25618
+ content: normalizedContent.content,
25619
+ ...typeof message.thinking === "string" && message.thinking.length > 0 ? { reasoning: message.thinking } : {},
25620
+ ...toolCalls.length > 0 ? { tool_calls: toolCalls } : {},
25621
+ ...normalizedContent.unrecognizedImages ? { images: normalizedContent.unrecognizedImages } : {}
25622
+ };
25623
+ }
25624
+ function normalizeMessages(messages) {
25625
+ if (!Array.isArray(messages)) {
25626
+ return [];
25627
+ }
25628
+ const pendingToolCallIds = /* @__PURE__ */ new Map();
25629
+ let syntheticToolCallIdOffset = 0;
25630
+ return messages.flatMap((message) => {
25631
+ if (!isObject(message)) {
25632
+ return [];
25633
+ }
25634
+ const ollamaMessage = message;
25635
+ let toolCallId;
25636
+ if (ollamaMessage.role === "tool") {
25637
+ const toolName = ollamaMessage.tool_name;
25638
+ if (typeof toolName === "string") {
25639
+ toolCallId = pendingToolCallIds.get(toolName)?.shift();
25640
+ }
25641
+ }
25642
+ const normalized = normalizeMessage(
25643
+ ollamaMessage,
25644
+ toolCallId,
25645
+ syntheticToolCallIdOffset
25646
+ );
25647
+ if (Array.isArray(ollamaMessage.tool_calls)) {
25648
+ syntheticToolCallIdOffset += ollamaMessage.tool_calls.length;
25649
+ }
25650
+ if (ollamaMessage.role === "assistant" && normalized) {
25651
+ const toolCalls = Array.isArray(normalized.tool_calls) ? normalized.tool_calls : [];
25652
+ for (const toolCall of toolCalls) {
25653
+ if (!isObject(toolCall) || !isObject(toolCall.function)) {
25654
+ continue;
25655
+ }
25656
+ const name = toolCall.function.name;
25657
+ const id = toolCall.id;
25658
+ if (typeof name === "string" && typeof id === "string") {
25659
+ const ids = pendingToolCallIds.get(name) ?? [];
25660
+ ids.push(id);
25661
+ pendingToolCallIds.set(name, ids);
25662
+ }
25663
+ }
25664
+ }
25665
+ return normalized ? [normalized] : [];
25666
+ });
25667
+ }
25668
+ function normalizeToolDefinition(tool) {
25669
+ const fn = tool.function;
25670
+ if (!fn || typeof fn.name !== "string" || fn.name.length === 0) {
25671
+ return void 0;
25672
+ }
25673
+ return {
25674
+ type: "function",
25675
+ function: {
25676
+ name: fn.name,
25677
+ ...typeof fn.description === "string" ? { description: fn.description } : {},
25678
+ ...isObject(fn.parameters) ? { parameters: fn.parameters } : {}
25679
+ }
25680
+ };
25681
+ }
25682
+ function extractToolsMetadata(tools) {
25683
+ if (!Array.isArray(tools)) {
25684
+ return {};
25685
+ }
25686
+ const normalized = tools.flatMap((tool) => {
25687
+ if (!isObject(tool)) {
25688
+ return [];
25689
+ }
25690
+ const definition = normalizeToolDefinition(tool);
25691
+ return definition ? [definition] : [];
25692
+ });
25693
+ return normalized.length > 0 ? { tools: normalized } : {};
25694
+ }
25695
+ function extractOptionsMetadata(options) {
25696
+ if (!isObject(options)) {
25697
+ return {};
25698
+ }
25699
+ const metadata = {};
25700
+ const mappings = [
25701
+ ["temperature", "temperature"],
25702
+ ["top_p", "top_p"],
25703
+ ["num_predict", "max_tokens"],
25704
+ ["frequency_penalty", "frequency_penalty"],
25705
+ ["presence_penalty", "presence_penalty"],
25706
+ ["stop", "stop"]
25707
+ ];
25708
+ for (const [source, target] of mappings) {
25709
+ if (options[source] !== void 0) {
25710
+ metadata[target] = options[source];
25711
+ }
25712
+ }
25713
+ return metadata;
25714
+ }
25715
+ function extractRequestMetadata(request) {
25716
+ return {
25717
+ provider: "ollama",
25718
+ ...typeof request?.model === "string" ? { model: request.model } : {},
25719
+ ...extractOptionsMetadata(request?.options),
25720
+ ...request?.format !== void 0 ? { response_format: request.format } : {}
25721
+ };
25722
+ }
25723
+ function extractOllamaChatInput([request]) {
25724
+ return {
25725
+ input: normalizeMessages(request.messages),
25726
+ metadata: {
25727
+ ...extractRequestMetadata(request),
25728
+ ...extractToolsMetadata(request.tools)
25729
+ }
25730
+ };
25731
+ }
25732
+ function extractOllamaGenerateInput([request]) {
25733
+ const normalizedPrompt = normalizeTextAndImages(
25734
+ typeof request.prompt === "string" ? request.prompt : "",
25735
+ Array.isArray(request.images) ? request.images : void 0
25736
+ );
25737
+ const input = [
25738
+ ...typeof request.system === "string" ? [{ role: "system", content: request.system }] : [],
25739
+ {
25740
+ role: "user",
25741
+ content: normalizedPrompt.content,
25742
+ ...typeof request.suffix === "string" ? { suffix: request.suffix } : {},
25743
+ ...normalizedPrompt.unrecognizedImages ? { images: normalizedPrompt.unrecognizedImages } : {}
25744
+ }
25745
+ ];
25746
+ return {
25747
+ input,
25748
+ metadata: extractRequestMetadata(request)
25749
+ };
25750
+ }
25751
+ function extractOllamaEmbedInput([request]) {
25752
+ return {
25753
+ input: request.input,
25754
+ metadata: extractRequestMetadata(request)
25755
+ };
25756
+ }
25757
+ function extractOllamaChatOutput(result, syntheticToolCallIdOffset = 0) {
25758
+ if (!isObject(result) || !isObject(result.message)) {
25759
+ return void 0;
25760
+ }
25761
+ const message = normalizeMessage(
25762
+ result.message,
25763
+ void 0,
25764
+ syntheticToolCallIdOffset
25765
+ );
25766
+ if (!message) {
25767
+ return void 0;
25768
+ }
25769
+ const toolCalls = Array.isArray(message.tool_calls) ? message.tool_calls : [];
25770
+ return [
25771
+ {
25772
+ index: 0,
25773
+ finish_reason: normalizeFinishReason(result, toolCalls.length > 0),
25774
+ message
25775
+ }
25776
+ ];
25777
+ }
25778
+ function extractOllamaGenerateOutput(result) {
25779
+ if (!isObject(result) || typeof result.response !== "string") {
25780
+ return void 0;
25781
+ }
25782
+ return [
25783
+ {
25784
+ index: 0,
25785
+ finish_reason: normalizeFinishReason(result),
25786
+ message: {
25787
+ role: "assistant",
25788
+ content: result.response,
25789
+ ...typeof result.thinking === "string" && result.thinking.length > 0 ? { reasoning: result.thinking } : {}
25790
+ }
25791
+ }
25792
+ ];
25793
+ }
25794
+ function extractOllamaEmbedOutput(result) {
25795
+ const embedding = Array.isArray(result?.embeddings) ? result.embeddings[0] : void 0;
25796
+ return Array.isArray(embedding) ? { embedding_length: embedding.length } : void 0;
25797
+ }
25798
+ function extractOllamaResponseMetadata(result) {
25799
+ return typeof result?.model === "string" ? { model: result.model } : void 0;
25800
+ }
25801
+ function extractOllamaMetrics(result) {
25802
+ const metrics = {};
25803
+ const promptTokens = result?.prompt_eval_count;
25804
+ const completionTokens = result?.eval_count;
25805
+ if (isNonNegativeNumber(promptTokens)) {
25806
+ metrics.prompt_tokens = promptTokens;
25807
+ }
25808
+ if (isNonNegativeNumber(completionTokens)) {
25809
+ metrics.completion_tokens = completionTokens;
25810
+ }
25811
+ if (isNonNegativeNumber(promptTokens) || isNonNegativeNumber(completionTokens)) {
25812
+ metrics.tokens = (isNonNegativeNumber(promptTokens) ? promptTokens : 0) + (isNonNegativeNumber(completionTokens) ? completionTokens : 0);
25813
+ }
25814
+ return metrics;
25815
+ }
25816
+ function aggregateOllamaChatChunks(chunks, _result, event, _startTime) {
25817
+ const last = chunks.at(-1);
25818
+ const message = {
25819
+ role: "assistant",
25820
+ content: chunks.map((chunk) => chunk.message?.content ?? "").join(""),
25821
+ thinking: chunks.map((chunk) => chunk.message?.thinking ?? "").join(""),
25822
+ tool_calls: chunks.flatMap((chunk) => chunk.message?.tool_calls ?? [])
25823
+ };
25824
+ const response = {
25825
+ ...last,
25826
+ message
25827
+ };
25828
+ return {
25829
+ output: extractOllamaChatOutput(
25830
+ response,
25831
+ countOllamaToolCalls(event?.arguments?.[0]?.messages)
25832
+ ),
25833
+ metrics: extractOllamaMetrics(last ?? {}),
25834
+ metadata: extractOllamaResponseMetadata(last ?? {})
25835
+ };
25836
+ }
25837
+ function aggregateOllamaGenerateChunks(chunks, _result, _event, _startTime) {
25838
+ const last = chunks.at(-1);
25839
+ const response = {
25840
+ ...last,
25841
+ response: chunks.map((chunk) => chunk.response ?? "").join(""),
25842
+ thinking: chunks.map((chunk) => chunk.thinking ?? "").join("")
25843
+ };
25844
+ return {
25845
+ output: extractOllamaGenerateOutput(response),
25846
+ metrics: extractOllamaMetrics(last ?? {}),
25847
+ metadata: extractOllamaResponseMetadata(last ?? {})
25848
+ };
25849
+ }
25850
+
23605
25851
  // src/instrumentation/plugins/google-adk-channels.ts
23606
25852
  var googleADKChannels = defineChannels(
23607
25853
  "@google/adk",
@@ -24238,15 +26484,32 @@ function aggregateUsageFromEvents(events) {
24238
26484
  if (usage.thoughtsTokenCount !== void 0) {
24239
26485
  aggregated.thoughtsTokenCount = (aggregated.thoughtsTokenCount ?? 0) + usage.thoughtsTokenCount;
24240
26486
  }
26487
+ if (usage.toolUsePromptTokenCount !== void 0) {
26488
+ aggregated.toolUsePromptTokenCount = (aggregated.toolUsePromptTokenCount ?? 0) + usage.toolUsePromptTokenCount;
26489
+ }
26490
+ for (const detailsField of [
26491
+ "promptTokensDetails",
26492
+ "cacheTokensDetails",
26493
+ "candidatesTokensDetails",
26494
+ "toolUsePromptTokensDetails"
26495
+ ]) {
26496
+ const details = usage[detailsField];
26497
+ if (details !== void 0) {
26498
+ aggregated[detailsField] = [
26499
+ ...aggregated[detailsField] ?? [],
26500
+ ...details
26501
+ ];
26502
+ }
26503
+ }
24241
26504
  }
24242
26505
  return hasUsage ? aggregated : void 0;
24243
26506
  }
24244
26507
  function populateUsageMetrics2(metrics, usage) {
24245
- if (usage.promptTokenCount !== void 0) {
24246
- metrics.prompt_tokens = usage.promptTokenCount;
26508
+ if (usage.promptTokenCount !== void 0 || usage.toolUsePromptTokenCount !== void 0) {
26509
+ metrics.prompt_tokens = (usage.promptTokenCount ?? 0) + (usage.toolUsePromptTokenCount ?? 0);
24247
26510
  }
24248
- if (usage.candidatesTokenCount !== void 0) {
24249
- metrics.completion_tokens = usage.candidatesTokenCount;
26511
+ if (usage.candidatesTokenCount !== void 0 || usage.thoughtsTokenCount !== void 0) {
26512
+ metrics.completion_tokens = (usage.candidatesTokenCount ?? 0) + (usage.thoughtsTokenCount ?? 0);
24250
26513
  }
24251
26514
  if (usage.totalTokenCount !== void 0) {
24252
26515
  metrics.tokens = usage.totalTokenCount;
@@ -24257,6 +26520,19 @@ function populateUsageMetrics2(metrics, usage) {
24257
26520
  if (usage.thoughtsTokenCount !== void 0) {
24258
26521
  metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
24259
26522
  }
26523
+ for (const detail of usage.promptTokensDetails ?? []) {
26524
+ if (detail.modality === "AUDIO" && detail.tokenCount !== void 0) {
26525
+ metrics.prompt_audio_tokens = (metrics.prompt_audio_tokens ?? 0) + detail.tokenCount;
26526
+ }
26527
+ }
26528
+ for (const detail of usage.candidatesTokensDetails ?? []) {
26529
+ if (detail.modality === "AUDIO" && detail.tokenCount !== void 0) {
26530
+ metrics.completion_audio_tokens = (metrics.completion_audio_tokens ?? 0) + detail.tokenCount;
26531
+ }
26532
+ if (detail.modality === "IMAGE" && detail.tokenCount !== void 0) {
26533
+ metrics.completion_image_tokens = (metrics.completion_image_tokens ?? 0) + detail.tokenCount;
26534
+ }
26535
+ }
24260
26536
  }
24261
26537
  function cleanMetrics4(metrics) {
24262
26538
  const cleaned = {};
@@ -27325,7 +29601,7 @@ var FlueObserveBridge = class {
27325
29601
  return;
27326
29602
  }
27327
29603
  const state = this.operationsById.get(event.operationId) ?? this.startSyntheticOperation(event);
27328
- const output = operationOutput(event);
29604
+ const output = operationOutput(event) ?? outputFromAgentTurn(state.latestAgentOutput);
27329
29605
  const metadata = {
27330
29606
  ...state.metadata,
27331
29607
  ...extractEventMetadata(event),
@@ -27334,7 +29610,7 @@ var FlueObserveBridge = class {
27334
29610
  };
27335
29611
  this.finishPendingChildrenForOperation(event, output);
27336
29612
  safeLog3(state.span, {
27337
- ...event.isError ? { error: toLoggedError(event.error) } : {},
29613
+ ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.error) } : {},
27338
29614
  metadata,
27339
29615
  metrics: durationMetrics2(event.durationMs),
27340
29616
  output
@@ -27365,7 +29641,7 @@ var FlueObserveBridge = class {
27365
29641
  };
27366
29642
  const parent = this.parentSpanForTurn(event);
27367
29643
  const span = startFlueSpan(parent, {
27368
- name: `llm:${model ?? event.purpose ?? "unknown"}`,
29644
+ name: "flue.turn",
27369
29645
  spanAttributes: { type: "llm" /* LLM */ },
27370
29646
  startTime: eventTime(event.timestamp),
27371
29647
  event: {
@@ -27409,6 +29685,12 @@ var FlueObserveBridge = class {
27409
29685
  },
27410
29686
  output
27411
29687
  });
29688
+ if (event.purpose === "agent" && event.operationId) {
29689
+ const operation = this.operationsById.get(event.operationId);
29690
+ if (operation) {
29691
+ operation.latestAgentOutput = output;
29692
+ }
29693
+ }
27412
29694
  safeEnd(state.span, eventTime(event.timestamp));
27413
29695
  this.turnsByKey.delete(key);
27414
29696
  }
@@ -27488,7 +29770,7 @@ var FlueObserveBridge = class {
27488
29770
  return;
27489
29771
  }
27490
29772
  safeLog3(state.span, {
27491
- ...event.isError ? { error: toLoggedError(event.result) } : {},
29773
+ ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.result) } : {},
27492
29774
  metadata: {
27493
29775
  ...state.metadata,
27494
29776
  ...extractEventMetadata(event),
@@ -27534,6 +29816,7 @@ var FlueObserveBridge = class {
27534
29816
  ...event.usage ? { "flue.usage": event.usage } : {}
27535
29817
  };
27536
29818
  safeLog3(state.span, {
29819
+ ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.error) } : {},
27537
29820
  metadata,
27538
29821
  metrics: {
27539
29822
  ...durationMetrics2(event.durationMs),
@@ -27638,7 +29921,7 @@ var FlueObserveBridge = class {
27638
29921
  ...event.purpose ? { "flue.turn_purpose": event.purpose } : {}
27639
29922
  };
27640
29923
  const span = startFlueSpan(this.parentSpanForEvent(event), {
27641
- name: `llm:${model ?? event.purpose ?? "unknown"}`,
29924
+ name: "flue.turn",
27642
29925
  spanAttributes: { type: "llm" /* LLM */ },
27643
29926
  startTime: eventTime(event.timestamp),
27644
29927
  event: { metadata }
@@ -27770,7 +30053,10 @@ function extractEventMetadata(event, ctx) {
27770
30053
  return {
27771
30054
  ...event.runId ? { "flue.run_id": event.runId } : {},
27772
30055
  ...event.instanceId ? { "flue.instance_id": event.instanceId } : {},
30056
+ ...event.submissionId ? { "flue.submission_id": event.submissionId } : {},
27773
30057
  ...event.dispatchId ? { "flue.dispatch_id": event.dispatchId } : {},
30058
+ ...event.agentName ? { "flue.agent_name": event.agentName } : {},
30059
+ ...event.conversationId ? { "flue.conversation_id": event.conversationId } : {},
27774
30060
  ...typeof event.eventIndex === "number" ? { "flue.event_index": event.eventIndex } : {},
27775
30061
  ...event.session ? { "flue.session": event.session } : {},
27776
30062
  ...event.parentSession ? { "flue.parent_session": event.parentSession } : {},
@@ -27799,7 +30085,7 @@ function flueTurnRequestInput(event) {
27799
30085
  return event.request?.input ?? event.input;
27800
30086
  }
27801
30087
  function flueTurnRequestModel(event) {
27802
- return event.request?.model ?? event.model;
30088
+ return event.request?.requestedModel ?? event.request?.model ?? event.model;
27803
30089
  }
27804
30090
  function flueTurnRequestProvider(event) {
27805
30091
  return event.request?.providerName ?? event.provider ?? event.request?.providerId;
@@ -27808,10 +30094,10 @@ function flueTurnRequestApi(event) {
27808
30094
  return event.request?.api ?? event.api;
27809
30095
  }
27810
30096
  function flueTurnRequestReasoning(event) {
27811
- return event.request?.reasoning ?? event.reasoning;
30097
+ return event.request?.reasoningLevel ?? event.request?.reasoning ?? event.reasoning;
27812
30098
  }
27813
30099
  function flueTurnModel(event) {
27814
- return event.request?.model ?? event.model;
30100
+ return event.response?.responseModel ?? event.request?.requestedModel ?? event.request?.model ?? event.model;
27815
30101
  }
27816
30102
  function flueTurnProvider(event) {
27817
30103
  return event.request?.providerName ?? event.provider ?? event.request?.providerId;
@@ -27826,7 +30112,7 @@ function flueTurnOutput(event) {
27826
30112
  return event.response?.output ?? event.output;
27827
30113
  }
27828
30114
  function flueTurnStopReason(event) {
27829
- return event.response?.stopReason ?? event.stopReason;
30115
+ return event.response?.finishReason ?? event.response?.stopReason ?? event.stopReason;
27830
30116
  }
27831
30117
  function flueTurnError(event) {
27832
30118
  return event.response?.error ?? event.response?.errorInfo?.message ?? event.error;
@@ -27841,6 +30127,9 @@ function flueToolInput(event) {
27841
30127
  return event.input;
27842
30128
  }
27843
30129
  function flueToolOutput(event) {
30130
+ if (Object.hasOwn(event, "effectiveResult")) {
30131
+ return event.effectiveResult;
30132
+ }
27844
30133
  return event.output !== void 0 ? event.output : event.result;
27845
30134
  }
27846
30135
  function flueToolError(event) {
@@ -27848,10 +30137,36 @@ function flueToolError(event) {
27848
30137
  }
27849
30138
  function operationOutput(event) {
27850
30139
  if (event.operationKind === "prompt" || event.operationKind === "skill") {
27851
- return llmResultFromOperationResult(event.result);
30140
+ return outputFromAgentInvocation(event.agentOutput) ?? llmResultFromOperationResult(event.result);
27852
30141
  }
27853
30142
  return event.result ?? (event.operationKind === "compact" ? { completed: true } : void 0);
27854
30143
  }
30144
+ function outputFromAgentInvocation(output) {
30145
+ if (output?.type === "text") {
30146
+ return output.text;
30147
+ }
30148
+ if (output?.type === "data") {
30149
+ return output.data;
30150
+ }
30151
+ return void 0;
30152
+ }
30153
+ function outputFromAgentTurn(output) {
30154
+ if (!isObjectLike(output)) {
30155
+ return output;
30156
+ }
30157
+ const content = Reflect.get(output, "content");
30158
+ if (!Array.isArray(content)) {
30159
+ return output;
30160
+ }
30161
+ const text = content.flatMap((part) => {
30162
+ if (!isObjectLike(part) || Reflect.get(part, "type") !== "text") {
30163
+ return [];
30164
+ }
30165
+ const value = Reflect.get(part, "text");
30166
+ return typeof value === "string" ? [value] : [];
30167
+ });
30168
+ return text.length > 0 ? text.join("") : output;
30169
+ }
27855
30170
  function llmResultFromOperationResult(result) {
27856
30171
  if (!isObjectLike(result)) {
27857
30172
  return result;
@@ -27950,7 +30265,7 @@ function safeEnd(span, endTime) {
27950
30265
  }
27951
30266
  }
27952
30267
  function logInstrumentationError3(label, error) {
27953
- console.error(`Error in ${label} instrumentation:`, error);
30268
+ debugLogger.debug(`Error in ${label} instrumentation:`, error);
27954
30269
  }
27955
30270
 
27956
30271
  // src/wrappers/langchain/callback-handler.ts
@@ -28622,7 +30937,7 @@ var LangSmithPlugin = class extends BasePlugin {
28622
30937
  const inputs = preferOwnValue(run, previous, "inputs");
28623
30938
  const outputs = preferOwnValue(run, previous, "outputs");
28624
30939
  const error = errorMessage(preferOwnValue(run, previous, "error"));
28625
- const metadata = extractMetadata(run, previous);
30940
+ const metadata = extractMetadata2(run, previous);
28626
30941
  const tags = extractTags(preferOwnValue(run, previous, "tags"));
28627
30942
  const metrics = extractMetrics(run, previous);
28628
30943
  span.log({
@@ -28727,7 +31042,7 @@ function mapRunType(runType) {
28727
31042
  return "task" /* TASK */;
28728
31043
  }
28729
31044
  }
28730
- function extractMetadata(run, previous) {
31045
+ function extractMetadata2(run, previous) {
28731
31046
  const extra = preferOwnValue(run, previous, "extra");
28732
31047
  const rawMetadata = ownValue(extra, "metadata");
28733
31048
  if (!isRecord2(rawMetadata)) {
@@ -28879,12 +31194,13 @@ var piCodingAgentChannels = defineChannels(
28879
31194
  );
28880
31195
 
28881
31196
  // src/instrumentation/plugins/pi-coding-agent-plugin.ts
28882
- var piStreamPatchStates = /* @__PURE__ */ new WeakMap();
31197
+ var piAgentPatchStates = /* @__PURE__ */ new WeakMap();
31198
+ var piAgentEventSubscriptions = /* @__PURE__ */ new WeakSet();
28883
31199
  var piPromptContextStore;
28884
31200
  var PiCodingAgentPlugin = class extends BasePlugin {
28885
31201
  activePromptStates = /* @__PURE__ */ new Set();
28886
31202
  onEnable() {
28887
- this.subscribeToPrompt();
31203
+ this.interceptPrompt();
28888
31204
  }
28889
31205
  onDisable() {
28890
31206
  for (const unsubscribe of this.unsubscribers) {
@@ -28892,65 +31208,74 @@ var PiCodingAgentPlugin = class extends BasePlugin {
28892
31208
  }
28893
31209
  this.unsubscribers = [];
28894
31210
  for (const state of [...this.activePromptStates]) {
28895
- void finalizePiPromptRun(state).catch((error) => {
28896
- logInstrumentationError4("Pi Coding Agent disable cleanup", error);
28897
- });
31211
+ finishPiPromptRun(state);
28898
31212
  }
28899
31213
  }
28900
- subscribeToPrompt() {
28901
- const channel2 = piCodingAgentChannels.prompt.tracingChannel();
28902
- const states = /* @__PURE__ */ new WeakMap();
28903
- const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(channel2);
28904
- const handlers = {
28905
- start: (event) => {
28906
- const state = startPiPromptRun(event, (state2) => {
28907
- this.activePromptStates.delete(state2);
28908
- });
28909
- if (state) {
28910
- this.activePromptStates.add(state);
28911
- states.set(event, state);
28912
- }
28913
- },
28914
- asyncEnd: async (event) => {
28915
- const state = states.get(event);
28916
- if (!state) {
28917
- return;
28918
- }
28919
- states.delete(event);
28920
- state.promptCallEnded = true;
28921
- if (!state.finalized && state.deferCompletionUntilTurnEnd && !state.turnEnded) {
28922
- if (!state.sawStreamFn) {
28923
- state.queued = true;
28924
- if (!state.streamPatchState.queuedPromptStates.includes(state)) {
28925
- state.streamPatchState.queuedPromptStates.push(state);
28926
- }
31214
+ interceptPrompt() {
31215
+ this.unsubscribers.push(
31216
+ piCodingAgentChannels.prompt.intercept(
31217
+ (target, thisArg, args, additional) => {
31218
+ const invokeTarget = () => Reflect.apply(target, thisArg, args);
31219
+ let state;
31220
+ try {
31221
+ state = startPiPromptRun(
31222
+ {
31223
+ ...additional,
31224
+ arguments: args,
31225
+ self: thisArg
31226
+ },
31227
+ (finalizedState) => {
31228
+ this.activePromptStates.delete(finalizedState);
31229
+ }
31230
+ );
31231
+ } catch (error) {
31232
+ logInstrumentationError4("Pi Coding Agent prompt start", error);
28927
31233
  }
28928
- return;
28929
- }
28930
- await finalizePiPromptRun(state);
28931
- },
28932
- error: async (event) => {
28933
- const state = states.get(event);
28934
- if (!state) {
28935
- return;
31234
+ if (!state) {
31235
+ return runWithAutoInstrumentationSuppressed(invokeTarget);
31236
+ }
31237
+ this.activePromptStates.add(state);
31238
+ return promptContextStore().run(
31239
+ state,
31240
+ () => runWithAutoInstrumentationSuppressed(() => {
31241
+ let result;
31242
+ try {
31243
+ result = invokeTarget();
31244
+ } catch (error) {
31245
+ finishPiPromptRun(state, error);
31246
+ throw error;
31247
+ }
31248
+ return Promise.resolve(result).then(
31249
+ (value) => {
31250
+ finishPiPromptCall(state);
31251
+ return value;
31252
+ },
31253
+ (error) => {
31254
+ finishPiPromptRun(state, error);
31255
+ throw error;
31256
+ }
31257
+ );
31258
+ })
31259
+ );
28936
31260
  }
28937
- states.delete(event);
28938
- await finalizePiPromptRun(state, event.error);
28939
- }
28940
- };
28941
- channel2.subscribe(handlers);
28942
- this.unsubscribers.push(() => {
28943
- unbindAutoInstrumentationSuppression?.();
28944
- channel2.unsubscribe(handlers);
28945
- });
31261
+ )
31262
+ );
28946
31263
  }
28947
31264
  };
31265
+ function finishPiPromptCall(state) {
31266
+ state.promptCallEnded = true;
31267
+ if (state.deferCompletionUntilTurnEnd && !state.turnEnded) {
31268
+ return;
31269
+ }
31270
+ finishPiPromptRun(state);
31271
+ }
28948
31272
  function startPiPromptRun(event, onFinalize) {
28949
31273
  const session = extractSession(event);
28950
31274
  const agent = session?.agent;
28951
31275
  if (!session || !isPiAgent(agent)) {
28952
31276
  return void 0;
28953
31277
  }
31278
+ installPiAgentInstrumentation(agent);
28954
31279
  const metadata = {
28955
31280
  ...extractSessionMetadata(session),
28956
31281
  ...extractPromptOptionsMetadata(event.arguments[1]),
@@ -28972,9 +31297,7 @@ function startPiPromptRun(event, onFinalize) {
28972
31297
  INSTRUMENTATION_NAMES.PI_CODING_AGENT
28973
31298
  )
28974
31299
  );
28975
- const streamPatchState = installPiStreamPatch(agent);
28976
31300
  const options = event.arguments[1];
28977
- const promptText = event.arguments[0];
28978
31301
  const state = {
28979
31302
  activeLlmSpans: /* @__PURE__ */ new Set(),
28980
31303
  activeToolSpans: /* @__PURE__ */ new Map(),
@@ -28986,29 +31309,10 @@ function startPiPromptRun(event, onFinalize) {
28986
31309
  metrics: {},
28987
31310
  onFinalize,
28988
31311
  promptCallEnded: false,
28989
- ...typeof promptText === "string" ? { promptText } : {},
28990
- queued: false,
28991
31312
  span,
28992
- sawStreamFn: false,
28993
31313
  startTime: getCurrentUnixTimestamp(),
28994
- streamPatchState,
28995
31314
  turnEnded: false
28996
31315
  };
28997
- state.restorePromptContext = enterPiPromptContext(state);
28998
- streamPatchState.activePromptStates.add(state);
28999
- try {
29000
- state.unsubscribeAgent = agent.subscribe(async (agentEvent) => {
29001
- try {
29002
- await runWithAutoInstrumentationSuppressed(
29003
- () => handlePiAgentEvent(state, agentEvent)
29004
- );
29005
- } catch (error) {
29006
- logInstrumentationError4("Pi Coding Agent event", error);
29007
- }
29008
- });
29009
- } catch (error) {
29010
- logInstrumentationError4("Pi Coding Agent event subscription", error);
29011
- }
29012
31316
  return state;
29013
31317
  }
29014
31318
  function extractSession(event) {
@@ -29022,111 +31326,55 @@ function promptContextStore() {
29022
31326
  piPromptContextStore ??= isomorph_default.newAsyncLocalStorage();
29023
31327
  return piPromptContextStore;
29024
31328
  }
29025
- function currentPromptContextFrames() {
29026
- return promptContextStore().getStore()?.frames ?? [];
29027
- }
29028
31329
  function currentPiPromptState() {
29029
- const frames = currentPromptContextFrames();
29030
- return frames[frames.length - 1]?.state;
29031
- }
29032
- function enterPiPromptContext(state) {
29033
- const frame = {
29034
- id: /* @__PURE__ */ Symbol("braintrust.pi-coding-agent.prompt"),
29035
- state
29036
- };
29037
- promptContextStore().enterWith({
29038
- frames: [...currentPromptContextFrames(), frame]
29039
- });
29040
- return () => {
29041
- const frames = currentPromptContextFrames().filter(
29042
- (candidate) => candidate.id !== frame.id
29043
- );
29044
- promptContextStore().enterWith(frames.length > 0 ? { frames } : void 0);
29045
- };
29046
- }
29047
- function installPiStreamPatch(agent) {
29048
- const existing = piStreamPatchStates.get(agent);
29049
- if (existing) {
29050
- if (agent.streamFn !== existing.wrappedStreamFn) {
29051
- debugLogger.debug(
29052
- "Pi Coding Agent streamFn changed while Braintrust instrumentation was active; preserving existing patch state."
29053
- );
29054
- }
29055
- return existing;
29056
- }
29057
- const patchState = {
29058
- activePromptStates: /* @__PURE__ */ new Set(),
29059
- agent,
29060
- originalStreamFn: agent.streamFn,
29061
- queuedPromptStates: [],
29062
- wrappedStreamFn: agent.streamFn
29063
- };
29064
- patchState.wrappedStreamFn = makeSharedInstrumentedStreamFn(patchState);
29065
- agent.streamFn = patchState.wrappedStreamFn;
29066
- piStreamPatchStates.set(agent, patchState);
29067
- return patchState;
29068
- }
29069
- function resolveStreamPromptState(patchState, context) {
29070
- let lastUserText;
29071
- if (Array.isArray(context.messages)) {
29072
- for (let i = context.messages.length - 1; i >= 0; i--) {
29073
- const message = context.messages[i];
29074
- if (isPiUserMessage(message)) {
29075
- if (typeof message.content === "string") {
29076
- lastUserText = message.content;
29077
- } else {
29078
- lastUserText = message.content.flatMap((part) => part.type === "text" ? [part.text] : []).join("");
29079
- }
29080
- break;
29081
- }
29082
- }
29083
- }
29084
- if (lastUserText !== void 0) {
29085
- const queuedMatch = patchState.queuedPromptStates.find(
29086
- (state) => state.promptText === lastUserText
29087
- );
29088
- if (queuedMatch) {
29089
- return queuedMatch;
29090
- }
29091
- const matches = [...patchState.activePromptStates].filter(
29092
- (state) => state.promptText === lastUserText
31330
+ return promptContextStore().getStore();
31331
+ }
31332
+ function installPiAgentInstrumentation(agent) {
31333
+ const existing = piAgentPatchStates.get(agent);
31334
+ if (!existing || agent.streamFn !== existing.wrappedStreamFn) {
31335
+ const patchState = {
31336
+ originalStreamFn: agent.streamFn,
31337
+ wrappedStreamFn: agent.streamFn
31338
+ };
31339
+ patchState.wrappedStreamFn = makeInstrumentedStreamFn(
31340
+ agent,
31341
+ patchState.originalStreamFn
29093
31342
  );
29094
- if (matches.length === 1) {
29095
- return matches[0];
29096
- }
31343
+ agent.streamFn = patchState.wrappedStreamFn;
31344
+ piAgentPatchStates.set(agent, patchState);
29097
31345
  }
29098
- const contextState = currentPiPromptState();
29099
- if (contextState && patchState.activePromptStates.has(contextState) && (!contextState.queued || lastUserText !== void 0 && contextState.promptText === lastUserText)) {
29100
- return contextState;
31346
+ if (piAgentEventSubscriptions.has(agent)) {
31347
+ return;
29101
31348
  }
29102
- if (patchState.activePromptStates.size === 1) {
29103
- return [...patchState.activePromptStates][0];
31349
+ try {
31350
+ agent.subscribe(async (event) => {
31351
+ const state = currentPiPromptState();
31352
+ if (!state || state.agent !== agent || state.finalized) {
31353
+ return;
31354
+ }
31355
+ try {
31356
+ await runWithAutoInstrumentationSuppressed(
31357
+ () => handlePiAgentEvent(state, event)
31358
+ );
31359
+ } catch (error) {
31360
+ logInstrumentationError4("Pi Coding Agent event", error);
31361
+ }
31362
+ });
31363
+ piAgentEventSubscriptions.add(agent);
31364
+ } catch (error) {
31365
+ logInstrumentationError4("Pi Coding Agent event subscription", error);
29104
31366
  }
29105
- return void 0;
29106
31367
  }
29107
- function makeSharedInstrumentedStreamFn(patchState) {
31368
+ function makeInstrumentedStreamFn(agent, originalStreamFn) {
29108
31369
  return async function instrumentedPiStreamFn(model, context, options) {
29109
- const state = resolveStreamPromptState(patchState, context);
29110
- if (!state) {
29111
- const invokeOriginal = () => Reflect.apply(patchState.originalStreamFn, this, [
29112
- model,
29113
- context,
29114
- options
29115
- ]);
29116
- return patchState.activePromptStates.size > 0 ? runWithAutoInstrumentationSuppressed(invokeOriginal) : invokeOriginal();
31370
+ const invokeOriginal = () => Reflect.apply(originalStreamFn, this, [model, context, options]);
31371
+ const state = currentPiPromptState();
31372
+ if (!state || state.agent !== agent || state.finalized) {
31373
+ return invokeOriginal();
29117
31374
  }
29118
- state.sawStreamFn = true;
29119
- removeQueuedPromptState(state);
29120
- state.streamPatchState.eventPromptState = state;
29121
31375
  const llmState = await startPiLlmSpan(state, model, context, options);
29122
31376
  try {
29123
- const stream = await runWithAutoInstrumentationSuppressed(
29124
- () => Reflect.apply(patchState.originalStreamFn, this, [
29125
- model,
29126
- context,
29127
- options
29128
- ])
29129
- );
31377
+ const stream = await runWithAutoInstrumentationSuppressed(invokeOriginal);
29130
31378
  return patchAssistantMessageStream(stream, state, llmState);
29131
31379
  } catch (error) {
29132
31380
  finishPiLlmSpan(state, llmState, void 0, error);
@@ -29273,13 +31521,6 @@ async function handlePiAgentEvent(state, event) {
29273
31521
  if (state.finalized) {
29274
31522
  return;
29275
31523
  }
29276
- const eventPromptState = state.streamPatchState.eventPromptState;
29277
- if (eventPromptState && eventPromptState !== state) {
29278
- return;
29279
- }
29280
- if (!eventPromptState && (state.queued || state.streamPatchState.activePromptStates.size > 1 && currentPiPromptState() !== state)) {
29281
- return;
29282
- }
29283
31524
  switch (event.type) {
29284
31525
  case "message_end":
29285
31526
  if (isPiAssistantMessage(event.message)) {
@@ -29294,11 +31535,8 @@ async function handlePiAgentEvent(state, event) {
29294
31535
  addMetrics(state.metrics, extractUsageMetrics2(event.message.usage));
29295
31536
  }
29296
31537
  }
29297
- if (state.streamPatchState.eventPromptState === state) {
29298
- state.streamPatchState.eventPromptState = void 0;
29299
- }
29300
31538
  if (state.promptCallEnded && state.deferCompletionUntilTurnEnd) {
29301
- await finalizePiPromptRun(state);
31539
+ finishPiPromptRun(state);
29302
31540
  }
29303
31541
  return;
29304
31542
  case "tool_execution_start":
@@ -29371,19 +31609,13 @@ function finishPiToolSpan(state, event) {
29371
31609
  }
29372
31610
  }
29373
31611
  }
29374
- async function finalizePiPromptRun(state, error) {
31612
+ function finishPiPromptRun(state, error) {
29375
31613
  if (state.finalized) {
29376
31614
  return;
29377
31615
  }
29378
31616
  state.finalized = true;
29379
31617
  state.onFinalize?.(state);
29380
- restorePiStreamFn(state);
29381
- try {
29382
- state.unsubscribeAgent?.();
29383
- } catch (unsubscribeError) {
29384
- logInstrumentationError4("Pi Coding Agent unsubscribe", unsubscribeError);
29385
- }
29386
- await finishOpenLlmSpans(state, error);
31618
+ finishOpenLlmSpans(state, error);
29387
31619
  finishOpenToolSpans(state, error);
29388
31620
  const metadata = {
29389
31621
  ...state.metadata,
@@ -29400,34 +31632,14 @@ async function finalizePiPromptRun(state, error) {
29400
31632
  output: state.output
29401
31633
  });
29402
31634
  } finally {
29403
- state.span.end();
29404
- }
29405
- }
29406
- function restorePiStreamFn(state) {
29407
- const patchState = state.streamPatchState;
29408
- patchState.activePromptStates.delete(state);
29409
- removeQueuedPromptState(state);
29410
- if (patchState.eventPromptState === state) {
29411
- patchState.eventPromptState = void 0;
29412
- }
29413
- state.restorePromptContext?.();
29414
- if (patchState.activePromptStates.size > 0) {
29415
- return;
29416
- }
29417
- if (patchState.agent.streamFn === patchState.wrappedStreamFn) {
29418
- patchState.agent.streamFn = patchState.originalStreamFn;
29419
- }
29420
- piStreamPatchStates.delete(patchState.agent);
29421
- }
29422
- function removeQueuedPromptState(state) {
29423
- state.queued = false;
29424
- const queuedPromptStates = state.streamPatchState.queuedPromptStates;
29425
- const index = queuedPromptStates.indexOf(state);
29426
- if (index >= 0) {
29427
- queuedPromptStates.splice(index, 1);
31635
+ try {
31636
+ state.span.end();
31637
+ } catch (endError) {
31638
+ logInstrumentationError4("Pi Coding Agent prompt end", endError);
31639
+ }
29428
31640
  }
29429
31641
  }
29430
- async function finishOpenLlmSpans(state, error) {
31642
+ function finishOpenLlmSpans(state, error) {
29431
31643
  for (const llmState of [...state.activeLlmSpans]) {
29432
31644
  finishPiLlmSpan(state, llmState, void 0, error);
29433
31645
  }
@@ -29508,7 +31720,7 @@ function normalizeAssistantMessage(message) {
29508
31720
  (part) => part.type === "thinking" && !part.redacted ? [part.thinking] : []
29509
31721
  ).join("");
29510
31722
  const toolCalls = message.content.flatMap(
29511
- (part) => part.type === "toolCall" ? [normalizeToolCall(part)] : []
31723
+ (part) => part.type === "toolCall" ? [normalizeToolCall2(part)] : []
29512
31724
  );
29513
31725
  return {
29514
31726
  role: "assistant",
@@ -29543,13 +31755,13 @@ function normalizeUserContent(content) {
29543
31755
  return part;
29544
31756
  });
29545
31757
  }
29546
- function normalizeToolCall(toolCall) {
31758
+ function normalizeToolCall2(toolCall) {
29547
31759
  return {
29548
31760
  id: toolCall.id,
29549
31761
  type: "function",
29550
31762
  function: {
29551
31763
  name: toolCall.name,
29552
- arguments: stringifyArguments(toolCall.arguments)
31764
+ arguments: stringifyArguments2(toolCall.arguments)
29553
31765
  }
29554
31766
  };
29555
31767
  }
@@ -29732,7 +31944,7 @@ function cleanMetrics5(metrics) {
29732
31944
  }
29733
31945
  return cleaned;
29734
31946
  }
29735
- function stringifyArguments(value) {
31947
+ function stringifyArguments2(value) {
29736
31948
  if (typeof value === "string") {
29737
31949
  return value;
29738
31950
  }
@@ -30100,6 +32312,15 @@ function handleMultiAgentStreamEvent(state, event, activeChildParents) {
30100
32312
  logInstrumentationError5("Strands Agent SDK multi-agent event", error);
30101
32313
  }
30102
32314
  }
32315
+ function buildModelSpanInput(event, attachmentCache) {
32316
+ const systemPrompt = typeof event.agent?.systemPrompt === "string" && event.agent.systemPrompt.length > 0 ? event.agent.systemPrompt : void 0;
32317
+ const processedMessages = Array.isArray(event.agent?.messages) ? processStrandsInputAttachments(event.agent.messages, attachmentCache) : void 0;
32318
+ if (!systemPrompt) {
32319
+ return processedMessages;
32320
+ }
32321
+ const systemMessage = { role: "system", content: systemPrompt };
32322
+ return Array.isArray(processedMessages) ? [systemMessage, ...processedMessages] : [systemMessage];
32323
+ }
30103
32324
  function startModelSpan(state, event) {
30104
32325
  if (state.activeModel) {
30105
32326
  finalizeModelSpan(state);
@@ -30117,10 +32338,7 @@ function startModelSpan(state, event) {
30117
32338
  withSpanInstrumentationName(
30118
32339
  {
30119
32340
  event: {
30120
- input: Array.isArray(event.agent?.messages) ? processStrandsInputAttachments(
30121
- event.agent.messages,
30122
- state.attachmentCache
30123
- ) : void 0,
32341
+ input: buildModelSpanInput(event, state.attachmentCache),
30124
32342
  metadata
30125
32343
  },
30126
32344
  name: formatModelSpanName(model),
@@ -30760,6 +32978,532 @@ function logInstrumentationError5(context, error) {
30760
32978
  debugLogger.debug(`${context}:`, error);
30761
32979
  }
30762
32980
 
32981
+ // src/instrumentation/plugins/cloudflare-ai-chat-channels.ts
32982
+ var cloudflareAIChatChannels = defineChannels(
32983
+ "@cloudflare/ai-chat",
32984
+ {
32985
+ runExclusiveChatTurn: channel({
32986
+ channelName: "AIChatAgent._runExclusiveChatTurn",
32987
+ kind: "async"
32988
+ }),
32989
+ onChatResponse: channel({
32990
+ channelName: "AIChatAgent.onChatResponse",
32991
+ kind: "sync-stream"
32992
+ })
32993
+ },
32994
+ { instrumentationName: INSTRUMENTATION_NAMES.CLOUDFLARE_AI_CHAT }
32995
+ );
32996
+
32997
+ // src/instrumentation/plugins/cloudflare-ai-chat-instrumentation.ts
32998
+ var wrappedResponseHooks = /* @__PURE__ */ new WeakSet();
32999
+ function instrumentCloudflareAIChatResponseHook(agent) {
33000
+ try {
33001
+ const original = Reflect.get(agent, "onChatResponse");
33002
+ if (typeof original !== "function" || wrappedResponseHooks.has(original)) {
33003
+ return;
33004
+ }
33005
+ const wrapped = function(result) {
33006
+ const args = [result];
33007
+ return cloudflareAIChatChannels.onChatResponse.traceSync(
33008
+ () => Reflect.apply(original, this, args),
33009
+ {
33010
+ arguments: args,
33011
+ self: this
33012
+ }
33013
+ );
33014
+ };
33015
+ wrappedResponseHooks.add(wrapped);
33016
+ defineWrappedMethod(agent, "onChatResponse", original, wrapped);
33017
+ } catch (error) {
33018
+ debugLogger.debug(
33019
+ "Failed to wrap @cloudflare/ai-chat response hook:",
33020
+ error
33021
+ );
33022
+ }
33023
+ }
33024
+ function defineWrappedMethod(target, property, original, wrapped) {
33025
+ const ownDescriptor = Object.getOwnPropertyDescriptor(target, property);
33026
+ Object.defineProperty(target, property, {
33027
+ configurable: ownDescriptor?.configurable ?? true,
33028
+ enumerable: ownDescriptor?.enumerable ?? false,
33029
+ value: wrapped,
33030
+ writable: ownDescriptor && "writable" in ownDescriptor ? ownDescriptor.writable : true
33031
+ });
33032
+ try {
33033
+ Object.defineProperty(wrapped, "name", {
33034
+ configurable: true,
33035
+ value: original.name
33036
+ });
33037
+ } catch {
33038
+ }
33039
+ }
33040
+
33041
+ // src/instrumentation/plugins/cloudflare-ai-chat-plugin.ts
33042
+ var BLOCKED_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
33043
+ var RESPONSE_STATE_RETENTION_MS = 6e4;
33044
+ var CloudflareAIChatPlugin = class extends BasePlugin {
33045
+ activeStates = /* @__PURE__ */ new Set();
33046
+ activeTurns = /* @__PURE__ */ new WeakMap();
33047
+ eventStates = /* @__PURE__ */ new WeakMap();
33048
+ onEnable() {
33049
+ this.subscribeToResponseHook();
33050
+ this.subscribeToTurnRunner();
33051
+ }
33052
+ onDisable() {
33053
+ for (const unsubscribe of this.unsubscribers) {
33054
+ unsubscribe();
33055
+ }
33056
+ this.unsubscribers = [];
33057
+ for (const state of this.activeStates) {
33058
+ this.cleanupState(state);
33059
+ }
33060
+ this.activeStates.clear();
33061
+ }
33062
+ subscribeToTurnRunner() {
33063
+ const tracingChannel = cloudflareAIChatChannels.runExclusiveChatTurn.tracingChannel();
33064
+ const unbindCurrentSpanStore = this.bindCurrentSpanStore(tracingChannel);
33065
+ const handlers = {
33066
+ start: (event) => {
33067
+ this.ensureEventState(event);
33068
+ },
33069
+ asyncEnd: (event) => {
33070
+ this.finishEvent(event);
33071
+ },
33072
+ error: (event) => {
33073
+ this.finishEvent(event, event.error);
33074
+ }
33075
+ };
33076
+ tracingChannel.subscribe(handlers);
33077
+ this.unsubscribers.push(() => {
33078
+ unbindCurrentSpanStore?.();
33079
+ tracingChannel.unsubscribe(handlers);
33080
+ });
33081
+ }
33082
+ subscribeToResponseHook() {
33083
+ const tracingChannel = cloudflareAIChatChannels.onChatResponse.tracingChannel();
33084
+ const handlers = {
33085
+ start: (event) => {
33086
+ let state;
33087
+ try {
33088
+ const agent = asObject(event.self);
33089
+ const result = event.arguments[0];
33090
+ state = agent ? this.findResponseState(
33091
+ agent,
33092
+ stringValue3(ownValue2(result, "requestId"))
33093
+ ) : void 0;
33094
+ if (!state) {
33095
+ return;
33096
+ }
33097
+ state.responseObserved = true;
33098
+ const output = serializeMessage(ownValue2(result, "message"));
33099
+ const status = stringValue3(ownValue2(result, "status"));
33100
+ const error = ownValue2(result, "error");
33101
+ const input = ownValue2(result, "continuation") === true ? state.input : serializeMessages(readProperty(agent, "messages"))?.filter(
33102
+ (message) => typeof output?.id !== "string" || message.id !== output.id
33103
+ );
33104
+ state.span.log({
33105
+ ...input !== void 0 ? { input } : {},
33106
+ ...output !== void 0 ? { output } : {},
33107
+ ...status === "error" && error !== void 0 ? { error } : {}
33108
+ });
33109
+ } catch (error) {
33110
+ debugLogger.debug(
33111
+ "Failed to process @cloudflare/ai-chat response hook:",
33112
+ error
33113
+ );
33114
+ } finally {
33115
+ if (state?.settled) {
33116
+ this.cleanupState(state);
33117
+ }
33118
+ }
33119
+ }
33120
+ };
33121
+ tracingChannel.subscribe(handlers);
33122
+ this.unsubscribers.push(() => tracingChannel.unsubscribe(handlers));
33123
+ }
33124
+ bindCurrentSpanStore(tracingChannel) {
33125
+ const globalState = _internalGetGlobalState();
33126
+ const contextManager = globalState?.contextManager;
33127
+ const startChannel = tracingChannel.start;
33128
+ const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
33129
+ if (!startChannel || !currentSpanStore || !contextManager) {
33130
+ return void 0;
33131
+ }
33132
+ startChannel.bindStore(currentSpanStore, (event) => {
33133
+ const state = this.ensureEventState(event);
33134
+ return state ? contextManager.wrapSpanForStore(state.span) : currentSpanStore.getStore();
33135
+ });
33136
+ return () => startChannel.unbindStore(currentSpanStore);
33137
+ }
33138
+ ensureEventState(event) {
33139
+ const eventKey = event;
33140
+ const known = this.eventStates.get(eventKey);
33141
+ if (known) {
33142
+ return known;
33143
+ }
33144
+ try {
33145
+ const agent = asObject(event.self);
33146
+ const requestId = stringValue3(event.arguments[0]);
33147
+ const key = requestId ?? /* @__PURE__ */ Symbol("cloudflare-ai-chat-turn");
33148
+ const activeForAgent = agent ? this.getActiveTurns(agent) : void 0;
33149
+ const existing = activeForAgent?.get(key);
33150
+ const state = existing && !existing.settled ? existing : this.createTurnState(agent, key);
33151
+ if (existing && !existing.settled) {
33152
+ state.depth += 1;
33153
+ }
33154
+ this.eventStates.set(eventKey, state);
33155
+ this.bindTurnCallback(event, agent, state);
33156
+ if (agent) {
33157
+ instrumentCloudflareAIChatResponseHook(agent);
33158
+ }
33159
+ return state;
33160
+ } catch (error) {
33161
+ debugLogger.debug(
33162
+ "Failed to start @cloudflare/ai-chat instrumentation:",
33163
+ error
33164
+ );
33165
+ return void 0;
33166
+ }
33167
+ }
33168
+ createTurnState(agent, key) {
33169
+ const span = startSpan(
33170
+ withSpanInstrumentationName(
33171
+ {
33172
+ name: "AIChatAgent.onChatMessage",
33173
+ spanAttributes: { type: "task" /* TASK */ }
33174
+ },
33175
+ INSTRUMENTATION_NAMES.CLOUDFLARE_AI_CHAT
33176
+ )
33177
+ );
33178
+ const state = {
33179
+ agent,
33180
+ depth: 1,
33181
+ ended: false,
33182
+ key,
33183
+ responseObserved: false,
33184
+ settled: false,
33185
+ span
33186
+ };
33187
+ this.activeStates.add(state);
33188
+ if (agent) {
33189
+ this.getActiveTurns(agent).set(key, state);
33190
+ }
33191
+ return state;
33192
+ }
33193
+ bindTurnCallback(event, agent, state) {
33194
+ const callback = event.arguments[1];
33195
+ if (typeof callback !== "function") {
33196
+ return;
33197
+ }
33198
+ try {
33199
+ event.arguments[1] = function(...args) {
33200
+ return withCurrent(state.span, () => {
33201
+ try {
33202
+ const input = serializeMessages(readProperty(agent, "messages"));
33203
+ if (input !== void 0 && state.input === void 0) {
33204
+ state.input = input;
33205
+ state.span.log({ input });
33206
+ }
33207
+ } catch (error) {
33208
+ debugLogger.debug(
33209
+ "Failed to capture @cloudflare/ai-chat messages:",
33210
+ error
33211
+ );
33212
+ }
33213
+ return Reflect.apply(callback, this, args);
33214
+ });
33215
+ };
33216
+ } catch (error) {
33217
+ debugLogger.debug(
33218
+ "Failed to bind @cloudflare/ai-chat turn callback context:",
33219
+ error
33220
+ );
33221
+ }
33222
+ }
33223
+ finishEvent(event, error) {
33224
+ const eventKey = event;
33225
+ const state = this.eventStates.get(eventKey);
33226
+ if (!state || state.ended) {
33227
+ return;
33228
+ }
33229
+ this.eventStates.delete(eventKey);
33230
+ if (error !== void 0 && state.pendingError === void 0) {
33231
+ state.pendingError = error;
33232
+ }
33233
+ state.depth -= 1;
33234
+ if (state.depth === 0) {
33235
+ state.settled = true;
33236
+ this.endState(state);
33237
+ if (state.responseObserved || error !== void 0) {
33238
+ this.cleanupState(state);
33239
+ } else {
33240
+ state.cleanupTimer = setTimeout(
33241
+ () => this.cleanupState(state),
33242
+ RESPONSE_STATE_RETENTION_MS
33243
+ );
33244
+ if (typeof state.cleanupTimer === "object" && state.cleanupTimer !== null && "unref" in state.cleanupTimer && typeof state.cleanupTimer.unref === "function") {
33245
+ state.cleanupTimer.unref();
33246
+ }
33247
+ }
33248
+ }
33249
+ }
33250
+ endState(state) {
33251
+ if (state.ended) {
33252
+ return;
33253
+ }
33254
+ state.ended = true;
33255
+ try {
33256
+ if (state.pendingError !== void 0) {
33257
+ state.span.log({ error: state.pendingError });
33258
+ }
33259
+ } finally {
33260
+ state.span.end();
33261
+ }
33262
+ }
33263
+ cleanupState(state) {
33264
+ if (state.cleanupTimer !== void 0) {
33265
+ clearTimeout(state.cleanupTimer);
33266
+ state.cleanupTimer = void 0;
33267
+ }
33268
+ try {
33269
+ this.endState(state);
33270
+ } finally {
33271
+ this.activeStates.delete(state);
33272
+ if (state.agent) {
33273
+ const activeForAgent = this.activeTurns.get(state.agent);
33274
+ if (activeForAgent?.get(state.key) === state) {
33275
+ activeForAgent.delete(state.key);
33276
+ }
33277
+ }
33278
+ }
33279
+ }
33280
+ getActiveTurns(agent) {
33281
+ let turns = this.activeTurns.get(agent);
33282
+ if (!turns) {
33283
+ turns = /* @__PURE__ */ new Map();
33284
+ this.activeTurns.set(agent, turns);
33285
+ }
33286
+ return turns;
33287
+ }
33288
+ findResponseState(agent, requestId) {
33289
+ const turns = this.activeTurns.get(agent);
33290
+ if (!turns) {
33291
+ return void 0;
33292
+ }
33293
+ if (requestId !== void 0) {
33294
+ return turns.get(requestId);
33295
+ }
33296
+ const active = [...turns.values()];
33297
+ return active.length === 1 ? active[0] : void 0;
33298
+ }
33299
+ };
33300
+ function asObject(value) {
33301
+ return value !== null && (typeof value === "object" || typeof value === "function") ? value : void 0;
33302
+ }
33303
+ function readProperty(value, key) {
33304
+ const object = asObject(value);
33305
+ return object ? Reflect.get(object, key) : void 0;
33306
+ }
33307
+ function ownValue2(value, key) {
33308
+ const object = asObject(value);
33309
+ if (!object) {
33310
+ return void 0;
33311
+ }
33312
+ const descriptor = Object.getOwnPropertyDescriptor(object, key);
33313
+ return descriptor && "value" in descriptor ? descriptor.value : void 0;
33314
+ }
33315
+ function stringValue3(value) {
33316
+ return typeof value === "string" ? value : void 0;
33317
+ }
33318
+ function serializeMessages(value) {
33319
+ if (!Array.isArray(value)) {
33320
+ return void 0;
33321
+ }
33322
+ return value.flatMap((message) => {
33323
+ const serialized = serializeMessage(message);
33324
+ return serialized === void 0 ? [] : [serialized];
33325
+ });
33326
+ }
33327
+ function serializeMessage(value) {
33328
+ const message = asObject(value);
33329
+ if (!message) {
33330
+ return void 0;
33331
+ }
33332
+ const serialized = [];
33333
+ const id = ownValue2(message, "id");
33334
+ const role = ownValue2(message, "role");
33335
+ const parts = ownValue2(message, "parts");
33336
+ if (typeof id === "string") {
33337
+ serialized.push(["id", id]);
33338
+ }
33339
+ if (typeof role === "string") {
33340
+ serialized.push(["role", role]);
33341
+ }
33342
+ const sanitizedParts = sanitizeLoggedValue2(parts);
33343
+ if (sanitizedParts !== void 0) {
33344
+ serialized.push(["parts", sanitizedParts]);
33345
+ }
33346
+ return serialized.length > 0 ? Object.fromEntries(serialized) : void 0;
33347
+ }
33348
+ function sanitizeLoggedValue2(value, seen = /* @__PURE__ */ new WeakSet(), depth = 0) {
33349
+ if (value === null || typeof value === "string" || typeof value === "boolean") {
33350
+ return value;
33351
+ }
33352
+ if (typeof value === "number") {
33353
+ return Number.isFinite(value) ? value : void 0;
33354
+ }
33355
+ const object = asObject(value);
33356
+ if (!object || depth >= 20 || typeof value === "function") {
33357
+ return void 0;
33358
+ }
33359
+ if (seen.has(object)) {
33360
+ return "[Circular]";
33361
+ }
33362
+ seen.add(object);
33363
+ if (Array.isArray(value)) {
33364
+ return value.map((entry) => sanitizeLoggedValue2(entry, seen, depth + 1));
33365
+ }
33366
+ const entries = [];
33367
+ for (const [key, descriptor] of Object.entries(
33368
+ Object.getOwnPropertyDescriptors(object)
33369
+ )) {
33370
+ if (BLOCKED_KEYS.has(key) || !descriptor.enumerable || !("value" in descriptor)) {
33371
+ continue;
33372
+ }
33373
+ const sanitized = sanitizeLoggedValue2(descriptor.value, seen, depth + 1);
33374
+ if (sanitized !== void 0) {
33375
+ entries.push([key, sanitized]);
33376
+ }
33377
+ }
33378
+ return Object.fromEntries(entries);
33379
+ }
33380
+
33381
+ // src/instrumentation/plugins/cloudflare-agents-channels.ts
33382
+ var cloudflareAgentsChannels = defineChannels(
33383
+ "agents",
33384
+ {
33385
+ runAgentTool: channel({
33386
+ channelName: "Agent.runAgentTool",
33387
+ kind: "async"
33388
+ })
33389
+ },
33390
+ { instrumentationName: INSTRUMENTATION_NAMES.CLOUDFLARE_AGENTS }
33391
+ );
33392
+
33393
+ // src/instrumentation/plugins/cloudflare-agents-plugin.ts
33394
+ var CLOUDFLARE_WORKERS_CONTEXT = {
33395
+ span_origin: {
33396
+ environment: { type: "server", name: "cloudflare_workers" }
33397
+ }
33398
+ };
33399
+ var CloudflareAgentsPlugin = class extends BasePlugin {
33400
+ onEnable() {
33401
+ const channel2 = cloudflareAgentsChannels.runAgentTool.tracingChannel();
33402
+ const spans = /* @__PURE__ */ new WeakMap();
33403
+ const handlers = {
33404
+ start: (event) => {
33405
+ try {
33406
+ const agentClass = event.arguments[0];
33407
+ const options = event.arguments[1];
33408
+ if (ownValue3(options, "detached")) {
33409
+ return;
33410
+ }
33411
+ const name = ownValue3(agentClass, "name");
33412
+ if (typeof name !== "string" || name.length === 0) {
33413
+ debugLogger.warn(
33414
+ "Skipping Cloudflare Agents runAgentTool span because the child agent class has no name."
33415
+ );
33416
+ return;
33417
+ }
33418
+ const span = _internalStartSpanWithContext(
33419
+ withSpanInstrumentationName(
33420
+ {
33421
+ name,
33422
+ spanAttributes: { type: "tool" /* TOOL */ },
33423
+ event: {
33424
+ input: ownValue3(options, "input")
33425
+ }
33426
+ },
33427
+ INSTRUMENTATION_NAMES.CLOUDFLARE_AGENTS
33428
+ ),
33429
+ CLOUDFLARE_WORKERS_CONTEXT
33430
+ );
33431
+ spans.set(event, span);
33432
+ } catch (error) {
33433
+ logInstrumentationError6("start", error);
33434
+ }
33435
+ },
33436
+ asyncEnd: (event) => {
33437
+ const span = spans.get(event);
33438
+ if (!span) {
33439
+ return;
33440
+ }
33441
+ spans.delete(event);
33442
+ try {
33443
+ const status = ownValue3(event.result, "status");
33444
+ if (status === "completed") {
33445
+ span.log({ output: ownValue3(event.result, "output") });
33446
+ } else {
33447
+ const error = ownValue3(event.result, "error");
33448
+ if (typeof error === "string") {
33449
+ span.log({ error });
33450
+ }
33451
+ }
33452
+ } catch (error) {
33453
+ logInstrumentationError6("completion", error);
33454
+ } finally {
33455
+ safelyEndSpan(span);
33456
+ }
33457
+ },
33458
+ error: (event) => {
33459
+ const span = spans.get(event);
33460
+ if (!span) {
33461
+ return;
33462
+ }
33463
+ spans.delete(event);
33464
+ try {
33465
+ span.log({ error: event.error });
33466
+ } catch (error) {
33467
+ logInstrumentationError6("rejection", error);
33468
+ } finally {
33469
+ safelyEndSpan(span);
33470
+ }
33471
+ }
33472
+ };
33473
+ channel2.subscribe(handlers);
33474
+ this.unsubscribers.push(() => channel2.unsubscribe(handlers));
33475
+ }
33476
+ onDisable() {
33477
+ for (const unsubscribe of this.unsubscribers) {
33478
+ unsubscribe();
33479
+ }
33480
+ this.unsubscribers = [];
33481
+ }
33482
+ };
33483
+ function ownValue3(value, key) {
33484
+ if (!isObjectLike2(value)) {
33485
+ return void 0;
33486
+ }
33487
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
33488
+ return descriptor && "value" in descriptor ? descriptor.value : void 0;
33489
+ }
33490
+ function isObjectLike2(value) {
33491
+ return typeof value === "object" && value !== null || typeof value === "function";
33492
+ }
33493
+ function safelyEndSpan(span) {
33494
+ try {
33495
+ span.end();
33496
+ } catch (error) {
33497
+ logInstrumentationError6("span end", error);
33498
+ }
33499
+ }
33500
+ function logInstrumentationError6(operation, error) {
33501
+ debugLogger.error(
33502
+ `Failed to process Cloudflare Agents ${operation} instrumentation:`,
33503
+ error
33504
+ );
33505
+ }
33506
+
30763
33507
  // src/instrumentation/braintrust-plugin.ts
30764
33508
  var BraintrustPlugin = class extends BasePlugin {
30765
33509
  config;
@@ -30768,13 +33512,16 @@ var BraintrustPlugin = class extends BasePlugin {
30768
33512
  anthropicPlugin = null;
30769
33513
  aiSDKPlugin = null;
30770
33514
  claudeAgentSDKPlugin = null;
33515
+ cloudflareThinkPlugin = null;
30771
33516
  cursorSDKPlugin = null;
30772
33517
  openAIAgentsPlugin = null;
30773
33518
  googleGenAIPlugin = null;
30774
33519
  huggingFacePlugin = null;
33520
+ huggingFaceTransformersPlugin = null;
30775
33521
  openRouterPlugin = null;
30776
33522
  openRouterAgentPlugin = null;
30777
33523
  mistralPlugin = null;
33524
+ ollamaPlugin = null;
30778
33525
  googleADKPlugin = null;
30779
33526
  coherePlugin = null;
30780
33527
  groqPlugin = null;
@@ -30786,6 +33533,8 @@ var BraintrustPlugin = class extends BasePlugin {
30786
33533
  langSmithPlugin = null;
30787
33534
  piCodingAgentPlugin = null;
30788
33535
  strandsAgentSDKPlugin = null;
33536
+ cloudflareAIChatPlugin = null;
33537
+ cloudflareAgentsPlugin = null;
30789
33538
  constructor(config = {}) {
30790
33539
  super();
30791
33540
  this.config = config;
@@ -30812,6 +33561,10 @@ var BraintrustPlugin = class extends BasePlugin {
30812
33561
  this.claudeAgentSDKPlugin = new ClaudeAgentSDKPlugin();
30813
33562
  this.claudeAgentSDKPlugin.enable();
30814
33563
  }
33564
+ if (integrations.cloudflareThink !== false) {
33565
+ this.cloudflareThinkPlugin = new CloudflareThinkPlugin();
33566
+ this.cloudflareThinkPlugin.enable();
33567
+ }
30815
33568
  if (integrations.cursorSDK !== false && integrations.cursor !== false) {
30816
33569
  this.cursorSDKPlugin = new CursorSDKPlugin();
30817
33570
  this.cursorSDKPlugin.enable();
@@ -30827,6 +33580,8 @@ var BraintrustPlugin = class extends BasePlugin {
30827
33580
  if (integrations.huggingface !== false) {
30828
33581
  this.huggingFacePlugin = new HuggingFacePlugin();
30829
33582
  this.huggingFacePlugin.enable();
33583
+ this.huggingFaceTransformersPlugin = new HuggingFaceTransformersPlugin();
33584
+ this.huggingFaceTransformersPlugin.enable();
30830
33585
  }
30831
33586
  if (integrations.openrouter !== false) {
30832
33587
  this.openRouterPlugin = new OpenRouterPlugin();
@@ -30840,6 +33595,10 @@ var BraintrustPlugin = class extends BasePlugin {
30840
33595
  this.mistralPlugin = new MistralPlugin();
30841
33596
  this.mistralPlugin.enable();
30842
33597
  }
33598
+ if (integrations.ollama !== false) {
33599
+ this.ollamaPlugin = new OllamaPlugin();
33600
+ this.ollamaPlugin.enable();
33601
+ }
30843
33602
  if (integrations.googleADK !== false) {
30844
33603
  this.googleADKPlugin = new GoogleADKPlugin();
30845
33604
  this.googleADKPlugin.enable();
@@ -30872,6 +33631,14 @@ var BraintrustPlugin = class extends BasePlugin {
30872
33631
  this.strandsAgentSDKPlugin = new StrandsAgentSDKPlugin();
30873
33632
  this.strandsAgentSDKPlugin.enable();
30874
33633
  }
33634
+ if (integrations.cloudflareAIChat !== false) {
33635
+ this.cloudflareAIChatPlugin = new CloudflareAIChatPlugin();
33636
+ this.cloudflareAIChatPlugin.enable();
33637
+ }
33638
+ if (integrations.cloudflareAgents !== false) {
33639
+ this.cloudflareAgentsPlugin = new CloudflareAgentsPlugin();
33640
+ this.cloudflareAgentsPlugin.enable();
33641
+ }
30875
33642
  if (integrations.flue !== false) {
30876
33643
  this.fluePlugin = new FluePlugin();
30877
33644
  this.fluePlugin.enable();
@@ -30908,6 +33675,10 @@ var BraintrustPlugin = class extends BasePlugin {
30908
33675
  this.claudeAgentSDKPlugin.disable();
30909
33676
  this.claudeAgentSDKPlugin = null;
30910
33677
  }
33678
+ if (this.cloudflareThinkPlugin) {
33679
+ this.cloudflareThinkPlugin.disable();
33680
+ this.cloudflareThinkPlugin = null;
33681
+ }
30911
33682
  if (this.cursorSDKPlugin) {
30912
33683
  this.cursorSDKPlugin.disable();
30913
33684
  this.cursorSDKPlugin = null;
@@ -30924,6 +33695,10 @@ var BraintrustPlugin = class extends BasePlugin {
30924
33695
  this.huggingFacePlugin.disable();
30925
33696
  this.huggingFacePlugin = null;
30926
33697
  }
33698
+ if (this.huggingFaceTransformersPlugin) {
33699
+ this.huggingFaceTransformersPlugin.disable();
33700
+ this.huggingFaceTransformersPlugin = null;
33701
+ }
30927
33702
  if (this.openRouterPlugin) {
30928
33703
  this.openRouterPlugin.disable();
30929
33704
  this.openRouterPlugin = null;
@@ -30936,6 +33711,10 @@ var BraintrustPlugin = class extends BasePlugin {
30936
33711
  this.mistralPlugin.disable();
30937
33712
  this.mistralPlugin = null;
30938
33713
  }
33714
+ if (this.ollamaPlugin) {
33715
+ this.ollamaPlugin.disable();
33716
+ this.ollamaPlugin = null;
33717
+ }
30939
33718
  if (this.googleADKPlugin) {
30940
33719
  this.googleADKPlugin.disable();
30941
33720
  this.googleADKPlugin = null;
@@ -30968,6 +33747,14 @@ var BraintrustPlugin = class extends BasePlugin {
30968
33747
  this.strandsAgentSDKPlugin.disable();
30969
33748
  this.strandsAgentSDKPlugin = null;
30970
33749
  }
33750
+ if (this.cloudflareAIChatPlugin) {
33751
+ this.cloudflareAIChatPlugin.disable();
33752
+ this.cloudflareAIChatPlugin = null;
33753
+ }
33754
+ if (this.cloudflareAgentsPlugin) {
33755
+ this.cloudflareAgentsPlugin.disable();
33756
+ this.cloudflareAgentsPlugin = null;
33757
+ }
30971
33758
  if (this.fluePlugin) {
30972
33759
  this.fluePlugin.disable();
30973
33760
  this.fluePlugin = null;
@@ -32651,6 +35438,9 @@ var envIntegrationAliases = {
32651
35438
  strandsagentsdk: "strandsAgentSDK",
32652
35439
  "strands-agent-sdk": "strandsAgentSDK",
32653
35440
  "@strands-agents/sdk": "strandsAgentSDK",
35441
+ agents: "cloudflareAgents",
35442
+ "cloudflare-agents": "cloudflareAgents",
35443
+ cloudflareagents: "cloudflareAgents",
32654
35444
  anthropic: "anthropic",
32655
35445
  aisdk: "aisdk",
32656
35446
  "ai-sdk": "aisdk",
@@ -32658,6 +35448,10 @@ var envIntegrationAliases = {
32658
35448
  vercel: "vercel",
32659
35449
  claudeagentsdk: "claudeAgentSDK",
32660
35450
  "claude-agent-sdk": "claudeAgentSDK",
35451
+ cloudflareaichat: "cloudflareAIChat",
35452
+ "cloudflare-ai-chat": "cloudflareAIChat",
35453
+ "@cloudflare/ai-chat": "cloudflareAIChat",
35454
+ cloudflarethink: "cloudflareThink",
32661
35455
  cursor: "cursor",
32662
35456
  "cursor-sdk": "cursorSDK",
32663
35457
  cursorsdk: "cursorSDK",
@@ -32672,10 +35466,13 @@ var envIntegrationAliases = {
32672
35466
  "google-genai": "googleGenAI",
32673
35467
  googlegenai: "googleGenAI",
32674
35468
  huggingface: "huggingface",
35469
+ "@huggingface/transformers": "huggingface",
35470
+ transformers: "huggingface",
32675
35471
  openrouter: "openrouter",
32676
35472
  openrouteragent: "openrouterAgent",
32677
35473
  "openrouter-agent": "openrouterAgent",
32678
35474
  mistral: "mistral",
35475
+ ollama: "ollama",
32679
35476
  googleadk: "googleADK",
32680
35477
  "google-adk": "googleADK",
32681
35478
  cohere: "cohere",
@@ -32710,6 +35507,8 @@ function getDefaultInstrumentationIntegrations() {
32710
35507
  googleADK: true,
32711
35508
  huggingface: true,
32712
35509
  claudeAgentSDK: true,
35510
+ cloudflareAIChat: true,
35511
+ cloudflareThink: true,
32713
35512
  cursor: true,
32714
35513
  cursorSDK: true,
32715
35514
  flue: true,
@@ -32718,6 +35517,7 @@ function getDefaultInstrumentationIntegrations() {
32718
35517
  openrouter: true,
32719
35518
  openrouterAgent: true,
32720
35519
  mistral: true,
35520
+ ollama: true,
32721
35521
  cohere: true,
32722
35522
  groq: true,
32723
35523
  bedrock: true,
@@ -32729,7 +35529,8 @@ function getDefaultInstrumentationIntegrations() {
32729
35529
  langgraph: true,
32730
35530
  langsmith: true,
32731
35531
  piCodingAgent: true,
32732
- strandsAgentSDK: true
35532
+ strandsAgentSDK: true,
35533
+ cloudflareAgents: true
32733
35534
  };
32734
35535
  }
32735
35536
  function readDisabledInstrumentationEnvConfig(disabledList) {
@@ -32747,7 +35548,9 @@ function readDisabledInstrumentationEnvConfig(disabledList) {
32747
35548
  }
32748
35549
 
32749
35550
  // src/instrumentation/registry.ts
32750
- var REGISTRY_STATE_KEY = /* @__PURE__ */ Symbol.for("braintrust.registry");
35551
+ var REGISTRY_STATE_KEY = /* @__PURE__ */ Symbol.for(
35552
+ `braintrust.registry.global-hooks.v${GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION}`
35553
+ );
32751
35554
  function getSharedState() {
32752
35555
  const state = globalThis[/* @__PURE__ */ Symbol.for("braintrust-state")];
32753
35556
  return state && typeof state === "object" ? state : void 0;