braintrust 3.11.0 → 3.12.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 (75) hide show
  1. package/README.md +8 -8
  2. package/dev/dist/index.d.mts +1 -1
  3. package/dev/dist/index.d.ts +1 -1
  4. package/dev/dist/index.js +2607 -316
  5. package/dev/dist/index.mjs +2388 -97
  6. package/dist/apply-auto-instrumentation.browser.d.mts +2 -0
  7. package/dist/apply-auto-instrumentation.browser.d.ts +2 -0
  8. package/dist/apply-auto-instrumentation.browser.js +18 -0
  9. package/dist/apply-auto-instrumentation.browser.mjs +0 -0
  10. package/dist/apply-auto-instrumentation.d.mts +2 -0
  11. package/dist/apply-auto-instrumentation.d.ts +2 -0
  12. package/dist/apply-auto-instrumentation.js +2534 -0
  13. package/dist/apply-auto-instrumentation.mjs +2534 -0
  14. package/dist/auto-instrumentations/bundler/esbuild.cjs +1802 -1283
  15. package/dist/auto-instrumentations/bundler/esbuild.d.mts +9 -5
  16. package/dist/auto-instrumentations/bundler/esbuild.d.ts +9 -5
  17. package/dist/auto-instrumentations/bundler/esbuild.mjs +10 -2
  18. package/dist/auto-instrumentations/bundler/next.cjs +3268 -0
  19. package/dist/auto-instrumentations/bundler/next.d.mts +3 -0
  20. package/dist/auto-instrumentations/bundler/next.d.ts +3 -0
  21. package/dist/auto-instrumentations/bundler/next.mjs +189 -0
  22. package/dist/auto-instrumentations/bundler/rollup.cjs +1802 -1283
  23. package/dist/auto-instrumentations/bundler/rollup.d.mts +9 -5
  24. package/dist/auto-instrumentations/bundler/rollup.d.ts +9 -5
  25. package/dist/auto-instrumentations/bundler/rollup.mjs +10 -2
  26. package/dist/auto-instrumentations/bundler/vite.cjs +1802 -1283
  27. package/dist/auto-instrumentations/bundler/vite.d.mts +9 -5
  28. package/dist/auto-instrumentations/bundler/vite.d.ts +9 -5
  29. package/dist/auto-instrumentations/bundler/vite.mjs +10 -2
  30. package/dist/auto-instrumentations/bundler/webpack-loader.cjs +1860 -1308
  31. package/dist/auto-instrumentations/bundler/webpack-loader.d.ts +3 -3
  32. package/dist/auto-instrumentations/bundler/webpack.cjs +1802 -1283
  33. package/dist/auto-instrumentations/bundler/webpack.d.mts +9 -5
  34. package/dist/auto-instrumentations/bundler/webpack.d.ts +9 -5
  35. package/dist/auto-instrumentations/bundler/webpack.mjs +6 -6
  36. package/dist/auto-instrumentations/{chunk-DIV5TO4S.mjs → chunk-2DPA74KK.mjs} +337 -1
  37. package/dist/auto-instrumentations/chunk-73BZUKVI.mjs +300 -0
  38. package/dist/auto-instrumentations/chunk-AFXRW7I7.mjs +18 -0
  39. package/dist/auto-instrumentations/hook.mjs +1712 -1460
  40. package/dist/auto-instrumentations/index.cjs +93 -0
  41. package/dist/auto-instrumentations/index.d.mts +5 -1
  42. package/dist/auto-instrumentations/index.d.ts +5 -1
  43. package/dist/auto-instrumentations/index.mjs +6 -247
  44. package/dist/auto-instrumentations/loader/esm-hook.mjs +19 -2
  45. package/dist/auto-instrumentations/plugin-D7nDswtC.d.mts +44 -0
  46. package/dist/auto-instrumentations/plugin-D7nDswtC.d.ts +44 -0
  47. package/dist/browser.d.mts +120 -31
  48. package/dist/browser.d.ts +120 -31
  49. package/dist/browser.js +2395 -123
  50. package/dist/browser.mjs +2395 -123
  51. package/dist/chunk-BW4DF4CY.js +816 -0
  52. package/dist/chunk-MSLBGITU.mjs +816 -0
  53. package/dist/cli.js +2407 -96
  54. package/dist/edge-light.d.mts +1 -1
  55. package/dist/edge-light.d.ts +1 -1
  56. package/dist/edge-light.js +2395 -123
  57. package/dist/edge-light.mjs +2395 -123
  58. package/dist/index.d.mts +120 -31
  59. package/dist/index.d.ts +120 -31
  60. package/dist/index.js +3362 -1849
  61. package/dist/index.mjs +2505 -992
  62. package/dist/instrumentation/index.d.mts +7860 -48
  63. package/dist/instrumentation/index.d.ts +7860 -48
  64. package/dist/instrumentation/index.js +2395 -95
  65. package/dist/instrumentation/index.mjs +2394 -95
  66. package/dist/workerd.d.mts +1 -1
  67. package/dist/workerd.d.ts +1 -1
  68. package/dist/workerd.js +2395 -123
  69. package/dist/workerd.mjs +2395 -123
  70. package/package.json +23 -3
  71. package/util/dist/index.js +6 -0
  72. package/util/dist/index.mjs +6 -0
  73. package/dist/auto-instrumentations/chunk-G6ZWXGZB.mjs +0 -116
  74. package/dist/auto-instrumentations/plugin-Df3qKIl2.d.mts +0 -22
  75. package/dist/auto-instrumentations/plugin-Df3qKIl2.d.ts +0 -22
package/dist/index.mjs CHANGED
@@ -1,101 +1,35 @@
1
- var __defProp = Object.defineProperty;
2
- var __export = (target, all) => {
3
- for (var name in all)
4
- __defProp(target, name, { get: all[name], enumerable: true });
5
- };
1
+ import {
2
+ __export,
3
+ aiSDKChannels,
4
+ anthropicChannels,
5
+ claudeAgentSDKChannels,
6
+ cohereChannels,
7
+ cursorSDKChannels,
8
+ flueChannels,
9
+ genkitChannels,
10
+ genkitCoreChannels,
11
+ getDefaultInstrumentationIntegrations,
12
+ gitHubCopilotChannels,
13
+ googleADKChannels,
14
+ googleGenAIChannels,
15
+ groqChannels,
16
+ huggingFaceChannels,
17
+ isomorph_default,
18
+ langChainChannels,
19
+ mistralChannels,
20
+ openAIAgentsCoreChannels,
21
+ openAIChannels,
22
+ openAICodexChannels,
23
+ openRouterAgentChannels,
24
+ openRouterChannels,
25
+ patchTracingChannel,
26
+ readDisabledInstrumentationEnvConfig
27
+ } from "./chunk-MSLBGITU.mjs";
6
28
 
7
29
  // src/node/config.ts
8
30
  import { AsyncLocalStorage } from "node:async_hooks";
9
31
  import * as diagnostics_channel from "node:diagnostics_channel";
10
32
  import * as path from "node:path";
11
-
12
- // src/auto-instrumentations/patch-tracing-channel.ts
13
- function patchTracingChannel(tracingChannelFn) {
14
- const dummyChannel = tracingChannelFn("__braintrust_probe__");
15
- const TracingChannel = dummyChannel?.constructor;
16
- if (!TracingChannel?.prototype) {
17
- return;
18
- }
19
- if (!Object.getOwnPropertyDescriptor(TracingChannel.prototype, "hasSubscribers")) {
20
- Object.defineProperty(TracingChannel.prototype, "hasSubscribers", {
21
- configurable: true,
22
- enumerable: false,
23
- get() {
24
- return Boolean(
25
- this.start?.hasSubscribers || this.end?.hasSubscribers || this.asyncStart?.hasSubscribers || this.asyncEnd?.hasSubscribers || this.error?.hasSubscribers
26
- );
27
- }
28
- });
29
- }
30
- if (TracingChannel.prototype.tracePromise) {
31
- TracingChannel.prototype.tracePromise = function(fn, context = {}, thisArg, ...args) {
32
- const start = this.start;
33
- const end = this.end;
34
- const asyncStart = this.asyncStart;
35
- const asyncEnd = this.asyncEnd;
36
- const error = this.error;
37
- function publishRejected(err) {
38
- context.error = err;
39
- error?.publish(context);
40
- asyncStart?.publish(context);
41
- asyncEnd?.publish(context);
42
- }
43
- function publishResolved(result) {
44
- context.result = result;
45
- asyncStart?.publish(context);
46
- asyncEnd?.publish(context);
47
- }
48
- return start.runStores(context, () => {
49
- try {
50
- const result = Reflect.apply(fn, thisArg, args);
51
- end?.publish(context);
52
- if (result && (typeof result === "object" || typeof result === "function") && typeof result.then === "function") {
53
- if (result.constructor === Promise) {
54
- return result.then(
55
- (res) => {
56
- publishResolved(res);
57
- return res;
58
- },
59
- (err) => {
60
- publishRejected(err);
61
- return Promise.reject(err);
62
- }
63
- );
64
- }
65
- void result.then(
66
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
67
- (resolved) => {
68
- try {
69
- publishResolved(resolved);
70
- } catch {
71
- }
72
- },
73
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
74
- (err) => {
75
- try {
76
- publishRejected(err);
77
- } catch {
78
- }
79
- }
80
- );
81
- return result;
82
- }
83
- context.result = result;
84
- asyncStart?.publish(context);
85
- asyncEnd?.publish(context);
86
- return result;
87
- } catch (err) {
88
- context.error = err;
89
- error?.publish(context);
90
- end?.publish(context);
91
- throw err;
92
- }
93
- });
94
- };
95
- }
96
- }
97
-
98
- // src/node/config.ts
99
33
  import * as fs from "node:fs/promises";
100
34
  import * as os from "node:os";
101
35
  import * as fsSync from "node:fs";
@@ -103,103 +37,6 @@ import * as crypto from "node:crypto";
103
37
  import { promisify } from "node:util";
104
38
  import * as zlib from "node:zlib";
105
39
 
106
- // src/isomorph.ts
107
- var DefaultAsyncLocalStorage = class {
108
- constructor() {
109
- }
110
- enterWith(_) {
111
- }
112
- run(_, callback) {
113
- return callback();
114
- }
115
- getStore() {
116
- return void 0;
117
- }
118
- };
119
- var DefaultChannel = class {
120
- constructor(name) {
121
- this.name = name;
122
- }
123
- hasSubscribers = false;
124
- subscribe(_subscription) {
125
- }
126
- unsubscribe(_subscription) {
127
- return false;
128
- }
129
- bindStore(_store, _transform) {
130
- }
131
- unbindStore(_store) {
132
- return false;
133
- }
134
- publish(_message) {
135
- }
136
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
137
- runStores(_message, fn, thisArg, ...args) {
138
- return fn.apply(thisArg, args);
139
- }
140
- };
141
- var DefaultTracingChannel = class {
142
- start;
143
- end;
144
- asyncStart;
145
- asyncEnd;
146
- error;
147
- constructor(nameOrChannels) {
148
- if (typeof nameOrChannels === "string") {
149
- this.start = new DefaultChannel(`tracing:${nameOrChannels}:start`);
150
- this.end = new DefaultChannel(`tracing:${nameOrChannels}:end`);
151
- this.asyncStart = new DefaultChannel(
152
- `tracing:${nameOrChannels}:asyncStart`
153
- );
154
- this.asyncEnd = new DefaultChannel(`tracing:${nameOrChannels}:asyncEnd`);
155
- this.error = new DefaultChannel(`tracing:${nameOrChannels}:error`);
156
- return;
157
- }
158
- this.start = nameOrChannels.start ?? new DefaultChannel("tracing:start");
159
- this.end = nameOrChannels.end ?? new DefaultChannel("tracing:end");
160
- this.asyncStart = nameOrChannels.asyncStart ?? new DefaultChannel("tracing:asyncStart");
161
- this.asyncEnd = nameOrChannels.asyncEnd ?? new DefaultChannel("tracing:asyncEnd");
162
- this.error = nameOrChannels.error ?? new DefaultChannel("tracing:error");
163
- }
164
- get hasSubscribers() {
165
- return this.start.hasSubscribers || this.end.hasSubscribers || this.asyncStart.hasSubscribers || this.asyncEnd.hasSubscribers || this.error.hasSubscribers;
166
- }
167
- subscribe(_handlers) {
168
- }
169
- unsubscribe(_handlers) {
170
- return false;
171
- }
172
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
173
- traceSync(fn, _message, thisArg, ...args) {
174
- return fn.apply(thisArg, args);
175
- }
176
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
177
- tracePromise(fn, _message, thisArg, ...args) {
178
- return fn.apply(thisArg, args);
179
- }
180
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
181
- traceCallback(fn, _position, _message, thisArg, ...args) {
182
- return fn.apply(thisArg, args);
183
- }
184
- };
185
- var iso = {
186
- buildType: "unknown",
187
- // Will be set by configureBrowser() or configureNode()
188
- getRepoInfo: async (_settings) => void 0,
189
- getPastNAncestors: async () => [],
190
- getEnv: (_name) => void 0,
191
- getCallerLocation: () => void 0,
192
- newAsyncLocalStorage: () => new DefaultAsyncLocalStorage(),
193
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
194
- newTracingChannel: (nameOrChannels) => new DefaultTracingChannel(nameOrChannels),
195
- processOn: (_0, _1) => {
196
- },
197
- basename: (filepath) => filepath.split(/[\\/]/).pop() || filepath,
198
- // eslint-disable-next-line no-restricted-properties -- preserving intentional console usage.
199
- writeln: (text) => console.log(text)
200
- };
201
- var isomorph_default = iso;
202
-
203
40
  // src/debug-logger.ts
204
41
  var PREFIX = "[braintrust]";
205
42
  var DEBUG_LOG_LEVEL_SYMBOL = /* @__PURE__ */ Symbol.for("braintrust-debug-log-level");
@@ -416,11 +253,11 @@ function truncateToByteLimit(s, byteLimit = 65536) {
416
253
  return new TextDecoder().decode(truncated);
417
254
  }
418
255
  async function getRepoInfo(settings) {
419
- if (settings && settings.collect === "none") {
256
+ if (!settings || settings.collect === "none") {
420
257
  return void 0;
421
258
  }
422
259
  const repo = await repoInfo();
423
- if (!repo || !settings || settings.collect === "all") {
260
+ if (!repo || settings.collect === "all") {
424
261
  return repo;
425
262
  }
426
263
  let sanitized = {};
@@ -1234,6 +1071,11 @@ function isPromiseLike(value) {
1234
1071
 
1235
1072
  // util/object_util.ts
1236
1073
  var SET_UNION_FIELDS = /* @__PURE__ */ new Set(["tags"]);
1074
+ var FORBIDDEN_MERGE_KEYS = /* @__PURE__ */ new Set([
1075
+ "__proto__",
1076
+ "constructor",
1077
+ "prototype"
1078
+ ]);
1237
1079
  function mergeDictsWithPaths({
1238
1080
  mergeInto,
1239
1081
  mergeFrom,
@@ -1256,6 +1098,7 @@ function mergeDictsWithPathsHelper({
1256
1098
  mergePaths
1257
1099
  }) {
1258
1100
  Object.entries(mergeFrom).forEach(([k, mergeFromV]) => {
1101
+ if (FORBIDDEN_MERGE_KEYS.has(k)) return;
1259
1102
  const fullPath = path2.concat([k]);
1260
1103
  const fullPathSerialized = JSON.stringify(fullPath);
1261
1104
  const mergeIntoV = recordFind(mergeInto, k);
@@ -5329,6 +5172,13 @@ var HTTPConnection = class _HTTPConnection {
5329
5172
  debugLogger.debug(
5330
5173
  `Retrying API request ${object_type} ${JSON.stringify(args)} ${e.status} ${e.text}`
5331
5174
  );
5175
+ const sleepTimeS = HTTP_RETRY_BASE_SLEEP_TIME_S * 2 ** i;
5176
+ debugLogger.info(
5177
+ `Sleeping for ${sleepTimeS}s before retrying API request`
5178
+ );
5179
+ await new Promise(
5180
+ (resolve) => setTimeout(resolve, sleepTimeS * 1e3)
5181
+ );
5332
5182
  continue;
5333
5183
  }
5334
5184
  throw e;
@@ -5978,20 +5828,7 @@ function startSpanParentArgs(args) {
5978
5828
  `Mismatch between expected span parent object type ${args.parentObjectType} and provided type ${parentComponents.data.object_type}`
5979
5829
  );
5980
5830
  }
5981
- const parentComponentsObjectIdLambda = spanComponentsToObjectIdLambda(
5982
- args.state,
5983
- parentComponents
5984
- );
5985
- const computeParentObjectId = async () => {
5986
- const parentComponentsObjectId = await parentComponentsObjectIdLambda();
5987
- if (await args.parentObjectId.get() !== parentComponentsObjectId) {
5988
- throw new Error(
5989
- `Mismatch between expected span parent object id ${await args.parentObjectId.get()} and provided id ${parentComponentsObjectId}`
5990
- );
5991
- }
5992
- return await args.parentObjectId.get();
5993
- };
5994
- argParentObjectId = new LazyValue(computeParentObjectId);
5831
+ argParentObjectId = args.parentObjectId;
5995
5832
  if (parentComponents.data.row_id) {
5996
5833
  argParentSpanIds = {
5997
5834
  spanId: parentComponents.data.span_id,
@@ -6377,6 +6214,7 @@ var TestBackgroundLogger = class {
6377
6214
  }
6378
6215
  };
6379
6216
  var BACKGROUND_LOGGER_BASE_SLEEP_TIME_S = 1;
6217
+ var HTTP_RETRY_BASE_SLEEP_TIME_S = 1;
6380
6218
  var HTTPBackgroundLogger = class _HTTPBackgroundLogger {
6381
6219
  apiConn;
6382
6220
  queue;
@@ -7007,17 +6845,10 @@ function init(projectOrOptions, optionalOptions) {
7007
6845
  if (repoInfo2) {
7008
6846
  return repoInfo2;
7009
6847
  }
7010
- let mergedGitMetadataSettings = {
7011
- ...state.gitMetadataSettings || {
7012
- collect: "all"
7013
- }
7014
- };
7015
- if (gitMetadataSettings) {
7016
- mergedGitMetadataSettings = mergeGitMetadataSettings(
7017
- mergedGitMetadataSettings,
7018
- gitMetadataSettings
7019
- );
7020
- }
6848
+ const mergedGitMetadataSettings = state.gitMetadataSettings == null ? gitMetadataSettings ?? { collect: "none" } : mergeGitMetadataSettings(
6849
+ state.gitMetadataSettings,
6850
+ gitMetadataSettings ?? { collect: "all" }
6851
+ );
7021
6852
  return await isomorph_default.getRepoInfo(mergedGitMetadataSettings);
7022
6853
  })();
7023
6854
  if (repoInfoArg) {
@@ -10408,15 +10239,15 @@ var BasePlugin = class {
10408
10239
  * @param handlers - Event handlers
10409
10240
  */
10410
10241
  subscribe(channelName, handlers) {
10411
- const channel2 = isomorph_default.newTracingChannel(channelName);
10412
- channel2.subscribe(handlers);
10242
+ const channel = isomorph_default.newTracingChannel(channelName);
10243
+ channel.subscribe(handlers);
10413
10244
  }
10414
10245
  /**
10415
10246
  * Subscribe to a channel for async methods (non-streaming).
10416
10247
  * Creates a span and logs input/output/metrics.
10417
10248
  */
10418
10249
  subscribeToChannel(channelName, config) {
10419
- const channel2 = isomorph_default.newTracingChannel(channelName);
10250
+ const channel = isomorph_default.newTracingChannel(channelName);
10420
10251
  const spans = /* @__PURE__ */ new WeakMap();
10421
10252
  const handlers = {
10422
10253
  start: (event) => {
@@ -10475,9 +10306,9 @@ var BasePlugin = class {
10475
10306
  spans.delete(event);
10476
10307
  }
10477
10308
  };
10478
- channel2.subscribe(handlers);
10309
+ channel.subscribe(handlers);
10479
10310
  this.unsubscribers.push(() => {
10480
- channel2.unsubscribe(handlers);
10311
+ channel.unsubscribe(handlers);
10481
10312
  });
10482
10313
  }
10483
10314
  /**
@@ -10485,7 +10316,7 @@ var BasePlugin = class {
10485
10316
  * Handles both streaming and non-streaming responses.
10486
10317
  */
10487
10318
  subscribeToStreamingChannel(channelName, config) {
10488
- const channel2 = isomorph_default.newTracingChannel(channelName);
10319
+ const channel = isomorph_default.newTracingChannel(channelName);
10489
10320
  const spans = /* @__PURE__ */ new WeakMap();
10490
10321
  const handlers = {
10491
10322
  start: (event) => {
@@ -10602,9 +10433,9 @@ var BasePlugin = class {
10602
10433
  spans.delete(event);
10603
10434
  }
10604
10435
  };
10605
- channel2.subscribe(handlers);
10436
+ channel.subscribe(handlers);
10606
10437
  this.unsubscribers.push(() => {
10607
- channel2.unsubscribe(handlers);
10438
+ channel.unsubscribe(handlers);
10608
10439
  });
10609
10440
  }
10610
10441
  /**
@@ -10612,7 +10443,7 @@ var BasePlugin = class {
10612
10443
  * Used for methods like beta.chat.completions.stream() and responses.stream().
10613
10444
  */
10614
10445
  subscribeToSyncStreamChannel(channelName, config) {
10615
- const channel2 = isomorph_default.newTracingChannel(channelName);
10446
+ const channel = isomorph_default.newTracingChannel(channelName);
10616
10447
  const spans = /* @__PURE__ */ new WeakMap();
10617
10448
  const handlers = {
10618
10449
  start: (event) => {
@@ -10714,9 +10545,9 @@ var BasePlugin = class {
10714
10545
  spans.delete(event);
10715
10546
  }
10716
10547
  };
10717
- channel2.subscribe(handlers);
10548
+ channel.subscribe(handlers);
10718
10549
  this.unsubscribers.push(() => {
10719
- channel2.unsubscribe(handlers);
10550
+ channel.unsubscribe(handlers);
10720
10551
  });
10721
10552
  }
10722
10553
  };
@@ -10821,10 +10652,10 @@ function runStreamingCompletionHook(args) {
10821
10652
  console.error(`Error in onComplete hook for ${args.channelName}:`, error);
10822
10653
  }
10823
10654
  }
10824
- function traceAsyncChannel(channel2, config) {
10825
- const tracingChannel2 = channel2.tracingChannel();
10655
+ function traceAsyncChannel(channel, config) {
10656
+ const tracingChannel2 = channel.tracingChannel();
10826
10657
  const states = /* @__PURE__ */ new WeakMap();
10827
- const channelName = channel2.channelName;
10658
+ const channelName = channel.channelName;
10828
10659
  const unbindCurrentSpanStore = bindCurrentSpanStoreToStart(
10829
10660
  tracingChannel2,
10830
10661
  states,
@@ -10883,10 +10714,10 @@ function traceAsyncChannel(channel2, config) {
10883
10714
  tracingChannel2.unsubscribe(handlers);
10884
10715
  };
10885
10716
  }
10886
- function traceStreamingChannel(channel2, config) {
10887
- const tracingChannel2 = channel2.tracingChannel();
10717
+ function traceStreamingChannel(channel, config) {
10718
+ const tracingChannel2 = channel.tracingChannel();
10888
10719
  const states = /* @__PURE__ */ new WeakMap();
10889
- const channelName = channel2.channelName;
10720
+ const channelName = channel.channelName;
10890
10721
  const unbindCurrentSpanStore = bindCurrentSpanStoreToStart(
10891
10722
  tracingChannel2,
10892
10723
  states,
@@ -11042,10 +10873,10 @@ function traceStreamingChannel(channel2, config) {
11042
10873
  tracingChannel2.unsubscribe(handlers);
11043
10874
  };
11044
10875
  }
11045
- function traceSyncStreamChannel(channel2, config) {
11046
- const tracingChannel2 = channel2.tracingChannel();
10876
+ function traceSyncStreamChannel(channel, config) {
10877
+ const tracingChannel2 = channel.tracingChannel();
11047
10878
  const states = /* @__PURE__ */ new WeakMap();
11048
- const channelName = channel2.channelName;
10879
+ const channelName = channel.channelName;
11049
10880
  const unbindCurrentSpanStore = bindCurrentSpanStoreToStart(
11050
10881
  tracingChannel2,
11051
10882
  states,
@@ -11324,92 +11155,6 @@ function processInputAttachments(input) {
11324
11155
  return processNode(input);
11325
11156
  }
11326
11157
 
11327
- // src/instrumentation/core/channel-definitions.ts
11328
- function channel(spec) {
11329
- return spec;
11330
- }
11331
- function defineChannels(pkg, channels) {
11332
- return Object.fromEntries(
11333
- Object.entries(channels).map(([key, spec]) => {
11334
- const fullChannelName = `orchestrion:${pkg}:${spec.channelName}`;
11335
- if (spec.kind === "async") {
11336
- const asyncSpec = spec;
11337
- const tracingChannel3 = () => isomorph_default.newTracingChannel(
11338
- fullChannelName
11339
- );
11340
- return [
11341
- key,
11342
- {
11343
- ...asyncSpec,
11344
- tracingChannel: tracingChannel3,
11345
- tracePromise: (fn, context) => tracingChannel3().tracePromise(
11346
- fn,
11347
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
11348
- context
11349
- )
11350
- }
11351
- ];
11352
- }
11353
- const syncSpec = spec;
11354
- const tracingChannel2 = () => isomorph_default.newTracingChannel(
11355
- fullChannelName
11356
- );
11357
- return [
11358
- key,
11359
- {
11360
- ...syncSpec,
11361
- tracingChannel: tracingChannel2,
11362
- traceSync: (fn, context) => tracingChannel2().traceSync(
11363
- fn,
11364
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
11365
- context
11366
- )
11367
- }
11368
- ];
11369
- })
11370
- );
11371
- }
11372
-
11373
- // src/instrumentation/plugins/openai-channels.ts
11374
- var openAIChannels = defineChannels("openai", {
11375
- chatCompletionsCreate: channel({
11376
- channelName: "chat.completions.create",
11377
- kind: "async"
11378
- }),
11379
- embeddingsCreate: channel({
11380
- channelName: "embeddings.create",
11381
- kind: "async"
11382
- }),
11383
- betaChatCompletionsParse: channel({
11384
- channelName: "beta.chat.completions.parse",
11385
- kind: "async"
11386
- }),
11387
- betaChatCompletionsStream: channel({
11388
- channelName: "beta.chat.completions.stream",
11389
- kind: "sync-stream"
11390
- }),
11391
- moderationsCreate: channel({
11392
- channelName: "moderations.create",
11393
- kind: "async"
11394
- }),
11395
- responsesCreate: channel({
11396
- channelName: "responses.create",
11397
- kind: "async"
11398
- }),
11399
- responsesStream: channel({
11400
- channelName: "responses.stream",
11401
- kind: "sync-stream"
11402
- }),
11403
- responsesParse: channel({
11404
- channelName: "responses.parse",
11405
- kind: "async"
11406
- }),
11407
- responsesCompact: channel({
11408
- channelName: "responses.compact",
11409
- kind: "async"
11410
- })
11411
- });
11412
-
11413
11158
  // src/openai-utils.ts
11414
11159
  var BRAINTRUST_CACHED_STREAM_METRIC = "__braintrust_cached_metric";
11415
11160
  var LEGACY_CACHED_HEADER = "x-cached";
@@ -11922,18 +11667,6 @@ function aggregateResponseStreamEvents(chunks, _streamResult, endEvent) {
11922
11667
  };
11923
11668
  }
11924
11669
 
11925
- // src/instrumentation/plugins/openai-codex-channels.ts
11926
- var openAICodexChannels = defineChannels("@openai/codex-sdk", {
11927
- run: channel({
11928
- channelName: "Thread.run",
11929
- kind: "async"
11930
- }),
11931
- runStreamed: channel({
11932
- channelName: "Thread.runStreamed",
11933
- kind: "async"
11934
- })
11935
- });
11936
-
11937
11670
  // src/instrumentation/plugins/openai-codex-plugin.ts
11938
11671
  var PATCHED_STREAMED_TURN = /* @__PURE__ */ Symbol.for(
11939
11672
  "braintrust.openai-codex.patched-streamed-turn"
@@ -11950,7 +11683,7 @@ var OpenAICodexPlugin = class extends BasePlugin {
11950
11683
  this.unsubscribers = [];
11951
11684
  }
11952
11685
  subscribeToRun() {
11953
- const channel2 = openAICodexChannels.run.tracingChannel();
11686
+ const channel = openAICodexChannels.run.tracingChannel();
11954
11687
  const states = /* @__PURE__ */ new WeakMap();
11955
11688
  const handlers = {
11956
11689
  start: (event) => {
@@ -11973,13 +11706,13 @@ var OpenAICodexPlugin = class extends BasePlugin {
11973
11706
  await finalizeCodexRun(state, { error: event.error });
11974
11707
  }
11975
11708
  };
11976
- channel2.subscribe(handlers);
11709
+ channel.subscribe(handlers);
11977
11710
  this.unsubscribers.push(() => {
11978
- channel2.unsubscribe(handlers);
11711
+ channel.unsubscribe(handlers);
11979
11712
  });
11980
11713
  }
11981
11714
  subscribeToRunStreamed() {
11982
- const channel2 = openAICodexChannels.runStreamed.tracingChannel();
11715
+ const channel = openAICodexChannels.runStreamed.tracingChannel();
11983
11716
  const states = /* @__PURE__ */ new WeakMap();
11984
11717
  const handlers = {
11985
11718
  start: (event) => {
@@ -12002,9 +11735,9 @@ var OpenAICodexPlugin = class extends BasePlugin {
12002
11735
  await finalizeCodexRun(state, { error: event.error });
12003
11736
  }
12004
11737
  };
12005
- channel2.subscribe(handlers);
11738
+ channel.subscribe(handlers);
12006
11739
  this.unsubscribers.push(() => {
12007
- channel2.unsubscribe(handlers);
11740
+ channel.unsubscribe(handlers);
12008
11741
  });
12009
11742
  }
12010
11743
  };
@@ -12577,22 +12310,6 @@ function extractAnthropicCacheTokens(cacheReadTokens = 0, cacheCreationTokens =
12577
12310
  return cacheTokens;
12578
12311
  }
12579
12312
 
12580
- // src/instrumentation/plugins/anthropic-channels.ts
12581
- var anthropicChannels = defineChannels("@anthropic-ai/sdk", {
12582
- messagesCreate: channel({
12583
- channelName: "messages.create",
12584
- kind: "async"
12585
- }),
12586
- betaMessagesCreate: channel({
12587
- channelName: "beta.messages.create",
12588
- kind: "async"
12589
- }),
12590
- betaMessagesToolRunner: channel({
12591
- channelName: "beta.messages.toolRunner",
12592
- kind: "sync-stream"
12593
- })
12594
- });
12595
-
12596
12313
  // src/instrumentation/plugins/anthropic-plugin.ts
12597
12314
  var ANTHROPIC_TOOL_RUNNER_TOOL_WRAPPED = /* @__PURE__ */ Symbol.for(
12598
12315
  "braintrust.anthropic_tool_runner_tool_wrapped"
@@ -13389,68 +13106,6 @@ function serializeAISDKToolsForLogging(tools) {
13389
13106
  return serialized;
13390
13107
  }
13391
13108
 
13392
- // src/instrumentation/plugins/ai-sdk-channels.ts
13393
- var aiSDKChannels = defineChannels("ai", {
13394
- generateText: channel({
13395
- channelName: "generateText",
13396
- kind: "async"
13397
- }),
13398
- streamText: channel({
13399
- channelName: "streamText",
13400
- kind: "async"
13401
- }),
13402
- streamTextSync: channel({
13403
- channelName: "streamText.sync",
13404
- kind: "sync-stream"
13405
- }),
13406
- generateObject: channel({
13407
- channelName: "generateObject",
13408
- kind: "async"
13409
- }),
13410
- streamObject: channel({
13411
- channelName: "streamObject",
13412
- kind: "async"
13413
- }),
13414
- streamObjectSync: channel({
13415
- channelName: "streamObject.sync",
13416
- kind: "sync-stream"
13417
- }),
13418
- embed: channel(
13419
- {
13420
- channelName: "embed",
13421
- kind: "async"
13422
- }
13423
- ),
13424
- embedMany: channel({
13425
- channelName: "embedMany",
13426
- kind: "async"
13427
- }),
13428
- rerank: channel({
13429
- channelName: "rerank",
13430
- kind: "async"
13431
- }),
13432
- agentGenerate: channel({
13433
- channelName: "Agent.generate",
13434
- kind: "async"
13435
- }),
13436
- agentStream: channel({
13437
- channelName: "Agent.stream",
13438
- kind: "async"
13439
- }),
13440
- agentStreamSync: channel({
13441
- channelName: "Agent.stream.sync",
13442
- kind: "sync-stream"
13443
- }),
13444
- toolLoopAgentGenerate: channel({
13445
- channelName: "ToolLoopAgent.generate",
13446
- kind: "async"
13447
- }),
13448
- toolLoopAgentStream: channel({
13449
- channelName: "ToolLoopAgent.stream",
13450
- kind: "async"
13451
- })
13452
- });
13453
-
13454
13109
  // src/instrumentation/plugins/ai-sdk-plugin.ts
13455
13110
  var DEFAULT_DENY_OUTPUT_PATHS = [
13456
13111
  // v3
@@ -13713,11 +13368,11 @@ function resolveDenyOutputPaths(event, defaultDenyOutputPaths) {
13713
13368
  if (Array.isArray(event?.denyOutputPaths)) {
13714
13369
  return event.denyOutputPaths;
13715
13370
  }
13716
- const firstArgument = event?.arguments && event.arguments.length > 0 ? event.arguments[0] : void 0;
13717
- if (!firstArgument || typeof firstArgument !== "object") {
13371
+ const firstArgument2 = event?.arguments && event.arguments.length > 0 ? event.arguments[0] : void 0;
13372
+ if (!firstArgument2 || typeof firstArgument2 !== "object") {
13718
13373
  return defaultDenyOutputPaths;
13719
13374
  }
13720
- const runtimeDenyOutputPaths = firstArgument[RUNTIME_DENY_OUTPUT_PATHS];
13375
+ const runtimeDenyOutputPaths = firstArgument2[RUNTIME_DENY_OUTPUT_PATHS];
13721
13376
  if (Array.isArray(runtimeDenyOutputPaths) && runtimeDenyOutputPaths.every((path2) => typeof path2 === "string")) {
13722
13377
  return runtimeDenyOutputPaths;
13723
13378
  }
@@ -15088,17 +14743,6 @@ function omit(obj, paths) {
15088
14743
  return result;
15089
14744
  }
15090
14745
 
15091
- // src/instrumentation/plugins/claude-agent-sdk-channels.ts
15092
- var claudeAgentSDKChannels = defineChannels(
15093
- "@anthropic-ai/claude-agent-sdk",
15094
- {
15095
- query: channel({
15096
- channelName: "query",
15097
- kind: "sync-stream"
15098
- })
15099
- }
15100
- );
15101
-
15102
14746
  // src/instrumentation/plugins/claude-agent-sdk-instrumentation-constants.ts
15103
14747
  var CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION = "__braintrust_skip_local_tool_hooks";
15104
14748
 
@@ -16284,7 +15928,7 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
16284
15928
  this.unsubscribers = [];
16285
15929
  }
16286
15930
  subscribeToQuery() {
16287
- const channel2 = claudeAgentSDKChannels.query.tracingChannel();
15931
+ const channel = claudeAgentSDKChannels.query.tracingChannel();
16288
15932
  const spans = /* @__PURE__ */ new WeakMap();
16289
15933
  const handlers = {
16290
15934
  start: (event) => {
@@ -16491,33 +16135,13 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
16491
16135
  spans.delete(event);
16492
16136
  }
16493
16137
  };
16494
- channel2.subscribe(handlers);
16138
+ channel.subscribe(handlers);
16495
16139
  this.unsubscribers.push(() => {
16496
- channel2.unsubscribe(handlers);
16140
+ channel.unsubscribe(handlers);
16497
16141
  });
16498
16142
  }
16499
16143
  };
16500
16144
 
16501
- // src/instrumentation/plugins/cursor-sdk-channels.ts
16502
- var cursorSDKChannels = defineChannels("@cursor/sdk", {
16503
- create: channel({
16504
- channelName: "Agent.create",
16505
- kind: "async"
16506
- }),
16507
- resume: channel({
16508
- channelName: "Agent.resume",
16509
- kind: "async"
16510
- }),
16511
- prompt: channel({
16512
- channelName: "Agent.prompt",
16513
- kind: "async"
16514
- }),
16515
- send: channel({
16516
- channelName: "agent.send",
16517
- kind: "async"
16518
- })
16519
- });
16520
-
16521
16145
  // src/instrumentation/plugins/cursor-sdk-plugin.ts
16522
16146
  var PATCHED_AGENT = /* @__PURE__ */ Symbol.for("braintrust.cursor-sdk.auto-patched-agent");
16523
16147
  var PATCHED_RUN = /* @__PURE__ */ Symbol.for("braintrust.cursor-sdk.patched-run");
@@ -16540,8 +16164,8 @@ var CursorSDKPlugin = class extends BasePlugin {
16540
16164
  this.subscribeToAgentFactory(cursorSDKChannels.create);
16541
16165
  this.subscribeToAgentFactory(cursorSDKChannels.resume);
16542
16166
  }
16543
- subscribeToAgentFactory(channel2) {
16544
- const tracingChannel2 = channel2.tracingChannel();
16167
+ subscribeToAgentFactory(channel) {
16168
+ const tracingChannel2 = channel.tracingChannel();
16545
16169
  const handlers = {
16546
16170
  asyncEnd: (event) => {
16547
16171
  patchCursorAgentInPlace(event.result);
@@ -16555,7 +16179,7 @@ var CursorSDKPlugin = class extends BasePlugin {
16555
16179
  });
16556
16180
  }
16557
16181
  subscribeToPrompt() {
16558
- const channel2 = cursorSDKChannels.prompt.tracingChannel();
16182
+ const channel = cursorSDKChannels.prompt.tracingChannel();
16559
16183
  const states = /* @__PURE__ */ new WeakMap();
16560
16184
  const handlers = {
16561
16185
  start: (event) => {
@@ -16610,13 +16234,13 @@ var CursorSDKPlugin = class extends BasePlugin {
16610
16234
  states.delete(event);
16611
16235
  }
16612
16236
  };
16613
- channel2.subscribe(handlers);
16237
+ channel.subscribe(handlers);
16614
16238
  this.unsubscribers.push(() => {
16615
- channel2.unsubscribe(handlers);
16239
+ channel.unsubscribe(handlers);
16616
16240
  });
16617
16241
  }
16618
16242
  subscribeToSend() {
16619
- const channel2 = cursorSDKChannels.send.tracingChannel();
16243
+ const channel = cursorSDKChannels.send.tracingChannel();
16620
16244
  const states = /* @__PURE__ */ new WeakMap();
16621
16245
  const handlers = {
16622
16246
  start: (event) => {
@@ -16690,9 +16314,9 @@ var CursorSDKPlugin = class extends BasePlugin {
16690
16314
  states.delete(event);
16691
16315
  }
16692
16316
  };
16693
- channel2.subscribe(handlers);
16317
+ channel.subscribe(handlers);
16694
16318
  this.unsubscribers.push(() => {
16695
- channel2.unsubscribe(handlers);
16319
+ channel.unsubscribe(handlers);
16696
16320
  });
16697
16321
  }
16698
16322
  };
@@ -17376,88 +17000,513 @@ function cleanMetrics2(metrics) {
17376
17000
  return cleaned;
17377
17001
  }
17378
17002
 
17379
- // src/instrumentation/plugins/google-genai-channels.ts
17380
- var googleGenAIChannels = defineChannels("@google/genai", {
17381
- generateContent: channel({
17382
- channelName: "models.generateContent",
17383
- kind: "async"
17384
- }),
17385
- generateContentStream: channel({
17386
- channelName: "models.generateContentStream",
17387
- kind: "async"
17388
- }),
17389
- embedContent: channel({
17390
- channelName: "models.embedContent",
17391
- kind: "async"
17392
- })
17393
- });
17394
-
17395
- // src/instrumentation/plugins/google-genai-plugin.ts
17396
- var GOOGLE_GENAI_INTERNAL_CONTEXT = {
17397
- caller_filename: "<node-internal>",
17398
- caller_functionname: "<node-internal>",
17399
- caller_lineno: 0
17400
- };
17401
- function createWrapperParityEvent(args) {
17402
- return {
17403
- context: GOOGLE_GENAI_INTERNAL_CONTEXT,
17404
- input: args.input,
17405
- metadata: args.metadata
17406
- };
17003
+ // src/instrumentation/plugins/openai-agents-trace-processor.ts
17004
+ function isSpanData(spanData, type) {
17005
+ return spanData.type === type;
17006
+ }
17007
+ function spanTypeFromAgents(span) {
17008
+ const spanType = span.spanData.type;
17009
+ if (spanType === "function" || spanType === "guardrail" || spanType === "mcp_tools") {
17010
+ return "tool" /* TOOL */;
17011
+ }
17012
+ if (spanType === "generation" || spanType === "response" || spanType === "transcription" || spanType === "speech") {
17013
+ return "llm" /* LLM */;
17014
+ }
17015
+ return "task" /* TASK */;
17016
+ }
17017
+ function spanNameFromAgents(span) {
17018
+ const spanData = span.spanData;
17019
+ if ("name" in spanData && spanData.name) {
17020
+ return spanData.name;
17021
+ }
17022
+ switch (spanData.type) {
17023
+ case "generation":
17024
+ return "Generation";
17025
+ case "response":
17026
+ return "Response";
17027
+ case "handoff":
17028
+ return "Handoff";
17029
+ case "mcp_tools":
17030
+ return isSpanData(spanData, "mcp_tools") && spanData.server ? `List Tools (${spanData.server})` : "MCP List Tools";
17031
+ case "transcription":
17032
+ return "Transcription";
17033
+ case "speech":
17034
+ return "Speech";
17035
+ case "speech_group":
17036
+ return "Speech Group";
17037
+ default:
17038
+ return "Unknown";
17039
+ }
17407
17040
  }
17408
- var GoogleGenAIPlugin = class extends BasePlugin {
17409
- onEnable() {
17410
- this.subscribeToGoogleGenAIChannels();
17041
+ function getTimeElapsed(end, start) {
17042
+ if (!start || !end) {
17043
+ return void 0;
17411
17044
  }
17412
- onDisable() {
17413
- this.unsubscribers = unsubscribeAll(this.unsubscribers);
17045
+ const startTime = new Date(start).getTime();
17046
+ const endTime = new Date(end).getTime();
17047
+ if (Number.isNaN(startTime) || Number.isNaN(endTime)) {
17048
+ return void 0;
17414
17049
  }
17415
- subscribeToGoogleGenAIChannels() {
17416
- this.subscribeToGenerateContentChannel();
17417
- this.subscribeToGenerateContentStreamChannel();
17418
- this.subscribeToEmbedContentChannel();
17050
+ return (endTime - startTime) / 1e3;
17051
+ }
17052
+ function getNumberProperty2(obj, key) {
17053
+ if (!isObject(obj) || !(key in obj)) {
17054
+ return void 0;
17419
17055
  }
17420
- subscribeToGenerateContentChannel() {
17421
- const tracingChannel2 = googleGenAIChannels.generateContent.tracingChannel();
17422
- const states = /* @__PURE__ */ new WeakMap();
17423
- const unbindCurrentSpanStore = bindCurrentSpanStoreToStart2(
17424
- tracingChannel2,
17425
- states,
17426
- (event) => {
17427
- const params = event.arguments[0];
17428
- const input = serializeGenerateContentInput(params);
17429
- const metadata = extractGenerateContentMetadata(params);
17430
- const span = startSpan({
17431
- name: "generate_content",
17432
- spanAttributes: {
17433
- type: "llm" /* LLM */
17434
- },
17435
- event: createWrapperParityEvent({ input, metadata })
17436
- });
17437
- return {
17438
- span,
17439
- startTime: getCurrentUnixTimestamp()
17440
- };
17056
+ const value = obj[key];
17057
+ return typeof value === "number" ? value : void 0;
17058
+ }
17059
+ function parseUsageMetrics(usage) {
17060
+ const metrics = {};
17061
+ if (!isObject(usage)) {
17062
+ return metrics;
17063
+ }
17064
+ const promptTokens = getNumberProperty2(usage, "prompt_tokens") ?? getNumberProperty2(usage, "input_tokens") ?? getNumberProperty2(usage, "promptTokens") ?? getNumberProperty2(usage, "inputTokens");
17065
+ const completionTokens = getNumberProperty2(usage, "completion_tokens") ?? getNumberProperty2(usage, "output_tokens") ?? getNumberProperty2(usage, "completionTokens") ?? getNumberProperty2(usage, "outputTokens");
17066
+ const totalTokens = getNumberProperty2(usage, "total_tokens") ?? getNumberProperty2(usage, "totalTokens");
17067
+ if (promptTokens !== void 0) {
17068
+ metrics.prompt_tokens = promptTokens;
17069
+ }
17070
+ if (completionTokens !== void 0) {
17071
+ metrics.completion_tokens = completionTokens;
17072
+ }
17073
+ if (totalTokens !== void 0) {
17074
+ metrics.tokens = totalTokens;
17075
+ } else if (promptTokens !== void 0 && completionTokens !== void 0) {
17076
+ metrics.tokens = promptTokens + completionTokens;
17077
+ }
17078
+ const inputDetails = usage.input_tokens_details;
17079
+ const cachedTokens = getNumberProperty2(inputDetails, "cached_tokens");
17080
+ const cacheWriteTokens = getNumberProperty2(
17081
+ inputDetails,
17082
+ "cache_write_tokens"
17083
+ );
17084
+ if (cachedTokens !== void 0) {
17085
+ metrics.prompt_cached_tokens = cachedTokens;
17086
+ }
17087
+ if (cacheWriteTokens !== void 0) {
17088
+ metrics.prompt_cache_creation_tokens = cacheWriteTokens;
17089
+ }
17090
+ return metrics;
17091
+ }
17092
+ var OpenAIAgentsTraceProcessor = class _OpenAIAgentsTraceProcessor {
17093
+ static DEFAULT_MAX_TRACES = 1e4;
17094
+ logger;
17095
+ maxTraces;
17096
+ traceSpans = /* @__PURE__ */ new Map();
17097
+ traceOrder = [];
17098
+ _traceSpans = this.traceSpans;
17099
+ constructor(options = {}) {
17100
+ this.logger = options.logger;
17101
+ this.maxTraces = options.maxTraces ?? _OpenAIAgentsTraceProcessor.DEFAULT_MAX_TRACES;
17102
+ }
17103
+ evictOldestTrace() {
17104
+ const oldestTraceId = this.traceOrder.shift();
17105
+ if (oldestTraceId) {
17106
+ this.traceSpans.delete(oldestTraceId);
17107
+ }
17108
+ }
17109
+ onTraceStart(trace) {
17110
+ if (!trace?.traceId) {
17111
+ return Promise.resolve();
17112
+ }
17113
+ if (this.traceOrder.length >= this.maxTraces) {
17114
+ this.evictOldestTrace();
17115
+ }
17116
+ const current = currentSpan();
17117
+ const span = current && current !== NOOP_SPAN ? current.startSpan({
17118
+ name: trace.name,
17119
+ type: "task" /* TASK */
17120
+ }) : this.logger ? this.logger.startSpan({
17121
+ name: trace.name,
17122
+ type: "task" /* TASK */
17123
+ }) : startSpan({
17124
+ name: trace.name,
17125
+ type: "task" /* TASK */
17126
+ });
17127
+ span.log({
17128
+ input: "Agent workflow started",
17129
+ metadata: {
17130
+ group_id: trace.groupId,
17131
+ ...trace.metadata || {}
17441
17132
  }
17442
- );
17443
- const handlers = {
17444
- start: (event) => {
17445
- ensureSpanState(states, event, () => {
17446
- const params = event.arguments[0];
17447
- const input = serializeGenerateContentInput(params);
17448
- const metadata = extractGenerateContentMetadata(params);
17449
- const span = startSpan({
17450
- name: "generate_content",
17451
- spanAttributes: {
17452
- type: "llm" /* LLM */
17453
- },
17454
- event: createWrapperParityEvent({ input, metadata })
17455
- });
17456
- return {
17457
- span,
17458
- startTime: getCurrentUnixTimestamp()
17459
- };
17460
- });
17133
+ });
17134
+ this.traceSpans.set(trace.traceId, {
17135
+ rootSpan: span,
17136
+ childSpans: /* @__PURE__ */ new Map(),
17137
+ metadata: {
17138
+ firstInput: null,
17139
+ lastOutput: null
17140
+ }
17141
+ });
17142
+ this.traceOrder.push(trace.traceId);
17143
+ return Promise.resolve();
17144
+ }
17145
+ async onTraceEnd(trace) {
17146
+ const traceData = this.traceSpans.get(trace?.traceId);
17147
+ if (!traceData) {
17148
+ return;
17149
+ }
17150
+ try {
17151
+ traceData.rootSpan.log({
17152
+ input: traceData.metadata.firstInput,
17153
+ output: traceData.metadata.lastOutput
17154
+ });
17155
+ traceData.rootSpan.end();
17156
+ await traceData.rootSpan.flush();
17157
+ } finally {
17158
+ this.traceSpans.delete(trace.traceId);
17159
+ const orderIndex = this.traceOrder.indexOf(trace.traceId);
17160
+ if (orderIndex > -1) {
17161
+ this.traceOrder.splice(orderIndex, 1);
17162
+ }
17163
+ }
17164
+ }
17165
+ onSpanStart(span) {
17166
+ if (!span?.spanId || !span.traceId) {
17167
+ return Promise.resolve();
17168
+ }
17169
+ const traceData = this.traceSpans.get(span.traceId);
17170
+ if (!traceData) {
17171
+ return Promise.resolve();
17172
+ }
17173
+ const parentSpan = span.parentId ? traceData.childSpans.get(span.parentId) : traceData.rootSpan;
17174
+ if (!parentSpan) {
17175
+ return Promise.resolve();
17176
+ }
17177
+ const childSpan = parentSpan.startSpan({
17178
+ name: spanNameFromAgents(span),
17179
+ type: spanTypeFromAgents(span)
17180
+ });
17181
+ traceData.childSpans.set(span.spanId, childSpan);
17182
+ return Promise.resolve();
17183
+ }
17184
+ onSpanEnd(span) {
17185
+ if (!span?.spanId || !span.traceId) {
17186
+ return Promise.resolve();
17187
+ }
17188
+ const traceData = this.traceSpans.get(span.traceId);
17189
+ if (!traceData) {
17190
+ return Promise.resolve();
17191
+ }
17192
+ const braintrustSpan = traceData.childSpans.get(span.spanId);
17193
+ if (!braintrustSpan) {
17194
+ return Promise.resolve();
17195
+ }
17196
+ const logData = this.extractLogData(span);
17197
+ braintrustSpan.log({
17198
+ error: span.error,
17199
+ ...logData
17200
+ });
17201
+ braintrustSpan.end();
17202
+ traceData.childSpans.delete(span.spanId);
17203
+ const input = logData.input;
17204
+ const output = logData.output;
17205
+ if (traceData.metadata.firstInput === null && input != null) {
17206
+ traceData.metadata.firstInput = input;
17207
+ }
17208
+ if (output != null) {
17209
+ traceData.metadata.lastOutput = output;
17210
+ }
17211
+ return Promise.resolve();
17212
+ }
17213
+ async shutdown() {
17214
+ if (this.logger && typeof this.logger.flush === "function") {
17215
+ await this.logger.flush();
17216
+ }
17217
+ }
17218
+ async forceFlush() {
17219
+ if (this.logger && typeof this.logger.flush === "function") {
17220
+ await this.logger.flush();
17221
+ }
17222
+ }
17223
+ extractLogData(span) {
17224
+ const spanData = span.spanData;
17225
+ switch (spanData.type) {
17226
+ case "agent":
17227
+ return this.extractAgentLogData(spanData);
17228
+ case "response":
17229
+ return this.extractResponseLogData(spanData, span);
17230
+ case "function":
17231
+ return this.extractFunctionLogData(spanData);
17232
+ case "handoff":
17233
+ return this.extractHandoffLogData(spanData);
17234
+ case "guardrail":
17235
+ return this.extractGuardrailLogData(spanData);
17236
+ case "generation":
17237
+ return this.extractGenerationLogData(spanData, span);
17238
+ case "custom":
17239
+ return this.extractCustomLogData(spanData);
17240
+ case "mcp_tools":
17241
+ return this.extractMCPListToolsLogData(spanData);
17242
+ case "transcription":
17243
+ return this.extractTranscriptionLogData(spanData);
17244
+ case "speech":
17245
+ return this.extractSpeechLogData(spanData);
17246
+ case "speech_group":
17247
+ return this.extractSpeechGroupLogData(spanData);
17248
+ default:
17249
+ return {};
17250
+ }
17251
+ }
17252
+ extractAgentLogData(spanData) {
17253
+ return {
17254
+ metadata: {
17255
+ tools: spanData.tools,
17256
+ handoffs: spanData.handoffs,
17257
+ output_type: spanData.output_type
17258
+ }
17259
+ };
17260
+ }
17261
+ extractResponseLogData(spanData, span) {
17262
+ const response = spanData._response;
17263
+ const output = isObject(response) ? response.output : void 0;
17264
+ const usage = isObject(response) ? response.usage : void 0;
17265
+ const metrics = {
17266
+ ...this.extractTimingMetrics(span),
17267
+ ...parseUsageMetrics(usage)
17268
+ };
17269
+ return {
17270
+ input: spanData._input,
17271
+ output,
17272
+ metadata: isObject(response) ? this.omitKeys(response, ["output", "usage"]) : {},
17273
+ metrics
17274
+ };
17275
+ }
17276
+ extractFunctionLogData(spanData) {
17277
+ return {
17278
+ input: spanData.input,
17279
+ output: spanData.output
17280
+ };
17281
+ }
17282
+ extractHandoffLogData(spanData) {
17283
+ return {
17284
+ metadata: {
17285
+ from_agent: spanData.from_agent,
17286
+ to_agent: spanData.to_agent
17287
+ }
17288
+ };
17289
+ }
17290
+ extractGuardrailLogData(spanData) {
17291
+ return {
17292
+ metadata: {
17293
+ triggered: spanData.triggered
17294
+ }
17295
+ };
17296
+ }
17297
+ extractGenerationLogData(spanData, span) {
17298
+ return {
17299
+ input: spanData.input,
17300
+ output: spanData.output,
17301
+ metadata: {
17302
+ model: spanData.model,
17303
+ model_config: spanData.model_config
17304
+ },
17305
+ metrics: {
17306
+ ...this.extractTimingMetrics(span),
17307
+ ...parseUsageMetrics(spanData.usage)
17308
+ }
17309
+ };
17310
+ }
17311
+ extractCustomLogData(spanData) {
17312
+ return spanData.data || {};
17313
+ }
17314
+ extractMCPListToolsLogData(spanData) {
17315
+ return {
17316
+ output: spanData.result,
17317
+ metadata: {
17318
+ server: spanData.server
17319
+ }
17320
+ };
17321
+ }
17322
+ extractTranscriptionLogData(spanData) {
17323
+ return {
17324
+ input: spanData.input,
17325
+ output: spanData.output,
17326
+ metadata: {
17327
+ model: spanData.model,
17328
+ model_config: spanData.model_config
17329
+ }
17330
+ };
17331
+ }
17332
+ extractSpeechLogData(spanData) {
17333
+ return {
17334
+ input: spanData.input,
17335
+ output: spanData.output,
17336
+ metadata: {
17337
+ model: spanData.model,
17338
+ model_config: spanData.model_config
17339
+ }
17340
+ };
17341
+ }
17342
+ extractSpeechGroupLogData(spanData) {
17343
+ return {
17344
+ input: spanData.input
17345
+ };
17346
+ }
17347
+ extractTimingMetrics(span) {
17348
+ const timeToFirstToken = getTimeElapsed(
17349
+ span.endedAt ?? void 0,
17350
+ span.startedAt ?? void 0
17351
+ );
17352
+ return timeToFirstToken === void 0 ? {} : { time_to_first_token: timeToFirstToken };
17353
+ }
17354
+ omitKeys(value, keys) {
17355
+ const result = {};
17356
+ for (const [key, fieldValue] of Object.entries(value)) {
17357
+ if (!keys.includes(key)) {
17358
+ result[key] = fieldValue;
17359
+ }
17360
+ }
17361
+ return result;
17362
+ }
17363
+ };
17364
+
17365
+ // src/instrumentation/plugins/openai-agents-plugin.ts
17366
+ function firstArgument(args) {
17367
+ if (Array.isArray(args)) {
17368
+ return args[0];
17369
+ }
17370
+ if (isObject(args) && "length" in args && typeof args.length === "number" && Number.isInteger(args.length) && args.length >= 0) {
17371
+ return Array.from(args)[0];
17372
+ }
17373
+ return void 0;
17374
+ }
17375
+ function isOpenAIAgentsTrace(value) {
17376
+ return isObject(value) && value.type === "trace" && typeof value.traceId === "string";
17377
+ }
17378
+ function isOpenAIAgentsSpan(value) {
17379
+ return isObject(value) && value.type === "trace.span" && typeof value.traceId === "string" && typeof value.spanId === "string";
17380
+ }
17381
+ var OpenAIAgentsPlugin = class extends BasePlugin {
17382
+ processor = new OpenAIAgentsTraceProcessor();
17383
+ onEnable() {
17384
+ this.subscribeToTraceLifecycle();
17385
+ }
17386
+ onDisable() {
17387
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
17388
+ void this.processor.shutdown();
17389
+ }
17390
+ subscribeToTraceLifecycle() {
17391
+ const traceStartChannel = openAIAgentsCoreChannels.onTraceStart.tracingChannel();
17392
+ const traceStartHandlers = {
17393
+ start: (event) => {
17394
+ const trace = firstArgument(event.arguments);
17395
+ if (isOpenAIAgentsTrace(trace)) {
17396
+ void this.processor.onTraceStart(trace);
17397
+ }
17398
+ }
17399
+ };
17400
+ traceStartChannel.subscribe(traceStartHandlers);
17401
+ this.unsubscribers.push(
17402
+ () => traceStartChannel.unsubscribe(traceStartHandlers)
17403
+ );
17404
+ const traceEndChannel = openAIAgentsCoreChannels.onTraceEnd.tracingChannel();
17405
+ const traceEndHandlers = {
17406
+ start: (event) => {
17407
+ const trace = firstArgument(event.arguments);
17408
+ if (isOpenAIAgentsTrace(trace)) {
17409
+ void this.processor.onTraceEnd(trace);
17410
+ }
17411
+ }
17412
+ };
17413
+ traceEndChannel.subscribe(traceEndHandlers);
17414
+ this.unsubscribers.push(
17415
+ () => traceEndChannel.unsubscribe(traceEndHandlers)
17416
+ );
17417
+ const spanStartChannel = openAIAgentsCoreChannels.onSpanStart.tracingChannel();
17418
+ const spanStartHandlers = {
17419
+ start: (event) => {
17420
+ const span = firstArgument(event.arguments);
17421
+ if (isOpenAIAgentsSpan(span)) {
17422
+ void this.processor.onSpanStart(span);
17423
+ }
17424
+ }
17425
+ };
17426
+ spanStartChannel.subscribe(spanStartHandlers);
17427
+ this.unsubscribers.push(
17428
+ () => spanStartChannel.unsubscribe(spanStartHandlers)
17429
+ );
17430
+ const spanEndChannel = openAIAgentsCoreChannels.onSpanEnd.tracingChannel();
17431
+ const spanEndHandlers = {
17432
+ start: (event) => {
17433
+ const span = firstArgument(event.arguments);
17434
+ if (isOpenAIAgentsSpan(span)) {
17435
+ void this.processor.onSpanEnd(span);
17436
+ }
17437
+ }
17438
+ };
17439
+ spanEndChannel.subscribe(spanEndHandlers);
17440
+ this.unsubscribers.push(() => spanEndChannel.unsubscribe(spanEndHandlers));
17441
+ }
17442
+ };
17443
+
17444
+ // src/instrumentation/plugins/google-genai-plugin.ts
17445
+ var GOOGLE_GENAI_INTERNAL_CONTEXT = {
17446
+ caller_filename: "<node-internal>",
17447
+ caller_functionname: "<node-internal>",
17448
+ caller_lineno: 0
17449
+ };
17450
+ function createWrapperParityEvent(args) {
17451
+ return {
17452
+ context: GOOGLE_GENAI_INTERNAL_CONTEXT,
17453
+ input: args.input,
17454
+ metadata: args.metadata
17455
+ };
17456
+ }
17457
+ var GoogleGenAIPlugin = class extends BasePlugin {
17458
+ onEnable() {
17459
+ this.subscribeToGoogleGenAIChannels();
17460
+ }
17461
+ onDisable() {
17462
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
17463
+ }
17464
+ subscribeToGoogleGenAIChannels() {
17465
+ this.subscribeToGenerateContentChannel();
17466
+ this.subscribeToGenerateContentStreamChannel();
17467
+ this.subscribeToEmbedContentChannel();
17468
+ }
17469
+ subscribeToGenerateContentChannel() {
17470
+ const tracingChannel2 = googleGenAIChannels.generateContent.tracingChannel();
17471
+ const states = /* @__PURE__ */ new WeakMap();
17472
+ const unbindCurrentSpanStore = bindCurrentSpanStoreToStart2(
17473
+ tracingChannel2,
17474
+ states,
17475
+ (event) => {
17476
+ const params = event.arguments[0];
17477
+ const input = serializeGenerateContentInput(params);
17478
+ const metadata = extractGenerateContentMetadata(params);
17479
+ const span = startSpan({
17480
+ name: "generate_content",
17481
+ spanAttributes: {
17482
+ type: "llm" /* LLM */
17483
+ },
17484
+ event: createWrapperParityEvent({ input, metadata })
17485
+ });
17486
+ return {
17487
+ span,
17488
+ startTime: getCurrentUnixTimestamp()
17489
+ };
17490
+ }
17491
+ );
17492
+ const handlers = {
17493
+ start: (event) => {
17494
+ ensureSpanState(states, event, () => {
17495
+ const params = event.arguments[0];
17496
+ const input = serializeGenerateContentInput(params);
17497
+ const metadata = extractGenerateContentMetadata(params);
17498
+ const span = startSpan({
17499
+ name: "generate_content",
17500
+ spanAttributes: {
17501
+ type: "llm" /* LLM */
17502
+ },
17503
+ event: createWrapperParityEvent({ input, metadata })
17504
+ });
17505
+ return {
17506
+ span,
17507
+ startTime: getCurrentUnixTimestamp()
17508
+ };
17509
+ });
17461
17510
  },
17462
17511
  asyncEnd: (event) => {
17463
17512
  const spanState = states.get(event);
@@ -18139,30 +18188,6 @@ function tryToDict(obj) {
18139
18188
  return null;
18140
18189
  }
18141
18190
 
18142
- // src/instrumentation/plugins/huggingface-channels.ts
18143
- var huggingFaceChannels = defineChannels("@huggingface/inference", {
18144
- chatCompletion: channel({
18145
- channelName: "chatCompletion",
18146
- kind: "async"
18147
- }),
18148
- chatCompletionStream: channel({
18149
- channelName: "chatCompletionStream",
18150
- kind: "sync-stream"
18151
- }),
18152
- textGeneration: channel({
18153
- channelName: "textGeneration",
18154
- kind: "async"
18155
- }),
18156
- textGenerationStream: channel({
18157
- channelName: "textGenerationStream",
18158
- kind: "sync-stream"
18159
- }),
18160
- featureExtraction: channel({
18161
- channelName: "featureExtraction",
18162
- kind: "async"
18163
- })
18164
- });
18165
-
18166
18191
  // src/instrumentation/plugins/huggingface-plugin.ts
18167
18192
  var REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
18168
18193
  "dimensions",
@@ -18587,22 +18612,6 @@ function extractTextGenerationStreamMetadata(chunks) {
18587
18612
  return void 0;
18588
18613
  }
18589
18614
 
18590
- // src/instrumentation/plugins/openrouter-agent-channels.ts
18591
- var openRouterAgentChannels = defineChannels("@openrouter/agent", {
18592
- callModel: channel({
18593
- channelName: "callModel",
18594
- kind: "sync-stream"
18595
- }),
18596
- callModelTurn: channel({
18597
- channelName: "callModel.turn",
18598
- kind: "async"
18599
- }),
18600
- toolExecute: channel({
18601
- channelName: "tool.execute",
18602
- kind: "async"
18603
- })
18604
- });
18605
-
18606
18615
  // src/instrumentation/plugins/openrouter-agent-plugin.ts
18607
18616
  var OpenRouterAgentPlugin = class extends BasePlugin {
18608
18617
  onEnable() {
@@ -19372,40 +19381,6 @@ function normalizeError(error) {
19372
19381
  return error instanceof Error ? error : new Error(String(error));
19373
19382
  }
19374
19383
 
19375
- // src/instrumentation/plugins/openrouter-channels.ts
19376
- var openRouterChannels = defineChannels("@openrouter/sdk", {
19377
- chatSend: channel({
19378
- channelName: "chat.send",
19379
- kind: "async"
19380
- }),
19381
- embeddingsGenerate: channel({
19382
- channelName: "embeddings.generate",
19383
- kind: "async"
19384
- }),
19385
- rerankRerank: channel(
19386
- {
19387
- channelName: "rerank.rerank",
19388
- kind: "async"
19389
- }
19390
- ),
19391
- betaResponsesSend: channel({
19392
- channelName: "beta.responses.send",
19393
- kind: "async"
19394
- }),
19395
- callModel: channel({
19396
- channelName: "callModel",
19397
- kind: "sync-stream"
19398
- }),
19399
- callModelTurn: channel({
19400
- channelName: "callModel.turn",
19401
- kind: "async"
19402
- }),
19403
- toolExecute: channel({
19404
- channelName: "tool.execute",
19405
- kind: "async"
19406
- })
19407
- });
19408
-
19409
19384
  // src/instrumentation/plugins/openrouter-plugin.ts
19410
19385
  var OpenRouterPlugin = class extends BasePlugin {
19411
19386
  onEnable() {
@@ -20445,54 +20420,6 @@ function normalizeError2(error) {
20445
20420
  return error instanceof Error ? error : new Error(String(error));
20446
20421
  }
20447
20422
 
20448
- // src/instrumentation/plugins/mistral-channels.ts
20449
- var mistralChannels = defineChannels("@mistralai/mistralai", {
20450
- chatComplete: channel({
20451
- channelName: "chat.complete",
20452
- kind: "async"
20453
- }),
20454
- chatStream: channel({
20455
- channelName: "chat.stream",
20456
- kind: "async"
20457
- }),
20458
- embeddingsCreate: channel({
20459
- channelName: "embeddings.create",
20460
- kind: "async"
20461
- }),
20462
- classifiersModerate: channel({
20463
- channelName: "classifiers.moderate",
20464
- kind: "async"
20465
- }),
20466
- classifiersModerateChat: channel({
20467
- channelName: "classifiers.moderateChat",
20468
- kind: "async"
20469
- }),
20470
- classifiersClassify: channel({
20471
- channelName: "classifiers.classify",
20472
- kind: "async"
20473
- }),
20474
- classifiersClassifyChat: channel({
20475
- channelName: "classifiers.classifyChat",
20476
- kind: "async"
20477
- }),
20478
- fimComplete: channel({
20479
- channelName: "fim.complete",
20480
- kind: "async"
20481
- }),
20482
- fimStream: channel({
20483
- channelName: "fim.stream",
20484
- kind: "async"
20485
- }),
20486
- agentsComplete: channel({
20487
- channelName: "agents.complete",
20488
- kind: "async"
20489
- }),
20490
- agentsStream: channel({
20491
- channelName: "agents.stream",
20492
- kind: "async"
20493
- })
20494
- });
20495
-
20496
20423
  // src/instrumentation/plugins/mistral-plugin.ts
20497
20424
  var MistralPlugin = class extends BasePlugin {
20498
20425
  onEnable() {
@@ -21110,22 +21037,6 @@ function aggregateMistralStreamChunks(chunks) {
21110
21037
  };
21111
21038
  }
21112
21039
 
21113
- // src/instrumentation/plugins/google-adk-channels.ts
21114
- var googleADKChannels = defineChannels("@google/adk", {
21115
- runnerRunAsync: channel({
21116
- channelName: "runner.runAsync",
21117
- kind: "sync-stream"
21118
- }),
21119
- agentRunAsync: channel({
21120
- channelName: "agent.runAsync",
21121
- kind: "sync-stream"
21122
- }),
21123
- toolRunAsync: channel({
21124
- channelName: "tool.runAsync",
21125
- kind: "async"
21126
- })
21127
- });
21128
-
21129
21040
  // src/instrumentation/plugins/google-adk-plugin.ts
21130
21041
  var GoogleADKPlugin = class extends BasePlugin {
21131
21042
  activeRunnerSpans = /* @__PURE__ */ new Map();
@@ -21757,26 +21668,6 @@ function cleanMetrics4(metrics) {
21757
21668
  return cleaned;
21758
21669
  }
21759
21670
 
21760
- // src/instrumentation/plugins/cohere-channels.ts
21761
- var cohereChannels = defineChannels("cohere-ai", {
21762
- chat: channel({
21763
- channelName: "chat",
21764
- kind: "async"
21765
- }),
21766
- chatStream: channel({
21767
- channelName: "chatStream",
21768
- kind: "async"
21769
- }),
21770
- embed: channel({
21771
- channelName: "embed",
21772
- kind: "async"
21773
- }),
21774
- rerank: channel({
21775
- channelName: "rerank",
21776
- kind: "async"
21777
- })
21778
- });
21779
-
21780
21671
  // src/instrumentation/plugins/cohere-plugin.ts
21781
21672
  var CoherePlugin = class extends BasePlugin {
21782
21673
  onEnable() {
@@ -22443,20 +22334,6 @@ function aggregateCohereChatStreamChunks(chunks) {
22443
22334
  };
22444
22335
  }
22445
22336
 
22446
- // src/instrumentation/plugins/groq-channels.ts
22447
- var groqChannels = defineChannels("groq-sdk", {
22448
- chatCompletionsCreate: channel({
22449
- channelName: "chat.completions.create",
22450
- kind: "async"
22451
- }),
22452
- embeddingsCreate: channel(
22453
- {
22454
- channelName: "embeddings.create",
22455
- kind: "async"
22456
- }
22457
- )
22458
- });
22459
-
22460
22337
  // src/instrumentation/plugins/groq-plugin.ts
22461
22338
  var GroqPlugin = class extends BasePlugin {
22462
22339
  onEnable() {
@@ -22553,40 +22430,6 @@ function aggregateGroqReasoning(chunks) {
22553
22430
  return reasoning.length > 0 ? reasoning : void 0;
22554
22431
  }
22555
22432
 
22556
- // src/instrumentation/plugins/genkit-channels.ts
22557
- var genkitChannels = defineChannels("@genkit-ai/ai", {
22558
- generate: channel({
22559
- channelName: "generate",
22560
- kind: "async"
22561
- }),
22562
- generateStream: channel({
22563
- channelName: "generateStream",
22564
- kind: "sync-stream"
22565
- }),
22566
- embed: channel({
22567
- channelName: "embed",
22568
- kind: "async"
22569
- }),
22570
- embedMany: channel({
22571
- channelName: "embedMany",
22572
- kind: "async"
22573
- }),
22574
- actionRun: channel({
22575
- channelName: "action.run",
22576
- kind: "async"
22577
- }),
22578
- actionStream: channel({
22579
- channelName: "action.stream",
22580
- kind: "sync-stream"
22581
- })
22582
- });
22583
- var genkitCoreChannels = defineChannels("@genkit-ai/core", {
22584
- actionSpan: channel({
22585
- channelName: "action.span",
22586
- kind: "async"
22587
- })
22588
- });
22589
-
22590
22433
  // src/instrumentation/plugins/genkit-plugin.ts
22591
22434
  var GenkitPlugin = class extends BasePlugin {
22592
22435
  onEnable() {
@@ -23138,22 +22981,6 @@ function stringValue(value) {
23138
22981
  return typeof value === "string" ? value : void 0;
23139
22982
  }
23140
22983
 
23141
- // src/instrumentation/plugins/github-copilot-channels.ts
23142
- var gitHubCopilotChannels = defineChannels("@github/copilot-sdk", {
23143
- createSession: channel({
23144
- channelName: "client.createSession",
23145
- kind: "async"
23146
- }),
23147
- resumeSession: channel({
23148
- channelName: "client.resumeSession",
23149
- kind: "async"
23150
- }),
23151
- sendAndWait: channel({
23152
- channelName: "session.sendAndWait",
23153
- kind: "async"
23154
- })
23155
- });
23156
-
23157
22984
  // src/instrumentation/plugins/github-copilot-plugin.ts
23158
22985
  var ROOT_AGENT_KEY = "__root__";
23159
22986
  function agentKey(agentId) {
@@ -23498,175 +23325,1860 @@ async function dispatchEvent(state, event) {
23498
23325
  d.agentDescription ?? ""
23499
23326
  );
23500
23327
  }
23501
- break;
23502
- }
23503
- case "subagent.completed": {
23504
- const d = event.data;
23505
- if (d && typeof d.toolCallId === "string") {
23506
- handleSubagentCompleted(
23507
- state,
23508
- d.toolCallId,
23509
- d.model,
23510
- d.totalTokens,
23511
- d.totalToolCalls,
23512
- d.durationMs
23513
- );
23328
+ break;
23329
+ }
23330
+ case "subagent.completed": {
23331
+ const d = event.data;
23332
+ if (d && typeof d.toolCallId === "string") {
23333
+ handleSubagentCompleted(
23334
+ state,
23335
+ d.toolCallId,
23336
+ d.model,
23337
+ d.totalTokens,
23338
+ d.totalToolCalls,
23339
+ d.durationMs
23340
+ );
23341
+ }
23342
+ break;
23343
+ }
23344
+ case "subagent.failed": {
23345
+ const d = event.data;
23346
+ if (d && typeof d.toolCallId === "string") {
23347
+ handleSubagentFailed(
23348
+ state,
23349
+ d.toolCallId,
23350
+ d.error ?? "sub-agent failed"
23351
+ );
23352
+ }
23353
+ break;
23354
+ }
23355
+ case "session.usage_info": {
23356
+ const d = event.data;
23357
+ if (d && typeof d.currentTokens === "number") {
23358
+ state.session.span.log({
23359
+ metadata: {
23360
+ "github_copilot.context_window.limit": d.tokenLimit,
23361
+ "github_copilot.context_window.current": d.currentTokens,
23362
+ "github_copilot.context_window.messages": d.messagesLength
23363
+ }
23364
+ });
23365
+ }
23366
+ break;
23367
+ }
23368
+ }
23369
+ }
23370
+ function injectTracingHooks2(config, state) {
23371
+ const existingHooks = config.hooks ?? {};
23372
+ const onSessionEnd = async (input, invocation) => {
23373
+ try {
23374
+ await existingHooks.onSessionEnd?.(input, invocation);
23375
+ } finally {
23376
+ handleSessionEnd(state, input.reason, input.error);
23377
+ state.unsubscribeEvents?.();
23378
+ }
23379
+ };
23380
+ config.hooks = {
23381
+ ...existingHooks,
23382
+ onSessionEnd
23383
+ };
23384
+ }
23385
+ function attachSessionEventListener(session, state) {
23386
+ const handler = (event) => {
23387
+ state.processing = state.processing.then(() => dispatchEvent(state, event)).catch((err) => {
23388
+ console.error(
23389
+ "[Braintrust] Error processing GitHub Copilot SDK event:",
23390
+ err
23391
+ );
23392
+ });
23393
+ };
23394
+ state.unsubscribeEvents = session.on(
23395
+ handler
23396
+ );
23397
+ }
23398
+ function isGitHubCopilotSession(value) {
23399
+ return value !== null && typeof value === "object" && typeof value.on === "function";
23400
+ }
23401
+ function makeSessionHandlers(sessionStates, configArgIndex, includeProviderMetadata) {
23402
+ return {
23403
+ start: (event) => {
23404
+ const config = event.arguments[configArgIndex];
23405
+ if (!config || typeof config !== "object") {
23406
+ return;
23407
+ }
23408
+ const sessionSpan = startSpan({
23409
+ name: "Copilot Session",
23410
+ spanAttributes: { type: "task" /* TASK */ }
23411
+ });
23412
+ const metadata = {};
23413
+ if (config.model) {
23414
+ metadata["github_copilot.model"] = config.model;
23415
+ }
23416
+ if (includeProviderMetadata && config.provider?.type) {
23417
+ metadata["github_copilot.provider_type"] = config.provider.type;
23418
+ }
23419
+ if (Object.keys(metadata).length > 0) {
23420
+ sessionSpan.log({ metadata });
23421
+ }
23422
+ const state = {
23423
+ session: makeSpanWithId(sessionSpan),
23424
+ activeTurns: /* @__PURE__ */ new Map(),
23425
+ pendingUserMessages: /* @__PURE__ */ new Map(),
23426
+ currentMessageContent: /* @__PURE__ */ new Map(),
23427
+ activeTools: /* @__PURE__ */ new Map(),
23428
+ subAgents: /* @__PURE__ */ new Map(),
23429
+ agentIdToToolCallId: /* @__PURE__ */ new Map(),
23430
+ processing: Promise.resolve(),
23431
+ totalInputTokens: 0,
23432
+ totalOutputTokens: 0
23433
+ };
23434
+ injectTracingHooks2(config, state);
23435
+ sessionStates.set(event, state);
23436
+ },
23437
+ asyncEnd: (event) => {
23438
+ const state = sessionStates.get(event);
23439
+ if (!state) {
23440
+ return;
23441
+ }
23442
+ const session = event.result;
23443
+ if (isGitHubCopilotSession(session)) {
23444
+ attachSessionEventListener(session, state);
23445
+ } else {
23446
+ state.session.span.end();
23447
+ }
23448
+ sessionStates.delete(event);
23449
+ },
23450
+ error: (event) => {
23451
+ const state = sessionStates.get(event);
23452
+ if (!state || !event.error) {
23453
+ return;
23454
+ }
23455
+ state.session.span.log({ error: event.error.message });
23456
+ state.session.span.end();
23457
+ sessionStates.delete(event);
23458
+ }
23459
+ };
23460
+ }
23461
+ var GitHubCopilotPlugin = class extends BasePlugin {
23462
+ onEnable() {
23463
+ this.subscribeToSessionChannels();
23464
+ }
23465
+ onDisable() {
23466
+ for (const unsubscribe of this.unsubscribers) {
23467
+ unsubscribe();
23468
+ }
23469
+ this.unsubscribers = [];
23470
+ }
23471
+ subscribeToSessionChannels() {
23472
+ const createChannel = gitHubCopilotChannels.createSession.tracingChannel();
23473
+ const resumeChannel = gitHubCopilotChannels.resumeSession.tracingChannel();
23474
+ const sessionStates = /* @__PURE__ */ new WeakMap();
23475
+ const createHandlers = makeSessionHandlers(
23476
+ sessionStates,
23477
+ 0,
23478
+ // config is arg 0 of createSession(config)
23479
+ true
23480
+ // include provider metadata
23481
+ );
23482
+ const resumeHandlers = makeSessionHandlers(
23483
+ sessionStates,
23484
+ 1,
23485
+ // config is arg 1 of resumeSession(sessionId, config)
23486
+ false
23487
+ // resumeSession config has no provider field
23488
+ );
23489
+ createChannel.subscribe(createHandlers);
23490
+ resumeChannel.subscribe(resumeHandlers);
23491
+ this.unsubscribers.push(
23492
+ () => createChannel.unsubscribe(createHandlers),
23493
+ () => resumeChannel.unsubscribe(resumeHandlers)
23494
+ );
23495
+ }
23496
+ };
23497
+
23498
+ // src/wrappers/flue.ts
23499
+ var WRAPPED_FLUE_CONTEXT = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-context");
23500
+ var WRAPPED_FLUE_HARNESS = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-harness");
23501
+ var WRAPPED_FLUE_SESSION = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-session");
23502
+ var SUBSCRIBED_FLUE_CONTEXT_EVENTS = /* @__PURE__ */ Symbol.for(
23503
+ "braintrust.flue.subscribed-context-events"
23504
+ );
23505
+ function wrapFlueContext(ctx) {
23506
+ if (!isPlausibleFlueContext(ctx)) {
23507
+ console.warn("Unsupported Flue context. Not wrapping.");
23508
+ return ctx;
23509
+ }
23510
+ const context = ctx;
23511
+ subscribeFlueContextEvents(context, { captureTurnSpans: true });
23512
+ return patchFlueContextInPlace(context);
23513
+ }
23514
+ function patchFlueContextInPlace(ctx) {
23515
+ const context = ctx;
23516
+ if (context[WRAPPED_FLUE_CONTEXT]) {
23517
+ return ctx;
23518
+ }
23519
+ const originalInit = context.init.bind(context);
23520
+ try {
23521
+ Object.defineProperty(context, WRAPPED_FLUE_CONTEXT, {
23522
+ configurable: false,
23523
+ enumerable: false,
23524
+ value: true
23525
+ });
23526
+ Object.defineProperty(context, "init", {
23527
+ configurable: true,
23528
+ value: async function wrappedFlueInit(options) {
23529
+ const harness = await originalInit(options);
23530
+ return wrapFlueHarness(harness);
23531
+ },
23532
+ writable: true
23533
+ });
23534
+ } catch {
23535
+ }
23536
+ return ctx;
23537
+ }
23538
+ function wrapFlueSession(session) {
23539
+ if (!isPlausibleFlueSession(session)) {
23540
+ console.warn("Unsupported Flue session. Not wrapping.");
23541
+ return session;
23542
+ }
23543
+ return patchFlueSessionInPlace(session);
23544
+ }
23545
+ function subscribeFlueContextEvents(ctx, options = {}) {
23546
+ if (!ctx || typeof ctx !== "object" || typeof ctx.subscribeEvent !== "function") {
23547
+ return void 0;
23548
+ }
23549
+ const context = ctx;
23550
+ const captureTurnSpans = options.captureTurnSpans ?? true;
23551
+ const existingSubscription = context[SUBSCRIBED_FLUE_CONTEXT_EVENTS];
23552
+ if (existingSubscription) {
23553
+ if (existingSubscription.captureTurnSpans || !captureTurnSpans) {
23554
+ return void 0;
23555
+ }
23556
+ try {
23557
+ existingSubscription.unsubscribe();
23558
+ } catch {
23559
+ }
23560
+ }
23561
+ try {
23562
+ const unsubscribe = ctx.subscribeEvent((event) => {
23563
+ flueChannels.contextEvent.traceSync(() => void 0, {
23564
+ arguments: [event],
23565
+ captureTurnSpans,
23566
+ context: ctx
23567
+ });
23568
+ });
23569
+ if (existingSubscription) {
23570
+ existingSubscription.captureTurnSpans = captureTurnSpans;
23571
+ existingSubscription.unsubscribe = unsubscribe;
23572
+ } else {
23573
+ Object.defineProperty(context, SUBSCRIBED_FLUE_CONTEXT_EVENTS, {
23574
+ configurable: false,
23575
+ enumerable: false,
23576
+ value: {
23577
+ captureTurnSpans,
23578
+ unsubscribe
23579
+ }
23580
+ });
23581
+ }
23582
+ return unsubscribe;
23583
+ } catch {
23584
+ return void 0;
23585
+ }
23586
+ }
23587
+ function wrapFlueHarness(harness) {
23588
+ if (!isPlausibleFlueHarness(harness)) {
23589
+ return harness;
23590
+ }
23591
+ const target = harness;
23592
+ if (target[WRAPPED_FLUE_HARNESS]) {
23593
+ return harness;
23594
+ }
23595
+ const originalSession = target.session.bind(target);
23596
+ try {
23597
+ Object.defineProperty(target, WRAPPED_FLUE_HARNESS, {
23598
+ configurable: false,
23599
+ enumerable: false,
23600
+ value: true
23601
+ });
23602
+ Object.defineProperty(target, "session", {
23603
+ configurable: true,
23604
+ value: async function wrappedFlueHarnessSession(name, options) {
23605
+ const session = await originalSession(name, options);
23606
+ return patchFlueSessionInPlace(session);
23607
+ },
23608
+ writable: true
23609
+ });
23610
+ const sessions = target.sessions;
23611
+ if (sessions && typeof sessions === "object") {
23612
+ patchFlueSessionFactory(sessions, "get");
23613
+ patchFlueSessionFactory(sessions, "create");
23614
+ }
23615
+ } catch {
23616
+ }
23617
+ return harness;
23618
+ }
23619
+ function patchFlueSessionInPlace(session) {
23620
+ if (session[WRAPPED_FLUE_SESSION]) {
23621
+ return session;
23622
+ }
23623
+ try {
23624
+ Object.defineProperty(session, WRAPPED_FLUE_SESSION, {
23625
+ configurable: false,
23626
+ enumerable: false,
23627
+ value: true
23628
+ });
23629
+ patchCallHandleMethod(session, "prompt", flueChannels.prompt);
23630
+ patchCallHandleMethod(session, "skill", flueChannels.skill);
23631
+ patchCallHandleMethod(session, "task", flueChannels.task);
23632
+ patchCompact(session);
23633
+ } catch {
23634
+ }
23635
+ return session;
23636
+ }
23637
+ function patchFlueSessionFactory(sessions, method) {
23638
+ const original = sessions[method];
23639
+ if (typeof original !== "function") {
23640
+ return;
23641
+ }
23642
+ const bound = original.bind(sessions);
23643
+ Object.defineProperty(sessions, method, {
23644
+ configurable: true,
23645
+ value: async function wrappedFlueSessionFactory(name, options) {
23646
+ const session = await bound(name, options);
23647
+ return patchFlueSessionInPlace(session);
23648
+ },
23649
+ writable: true
23650
+ });
23651
+ }
23652
+ function patchCallHandleMethod(session, method, channel) {
23653
+ const original = session[method];
23654
+ if (typeof original !== "function") {
23655
+ return;
23656
+ }
23657
+ const bound = original.bind(session);
23658
+ Object.defineProperty(session, method, {
23659
+ configurable: true,
23660
+ value(input, options) {
23661
+ const args = [input, options];
23662
+ const { originalResult, traced: traced2 } = traceFlueOperation(channel, {
23663
+ context: {
23664
+ arguments: args,
23665
+ operation: method,
23666
+ session
23667
+ },
23668
+ run: () => bound(input, options)
23669
+ });
23670
+ return preserveCallHandle(originalResult, traced2);
23671
+ },
23672
+ writable: true
23673
+ });
23674
+ }
23675
+ function patchCompact(session) {
23676
+ const original = session.compact;
23677
+ if (typeof original !== "function") {
23678
+ return;
23679
+ }
23680
+ const bound = original.bind(session);
23681
+ Object.defineProperty(session, "compact", {
23682
+ configurable: true,
23683
+ value() {
23684
+ const context = {
23685
+ arguments: [],
23686
+ operation: "compact",
23687
+ session
23688
+ };
23689
+ return flueChannels.compact.tracePromise(() => bound(), context);
23690
+ },
23691
+ writable: true
23692
+ });
23693
+ }
23694
+ function traceFlueOperation(channel, args) {
23695
+ const tracingChannel2 = channel.tracingChannel();
23696
+ const context = args.context;
23697
+ let originalResult;
23698
+ let traced2;
23699
+ const run = () => {
23700
+ try {
23701
+ originalResult = args.run();
23702
+ tracingChannel2.end?.publish(context);
23703
+ } catch (error) {
23704
+ context.error = normalizeError3(error);
23705
+ tracingChannel2.error?.publish(context);
23706
+ tracingChannel2.end?.publish(context);
23707
+ throw error;
23708
+ }
23709
+ traced2 = Promise.resolve(originalResult).then(
23710
+ (result) => {
23711
+ context.result = result;
23712
+ tracingChannel2.asyncStart?.publish(context);
23713
+ tracingChannel2.asyncEnd?.publish(context);
23714
+ return result;
23715
+ },
23716
+ (error) => {
23717
+ context.error = normalizeError3(error);
23718
+ tracingChannel2.error?.publish(context);
23719
+ tracingChannel2.asyncStart?.publish(context);
23720
+ tracingChannel2.asyncEnd?.publish(context);
23721
+ throw error;
23722
+ }
23723
+ );
23724
+ };
23725
+ if (tracingChannel2.start?.runStores) {
23726
+ tracingChannel2.start.runStores(context, run);
23727
+ } else {
23728
+ tracingChannel2.start?.publish(context);
23729
+ run();
23730
+ }
23731
+ return { originalResult, traced: traced2 };
23732
+ }
23733
+ function normalizeError3(error) {
23734
+ return error instanceof Error ? error : new Error(String(error));
23735
+ }
23736
+ function preserveCallHandle(originalHandle, traced2) {
23737
+ if (!isFlueCallHandle(originalHandle)) {
23738
+ return traced2;
23739
+ }
23740
+ const handle = originalHandle;
23741
+ const wrapped = {
23742
+ get signal() {
23743
+ return handle.signal;
23744
+ },
23745
+ abort(reason) {
23746
+ return handle.abort(reason);
23747
+ },
23748
+ then(onfulfilled, onrejected) {
23749
+ return traced2.then(onfulfilled, onrejected);
23750
+ }
23751
+ };
23752
+ return wrapped;
23753
+ }
23754
+ function isPlausibleFlueContext(value) {
23755
+ return !!value && typeof value === "object" && typeof value.init === "function";
23756
+ }
23757
+ function isPlausibleFlueHarness(value) {
23758
+ return !!value && typeof value === "object" && typeof value.session === "function";
23759
+ }
23760
+ function isPlausibleFlueSession(value) {
23761
+ return !!value && typeof value === "object" && typeof value.prompt === "function" && typeof value.skill === "function" && typeof value.task === "function" && typeof value.compact === "function";
23762
+ }
23763
+ function isFlueCallHandle(value) {
23764
+ return !!value && typeof value === "object" && typeof value.then === "function" && typeof value.abort === "function" && "signal" in value;
23765
+ }
23766
+
23767
+ // src/instrumentation/plugins/flue-plugin.ts
23768
+ var FluePlugin = class extends BasePlugin {
23769
+ activeOperationsById = /* @__PURE__ */ new Map();
23770
+ activeOperationsByScope = /* @__PURE__ */ new Map();
23771
+ compactionsByScope = /* @__PURE__ */ new Map();
23772
+ pendingOperationsByKey = /* @__PURE__ */ new Map();
23773
+ tasksById = /* @__PURE__ */ new Map();
23774
+ toolsById = /* @__PURE__ */ new Map();
23775
+ turnsByScope = /* @__PURE__ */ new Map();
23776
+ onEnable() {
23777
+ this.subscribeToContextCreation();
23778
+ this.subscribeToSessionCreation();
23779
+ this.subscribeToContextEvents();
23780
+ this.subscribeToSessionOperations();
23781
+ }
23782
+ onDisable() {
23783
+ for (const unsubscribe of this.unsubscribers) {
23784
+ unsubscribe();
23785
+ }
23786
+ this.unsubscribers = [];
23787
+ this.activeOperationsById.clear();
23788
+ this.activeOperationsByScope.clear();
23789
+ this.compactionsByScope.clear();
23790
+ this.pendingOperationsByKey.clear();
23791
+ this.tasksById.clear();
23792
+ this.toolsById.clear();
23793
+ this.turnsByScope.clear();
23794
+ }
23795
+ subscribeToContextCreation() {
23796
+ const channel = flueChannels.createContext.tracingChannel();
23797
+ const handlers = {
23798
+ end: (event) => {
23799
+ const ctx = event.result;
23800
+ if (!ctx) {
23801
+ return;
23802
+ }
23803
+ subscribeFlueContextEvents(ctx, { captureTurnSpans: false });
23804
+ patchFlueContextInPlace(ctx);
23805
+ },
23806
+ error: () => {
23807
+ }
23808
+ };
23809
+ channel.subscribe(handlers);
23810
+ this.unsubscribers.push(() => {
23811
+ channel.unsubscribe(handlers);
23812
+ });
23813
+ }
23814
+ subscribeToSessionCreation() {
23815
+ const channel = flueChannels.openSession.tracingChannel();
23816
+ const handlers = {
23817
+ asyncEnd: (event) => {
23818
+ if (event.result) {
23819
+ patchFlueSessionInPlace(
23820
+ event.result
23821
+ );
23822
+ }
23823
+ if (event.harness) {
23824
+ wrapFlueHarness(event.harness);
23825
+ }
23826
+ },
23827
+ error: () => {
23828
+ }
23829
+ };
23830
+ channel.subscribe(handlers);
23831
+ this.unsubscribers.push(() => {
23832
+ channel.unsubscribe(handlers);
23833
+ });
23834
+ }
23835
+ subscribeToSessionOperations() {
23836
+ this.subscribeToSessionOperation(flueChannels.prompt);
23837
+ this.subscribeToSessionOperation(flueChannels.skill);
23838
+ this.subscribeToSessionOperation(flueChannels.task);
23839
+ this.subscribeToCompact();
23840
+ }
23841
+ subscribeToSessionOperation(channel) {
23842
+ const tracingChannel2 = channel.tracingChannel();
23843
+ const states = /* @__PURE__ */ new WeakMap();
23844
+ const ensureState2 = (event) => {
23845
+ const existing = states.get(event);
23846
+ if (existing) {
23847
+ return existing;
23848
+ }
23849
+ const state = this.startOperationState({
23850
+ args: event.arguments,
23851
+ moduleVersion: typeof event.moduleVersion === "string" ? event.moduleVersion : void 0,
23852
+ operation: event.operation,
23853
+ session: event.session
23854
+ });
23855
+ states.set(event, state);
23856
+ return state;
23857
+ };
23858
+ const unbindCurrentSpanStore = this.bindCurrentSpanStoreToOperationStart(
23859
+ tracingChannel2,
23860
+ ensureState2
23861
+ );
23862
+ const handlers = {
23863
+ start: (event) => {
23864
+ ensureState2(event);
23865
+ },
23866
+ asyncEnd: (event) => {
23867
+ this.endOperationState(states.get(event), event.result);
23868
+ states.delete(event);
23869
+ },
23870
+ error: (event) => {
23871
+ const state = states.get(event);
23872
+ if (state && event.error) {
23873
+ safeLog3(state.span, { error: errorToString(event.error) });
23874
+ this.finishOperationState(state);
23875
+ }
23876
+ states.delete(event);
23877
+ }
23878
+ };
23879
+ tracingChannel2.subscribe(handlers);
23880
+ this.unsubscribers.push(() => {
23881
+ unbindCurrentSpanStore?.();
23882
+ tracingChannel2.unsubscribe(handlers);
23883
+ });
23884
+ }
23885
+ subscribeToCompact() {
23886
+ const tracingChannel2 = flueChannels.compact.tracingChannel();
23887
+ const states = /* @__PURE__ */ new WeakMap();
23888
+ const ensureState2 = (event) => {
23889
+ const existing = states.get(event);
23890
+ if (existing) {
23891
+ return existing;
23892
+ }
23893
+ const state = this.startOperationState({
23894
+ args: [],
23895
+ moduleVersion: typeof event.moduleVersion === "string" ? event.moduleVersion : void 0,
23896
+ operation: event.operation,
23897
+ session: event.session
23898
+ });
23899
+ states.set(event, state);
23900
+ return state;
23901
+ };
23902
+ const unbindCurrentSpanStore = this.bindCurrentSpanStoreToOperationStart(
23903
+ tracingChannel2,
23904
+ ensureState2
23905
+ );
23906
+ const handlers = {
23907
+ start: (event) => {
23908
+ ensureState2(event);
23909
+ },
23910
+ asyncEnd: (event) => {
23911
+ this.endOperationState(states.get(event), void 0);
23912
+ states.delete(event);
23913
+ },
23914
+ error: (event) => {
23915
+ const state = states.get(event);
23916
+ if (state && event.error) {
23917
+ safeLog3(state.span, { error: errorToString(event.error) });
23918
+ this.finishOperationState(state);
23919
+ }
23920
+ states.delete(event);
23921
+ }
23922
+ };
23923
+ tracingChannel2.subscribe(handlers);
23924
+ this.unsubscribers.push(() => {
23925
+ unbindCurrentSpanStore?.();
23926
+ tracingChannel2.unsubscribe(handlers);
23927
+ });
23928
+ }
23929
+ subscribeToContextEvents() {
23930
+ const channel = flueChannels.contextEvent.tracingChannel();
23931
+ const handlers = {
23932
+ start: (event) => {
23933
+ const flueEvent = event.arguments[0];
23934
+ if (!flueEvent) {
23935
+ return;
23936
+ }
23937
+ try {
23938
+ this.handleFlueEvent(flueEvent, {
23939
+ captureTurnSpans: event.captureTurnSpans !== false
23940
+ });
23941
+ } catch (error) {
23942
+ logInstrumentationError3("Flue event", error);
23943
+ }
23944
+ },
23945
+ error: () => {
23946
+ }
23947
+ };
23948
+ channel.subscribe(handlers);
23949
+ this.unsubscribers.push(() => {
23950
+ channel.unsubscribe(handlers);
23951
+ });
23952
+ }
23953
+ bindCurrentSpanStoreToOperationStart(tracingChannel2, ensureState2) {
23954
+ const state = _internalGetGlobalState();
23955
+ const startChannel = tracingChannel2.start;
23956
+ const contextManager = state?.contextManager;
23957
+ const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
23958
+ if (!currentSpanStore || !startChannel) {
23959
+ return void 0;
23960
+ }
23961
+ startChannel.bindStore(currentSpanStore, (event) => {
23962
+ const operationState = ensureState2(event);
23963
+ return contextManager.wrapSpanForStore(operationState.span);
23964
+ });
23965
+ return () => {
23966
+ startChannel.unbindStore(currentSpanStore);
23967
+ };
23968
+ }
23969
+ startOperationState(args) {
23970
+ const sessionName = getSessionName(args.session);
23971
+ const metadata = {
23972
+ ...extractOperationInputMetadata(args.operation, args.args),
23973
+ ...extractSessionMetadata(args.session),
23974
+ "flue.operation": args.operation,
23975
+ provider: "flue",
23976
+ ...args.moduleVersion ? { "flue.version": args.moduleVersion } : {}
23977
+ };
23978
+ const span = startSpan({
23979
+ name: `flue.session.${args.operation}`,
23980
+ spanAttributes: { type: "task" /* TASK */ }
23981
+ });
23982
+ const state = {
23983
+ metadata,
23984
+ operation: args.operation,
23985
+ sessionName,
23986
+ span,
23987
+ startTime: getCurrentUnixTimestamp()
23988
+ };
23989
+ safeLog3(span, {
23990
+ input: extractOperationInput(args.operation, args.args),
23991
+ metadata
23992
+ });
23993
+ this.pendingOperationQueue(operationKey(sessionName, args.operation)).push(
23994
+ state
23995
+ );
23996
+ addOperationToScope(
23997
+ this.activeOperationsByScope,
23998
+ sessionName ?? "unknown",
23999
+ state
24000
+ );
24001
+ return state;
24002
+ }
24003
+ endOperationState(state, result) {
24004
+ if (!state) {
24005
+ return;
24006
+ }
24007
+ const metadata = {
24008
+ ...state.metadata,
24009
+ ...extractPromptResponseMetadata(result)
24010
+ };
24011
+ const metrics = {
24012
+ ...buildDurationMetrics3(state.startTime),
24013
+ ...metricsFromUsage(result?.usage)
24014
+ };
24015
+ safeLog3(state.span, {
24016
+ metadata,
24017
+ metrics,
24018
+ output: extractOperationOutput(result)
24019
+ });
24020
+ this.finishCompactionsForOperation(state);
24021
+ this.finishOperationState(state);
24022
+ }
24023
+ finishOperationState(state) {
24024
+ removePendingOperation(this.pendingOperationsByKey, state);
24025
+ if (state.operationId) {
24026
+ this.activeOperationsById.delete(state.operationId);
24027
+ }
24028
+ removeScopedOperation(this.activeOperationsByScope, state);
24029
+ state.span.end();
24030
+ }
24031
+ handleFlueEvent(event, options) {
24032
+ switch (event.type) {
24033
+ case "operation_start":
24034
+ this.handleOperationStart(event);
24035
+ return;
24036
+ case "operation":
24037
+ this.handleOperation(event);
24038
+ return;
24039
+ case "text_delta":
24040
+ if (!options.captureTurnSpans) {
24041
+ return;
24042
+ }
24043
+ this.ensureTurnState(event).text.push(
24044
+ typeof event.text === "string" ? event.text : ""
24045
+ );
24046
+ return;
24047
+ case "thinking_start":
24048
+ if (!options.captureTurnSpans) {
24049
+ return;
24050
+ }
24051
+ this.handleThinkingStart(event);
24052
+ return;
24053
+ case "thinking_delta":
24054
+ if (!options.captureTurnSpans) {
24055
+ return;
24056
+ }
24057
+ this.handleThinkingDelta(event);
24058
+ return;
24059
+ case "thinking_end":
24060
+ if (!options.captureTurnSpans) {
24061
+ return;
24062
+ }
24063
+ this.handleThinkingEnd(event);
24064
+ return;
24065
+ case "turn":
24066
+ if (!options.captureTurnSpans) {
24067
+ return;
24068
+ }
24069
+ this.handleTurn(event);
24070
+ return;
24071
+ case "tool_start":
24072
+ this.handleToolStart(event, options);
24073
+ return;
24074
+ case "tool_call":
24075
+ this.handleToolCall(event);
24076
+ return;
24077
+ case "task_start":
24078
+ this.handleTaskStart(event);
24079
+ return;
24080
+ case "task":
24081
+ this.handleTask(event);
24082
+ return;
24083
+ case "compaction_start":
24084
+ this.handleCompactionStart(event);
24085
+ return;
24086
+ case "compaction":
24087
+ this.handleCompaction(event);
24088
+ return;
24089
+ default:
24090
+ return;
24091
+ }
24092
+ }
24093
+ handleOperationStart(event) {
24094
+ if (!isInstrumentedOperation(event.operationKind)) {
24095
+ return;
24096
+ }
24097
+ const state = this.takePendingOperationForEvent(event);
24098
+ if (!state) {
24099
+ return;
24100
+ }
24101
+ state.operationId = event.operationId;
24102
+ this.activeOperationsById.set(event.operationId, state);
24103
+ addScopedOperation(this.activeOperationsByScope, event, state);
24104
+ state.metadata = {
24105
+ ...state.metadata,
24106
+ ...extractEventMetadata(event),
24107
+ "flue.operation_id": event.operationId
24108
+ };
24109
+ safeLog3(state.span, { metadata: state.metadata });
24110
+ }
24111
+ handleOperation(event) {
24112
+ const state = event.operationId ? this.activeOperationsById.get(event.operationId) : void 0;
24113
+ if (!state) {
24114
+ return;
24115
+ }
24116
+ const metadata = {
24117
+ ...state.metadata,
24118
+ ...extractEventMetadata(event),
24119
+ ...typeof event.durationMs === "number" ? { "flue.duration_ms": event.durationMs } : {},
24120
+ ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
24121
+ };
24122
+ const metrics = metricsFromUsage(event.usage);
24123
+ safeLog3(state.span, {
24124
+ ...event.error ? { error: errorToString(event.error) } : {},
24125
+ metadata,
24126
+ ...Object.keys(metrics).length ? { metrics } : {}
24127
+ });
24128
+ }
24129
+ ensureTurnState(event) {
24130
+ const scope = scopeKey(event);
24131
+ const existing = this.turnsByScope.get(scope);
24132
+ if (existing) {
24133
+ return existing;
24134
+ }
24135
+ const parent = this.parentSpanForEvent(event);
24136
+ const metadata = {
24137
+ ...extractEventMetadata(event),
24138
+ provider: "flue"
24139
+ };
24140
+ const span = startFlueSpan(parent, {
24141
+ name: "flue.turn",
24142
+ spanAttributes: { type: "llm" /* LLM */ }
24143
+ });
24144
+ const state = {
24145
+ metadata,
24146
+ span,
24147
+ hasThinking: false,
24148
+ startTime: getCurrentUnixTimestamp(),
24149
+ text: [],
24150
+ thinking: [],
24151
+ toolCalls: []
24152
+ };
24153
+ safeLog3(span, { metadata });
24154
+ this.turnsByScope.set(scope, state);
24155
+ return state;
24156
+ }
24157
+ handleTurn(event) {
24158
+ const scope = scopeKey(event);
24159
+ const state = this.ensureTurnState(event);
24160
+ const text = state.text.join("");
24161
+ const reasoning = state.finalThinking ?? state.thinking.join("");
24162
+ const outputReasoning = reasoning || (state.hasThinking ? "[reasoning stream present; content unavailable]" : void 0);
24163
+ const metadata = {
24164
+ ...state.metadata,
24165
+ ...extractEventMetadata(event),
24166
+ ...event.model ? { model: event.model, "flue.model": event.model } : {},
24167
+ ...event.stopReason ? { "flue.stop_reason": event.stopReason } : {},
24168
+ ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {},
24169
+ provider: "flue"
24170
+ };
24171
+ safeLog3(state.span, {
24172
+ ...event.error ? { error: errorToString(event.error) } : {},
24173
+ metadata,
24174
+ metrics: {
24175
+ ...durationMsMetrics(event.durationMs),
24176
+ ...metricsFromUsage(event.usage)
24177
+ },
24178
+ output: toAssistantOutput(
24179
+ text,
24180
+ event.stopReason,
24181
+ outputReasoning,
24182
+ state.toolCalls
24183
+ )
24184
+ });
24185
+ state.span.end();
24186
+ this.turnsByScope.delete(scope);
24187
+ }
24188
+ handleThinkingDelta(event) {
24189
+ const delta = event.delta;
24190
+ if (typeof delta !== "string" || !delta) {
24191
+ return;
24192
+ }
24193
+ const state = this.ensureTurnState(event);
24194
+ state.hasThinking = true;
24195
+ state.metadata["flue.thinking"] = true;
24196
+ state.thinking.push(delta);
24197
+ }
24198
+ handleThinkingStart(event) {
24199
+ const state = this.ensureTurnState(event);
24200
+ state.hasThinking = true;
24201
+ state.metadata["flue.thinking"] = true;
24202
+ }
24203
+ handleThinkingEnd(event) {
24204
+ const state = this.ensureTurnState(event);
24205
+ state.hasThinking = true;
24206
+ state.metadata["flue.thinking"] = true;
24207
+ if (typeof event.content === "string" && event.content) {
24208
+ state.finalThinking = event.content;
24209
+ }
24210
+ }
24211
+ handleToolStart(event, options) {
24212
+ const toolCallId = event.toolCallId;
24213
+ if (!toolCallId) {
24214
+ return;
24215
+ }
24216
+ const parent = this.parentSpanForEvent(event);
24217
+ const scope = scopeKey(event);
24218
+ let turnState = this.turnsByScope.get(scope);
24219
+ if (!turnState && parent && options.captureTurnSpans) {
24220
+ turnState = this.ensureTurnState(event);
24221
+ }
24222
+ const metadata = {
24223
+ ...extractEventMetadata(event),
24224
+ ...event.toolName ? { "flue.tool_name": event.toolName } : {},
24225
+ "flue.tool_call_id": toolCallId,
24226
+ provider: "flue"
24227
+ };
24228
+ const span = startFlueSpan(parent, {
24229
+ name: `tool: ${event.toolName ?? "unknown"}`,
24230
+ spanAttributes: { type: "tool" /* TOOL */ }
24231
+ });
24232
+ if (turnState) {
24233
+ turnState.toolCalls.push({
24234
+ args: event.args,
24235
+ toolCallId,
24236
+ toolName: event.toolName
24237
+ });
24238
+ }
24239
+ safeLog3(span, {
24240
+ input: event.args,
24241
+ metadata
24242
+ });
24243
+ this.toolsById.set(toolKey(event), {
24244
+ metadata,
24245
+ span,
24246
+ startTime: getCurrentUnixTimestamp()
24247
+ });
24248
+ }
24249
+ handleToolCall(event) {
24250
+ const key = toolKey(event);
24251
+ const state = this.toolsById.get(key) ?? this.startSyntheticToolState(event, event.toolName ?? "unknown");
24252
+ const metadata = {
24253
+ ...state.metadata,
24254
+ ...extractEventMetadata(event),
24255
+ ...event.toolName ? { "flue.tool_name": event.toolName } : {},
24256
+ ...event.toolCallId ? { "flue.tool_call_id": event.toolCallId } : {},
24257
+ ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
24258
+ };
24259
+ safeLog3(state.span, {
24260
+ ...event.isError ? { error: errorToString(event.result) } : {},
24261
+ metadata,
24262
+ metrics: durationMsMetrics(event.durationMs),
24263
+ output: event.result
24264
+ });
24265
+ state.span.end();
24266
+ this.toolsById.delete(key);
24267
+ }
24268
+ handleTaskStart(event) {
24269
+ const parent = this.parentSpanForEvent(event);
24270
+ const metadata = {
24271
+ ...extractEventMetadata(event),
24272
+ ...event.role ? { "flue.role": event.role } : {},
24273
+ ...event.cwd ? { "flue.cwd": event.cwd } : {},
24274
+ "flue.task_id": event.taskId,
24275
+ provider: "flue"
24276
+ };
24277
+ const span = startFlueSpan(parent, {
24278
+ name: "flue.task",
24279
+ spanAttributes: { type: "task" /* TASK */ }
24280
+ });
24281
+ safeLog3(span, {
24282
+ input: event.prompt,
24283
+ metadata
24284
+ });
24285
+ this.tasksById.set(event.taskId, {
24286
+ metadata,
24287
+ span,
24288
+ startTime: getCurrentUnixTimestamp()
24289
+ });
24290
+ }
24291
+ handleTask(event) {
24292
+ const state = this.tasksById.get(event.taskId);
24293
+ if (!state) {
24294
+ return;
24295
+ }
24296
+ safeLog3(state.span, {
24297
+ ...event.isError ? { error: errorToString(event.result) } : {},
24298
+ metadata: {
24299
+ ...state.metadata,
24300
+ ...extractEventMetadata(event),
24301
+ ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
24302
+ },
24303
+ metrics: durationMsMetrics(event.durationMs),
24304
+ output: event.result
24305
+ });
24306
+ state.span.end();
24307
+ this.tasksById.delete(event.taskId);
24308
+ }
24309
+ handleCompactionStart(event) {
24310
+ const operationState = this.operationStateForEvent(event);
24311
+ const parent = operationState?.span ?? this.parentSpanForEvent(event);
24312
+ const metadata = {
24313
+ ...extractEventMetadata(event),
24314
+ ...event.reason ? { "flue.compaction_reason": event.reason } : {},
24315
+ provider: "flue"
24316
+ };
24317
+ const input = {
24318
+ ...typeof event.estimatedTokens === "number" ? { estimatedTokens: event.estimatedTokens } : {},
24319
+ ...event.reason ? { reason: event.reason } : {}
24320
+ };
24321
+ const span = startFlueSpan(parent, {
24322
+ name: "flue.compaction",
24323
+ spanAttributes: { type: "task" /* TASK */ }
24324
+ });
24325
+ safeLog3(span, {
24326
+ input,
24327
+ metadata
24328
+ });
24329
+ this.compactionsByScope.set(scopeKey(event), {
24330
+ input,
24331
+ metadata,
24332
+ operationState,
24333
+ span,
24334
+ startTime: getCurrentUnixTimestamp()
24335
+ });
24336
+ }
24337
+ handleCompaction(event) {
24338
+ const key = scopeKey(event);
24339
+ const state = this.compactionsByScope.get(key) ?? this.findCompactionState(event);
24340
+ if (!state) {
24341
+ return;
24342
+ }
24343
+ safeLog3(state.span, {
24344
+ metadata: {
24345
+ ...state.metadata,
24346
+ ...extractEventMetadata(event),
24347
+ ...typeof event.messagesBefore === "number" ? { "flue.messages_before": event.messagesBefore } : {},
24348
+ ...typeof event.messagesAfter === "number" ? { "flue.messages_after": event.messagesAfter } : {}
24349
+ },
24350
+ metrics: {
24351
+ ...durationMsMetrics(event.durationMs),
24352
+ ...metricsFromUsage(event.usage)
24353
+ },
24354
+ output: {
24355
+ messagesAfter: event.messagesAfter,
24356
+ messagesBefore: event.messagesBefore
24357
+ }
24358
+ });
24359
+ state.span.end();
24360
+ this.deleteCompactionState(state);
24361
+ }
24362
+ findCompactionState(event) {
24363
+ const operationState = this.operationStateForEvent(event);
24364
+ for (const state of this.compactionsByScope.values()) {
24365
+ if (operationState && state.operationState === operationState) {
24366
+ return state;
24367
+ }
24368
+ }
24369
+ return void 0;
24370
+ }
24371
+ finishCompactionsForOperation(operationState) {
24372
+ for (const state of [...this.compactionsByScope.values()]) {
24373
+ if (state.operationState !== operationState) {
24374
+ continue;
24375
+ }
24376
+ safeLog3(state.span, {
24377
+ input: state.input,
24378
+ metadata: state.metadata,
24379
+ metrics: {
24380
+ ...buildDurationMetrics3(state.startTime)
24381
+ },
24382
+ output: { completed: true }
24383
+ });
24384
+ state.span.end();
24385
+ this.deleteCompactionState(state);
24386
+ }
24387
+ }
24388
+ deleteCompactionState(state) {
24389
+ for (const [key, candidate] of this.compactionsByScope) {
24390
+ if (candidate !== state) {
24391
+ continue;
24392
+ }
24393
+ this.compactionsByScope.delete(key);
24394
+ return;
24395
+ }
24396
+ }
24397
+ startSyntheticToolState(event, toolName) {
24398
+ const parent = this.parentSpanForEvent(event);
24399
+ const metadata = {
24400
+ ...extractEventMetadata(event),
24401
+ ...event.toolCallId ? { "flue.tool_call_id": event.toolCallId } : {},
24402
+ "flue.tool_name": toolName,
24403
+ provider: "flue"
24404
+ };
24405
+ const span = startFlueSpan(parent, {
24406
+ name: `tool: ${toolName}`,
24407
+ spanAttributes: { type: "tool" /* TOOL */ }
24408
+ });
24409
+ safeLog3(span, { metadata });
24410
+ return { metadata, span, startTime: getCurrentUnixTimestamp() };
24411
+ }
24412
+ operationStateForEvent(event) {
24413
+ if (event.operationId) {
24414
+ const operation = this.activeOperationsById.get(event.operationId) ?? this.promotePendingOperationForEvent(event);
24415
+ if (operation) {
24416
+ return operation;
24417
+ }
24418
+ }
24419
+ return this.activeOperationForEventScope(event) ?? this.pendingOperationForEventScope(event);
24420
+ }
24421
+ parentSpanForEvent(event) {
24422
+ if (event.operationId) {
24423
+ const operation = this.operationStateForEvent(event);
24424
+ if (operation) {
24425
+ return operation.span;
24426
+ }
24427
+ }
24428
+ if (event.taskId) {
24429
+ return this.tasksById.get(event.taskId)?.span;
24430
+ }
24431
+ return this.operationStateForEvent(event)?.span;
24432
+ }
24433
+ promotePendingOperationForEvent(event) {
24434
+ if (!event.operationId) {
24435
+ return void 0;
24436
+ }
24437
+ const scopePrefixes = operationScopePrefixes(event);
24438
+ for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
24439
+ if (!candidateQueue.length || !operationKeyMatchesScopes(candidateKey, scopePrefixes)) {
24440
+ continue;
24441
+ }
24442
+ const state = candidateQueue.shift();
24443
+ if (!state) {
24444
+ return void 0;
24445
+ }
24446
+ state.operationId = event.operationId;
24447
+ this.activeOperationsById.set(event.operationId, state);
24448
+ addScopedOperation(this.activeOperationsByScope, event, state);
24449
+ state.metadata = {
24450
+ ...state.metadata,
24451
+ ...extractEventMetadata(event),
24452
+ "flue.operation_id": event.operationId
24453
+ };
24454
+ safeLog3(state.span, { metadata: state.metadata });
24455
+ return state;
24456
+ }
24457
+ return void 0;
24458
+ }
24459
+ activeOperationForEventScope(event) {
24460
+ for (const scope of operationScopeNames(event)) {
24461
+ const operations = this.activeOperationsByScope.get(scope);
24462
+ if (operations?.length) {
24463
+ return operations[operations.length - 1];
24464
+ }
24465
+ }
24466
+ return void 0;
24467
+ }
24468
+ pendingOperationForEventScope(event) {
24469
+ const scopePrefixes = operationScopePrefixes(event);
24470
+ for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
24471
+ if (!candidateQueue.length || !operationKeyMatchesScopes(candidateKey, scopePrefixes)) {
24472
+ continue;
24473
+ }
24474
+ return candidateQueue[0];
24475
+ }
24476
+ return void 0;
24477
+ }
24478
+ takePendingOperationForEvent(event) {
24479
+ const key = operationKey(event.session, event.operationKind);
24480
+ const queue2 = this.pendingOperationsByKey.get(key);
24481
+ if (queue2?.length) {
24482
+ return queue2.shift();
24483
+ }
24484
+ for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
24485
+ if (candidateKey.endsWith(`::${event.operationKind}`) && candidateQueue.length) {
24486
+ return candidateQueue.shift();
24487
+ }
24488
+ }
24489
+ return void 0;
24490
+ }
24491
+ pendingOperationQueue(key) {
24492
+ const existing = this.pendingOperationsByKey.get(key);
24493
+ if (existing) {
24494
+ return existing;
24495
+ }
24496
+ const queue2 = [];
24497
+ this.pendingOperationsByKey.set(key, queue2);
24498
+ return queue2;
24499
+ }
24500
+ };
24501
+ function isInstrumentedOperation(operation) {
24502
+ return operation === "prompt" || operation === "skill" || operation === "task" || operation === "compact";
24503
+ }
24504
+ function getSessionName(session) {
24505
+ return typeof session?.name === "string" ? session.name : void 0;
24506
+ }
24507
+ function operationKey(sessionName, operation) {
24508
+ return `${sessionName ?? "unknown"}::${operation}`;
24509
+ }
24510
+ function operationScopePrefixes(event) {
24511
+ const scopes = /* @__PURE__ */ new Set();
24512
+ for (const scope of operationScopeNames(event)) {
24513
+ scopes.add(`${scope}::`);
24514
+ }
24515
+ return scopes;
24516
+ }
24517
+ function operationKeyMatchesScopes(key, scopes) {
24518
+ for (const scope of scopes) {
24519
+ if (key.startsWith(scope)) {
24520
+ return true;
24521
+ }
24522
+ }
24523
+ return false;
24524
+ }
24525
+ function operationScopeNames(event) {
24526
+ const scopes = /* @__PURE__ */ new Set();
24527
+ if (event.session) {
24528
+ scopes.add(event.session);
24529
+ }
24530
+ if (event.parentSession) {
24531
+ scopes.add(event.parentSession);
24532
+ }
24533
+ if (!scopes.size) {
24534
+ scopes.add("unknown");
24535
+ }
24536
+ return scopes;
24537
+ }
24538
+ function addScopedOperation(operationsByScope, event, state) {
24539
+ for (const scope of operationScopeNames(event)) {
24540
+ addOperationToScope(operationsByScope, scope, state);
24541
+ }
24542
+ }
24543
+ function addOperationToScope(operationsByScope, scope, state) {
24544
+ const operations = operationsByScope.get(scope);
24545
+ if (operations) {
24546
+ if (!operations.includes(state)) {
24547
+ operations.push(state);
24548
+ }
24549
+ } else {
24550
+ operationsByScope.set(scope, [state]);
24551
+ }
24552
+ }
24553
+ function removeScopedOperation(operationsByScope, state) {
24554
+ for (const [scope, operations] of operationsByScope) {
24555
+ const index = operations.indexOf(state);
24556
+ if (index === -1) {
24557
+ continue;
24558
+ }
24559
+ operations.splice(index, 1);
24560
+ if (operations.length === 0) {
24561
+ operationsByScope.delete(scope);
24562
+ }
24563
+ }
24564
+ }
24565
+ function removePendingOperation(pendingOperationsByKey, state) {
24566
+ for (const [key, queue2] of pendingOperationsByKey) {
24567
+ const index = queue2.indexOf(state);
24568
+ if (index === -1) {
24569
+ continue;
24570
+ }
24571
+ queue2.splice(index, 1);
24572
+ if (queue2.length === 0) {
24573
+ pendingOperationsByKey.delete(key);
24574
+ }
24575
+ return;
24576
+ }
24577
+ }
24578
+ function extractSessionMetadata(session) {
24579
+ const sessionName = getSessionName(session);
24580
+ return sessionName ? { "flue.session": sessionName } : {};
24581
+ }
24582
+ function extractEventMetadata(event) {
24583
+ return {
24584
+ ...event.runId ? { "flue.run_id": event.runId } : {},
24585
+ ...typeof event.eventIndex === "number" ? { "flue.event_index": event.eventIndex } : {},
24586
+ ...event.session ? { "flue.session": event.session } : {},
24587
+ ...event.parentSession ? { "flue.parent_session": event.parentSession } : {},
24588
+ ...event.harness ? { "flue.harness": event.harness } : {},
24589
+ ...event.taskId ? { "flue.task_id": event.taskId } : {},
24590
+ ...event.operationId ? { "flue.operation_id": event.operationId } : {}
24591
+ };
24592
+ }
24593
+ function extractOperationInput(operation, args) {
24594
+ switch (operation) {
24595
+ case "prompt":
24596
+ case "task":
24597
+ return args[0];
24598
+ case "skill":
24599
+ return {
24600
+ args: getOptionObject(args[1])?.args,
24601
+ name: args[0]
24602
+ };
24603
+ case "compact":
24604
+ return void 0;
24605
+ }
24606
+ }
24607
+ function extractOperationInputMetadata(operation, args) {
24608
+ const options = getOptionObject(args[1]);
24609
+ return {
24610
+ ...operation === "skill" && typeof args[0] === "string" ? { "flue.skill_name": args[0] } : {},
24611
+ ...options?.model ? { model: options.model, "flue.model": options.model } : {},
24612
+ ...options?.role ? { "flue.role": options.role } : {},
24613
+ ...options?.thinkingLevel ? { "flue.thinking_level": options.thinkingLevel } : {},
24614
+ ...typeof options?.cwd === "string" ? { "flue.cwd": options.cwd } : {},
24615
+ ...Array.isArray(options?.tools) ? {
24616
+ "flue.tools_count": options.tools.length,
24617
+ tools: summarizeTools(options.tools)
24618
+ } : {},
24619
+ ...Array.isArray(options?.images) ? { "flue.images_count": options.images.length } : {},
24620
+ ...options?.result || options?.schema ? { "flue.result_schema": true } : {}
24621
+ };
24622
+ }
24623
+ function getOptionObject(value) {
24624
+ return isObject(value) ? value : void 0;
24625
+ }
24626
+ function summarizeTools(tools) {
24627
+ return tools.flatMap((tool) => {
24628
+ if (!isObject(tool)) {
24629
+ return [];
24630
+ }
24631
+ const name = typeof tool.name === "string" ? tool.name : void 0;
24632
+ if (!name) {
24633
+ return [];
24634
+ }
24635
+ return [
24636
+ {
24637
+ function: {
24638
+ description: typeof tool.description === "string" ? tool.description : void 0,
24639
+ name,
24640
+ parameters: tool.parameters
24641
+ },
24642
+ type: "function"
24643
+ }
24644
+ ];
24645
+ });
24646
+ }
24647
+ function extractPromptResponseMetadata(result) {
24648
+ const modelId = result?.model && typeof result.model.id === "string" ? result.model.id : void 0;
24649
+ return modelId ? {
24650
+ model: modelId,
24651
+ "flue.model": modelId
24652
+ } : {};
24653
+ }
24654
+ function extractOperationOutput(result) {
24655
+ if (!result) {
24656
+ return void 0;
24657
+ }
24658
+ if ("data" in result) {
24659
+ return result.data;
24660
+ }
24661
+ if ("text" in result) {
24662
+ return result.text;
24663
+ }
24664
+ return result;
24665
+ }
24666
+ function metricsFromUsage(usage) {
24667
+ return {
24668
+ ...typeof usage?.input === "number" ? { prompt_tokens: usage.input } : {},
24669
+ ...typeof usage?.output === "number" ? { completion_tokens: usage.output } : {},
24670
+ ...typeof usage?.cacheRead === "number" ? { prompt_cached_tokens: usage.cacheRead } : {},
24671
+ ...typeof usage?.cacheWrite === "number" ? { prompt_cache_creation_tokens: usage.cacheWrite } : {},
24672
+ ...typeof usage?.totalTokens === "number" ? { tokens: usage.totalTokens } : {},
24673
+ ...typeof usage?.cost?.total === "number" ? { estimated_cost: usage.cost.total } : {}
24674
+ };
24675
+ }
24676
+ function buildDurationMetrics3(startTime) {
24677
+ return {
24678
+ duration_ms: Math.max(0, (getCurrentUnixTimestamp() - startTime) * 1e3)
24679
+ };
24680
+ }
24681
+ function durationMsMetrics(durationMs) {
24682
+ return typeof durationMs === "number" ? { duration_ms: durationMs } : {};
24683
+ }
24684
+ function scopeKey(event) {
24685
+ if (event.operationId) {
24686
+ return `operation:${event.operationId}`;
24687
+ }
24688
+ if (event.taskId) {
24689
+ return `task:${event.taskId}`;
24690
+ }
24691
+ if (event.session) {
24692
+ return `session:${event.session}`;
24693
+ }
24694
+ return "flue:unknown";
24695
+ }
24696
+ function toolKey(event) {
24697
+ return `${scopeKey(event)}::tool:${event.toolCallId ?? "unknown"}`;
24698
+ }
24699
+ function toAssistantOutput(text, finishReason, reasoning, toolCalls) {
24700
+ return [
24701
+ {
24702
+ finish_reason: finishReason ?? "stop",
24703
+ index: 0,
24704
+ message: {
24705
+ content: text,
24706
+ ...reasoning ? { reasoning } : {},
24707
+ role: "assistant",
24708
+ ...toolCalls?.length ? {
24709
+ tool_calls: toolCalls.map((toolCall) => ({
24710
+ function: {
24711
+ arguments: toolCall.args === void 0 ? "{}" : JSON.stringify(toolCall.args),
24712
+ name: toolCall.toolName ?? "unknown"
24713
+ },
24714
+ ...toolCall.toolCallId ? { id: toolCall.toolCallId } : {},
24715
+ type: "function"
24716
+ }))
24717
+ } : {}
24718
+ }
24719
+ }
24720
+ ];
24721
+ }
24722
+ function startFlueSpan(parent, args) {
24723
+ return parent ? withCurrent(parent, () => startSpan(args)) : startSpan(args);
24724
+ }
24725
+ function safeLog3(span, event) {
24726
+ try {
24727
+ span.log(event);
24728
+ } catch (error) {
24729
+ logInstrumentationError3("Flue span log", error);
24730
+ }
24731
+ }
24732
+ function errorToString(error) {
24733
+ if (error instanceof Error) {
24734
+ return error.message;
24735
+ }
24736
+ if (typeof error === "string") {
24737
+ return error;
24738
+ }
24739
+ try {
24740
+ return JSON.stringify(error);
24741
+ } catch {
24742
+ return String(error);
24743
+ }
24744
+ }
24745
+ function logInstrumentationError3(label, error) {
24746
+ console.error(`Error in ${label} instrumentation:`, error);
24747
+ }
24748
+
24749
+ // src/wrappers/langchain/callback-handler.ts
24750
+ var BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME = "BraintrustCallbackHandler";
24751
+ var BraintrustLangChainCallbackHandler = class {
24752
+ name = BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
24753
+ spans = /* @__PURE__ */ new Map();
24754
+ skippedRuns = /* @__PURE__ */ new Set();
24755
+ parent;
24756
+ rootRunId;
24757
+ options;
24758
+ startTimes = /* @__PURE__ */ new Map();
24759
+ firstTokenTimes = /* @__PURE__ */ new Map();
24760
+ ttftMs = /* @__PURE__ */ new Map();
24761
+ constructor(options) {
24762
+ this.parent = options?.parent;
24763
+ this.options = {
24764
+ debug: options?.debug ?? false,
24765
+ excludeMetadataProps: options?.excludeMetadataProps ?? /^(l[sc]_|langgraph_|__pregel_|checkpoint_ns)/,
24766
+ logger: options?.logger
24767
+ };
24768
+ }
24769
+ startSpan({
24770
+ runId,
24771
+ parentRunId,
24772
+ ...args
24773
+ }) {
24774
+ if (this.spans.has(runId)) {
24775
+ return;
24776
+ }
24777
+ if (!parentRunId) {
24778
+ this.rootRunId = runId;
24779
+ }
24780
+ const tags = args.event?.tags;
24781
+ const spanAttributes = args.spanAttributes || {};
24782
+ spanAttributes.type = args.type || spanAttributes.type || "task";
24783
+ args.type = spanAttributes.type;
24784
+ const currentParent = (typeof this.parent === "function" ? this.parent() : this.parent) ?? currentSpan();
24785
+ let parentSpan;
24786
+ if (parentRunId && this.spans.has(parentRunId)) {
24787
+ parentSpan = this.spans.get(parentRunId);
24788
+ } else if (!Object.is(currentParent, NOOP_SPAN)) {
24789
+ parentSpan = currentParent;
24790
+ } else if (this.options.logger) {
24791
+ parentSpan = this.options.logger;
24792
+ } else {
24793
+ parentSpan = { startSpan };
24794
+ }
24795
+ args.event = {
24796
+ ...args.event,
24797
+ tags: void 0,
24798
+ metadata: {
24799
+ ...tags ? { tags } : {},
24800
+ ...args.event?.metadata,
24801
+ braintrust: {
24802
+ integration_name: "langchain-js",
24803
+ sdk_language: "javascript"
24804
+ },
24805
+ run_id: runId,
24806
+ parent_run_id: parentRunId,
24807
+ ...this.options.debug ? { runId, parentRunId } : {}
24808
+ }
24809
+ };
24810
+ let span = parentSpan.startSpan(args);
24811
+ if (!Object.is(this.options.logger, NOOP_SPAN) && Object.is(span, NOOP_SPAN)) {
24812
+ span = initLogger().startSpan(args);
24813
+ }
24814
+ this.spans.set(runId, span);
24815
+ }
24816
+ endSpan({
24817
+ runId,
24818
+ parentRunId,
24819
+ tags,
24820
+ metadata,
24821
+ ...args
24822
+ }) {
24823
+ if (!this.spans.has(runId)) {
24824
+ return;
24825
+ }
24826
+ if (this.skippedRuns.has(runId)) {
24827
+ this.skippedRuns.delete(runId);
24828
+ return;
24829
+ }
24830
+ const span = this.spans.get(runId);
24831
+ this.spans.delete(runId);
24832
+ if (runId === this.rootRunId) {
24833
+ this.rootRunId = void 0;
24834
+ }
24835
+ span.log({ ...args, metadata: { tags, ...metadata } });
24836
+ span.end();
24837
+ }
24838
+ async handleLLMStart(llm, prompts, runId, parentRunId, extraParams, tags, metadata, runName) {
24839
+ this.startSpan({
24840
+ runId,
24841
+ parentRunId,
24842
+ name: runName ?? getSerializedName(llm) ?? "LLM",
24843
+ type: "llm",
24844
+ event: {
24845
+ input: prompts,
24846
+ tags,
24847
+ metadata: {
24848
+ serialized: llm,
24849
+ name: runName,
24850
+ metadata,
24851
+ ...extraParams
24852
+ }
24853
+ }
24854
+ });
24855
+ }
24856
+ async handleLLMError(err, runId, parentRunId, tags) {
24857
+ this.endSpan({ runId, parentRunId, error: err, tags });
24858
+ }
24859
+ async handleLLMEnd(output, runId, parentRunId, tags) {
24860
+ const metrics = getMetricsFromResponse(output);
24861
+ const modelName2 = getModelNameFromResponse(output);
24862
+ const ttft = this.ttftMs.get(runId);
24863
+ if (ttft !== void 0) {
24864
+ metrics.time_to_first_token = ttft;
24865
+ }
24866
+ this.startTimes.delete(runId);
24867
+ this.firstTokenTimes.delete(runId);
24868
+ this.ttftMs.delete(runId);
24869
+ this.endSpan({
24870
+ runId,
24871
+ parentRunId,
24872
+ output,
24873
+ metrics,
24874
+ tags,
24875
+ metadata: {
24876
+ model: modelName2
24877
+ }
24878
+ });
24879
+ }
24880
+ async handleChatModelStart(llm, messages, runId, parentRunId, extraParams, tags, metadata, runName) {
24881
+ this.startTimes.set(runId, Date.now());
24882
+ this.firstTokenTimes.delete(runId);
24883
+ this.ttftMs.delete(runId);
24884
+ this.startSpan({
24885
+ runId,
24886
+ parentRunId,
24887
+ name: runName ?? getSerializedName(llm) ?? "Chat Model",
24888
+ type: "llm",
24889
+ event: {
24890
+ input: messages,
24891
+ tags,
24892
+ metadata: {
24893
+ serialized: llm,
24894
+ name: runName,
24895
+ metadata,
24896
+ ...extraParams
24897
+ }
24898
+ }
24899
+ });
24900
+ }
24901
+ async handleChainStart(chain, inputs, runId, parentRunId, tags, metadata, runType, runName) {
24902
+ if (tags?.includes("langsmith:hidden")) {
24903
+ this.skippedRuns.add(runId);
24904
+ return;
24905
+ }
24906
+ this.startSpan({
24907
+ runId,
24908
+ parentRunId,
24909
+ name: runName ?? getSerializedName(chain) ?? "Chain",
24910
+ event: {
24911
+ input: inputs,
24912
+ tags,
24913
+ metadata: {
24914
+ serialized: chain,
24915
+ name: runName,
24916
+ metadata,
24917
+ run_type: runType
24918
+ }
24919
+ }
24920
+ });
24921
+ }
24922
+ async handleChainError(err, runId, parentRunId, tags, kwargs) {
24923
+ this.endSpan({ runId, parentRunId, error: err, tags, metadata: kwargs });
24924
+ }
24925
+ async handleChainEnd(outputs, runId, parentRunId, tags, kwargs) {
24926
+ this.endSpan({
24927
+ runId,
24928
+ parentRunId,
24929
+ tags,
24930
+ output: outputs,
24931
+ metadata: { ...kwargs }
24932
+ });
24933
+ }
24934
+ async handleToolStart(tool, input, runId, parentRunId, tags, metadata, runName) {
24935
+ this.startSpan({
24936
+ runId,
24937
+ parentRunId,
24938
+ name: runName ?? getSerializedName(tool) ?? "Tool",
24939
+ type: "llm",
24940
+ event: {
24941
+ input: safeJsonParse(input),
24942
+ tags,
24943
+ metadata: {
24944
+ metadata,
24945
+ serialized: tool,
24946
+ input_str: input,
24947
+ input: safeJsonParse(input),
24948
+ name: runName
24949
+ }
24950
+ }
24951
+ });
24952
+ }
24953
+ async handleToolError(err, runId, parentRunId, tags) {
24954
+ this.endSpan({ runId, parentRunId, error: err, tags });
24955
+ }
24956
+ async handleToolEnd(output, runId, parentRunId, tags) {
24957
+ this.endSpan({ runId, parentRunId, output, tags });
24958
+ }
24959
+ async handleAgentAction(action, runId, parentRunId, tags) {
24960
+ this.startSpan({
24961
+ runId,
24962
+ parentRunId,
24963
+ type: "llm",
24964
+ name: typeof action.tool === "string" ? action.tool : "Agent",
24965
+ event: {
24966
+ input: action,
24967
+ tags
23514
24968
  }
23515
- break;
23516
- }
23517
- case "subagent.failed": {
23518
- const d = event.data;
23519
- if (d && typeof d.toolCallId === "string") {
23520
- handleSubagentFailed(
23521
- state,
23522
- d.toolCallId,
23523
- d.error ?? "sub-agent failed"
23524
- );
24969
+ });
24970
+ }
24971
+ async handleAgentEnd(action, runId, parentRunId, tags) {
24972
+ this.endSpan({ runId, parentRunId, output: action, tags });
24973
+ }
24974
+ async handleRetrieverStart(retriever, query, runId, parentRunId, tags, metadata, name) {
24975
+ this.startSpan({
24976
+ runId,
24977
+ parentRunId,
24978
+ name: name ?? getSerializedName(retriever) ?? "Retriever",
24979
+ type: "function",
24980
+ event: {
24981
+ input: query,
24982
+ tags,
24983
+ metadata: {
24984
+ serialized: retriever,
24985
+ metadata,
24986
+ name
24987
+ }
24988
+ }
24989
+ });
24990
+ }
24991
+ async handleRetrieverEnd(documents, runId, parentRunId, tags) {
24992
+ this.endSpan({ runId, parentRunId, output: documents, tags });
24993
+ }
24994
+ async handleRetrieverError(err, runId, parentRunId, tags) {
24995
+ this.endSpan({ runId, parentRunId, error: err, tags });
24996
+ }
24997
+ async handleLLMNewToken(_token, _idx, runId, _parentRunId, _tags) {
24998
+ if (!this.firstTokenTimes.has(runId)) {
24999
+ const now2 = Date.now();
25000
+ this.firstTokenTimes.set(runId, now2);
25001
+ const start = this.startTimes.get(runId);
25002
+ if (start !== void 0) {
25003
+ this.ttftMs.set(runId, (now2 - start) / 1e3);
23525
25004
  }
23526
- break;
23527
25005
  }
23528
- case "session.usage_info": {
23529
- const d = event.data;
23530
- if (d && typeof d.currentTokens === "number") {
23531
- state.session.span.log({
23532
- metadata: {
23533
- "github_copilot.context_window.limit": d.tokenLimit,
23534
- "github_copilot.context_window.current": d.currentTokens,
23535
- "github_copilot.context_window.messages": d.messagesLength
23536
- }
23537
- });
25006
+ }
25007
+ };
25008
+ function getSerializedName(serialized) {
25009
+ if (typeof serialized.name === "string") {
25010
+ return serialized.name;
25011
+ }
25012
+ const lastIdPart = serialized.id?.at(-1);
25013
+ return typeof lastIdPart === "string" ? lastIdPart : void 0;
25014
+ }
25015
+ function cleanObject(obj) {
25016
+ return Object.fromEntries(
25017
+ Object.entries(obj).filter(([, value]) => {
25018
+ if (typeof value !== "number") {
25019
+ return false;
23538
25020
  }
23539
- break;
25021
+ return Number.isFinite(value);
25022
+ })
25023
+ );
25024
+ }
25025
+ function walkGenerations(response) {
25026
+ const result = [];
25027
+ const generations = response.generations || [];
25028
+ for (const batch of generations) {
25029
+ if (Array.isArray(batch)) {
25030
+ for (const generation of batch) {
25031
+ if (isRecord(generation)) {
25032
+ result.push(generation);
25033
+ }
25034
+ }
25035
+ } else if (isRecord(batch)) {
25036
+ result.push(batch);
23540
25037
  }
23541
25038
  }
25039
+ return result;
23542
25040
  }
23543
- function injectTracingHooks2(config, state) {
23544
- const existingHooks = config.hooks ?? {};
23545
- const onSessionEnd = async (input, invocation) => {
23546
- try {
23547
- await existingHooks.onSessionEnd?.(input, invocation);
23548
- } finally {
23549
- handleSessionEnd(state, input.reason, input.error);
23550
- state.unsubscribeEvents?.();
25041
+ function getModelNameFromResponse(response) {
25042
+ for (const generation of walkGenerations(response)) {
25043
+ const message = generation.message;
25044
+ if (!isRecord(message)) {
25045
+ continue;
23551
25046
  }
23552
- };
23553
- config.hooks = {
23554
- ...existingHooks,
23555
- onSessionEnd
23556
- };
25047
+ const responseMetadata = message.response_metadata;
25048
+ if (!isRecord(responseMetadata)) {
25049
+ continue;
25050
+ }
25051
+ const modelName3 = responseMetadata.model_name ?? responseMetadata.model;
25052
+ if (typeof modelName3 === "string") {
25053
+ return modelName3;
25054
+ }
25055
+ }
25056
+ const llmOutput = response.llmOutput || {};
25057
+ const modelName2 = llmOutput.model_name ?? llmOutput.model;
25058
+ return typeof modelName2 === "string" ? modelName2 : void 0;
23557
25059
  }
23558
- function attachSessionEventListener(session, state) {
23559
- const handler = (event) => {
23560
- state.processing = state.processing.then(() => dispatchEvent(state, event)).catch((err) => {
23561
- console.error(
23562
- "[Braintrust] Error processing GitHub Copilot SDK event:",
23563
- err
23564
- );
25060
+ function getMetricsFromResponse(response) {
25061
+ for (const generation of walkGenerations(response)) {
25062
+ const message = generation.message;
25063
+ if (!isRecord(message)) {
25064
+ continue;
25065
+ }
25066
+ const usageMetadata = message.usage_metadata;
25067
+ if (!isRecord(usageMetadata)) {
25068
+ continue;
25069
+ }
25070
+ const inputTokenDetails = usageMetadata.input_token_details;
25071
+ return cleanObject({
25072
+ total_tokens: usageMetadata.total_tokens,
25073
+ prompt_tokens: usageMetadata.input_tokens,
25074
+ completion_tokens: usageMetadata.output_tokens,
25075
+ prompt_cache_creation_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_creation : void 0,
25076
+ prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0
23565
25077
  });
23566
- };
23567
- state.unsubscribeEvents = session.on(
23568
- handler
23569
- );
25078
+ }
25079
+ const llmOutput = response.llmOutput || {};
25080
+ const tokenUsage = isRecord(llmOutput.tokenUsage) ? llmOutput.tokenUsage : isRecord(llmOutput.estimatedTokens) ? llmOutput.estimatedTokens : {};
25081
+ return cleanObject({
25082
+ total_tokens: tokenUsage.totalTokens,
25083
+ prompt_tokens: tokenUsage.promptTokens,
25084
+ completion_tokens: tokenUsage.completionTokens
25085
+ });
23570
25086
  }
23571
- function isGitHubCopilotSession(value) {
23572
- return value !== null && typeof value === "object" && typeof value.on === "function";
25087
+ function safeJsonParse(input) {
25088
+ try {
25089
+ return JSON.parse(input);
25090
+ } catch {
25091
+ return input;
25092
+ }
23573
25093
  }
23574
- function makeSessionHandlers(sessionStates, configArgIndex, includeProviderMetadata) {
23575
- return {
23576
- start: (event) => {
23577
- const config = event.arguments[configArgIndex];
23578
- if (!config || typeof config !== "object") {
23579
- return;
23580
- }
23581
- const sessionSpan = startSpan({
23582
- name: "Copilot Session",
23583
- spanAttributes: { type: "task" /* TASK */ }
23584
- });
23585
- const metadata = {};
23586
- if (config.model) {
23587
- metadata["github_copilot.model"] = config.model;
23588
- }
23589
- if (includeProviderMetadata && config.provider?.type) {
23590
- metadata["github_copilot.provider_type"] = config.provider.type;
23591
- }
23592
- if (Object.keys(metadata).length > 0) {
23593
- sessionSpan.log({ metadata });
23594
- }
23595
- const state = {
23596
- session: makeSpanWithId(sessionSpan),
23597
- activeTurns: /* @__PURE__ */ new Map(),
23598
- pendingUserMessages: /* @__PURE__ */ new Map(),
23599
- currentMessageContent: /* @__PURE__ */ new Map(),
23600
- activeTools: /* @__PURE__ */ new Map(),
23601
- subAgents: /* @__PURE__ */ new Map(),
23602
- agentIdToToolCallId: /* @__PURE__ */ new Map(),
23603
- processing: Promise.resolve(),
23604
- totalInputTokens: 0,
23605
- totalOutputTokens: 0
23606
- };
23607
- injectTracingHooks2(config, state);
23608
- sessionStates.set(event, state);
23609
- },
23610
- asyncEnd: (event) => {
23611
- const state = sessionStates.get(event);
23612
- if (!state) {
23613
- return;
23614
- }
23615
- const session = event.result;
23616
- if (isGitHubCopilotSession(session)) {
23617
- attachSessionEventListener(session, state);
23618
- } else {
23619
- state.session.span.end();
23620
- }
23621
- sessionStates.delete(event);
23622
- },
23623
- error: (event) => {
23624
- const state = sessionStates.get(event);
23625
- if (!state || !event.error) {
23626
- return;
23627
- }
23628
- state.session.span.log({ error: event.error.message });
23629
- state.session.span.end();
23630
- sessionStates.delete(event);
23631
- }
23632
- };
25094
+ function isRecord(value) {
25095
+ return typeof value === "object" && value !== null && !Array.isArray(value);
23633
25096
  }
23634
- var GitHubCopilotPlugin = class extends BasePlugin {
25097
+
25098
+ // src/instrumentation/plugins/langchain-plugin.ts
25099
+ var LangChainPlugin = class extends BasePlugin {
25100
+ injectedManagers = /* @__PURE__ */ new WeakSet();
23635
25101
  onEnable() {
23636
- this.subscribeToSessionChannels();
25102
+ this.subscribeToConfigure(langChainChannels.configure);
25103
+ this.subscribeToConfigure(langChainChannels.configureSync);
23637
25104
  }
23638
25105
  onDisable() {
23639
25106
  for (const unsubscribe of this.unsubscribers) {
23640
25107
  unsubscribe();
23641
25108
  }
23642
25109
  this.unsubscribers = [];
25110
+ this.injectedManagers = /* @__PURE__ */ new WeakSet();
23643
25111
  }
23644
- subscribeToSessionChannels() {
23645
- const createChannel = gitHubCopilotChannels.createSession.tracingChannel();
23646
- const resumeChannel = gitHubCopilotChannels.resumeSession.tracingChannel();
23647
- const sessionStates = /* @__PURE__ */ new WeakMap();
23648
- const createHandlers = makeSessionHandlers(
23649
- sessionStates,
23650
- 0,
23651
- // config is arg 0 of createSession(config)
23652
- true
23653
- // include provider metadata
23654
- );
23655
- const resumeHandlers = makeSessionHandlers(
23656
- sessionStates,
23657
- 1,
23658
- // config is arg 1 of resumeSession(sessionId, config)
23659
- false
23660
- // resumeSession config has no provider field
23661
- );
23662
- createChannel.subscribe(createHandlers);
23663
- resumeChannel.subscribe(resumeHandlers);
23664
- this.unsubscribers.push(
23665
- () => createChannel.unsubscribe(createHandlers),
23666
- () => resumeChannel.unsubscribe(resumeHandlers)
23667
- );
25112
+ subscribeToConfigure(channel) {
25113
+ const tracingChannel2 = channel.tracingChannel();
25114
+ const handlers = {
25115
+ start: (event) => {
25116
+ injectHandlerIntoArguments(event.arguments);
25117
+ },
25118
+ end: (event) => {
25119
+ this.injectHandler(event.result);
25120
+ }
25121
+ };
25122
+ tracingChannel2.subscribe(handlers);
25123
+ this.unsubscribers.push(() => {
25124
+ tracingChannel2.unsubscribe(handlers);
25125
+ });
25126
+ }
25127
+ injectHandler(result) {
25128
+ if (!isCallbackManager(result)) {
25129
+ return;
25130
+ }
25131
+ if (this.injectedManagers.has(result) || hasBraintrustHandler(result)) {
25132
+ return;
25133
+ }
25134
+ try {
25135
+ result.addHandler(new BraintrustLangChainCallbackHandler(), true);
25136
+ this.injectedManagers.add(result);
25137
+ } catch {
25138
+ }
23668
25139
  }
23669
25140
  };
25141
+ function isCallbackManager(value) {
25142
+ if (typeof value !== "object" || value === null) {
25143
+ return false;
25144
+ }
25145
+ const maybeManager = value;
25146
+ return typeof maybeManager.addHandler === "function";
25147
+ }
25148
+ function hasBraintrustHandler(manager) {
25149
+ return manager.handlers?.some((handler) => {
25150
+ if (typeof handler !== "object" || handler === null) {
25151
+ return false;
25152
+ }
25153
+ const name = Reflect.get(handler, "name");
25154
+ return name === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
25155
+ }) ?? false;
25156
+ }
25157
+ function injectHandlerIntoArguments(args) {
25158
+ if (!isWritableArgumentsObject(args)) {
25159
+ return;
25160
+ }
25161
+ const inheritedHandlers = Reflect.get(args, "0");
25162
+ const handler = new BraintrustLangChainCallbackHandler();
25163
+ if (inheritedHandlers === void 0 || inheritedHandlers === null) {
25164
+ Reflect.set(args, "0", [handler]);
25165
+ return;
25166
+ }
25167
+ if (Array.isArray(inheritedHandlers)) {
25168
+ if (!inheritedHandlers.some(isBraintrustHandler)) {
25169
+ inheritedHandlers.push(handler);
25170
+ }
25171
+ }
25172
+ }
25173
+ function isWritableArgumentsObject(args) {
25174
+ return typeof args === "object" && args !== null;
25175
+ }
25176
+ function isBraintrustHandler(handler) {
25177
+ if (typeof handler !== "object" || handler === null) {
25178
+ return false;
25179
+ }
25180
+ return Reflect.get(handler, "name") === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
25181
+ }
23670
25182
 
23671
25183
  // src/instrumentation/braintrust-plugin.ts
23672
25184
  function getIntegrationConfig(integrations, key) {
@@ -23680,6 +25192,7 @@ var BraintrustPlugin = class extends BasePlugin {
23680
25192
  aiSDKPlugin = null;
23681
25193
  claudeAgentSDKPlugin = null;
23682
25194
  cursorSDKPlugin = null;
25195
+ openAIAgentsPlugin = null;
23683
25196
  googleGenAIPlugin = null;
23684
25197
  huggingFacePlugin = null;
23685
25198
  openRouterPlugin = null;
@@ -23690,6 +25203,8 @@ var BraintrustPlugin = class extends BasePlugin {
23690
25203
  groqPlugin = null;
23691
25204
  genkitPlugin = null;
23692
25205
  gitHubCopilotPlugin = null;
25206
+ fluePlugin = null;
25207
+ langChainPlugin = null;
23693
25208
  constructor(config = {}) {
23694
25209
  super();
23695
25210
  this.config = config;
@@ -23720,6 +25235,10 @@ var BraintrustPlugin = class extends BasePlugin {
23720
25235
  this.cursorSDKPlugin = new CursorSDKPlugin();
23721
25236
  this.cursorSDKPlugin.enable();
23722
25237
  }
25238
+ if (integrations.openAIAgents !== false) {
25239
+ this.openAIAgentsPlugin = new OpenAIAgentsPlugin();
25240
+ this.openAIAgentsPlugin.enable();
25241
+ }
23723
25242
  if (integrations.googleGenAI !== false && integrations.google !== false) {
23724
25243
  this.googleGenAIPlugin = new GoogleGenAIPlugin();
23725
25244
  this.googleGenAIPlugin.enable();
@@ -23760,6 +25279,14 @@ var BraintrustPlugin = class extends BasePlugin {
23760
25279
  this.gitHubCopilotPlugin = new GitHubCopilotPlugin();
23761
25280
  this.gitHubCopilotPlugin.enable();
23762
25281
  }
25282
+ if (getIntegrationConfig(integrations, "flue") !== false) {
25283
+ this.fluePlugin = new FluePlugin();
25284
+ this.fluePlugin.enable();
25285
+ }
25286
+ if (integrations.langchain !== false && integrations.langgraph !== false) {
25287
+ this.langChainPlugin = new LangChainPlugin();
25288
+ this.langChainPlugin.enable();
25289
+ }
23763
25290
  }
23764
25291
  onDisable() {
23765
25292
  if (this.openaiPlugin) {
@@ -23786,6 +25313,10 @@ var BraintrustPlugin = class extends BasePlugin {
23786
25313
  this.cursorSDKPlugin.disable();
23787
25314
  this.cursorSDKPlugin = null;
23788
25315
  }
25316
+ if (this.openAIAgentsPlugin) {
25317
+ this.openAIAgentsPlugin.disable();
25318
+ this.openAIAgentsPlugin = null;
25319
+ }
23789
25320
  if (this.googleGenAIPlugin) {
23790
25321
  this.googleGenAIPlugin.disable();
23791
25322
  this.googleGenAIPlugin = null;
@@ -23826,6 +25357,14 @@ var BraintrustPlugin = class extends BasePlugin {
23826
25357
  this.gitHubCopilotPlugin.disable();
23827
25358
  this.gitHubCopilotPlugin = null;
23828
25359
  }
25360
+ if (this.fluePlugin) {
25361
+ this.fluePlugin.disable();
25362
+ this.fluePlugin = null;
25363
+ }
25364
+ if (this.langChainPlugin) {
25365
+ this.langChainPlugin.disable();
25366
+ this.langChainPlugin = null;
25367
+ }
23829
25368
  }
23830
25369
  };
23831
25370
 
@@ -23907,50 +25446,16 @@ var PluginRegistry = class {
23907
25446
  * Get default configuration (all integrations enabled).
23908
25447
  */
23909
25448
  getDefaultConfig() {
23910
- return {
23911
- openai: true,
23912
- openaiCodexSDK: true,
23913
- anthropic: true,
23914
- vercel: true,
23915
- aisdk: true,
23916
- google: true,
23917
- googleGenAI: true,
23918
- googleADK: true,
23919
- huggingface: true,
23920
- claudeAgentSDK: true,
23921
- cursor: true,
23922
- cursorSDK: true,
23923
- openrouter: true,
23924
- openrouterAgent: true,
23925
- mistral: true,
23926
- cohere: true,
23927
- groq: true,
23928
- genkit: true,
23929
- gitHubCopilot: true
23930
- };
25449
+ return getDefaultInstrumentationIntegrations();
23931
25450
  }
23932
25451
  /**
23933
25452
  * Read configuration from environment variables.
23934
25453
  * Supports: BRAINTRUST_DISABLE_INSTRUMENTATION=openai,anthropic,...
23935
25454
  */
23936
25455
  readEnvConfig() {
23937
- const integrations = {};
23938
- const disabledList = isomorph_default.getEnv("BRAINTRUST_DISABLE_INSTRUMENTATION");
23939
- if (disabledList) {
23940
- const disabled = disabledList.split(",").map((s) => s.trim().toLowerCase()).filter((s) => s.length > 0);
23941
- for (const sdk of disabled) {
23942
- if (sdk === "cursor-sdk") {
23943
- integrations.cursorSDK = false;
23944
- } else if (sdk === "githubcopilot" || sdk === "github-copilot" || sdk === "copilot-sdk") {
23945
- integrations.gitHubCopilot = false;
23946
- } else if (sdk === "openai-codex-sdk") {
23947
- integrations.openaiCodexSDK = false;
23948
- } else {
23949
- integrations[sdk] = false;
23950
- }
23951
- }
23952
- }
23953
- return { integrations };
25456
+ return readDisabledInstrumentationEnvConfig(
25457
+ isomorph_default.getEnv("BRAINTRUST_DISABLE_INSTRUMENTATION")
25458
+ );
23954
25459
  }
23955
25460
  };
23956
25461
  var registry = new PluginRegistry();
@@ -24003,8 +25508,10 @@ __export(exports_exports, {
24003
25508
  Attachment: () => Attachment,
24004
25509
  AttachmentReference: () => AttachmentReference,
24005
25510
  BRAINTRUST_CURRENT_SPAN_STORE: () => BRAINTRUST_CURRENT_SPAN_STORE,
25511
+ BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME: () => BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME,
24006
25512
  BaseAttachment: () => BaseAttachment,
24007
25513
  BaseExperiment: () => BaseExperiment,
25514
+ BraintrustLangChainCallbackHandler: () => BraintrustLangChainCallbackHandler,
24008
25515
  BraintrustMiddleware: () => BraintrustMiddleware,
24009
25516
  BraintrustState: () => BraintrustState,
24010
25517
  BraintrustStream: () => BraintrustStream,
@@ -24130,6 +25637,8 @@ __export(exports_exports, {
24130
25637
  wrapCohere: () => wrapCohere,
24131
25638
  wrapCopilotClient: () => wrapCopilotClient,
24132
25639
  wrapCursorSDK: () => wrapCursorSDK,
25640
+ wrapFlueContext: () => wrapFlueContext,
25641
+ wrapFlueSession: () => wrapFlueSession,
24133
25642
  wrapGenkit: () => wrapGenkit,
24134
25643
  wrapGoogleADK: () => wrapGoogleADK,
24135
25644
  wrapGoogleGenAI: () => wrapGoogleGenAI,
@@ -24357,11 +25866,11 @@ function createChannelContext(_channel, params, span_info) {
24357
25866
  span_info
24358
25867
  };
24359
25868
  }
24360
- async function tracePromiseWithResponse(channel2, traceContext, apiPromise) {
25869
+ async function tracePromiseWithResponse(channel, traceContext, apiPromise) {
24361
25870
  let enhancedResponse;
24362
25871
  const tracePromise = (
24363
25872
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
24364
- channel2.tracePromise
25873
+ channel.tracePromise
24365
25874
  );
24366
25875
  const data = await tracePromise(async () => {
24367
25876
  enhancedResponse = await apiPromise.withResponse();
@@ -24424,16 +25933,16 @@ function responsesProxy(openai) {
24424
25933
  }
24425
25934
  });
24426
25935
  }
24427
- function wrapResponsesAsync(target, channel2) {
25936
+ function wrapResponsesAsync(target, channel) {
24428
25937
  return (allParams, options) => {
24429
25938
  const { span_info, params } = splitSpanInfo(allParams);
24430
25939
  let executionPromise = null;
24431
25940
  const ensureExecuted = () => {
24432
25941
  if (!executionPromise) {
24433
25942
  executionPromise = (async () => {
24434
- const traceContext = createChannelContext(channel2, params, span_info);
25943
+ const traceContext = createChannelContext(channel, params, span_info);
24435
25944
  const apiPromise = target(params, options);
24436
- return tracePromiseWithResponse(channel2, traceContext, apiPromise);
25945
+ return tracePromiseWithResponse(channel, traceContext, apiPromise);
24437
25946
  })();
24438
25947
  }
24439
25948
  return executionPromise;
@@ -24441,10 +25950,10 @@ function wrapResponsesAsync(target, channel2) {
24441
25950
  return createLazyAPIPromise(ensureExecuted);
24442
25951
  };
24443
25952
  }
24444
- function wrapResponsesSyncStream(target, channel2) {
25953
+ function wrapResponsesSyncStream(target, channel) {
24445
25954
  return (allParams, options) => {
24446
25955
  const { span_info, params } = splitSpanInfo(allParams);
24447
- return channel2.traceSync(() => target(params, options), {
25956
+ return channel.traceSync(() => target(params, options), {
24448
25957
  arguments: [params],
24449
25958
  span_info
24450
25959
  });
@@ -24632,16 +26141,16 @@ function createEndpointProxy(target, wrapperFn) {
24632
26141
  }
24633
26142
  });
24634
26143
  }
24635
- function wrapApiCreateWithChannel(create, channel2) {
26144
+ function wrapApiCreateWithChannel(create, channel) {
24636
26145
  return (allParams, options) => {
24637
26146
  const { span_info, params } = splitSpanInfo(allParams);
24638
26147
  let executionPromise = null;
24639
26148
  const ensureExecuted = () => {
24640
26149
  if (!executionPromise) {
24641
26150
  executionPromise = (async () => {
24642
- const traceContext = createChannelContext(channel2, params, span_info);
26151
+ const traceContext = createChannelContext(channel, params, span_info);
24643
26152
  return tracePromiseWithResponse(
24644
- channel2,
26153
+ channel,
24645
26154
  traceContext,
24646
26155
  create(params, options)
24647
26156
  );
@@ -24763,11 +26272,11 @@ var wrapAgentStream = (stream, instance, options = {}) => {
24763
26272
  options
24764
26273
  )({ ...instance.settings, ...params });
24765
26274
  };
24766
- var makeGenerateTextWrapper = (channel2, name, generateText, contextOptions = {}, options = {}) => {
26275
+ var makeGenerateTextWrapper = (channel, name, generateText, contextOptions = {}, options = {}) => {
24767
26276
  const wrapper = async function(allParams) {
24768
26277
  const { span_info, ...params } = allParams;
24769
26278
  const tracedParams = { ...params };
24770
- return channel2.tracePromise(
26279
+ return channel.tracePromise(
24771
26280
  () => generateText(tracedParams),
24772
26281
  createAISDKChannelContext(tracedParams, {
24773
26282
  aiSDK: contextOptions.aiSDK,
@@ -24801,11 +26310,11 @@ var wrapGenerateObject = (generateObject, options = {}, aiSDK) => {
24801
26310
  options
24802
26311
  );
24803
26312
  };
24804
- var makeEmbedWrapper = (channel2, name, embed, contextOptions = {}, options = {}) => {
26313
+ var makeEmbedWrapper = (channel, name, embed, contextOptions = {}, options = {}) => {
24805
26314
  const wrapper = async function(allParams) {
24806
26315
  const { span_info, ...params } = allParams;
24807
26316
  const tracedParams = { ...params };
24808
- return channel2.tracePromise(
26317
+ return channel.tracePromise(
24809
26318
  () => embed(tracedParams),
24810
26319
  createAISDKChannelContext(tracedParams, {
24811
26320
  aiSDK: contextOptions.aiSDK,
@@ -24862,7 +26371,7 @@ var makeRerankWrapper = (rerank, contextOptions = {}, options = {}) => {
24862
26371
  var wrapRerank = (rerank, options = {}, aiSDK) => {
24863
26372
  return makeRerankWrapper(rerank, { aiSDK }, options);
24864
26373
  };
24865
- var makeStreamWrapper = (channel2, name, streamText, contextOptions = {}, options = {}) => {
26374
+ var makeStreamWrapper = (channel, name, streamText, contextOptions = {}, options = {}) => {
24866
26375
  const wrapper = function(allParams) {
24867
26376
  const { span_info, ...params } = allParams;
24868
26377
  const tracedParams = { ...params };
@@ -24875,7 +26384,7 @@ var makeStreamWrapper = (channel2, name, streamText, contextOptions = {}, option
24875
26384
  spanType: contextOptions.spanType
24876
26385
  })
24877
26386
  });
24878
- return channel2.tracePromise(() => streamText(tracedParams), context);
26387
+ return channel.tracePromise(() => streamText(tracedParams), context);
24879
26388
  };
24880
26389
  Object.defineProperty(wrapper, "name", { value: name, writable: false });
24881
26390
  return wrapper;
@@ -25229,7 +26738,7 @@ function extractModelParameters(params, excludeKeys) {
25229
26738
  }
25230
26739
  return modelParams;
25231
26740
  }
25232
- function getNumberProperty2(obj, key) {
26741
+ function getNumberProperty3(obj, key) {
25233
26742
  if (!obj || typeof obj !== "object" || !(key in obj)) {
25234
26743
  return void 0;
25235
26744
  }
@@ -25238,31 +26747,31 @@ function getNumberProperty2(obj, key) {
25238
26747
  }
25239
26748
  function normalizeUsageMetrics(usage, provider, providerMetadata) {
25240
26749
  const metrics = {};
25241
- const inputTokens = getNumberProperty2(usage, "inputTokens");
26750
+ const inputTokens = getNumberProperty3(usage, "inputTokens");
25242
26751
  if (inputTokens !== void 0) {
25243
26752
  metrics.prompt_tokens = inputTokens;
25244
26753
  }
25245
- const outputTokens = getNumberProperty2(usage, "outputTokens");
26754
+ const outputTokens = getNumberProperty3(usage, "outputTokens");
25246
26755
  if (outputTokens !== void 0) {
25247
26756
  metrics.completion_tokens = outputTokens;
25248
26757
  }
25249
- const totalTokens = getNumberProperty2(usage, "totalTokens");
26758
+ const totalTokens = getNumberProperty3(usage, "totalTokens");
25250
26759
  if (totalTokens !== void 0) {
25251
26760
  metrics.tokens = totalTokens;
25252
26761
  }
25253
- const reasoningTokens = getNumberProperty2(usage, "reasoningTokens");
26762
+ const reasoningTokens = getNumberProperty3(usage, "reasoningTokens");
25254
26763
  if (reasoningTokens !== void 0) {
25255
26764
  metrics.completion_reasoning_tokens = reasoningTokens;
25256
26765
  }
25257
- const cachedInputTokens = getNumberProperty2(usage, "cachedInputTokens");
26766
+ const cachedInputTokens = getNumberProperty3(usage, "cachedInputTokens");
25258
26767
  if (cachedInputTokens !== void 0) {
25259
26768
  metrics.prompt_cached_tokens = cachedInputTokens;
25260
26769
  }
25261
26770
  if (provider === "anthropic") {
25262
26771
  const anthropicMetadata = providerMetadata?.anthropic;
25263
26772
  if (anthropicMetadata) {
25264
- const cacheReadTokens = getNumberProperty2(anthropicMetadata.usage, "cache_read_input_tokens") || 0;
25265
- const cacheCreationTokens = getNumberProperty2(
26773
+ const cacheReadTokens = getNumberProperty3(anthropicMetadata.usage, "cache_read_input_tokens") || 0;
26774
+ const cacheCreationTokens = getNumberProperty3(
25266
26775
  anthropicMetadata.usage,
25267
26776
  "cache_creation_input_tokens"
25268
26777
  ) || 0;
@@ -25585,10 +27094,10 @@ function betaMessagesProxy(messages, anthropic) {
25585
27094
  }
25586
27095
  });
25587
27096
  }
25588
- function createProxy(create, channel2) {
27097
+ function createProxy(create, channel) {
25589
27098
  return new TypedApplyProxy(create, {
25590
27099
  apply(target, thisArg, argArray) {
25591
- return channel2.tracePromise(
27100
+ return channel.tracePromise(
25592
27101
  () => Reflect.apply(target, thisArg, argArray),
25593
27102
  {
25594
27103
  arguments: argArray
@@ -25597,7 +27106,7 @@ function createProxy(create, channel2) {
25597
27106
  }
25598
27107
  });
25599
27108
  }
25600
- function toolRunnerProxy(toolRunner, anthropic, channel2) {
27109
+ function toolRunnerProxy(toolRunner, anthropic, channel) {
25601
27110
  return new TypedApplyProxy(toolRunner, {
25602
27111
  apply(target, thisArg, argArray) {
25603
27112
  const invocationTarget = thisArg && typeof thisArg === "object" ? new Proxy(thisArg, {
@@ -25608,7 +27117,7 @@ function toolRunnerProxy(toolRunner, anthropic, channel2) {
25608
27117
  return Reflect.get(currentTarget, prop, receiver);
25609
27118
  }
25610
27119
  }) : { _client: anthropic };
25611
- return channel2.traceSync(
27120
+ return channel.traceSync(
25612
27121
  () => Reflect.apply(target, invocationTarget, argArray),
25613
27122
  {
25614
27123
  arguments: argArray
@@ -26237,17 +27746,17 @@ function wrapGenkit(genkit) {
26237
27746
  console.warn("Unsupported Genkit object. Not wrapping.");
26238
27747
  return genkit;
26239
27748
  }
26240
- function isRecord(value) {
27749
+ function isRecord2(value) {
26241
27750
  return typeof value === "object" && value !== null;
26242
27751
  }
26243
27752
  function isPropertyBag(value) {
26244
- return isRecord(value) || typeof value === "function";
27753
+ return isRecord2(value) || typeof value === "function";
26245
27754
  }
26246
27755
  function hasFunction(value, methodName) {
26247
27756
  return isPropertyBag(value) && methodName in value && typeof value[methodName] === "function";
26248
27757
  }
26249
27758
  function isGenkitInstance(value) {
26250
- return isRecord(value) && (hasFunction(value, "generate") || hasFunction(value, "generateStream") || hasFunction(value, "defineFlow") || hasFunction(value, "defineTool"));
27759
+ return isRecord2(value) && (hasFunction(value, "generate") || hasFunction(value, "generateStream") || hasFunction(value, "defineFlow") || hasFunction(value, "defineTool"));
26251
27760
  }
26252
27761
  function isGenkitModule(value) {
26253
27762
  return hasFunction(value, "genkit");
@@ -26301,7 +27810,7 @@ function patchGenkitRegistry(instance) {
26301
27810
  patchGenkitRegistryConstructor(registry2);
26302
27811
  }
26303
27812
  function patchGenkitRegistryLookup(registry2) {
26304
- if (!isRecord(registry2) || hasRegistryPatchedFlag(registry2) || !hasFunction(registry2, "lookupAction")) {
27813
+ if (!isRecord2(registry2) || hasRegistryPatchedFlag(registry2) || !hasFunction(registry2, "lookupAction")) {
26305
27814
  return;
26306
27815
  }
26307
27816
  const originalLookupAction = registry2.lookupAction;
@@ -26327,7 +27836,7 @@ function patchGenkitRegistryLookup(registry2) {
26327
27836
  }
26328
27837
  }
26329
27838
  function patchGenkitRegistryConstructor(registry2) {
26330
- if (!isRecord(registry2)) {
27839
+ if (!isRecord2(registry2)) {
26331
27840
  return;
26332
27841
  }
26333
27842
  const constructor = registry2.constructor;
@@ -26343,7 +27852,7 @@ function patchGenkitRegistryConstructor(registry2) {
26343
27852
  configurable: true,
26344
27853
  value: (...args) => {
26345
27854
  const childRegistry = originalWithParent.apply(constructor, args);
26346
- if (args.some((arg) => isRecord(arg) && hasRegistryPatchedFlag(arg))) {
27855
+ if (args.some((arg) => isRecord2(arg) && hasRegistryPatchedFlag(arg))) {
26347
27856
  patchGenkitRegistryLookup(childRegistry);
26348
27857
  patchGenkitRegistryConstructor(childRegistry);
26349
27858
  }
@@ -26442,7 +27951,7 @@ function hasRegistryConstructorPatchedFlag(value) {
26442
27951
  );
26443
27952
  }
26444
27953
  function isPromiseLike2(value) {
26445
- return isRecord(value) && "then" in value && typeof value.then === "function";
27954
+ return isRecord2(value) && "then" in value && typeof value.then === "function";
26446
27955
  }
26447
27956
 
26448
27957
  // src/wrappers/huggingface.ts
@@ -26805,14 +28314,14 @@ function wrapMistral(mistral) {
26805
28314
  console.warn("Unsupported Mistral library. Not wrapping.");
26806
28315
  return mistral;
26807
28316
  }
26808
- function isRecord2(value) {
28317
+ function isRecord3(value) {
26809
28318
  return typeof value === "object" && value !== null;
26810
28319
  }
26811
28320
  function hasFunction3(value, methodName) {
26812
- return isRecord2(value) && methodName in value && typeof value[methodName] === "function";
28321
+ return isRecord3(value) && methodName in value && typeof value[methodName] === "function";
26813
28322
  }
26814
28323
  function isSupportedMistralClient(value) {
26815
- if (!isRecord2(value)) {
28324
+ if (!isRecord3(value)) {
26816
28325
  return false;
26817
28326
  }
26818
28327
  return value.chat !== void 0 && hasChat(value.chat) || value.embeddings !== void 0 && hasEmbeddings(value.embeddings) || value.fim !== void 0 && hasFim(value.fim) || value.agents !== void 0 && hasAgents(value.agents) || value.classifiers !== void 0 && hasClassifiers(value.classifiers);
@@ -26996,14 +28505,14 @@ function wrapCohere(cohere) {
26996
28505
  return cohere;
26997
28506
  }
26998
28507
  var cohereProxyCache = /* @__PURE__ */ new WeakMap();
26999
- function isRecord3(value) {
28508
+ function isRecord4(value) {
27000
28509
  return typeof value === "object" && value !== null;
27001
28510
  }
27002
28511
  function hasFunction4(value, methodName) {
27003
- return isRecord3(value) && methodName in value && typeof value[methodName] === "function";
28512
+ return isRecord4(value) && methodName in value && typeof value[methodName] === "function";
27004
28513
  }
27005
28514
  function isSupportedCohereClient(value) {
27006
- if (!isRecord3(value)) {
28515
+ if (!isRecord4(value)) {
27007
28516
  return false;
27008
28517
  }
27009
28518
  return hasFunction4(value, "chat") || hasFunction4(value, "chatStream") || hasFunction4(value, "embed") || hasFunction4(value, "rerank");
@@ -27063,20 +28572,20 @@ function wrapGroq(groq) {
27063
28572
  console.warn("Unsupported Groq library. Not wrapping.");
27064
28573
  return groq;
27065
28574
  }
27066
- function isRecord4(value) {
28575
+ function isRecord5(value) {
27067
28576
  return typeof value === "object" && value !== null;
27068
28577
  }
27069
28578
  function hasFunction5(value, methodName) {
27070
- return isRecord4(value) && methodName in value && typeof value[methodName] === "function";
28579
+ return isRecord5(value) && methodName in value && typeof value[methodName] === "function";
27071
28580
  }
27072
28581
  function hasChat2(value) {
27073
- return isRecord4(value) && isRecord4(value.completions) && hasFunction5(value.completions, "create");
28582
+ return isRecord5(value) && isRecord5(value.completions) && hasFunction5(value.completions, "create");
27074
28583
  }
27075
28584
  function hasEmbeddings2(value) {
27076
28585
  return hasFunction5(value, "create");
27077
28586
  }
27078
28587
  function isSupportedGroqClient(value) {
27079
- return isRecord4(value) && (value.chat !== void 0 && hasChat2(value.chat) || value.embeddings !== void 0 && hasEmbeddings2(value.embeddings));
28588
+ return isRecord5(value) && (value.chat !== void 0 && hasChat2(value.chat) || value.embeddings !== void 0 && hasEmbeddings2(value.embeddings));
27080
28589
  }
27081
28590
  function groqProxy(groq) {
27082
28591
  const privateMethodWorkaroundCache = /* @__PURE__ */ new WeakMap();
@@ -31054,8 +32563,10 @@ export {
31054
32563
  Attachment,
31055
32564
  AttachmentReference,
31056
32565
  BRAINTRUST_CURRENT_SPAN_STORE,
32566
+ BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME,
31057
32567
  BaseAttachment,
31058
32568
  BaseExperiment,
32569
+ BraintrustLangChainCallbackHandler,
31059
32570
  BraintrustMiddleware,
31060
32571
  BraintrustState,
31061
32572
  BraintrustStream,
@@ -31182,6 +32693,8 @@ export {
31182
32693
  wrapCohere,
31183
32694
  wrapCopilotClient,
31184
32695
  wrapCursorSDK,
32696
+ wrapFlueContext,
32697
+ wrapFlueSession,
31185
32698
  wrapGenkit,
31186
32699
  wrapGoogleADK,
31187
32700
  wrapGoogleGenAI,