braintrust 3.26.0 → 3.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dev/dist/index.js +2440 -1067
  2. package/dev/dist/index.mjs +1644 -271
  3. package/dist/apply-auto-instrumentation.js +320 -261
  4. package/dist/apply-auto-instrumentation.mjs +118 -59
  5. package/dist/auto-instrumentations/bundler/esbuild.cjs +377 -59
  6. package/dist/auto-instrumentations/bundler/esbuild.mjs +5 -4
  7. package/dist/auto-instrumentations/bundler/next.cjs +379 -61
  8. package/dist/auto-instrumentations/bundler/next.mjs +6 -5
  9. package/dist/auto-instrumentations/bundler/rollup.cjs +377 -59
  10. package/dist/auto-instrumentations/bundler/rollup.mjs +5 -4
  11. package/dist/auto-instrumentations/bundler/vite.cjs +406 -60
  12. package/dist/auto-instrumentations/bundler/vite.mjs +34 -5
  13. package/dist/auto-instrumentations/bundler/webpack-loader.cjs +363 -59
  14. package/dist/auto-instrumentations/bundler/webpack.cjs +377 -59
  15. package/dist/auto-instrumentations/bundler/webpack.mjs +6 -5
  16. package/dist/auto-instrumentations/{chunk-AKKPLXTP.mjs → chunk-2AMDGD65.mjs} +160 -57
  17. package/dist/auto-instrumentations/{chunk-V5LEODRX.mjs → chunk-BW33ULMW.mjs} +1 -1
  18. package/dist/auto-instrumentations/{chunk-XYN63IG5.mjs → chunk-I55G56ZL.mjs} +21 -58
  19. package/dist/auto-instrumentations/{chunk-NRE4QUQR.mjs → chunk-JPUFNW7X.mjs} +140 -0
  20. package/dist/auto-instrumentations/{chunk-6E22MYSW.mjs → chunk-XEYKUBLY.mjs} +30 -4
  21. package/dist/auto-instrumentations/{chunk-XZHHE4Y3.mjs → chunk-ZNHTSSGI.mjs} +155 -2
  22. package/dist/auto-instrumentations/hook.mjs +161 -3
  23. package/dist/auto-instrumentations/index.cjs +296 -1
  24. package/dist/auto-instrumentations/index.d.mts +5 -1
  25. package/dist/auto-instrumentations/index.d.ts +5 -1
  26. package/dist/auto-instrumentations/index.mjs +6 -2
  27. package/dist/auto-instrumentations/loader/cjs-patch.cjs +105 -57
  28. package/dist/auto-instrumentations/loader/cjs-patch.mjs +2 -2
  29. package/dist/auto-instrumentations/loader/esm-hook.mjs +1 -1
  30. package/dist/browser.d.mts +57 -5
  31. package/dist/browser.d.ts +57 -5
  32. package/dist/browser.js +1855 -285
  33. package/dist/browser.mjs +1855 -285
  34. package/dist/{chunk-PN7EWK66.mjs → chunk-CZM5JIQL.mjs} +209 -1
  35. package/dist/{chunk-VYNNEKSA.js → chunk-MF7NU6BT.js} +216 -8
  36. package/dist/{chunk-VRZZQPAA.js → chunk-QRHGVBKU.js} +2403 -1220
  37. package/dist/{chunk-XIZOM2HO.mjs → chunk-YKD22IMR.mjs} +1454 -271
  38. package/dist/cli.js +1645 -272
  39. package/dist/edge-light.d.mts +1 -1
  40. package/dist/edge-light.d.ts +1 -1
  41. package/dist/edge-light.js +1855 -285
  42. package/dist/edge-light.mjs +1855 -285
  43. package/dist/index.d.mts +57 -5
  44. package/dist/index.d.ts +57 -5
  45. package/dist/index.js +600 -413
  46. package/dist/index.mjs +201 -14
  47. package/dist/instrumentation/index.d.mts +8 -0
  48. package/dist/instrumentation/index.d.ts +8 -0
  49. package/dist/instrumentation/index.js +1839 -466
  50. package/dist/instrumentation/index.mjs +1839 -466
  51. package/dist/vitest-evals-reporter.js +45 -43
  52. package/dist/vitest-evals-reporter.mjs +5 -3
  53. package/dist/workerd.d.mts +1 -1
  54. package/dist/workerd.d.ts +1 -1
  55. package/dist/workerd.js +1855 -285
  56. package/dist/workerd.mjs +1855 -285
  57. package/package.json +1 -1
@@ -3,8 +3,10 @@ var GLOBAL_INSTRUMENTATION_HOOKS_KEY = "__braintrust_instrumentation_hooks";
3
3
  var GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION = 1;
4
4
  var GLOBAL_INSTRUMENTATION_HOOKS_REGISTRY_BRAND = "braintrust.global-instrumentation-hooks.registry";
5
5
  var GLOBAL_INSTRUMENTATION_HOOK_BRAND = "braintrust.global-instrumentation-hooks.hook";
6
+ var GLOBAL_INVOCATION_HOOK_BRAND = "braintrust.global-instrumentation-hooks.invocation-hook";
6
7
  var registryBrand = Symbol.for(GLOBAL_INSTRUMENTATION_HOOKS_REGISTRY_BRAND);
7
8
  var hookBrand = Symbol.for(GLOBAL_INSTRUMENTATION_HOOK_BRAND);
9
+ var invocationHookBrand = Symbol.for(GLOBAL_INVOCATION_HOOK_BRAND);
8
10
  var errorReporter;
9
11
  function setGlobalHookErrorReporter(reporter) {
10
12
  const previousReporter = errorReporter;
@@ -149,12 +151,69 @@ var traceEvents = [
149
151
  "asyncEnd",
150
152
  "error"
151
153
  ];
154
+ function traceInvocation(hook, operator, target, thisArg, args, additional, callbackIndex = -1) {
155
+ const context = {
156
+ ...additional,
157
+ arguments: args,
158
+ self: thisArg
159
+ };
160
+ const invoke = () => hook.invoke(target, thisArg, args, additional);
161
+ if (operator === "traceCallback") {
162
+ return hook.traceCallback(invoke, callbackIndex, context);
163
+ }
164
+ if (operator === "tracePromise") {
165
+ return hook.tracePromise(invoke, context);
166
+ }
167
+ return hook.traceSync(invoke, context);
168
+ }
169
+ var InvocationHook = class {
170
+ interceptors = [];
171
+ get hasInterceptors() {
172
+ return this.interceptors.length > 0;
173
+ }
174
+ intercept(interceptor) {
175
+ if (typeof interceptor !== "function") {
176
+ throw new TypeError("interceptor must be a function");
177
+ }
178
+ this.interceptors = [...this.interceptors, interceptor];
179
+ let active = true;
180
+ return () => {
181
+ if (!active) {
182
+ return;
183
+ }
184
+ active = false;
185
+ const index = this.interceptors.indexOf(interceptor);
186
+ if (index !== -1) {
187
+ this.interceptors = [
188
+ ...this.interceptors.slice(0, index),
189
+ ...this.interceptors.slice(index + 1)
190
+ ];
191
+ }
192
+ };
193
+ }
194
+ invoke(target, thisArg, args, additional) {
195
+ const interceptors = this.interceptors;
196
+ if (interceptors.length === 0) {
197
+ return Reflect.apply(target, thisArg, args);
198
+ }
199
+ let next = target;
200
+ for (let index = interceptors.length - 1; index >= 0; index -= 1) {
201
+ const interceptor = interceptors[index];
202
+ const downstream = next;
203
+ next = function(...nextArgs) {
204
+ return interceptor(downstream, this, nextArgs, additional);
205
+ };
206
+ }
207
+ return Reflect.apply(next, thisArg, args);
208
+ }
209
+ };
152
210
  var TracingHook = class {
153
211
  start;
154
212
  end;
155
213
  asyncStart;
156
214
  asyncEnd;
157
215
  error;
216
+ invocationHook = new InvocationHook();
158
217
  constructor(nameOrChannels) {
159
218
  Object.defineProperty(this, hookBrand, {
160
219
  configurable: false,
@@ -162,6 +221,12 @@ var TracingHook = class {
162
221
  value: GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION,
163
222
  writable: false
164
223
  });
224
+ Object.defineProperty(this, invocationHookBrand, {
225
+ configurable: false,
226
+ enumerable: false,
227
+ value: GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION,
228
+ writable: false
229
+ });
165
230
  if (typeof nameOrChannels === "string") {
166
231
  this.start = new HookChannel(`tracing:${nameOrChannels}:start`);
167
232
  this.end = new HookChannel(`tracing:${nameOrChannels}:end`);
@@ -179,6 +244,26 @@ var TracingHook = class {
179
244
  get hasSubscribers() {
180
245
  return this.start.hasSubscribers || this.end.hasSubscribers || this.asyncStart.hasSubscribers || this.asyncEnd.hasSubscribers || this.error.hasSubscribers;
181
246
  }
247
+ get hasInterceptors() {
248
+ return this.invocationHook.hasInterceptors;
249
+ }
250
+ intercept(interceptor) {
251
+ return this.invocationHook.intercept(interceptor);
252
+ }
253
+ invoke(target, thisArg, args, additional) {
254
+ return this.invocationHook.invoke(target, thisArg, args, additional);
255
+ }
256
+ traceInvocation(operator, target, thisArg, args, additional, callbackIndex = -1) {
257
+ return traceInvocation(
258
+ this,
259
+ operator,
260
+ target,
261
+ thisArg,
262
+ args,
263
+ additional,
264
+ callbackIndex
265
+ );
266
+ }
182
267
  subscribe(handlers) {
183
268
  for (const eventName of traceEvents) {
184
269
  const handler = handlers[eventName];
@@ -400,6 +485,60 @@ function hasTracingHookShape(value) {
400
485
  return false;
401
486
  }
402
487
  }
488
+ function hasInvocationHookShape(value) {
489
+ if (typeof value !== "object" && typeof value !== "function" || value === null) {
490
+ return false;
491
+ }
492
+ try {
493
+ const hook = value;
494
+ return value[invocationHookBrand] === GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION && typeof hook.hasInterceptors === "boolean" && typeof hook.intercept === "function" && typeof hook.invoke === "function";
495
+ } catch {
496
+ return false;
497
+ }
498
+ }
499
+ function installInvocationHook(value) {
500
+ const hasInvocationHook = hasInvocationHookShape(value);
501
+ const invocationHook = new InvocationHook();
502
+ try {
503
+ if (!hasInvocationHook) {
504
+ Object.defineProperties(value, {
505
+ [invocationHookBrand]: {
506
+ configurable: false,
507
+ enumerable: false,
508
+ value: GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION,
509
+ writable: false
510
+ },
511
+ hasInterceptors: {
512
+ configurable: false,
513
+ enumerable: false,
514
+ get: () => invocationHook.hasInterceptors
515
+ },
516
+ intercept: {
517
+ configurable: false,
518
+ enumerable: false,
519
+ value: invocationHook.intercept.bind(invocationHook),
520
+ writable: false
521
+ },
522
+ invoke: {
523
+ configurable: false,
524
+ enumerable: false,
525
+ value: invocationHook.invoke.bind(invocationHook),
526
+ writable: false
527
+ }
528
+ });
529
+ }
530
+ if (typeof value.traceInvocation !== "function") {
531
+ Object.defineProperty(value, "traceInvocation", {
532
+ configurable: false,
533
+ enumerable: false,
534
+ value: traceInvocation.bind(void 0, value),
535
+ writable: false
536
+ });
537
+ }
538
+ } catch (error) {
539
+ reportError(error);
540
+ }
541
+ }
403
542
  function isCompatibleTracingHook(value) {
404
543
  try {
405
544
  return value[hookBrand] === GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION && hasTracingHookShape(value);
@@ -486,6 +625,7 @@ function newGlobalTracingChannel(nameOrChannels) {
486
625
  return inertTracingHook;
487
626
  }
488
627
  if (isCompatibleTracingHook(existing)) {
628
+ installInvocationHook(existing);
489
629
  return existing;
490
630
  }
491
631
  if (existing !== void 0) {
@@ -706,8 +846,7 @@ var transforms = {
706
846
  tracingHookDeclaration(state, node) {
707
847
  const {
708
848
  channelName,
709
- module: { name },
710
- operator
849
+ module: { name }
711
850
  } = state;
712
851
  const channelVariable = formatChannelVariable(channelName);
713
852
  const channelGetter = formatChannelGetter(channelName);
@@ -720,7 +859,7 @@ var transforms = {
720
859
  return;
721
860
  }
722
861
  const sharedHookLookup = hasSharedHookLookup ? "" : `
723
- const ${SHARED_HOOK_LOOKUP} = (__bt$hookName, __bt$operator) => {
862
+ const ${SHARED_HOOK_LOOKUP} = (__bt$hookName) => {
724
863
  try {
725
864
  const __bt$hooks = globalThis[${JSON.stringify(
726
865
  GLOBAL_INSTRUMENTATION_HOOKS_KEY
@@ -742,8 +881,7 @@ var transforms = {
742
881
  __bt$hook[Symbol.for(${JSON.stringify(
743
882
  GLOBAL_INSTRUMENTATION_HOOK_BRAND
744
883
  )})] !== ${GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION} ||
745
- typeof __bt$hook.hasSubscribers !== "boolean" ||
746
- typeof __bt$hook[__bt$operator] !== "function"
884
+ typeof __bt$hook.traceInvocation !== "function"
747
885
  ) return undefined;
748
886
  return __bt$hook;
749
887
  } catch {
@@ -756,8 +894,7 @@ var transforms = {
756
894
  let ${channelVariable};
757
895
  const ${channelGetter} = () =>
758
896
  ${channelVariable} ??= ${SHARED_HOOK_LOOKUP}(
759
- ${JSON.stringify(`orchestrion:${name}:${channelName}`)},
760
- ${JSON.stringify(operator)}
897
+ ${JSON.stringify(`orchestrion:${name}:${channelName}`)}
761
898
  );
762
899
  `;
763
900
  const sharedHookLookupIndex = node.body.findIndex(
@@ -832,28 +969,18 @@ function traceInstanceMethod(state, node, program) {
832
969
  ctor.value.body.body.push(...ctorBody);
833
970
  }
834
971
  function wrap(state, node) {
835
- const { operator, moduleVersion } = state;
836
- const wrapper = operator === "traceCallback" ? wrapCallback(state) : operator === "tracePromise" ? wrapPromise(state) : wrapSync(state);
972
+ const wrapper = wrapInvocation(state);
837
973
  const block = wrapper.body[0].body;
838
974
  const common = parse(
839
975
  node.type === "ArrowFunctionExpression" ? `
840
- const __bt$ctx = {
841
- arguments,
842
- moduleVersion: ${JSON.stringify(moduleVersion)}
843
- };
844
- const __bt$traced = () => {
976
+ const __bt$target = (...__bt$args) => {
845
977
  const __bt$wrapped = () => {};
846
- return __bt$wrapped(...arguments);
978
+ return __bt$wrapped(...__bt$args);
847
979
  };
848
980
  ` : `
849
- const __bt$ctx = {
850
- arguments,
851
- self: this,
852
- moduleVersion: ${JSON.stringify(moduleVersion)}
853
- };
854
- const __bt$traced = () => {
981
+ const __bt$target = function (...__bt$args) {
855
982
  const __bt$wrapped = () => {};
856
- return __bt$wrapped.apply(this, arguments);
983
+ return __bt$wrapped.apply(this, __bt$args);
857
984
  };
858
985
  `
859
986
  ).body;
@@ -895,49 +1022,25 @@ function wrapSuper(node) {
895
1022
  node.body.body.unshift(parse("const __bt$super = {}").body[0]);
896
1023
  }
897
1024
  }
898
- function wrapCallback(state) {
899
- const {
900
- channelName,
901
- functionQuery: { callbackIndex = -1 }
902
- } = state;
1025
+ function wrapInvocation(state) {
1026
+ const { channelName, moduleVersion, operator, functionQuery } = state;
903
1027
  const channelGetter = formatChannelGetter(channelName);
1028
+ const callbackIndex = functionQuery.callbackIndex ?? -1;
904
1029
  return parse(`
905
1030
  function wrapper () {
906
1031
  const __bt$hook = ${channelGetter}();
907
- if (!__bt$hook?.hasSubscribers) return __bt$traced();
908
- __bt$ctx.self ??= this;
909
- return __bt$hook.traceCallback(
910
- __bt$traced,
911
- ${callbackIndex},
912
- __bt$ctx
1032
+ if (!__bt$hook) return __bt$target.apply(this, arguments);
1033
+ return __bt$hook.traceInvocation(
1034
+ ${JSON.stringify(operator)},
1035
+ __bt$target,
1036
+ this,
1037
+ arguments,
1038
+ { moduleVersion: ${JSON.stringify(moduleVersion)} },
1039
+ ${callbackIndex}
913
1040
  );
914
1041
  }
915
1042
  `);
916
1043
  }
917
- function wrapPromise(state) {
918
- const { channelName } = state;
919
- const channelGetter = formatChannelGetter(channelName);
920
- return parse(`
921
- function wrapper () {
922
- const __bt$hook = ${channelGetter}();
923
- if (!__bt$hook?.hasSubscribers) return __bt$traced();
924
- __bt$ctx.self ??= this;
925
- return __bt$hook.tracePromise(__bt$traced, __bt$ctx);
926
- }
927
- `);
928
- }
929
- function wrapSync(state) {
930
- const { channelName } = state;
931
- const channelGetter = formatChannelGetter(channelName);
932
- return parse(`
933
- function wrapper () {
934
- const __bt$hook = ${channelGetter}();
935
- if (!__bt$hook?.hasSubscribers) return __bt$traced();
936
- __bt$ctx.self ??= this;
937
- return __bt$hook.traceSync(__bt$traced, __bt$ctx);
938
- }
939
- `);
940
- }
941
1044
 
942
1045
  // src/auto-instrumentations/orchestrion-js/transformer.ts
943
1046
  var Transformer = class {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  unplugin
3
- } from "./chunk-6E22MYSW.mjs";
3
+ } from "./chunk-XEYKUBLY.mjs";
4
4
 
5
5
  // src/auto-instrumentations/bundler/webpack.ts
6
6
  function braintrustWebpackPlugin(options = {}) {
@@ -3,7 +3,7 @@ import {
3
3
  GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION,
4
4
  GLOBAL_INSTRUMENTATION_HOOKS_REGISTRY_BRAND,
5
5
  GLOBAL_INSTRUMENTATION_HOOK_BRAND
6
- } from "./chunk-NRE4QUQR.mjs";
6
+ } from "./chunk-JPUFNW7X.mjs";
7
7
 
8
8
  // src/auto-instrumentations/orchestrion-js/matcher.ts
9
9
  import semifies from "semifies";
@@ -29,8 +29,7 @@ var transforms = {
29
29
  tracingHookDeclaration(state, node) {
30
30
  const {
31
31
  channelName,
32
- module: { name },
33
- operator
32
+ module: { name }
34
33
  } = state;
35
34
  const channelVariable = formatChannelVariable(channelName);
36
35
  const channelGetter = formatChannelGetter(channelName);
@@ -43,7 +42,7 @@ var transforms = {
43
42
  return;
44
43
  }
45
44
  const sharedHookLookup = hasSharedHookLookup ? "" : `
46
- const ${SHARED_HOOK_LOOKUP} = (__bt$hookName, __bt$operator) => {
45
+ const ${SHARED_HOOK_LOOKUP} = (__bt$hookName) => {
47
46
  try {
48
47
  const __bt$hooks = globalThis[${JSON.stringify(
49
48
  GLOBAL_INSTRUMENTATION_HOOKS_KEY
@@ -65,8 +64,7 @@ var transforms = {
65
64
  __bt$hook[Symbol.for(${JSON.stringify(
66
65
  GLOBAL_INSTRUMENTATION_HOOK_BRAND
67
66
  )})] !== ${GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION} ||
68
- typeof __bt$hook.hasSubscribers !== "boolean" ||
69
- typeof __bt$hook[__bt$operator] !== "function"
67
+ typeof __bt$hook.traceInvocation !== "function"
70
68
  ) return undefined;
71
69
  return __bt$hook;
72
70
  } catch {
@@ -79,8 +77,7 @@ var transforms = {
79
77
  let ${channelVariable};
80
78
  const ${channelGetter} = () =>
81
79
  ${channelVariable} ??= ${SHARED_HOOK_LOOKUP}(
82
- ${JSON.stringify(`orchestrion:${name}:${channelName}`)},
83
- ${JSON.stringify(operator)}
80
+ ${JSON.stringify(`orchestrion:${name}:${channelName}`)}
84
81
  );
85
82
  `;
86
83
  const sharedHookLookupIndex = node.body.findIndex(
@@ -155,28 +152,18 @@ function traceInstanceMethod(state, node, program) {
155
152
  ctor.value.body.body.push(...ctorBody);
156
153
  }
157
154
  function wrap(state, node) {
158
- const { operator, moduleVersion } = state;
159
- const wrapper = operator === "traceCallback" ? wrapCallback(state) : operator === "tracePromise" ? wrapPromise(state) : wrapSync(state);
155
+ const wrapper = wrapInvocation(state);
160
156
  const block = wrapper.body[0].body;
161
157
  const common = parse(
162
158
  node.type === "ArrowFunctionExpression" ? `
163
- const __bt$ctx = {
164
- arguments,
165
- moduleVersion: ${JSON.stringify(moduleVersion)}
166
- };
167
- const __bt$traced = () => {
159
+ const __bt$target = (...__bt$args) => {
168
160
  const __bt$wrapped = () => {};
169
- return __bt$wrapped(...arguments);
161
+ return __bt$wrapped(...__bt$args);
170
162
  };
171
163
  ` : `
172
- const __bt$ctx = {
173
- arguments,
174
- self: this,
175
- moduleVersion: ${JSON.stringify(moduleVersion)}
176
- };
177
- const __bt$traced = () => {
164
+ const __bt$target = function (...__bt$args) {
178
165
  const __bt$wrapped = () => {};
179
- return __bt$wrapped.apply(this, arguments);
166
+ return __bt$wrapped.apply(this, __bt$args);
180
167
  };
181
168
  `
182
169
  ).body;
@@ -218,49 +205,25 @@ function wrapSuper(node) {
218
205
  node.body.body.unshift(parse("const __bt$super = {}").body[0]);
219
206
  }
220
207
  }
221
- function wrapCallback(state) {
222
- const {
223
- channelName,
224
- functionQuery: { callbackIndex = -1 }
225
- } = state;
208
+ function wrapInvocation(state) {
209
+ const { channelName, moduleVersion, operator, functionQuery } = state;
226
210
  const channelGetter = formatChannelGetter(channelName);
211
+ const callbackIndex = functionQuery.callbackIndex ?? -1;
227
212
  return parse(`
228
213
  function wrapper () {
229
214
  const __bt$hook = ${channelGetter}();
230
- if (!__bt$hook?.hasSubscribers) return __bt$traced();
231
- __bt$ctx.self ??= this;
232
- return __bt$hook.traceCallback(
233
- __bt$traced,
234
- ${callbackIndex},
235
- __bt$ctx
215
+ if (!__bt$hook) return __bt$target.apply(this, arguments);
216
+ return __bt$hook.traceInvocation(
217
+ ${JSON.stringify(operator)},
218
+ __bt$target,
219
+ this,
220
+ arguments,
221
+ { moduleVersion: ${JSON.stringify(moduleVersion)} },
222
+ ${callbackIndex}
236
223
  );
237
224
  }
238
225
  `);
239
226
  }
240
- function wrapPromise(state) {
241
- const { channelName } = state;
242
- const channelGetter = formatChannelGetter(channelName);
243
- return parse(`
244
- function wrapper () {
245
- const __bt$hook = ${channelGetter}();
246
- if (!__bt$hook?.hasSubscribers) return __bt$traced();
247
- __bt$ctx.self ??= this;
248
- return __bt$hook.tracePromise(__bt$traced, __bt$ctx);
249
- }
250
- `);
251
- }
252
- function wrapSync(state) {
253
- const { channelName } = state;
254
- const channelGetter = formatChannelGetter(channelName);
255
- return parse(`
256
- function wrapper () {
257
- const __bt$hook = ${channelGetter}();
258
- if (!__bt$hook?.hasSubscribers) return __bt$traced();
259
- __bt$ctx.self ??= this;
260
- return __bt$hook.traceSync(__bt$traced, __bt$ctx);
261
- }
262
- `);
263
- }
264
227
 
265
228
  // src/auto-instrumentations/orchestrion-js/transformer.ts
266
229
  var Transformer = class {
@@ -3,8 +3,10 @@ var GLOBAL_INSTRUMENTATION_HOOKS_KEY = "__braintrust_instrumentation_hooks";
3
3
  var GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION = 1;
4
4
  var GLOBAL_INSTRUMENTATION_HOOKS_REGISTRY_BRAND = "braintrust.global-instrumentation-hooks.registry";
5
5
  var GLOBAL_INSTRUMENTATION_HOOK_BRAND = "braintrust.global-instrumentation-hooks.hook";
6
+ var GLOBAL_INVOCATION_HOOK_BRAND = "braintrust.global-instrumentation-hooks.invocation-hook";
6
7
  var registryBrand = Symbol.for(GLOBAL_INSTRUMENTATION_HOOKS_REGISTRY_BRAND);
7
8
  var hookBrand = Symbol.for(GLOBAL_INSTRUMENTATION_HOOK_BRAND);
9
+ var invocationHookBrand = Symbol.for(GLOBAL_INVOCATION_HOOK_BRAND);
8
10
  var errorReporter;
9
11
  function reportError(error) {
10
12
  try {
@@ -140,12 +142,69 @@ var traceEvents = [
140
142
  "asyncEnd",
141
143
  "error"
142
144
  ];
145
+ function traceInvocation(hook, operator, target, thisArg, args, additional, callbackIndex = -1) {
146
+ const context = {
147
+ ...additional,
148
+ arguments: args,
149
+ self: thisArg
150
+ };
151
+ const invoke = () => hook.invoke(target, thisArg, args, additional);
152
+ if (operator === "traceCallback") {
153
+ return hook.traceCallback(invoke, callbackIndex, context);
154
+ }
155
+ if (operator === "tracePromise") {
156
+ return hook.tracePromise(invoke, context);
157
+ }
158
+ return hook.traceSync(invoke, context);
159
+ }
160
+ var InvocationHook = class {
161
+ interceptors = [];
162
+ get hasInterceptors() {
163
+ return this.interceptors.length > 0;
164
+ }
165
+ intercept(interceptor) {
166
+ if (typeof interceptor !== "function") {
167
+ throw new TypeError("interceptor must be a function");
168
+ }
169
+ this.interceptors = [...this.interceptors, interceptor];
170
+ let active = true;
171
+ return () => {
172
+ if (!active) {
173
+ return;
174
+ }
175
+ active = false;
176
+ const index = this.interceptors.indexOf(interceptor);
177
+ if (index !== -1) {
178
+ this.interceptors = [
179
+ ...this.interceptors.slice(0, index),
180
+ ...this.interceptors.slice(index + 1)
181
+ ];
182
+ }
183
+ };
184
+ }
185
+ invoke(target, thisArg, args, additional) {
186
+ const interceptors = this.interceptors;
187
+ if (interceptors.length === 0) {
188
+ return Reflect.apply(target, thisArg, args);
189
+ }
190
+ let next = target;
191
+ for (let index = interceptors.length - 1; index >= 0; index -= 1) {
192
+ const interceptor = interceptors[index];
193
+ const downstream = next;
194
+ next = function(...nextArgs) {
195
+ return interceptor(downstream, this, nextArgs, additional);
196
+ };
197
+ }
198
+ return Reflect.apply(next, thisArg, args);
199
+ }
200
+ };
143
201
  var TracingHook = class {
144
202
  start;
145
203
  end;
146
204
  asyncStart;
147
205
  asyncEnd;
148
206
  error;
207
+ invocationHook = new InvocationHook();
149
208
  constructor(nameOrChannels) {
150
209
  Object.defineProperty(this, hookBrand, {
151
210
  configurable: false,
@@ -153,6 +212,12 @@ var TracingHook = class {
153
212
  value: GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION,
154
213
  writable: false
155
214
  });
215
+ Object.defineProperty(this, invocationHookBrand, {
216
+ configurable: false,
217
+ enumerable: false,
218
+ value: GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION,
219
+ writable: false
220
+ });
156
221
  if (typeof nameOrChannels === "string") {
157
222
  this.start = new HookChannel(`tracing:${nameOrChannels}:start`);
158
223
  this.end = new HookChannel(`tracing:${nameOrChannels}:end`);
@@ -170,6 +235,26 @@ var TracingHook = class {
170
235
  get hasSubscribers() {
171
236
  return this.start.hasSubscribers || this.end.hasSubscribers || this.asyncStart.hasSubscribers || this.asyncEnd.hasSubscribers || this.error.hasSubscribers;
172
237
  }
238
+ get hasInterceptors() {
239
+ return this.invocationHook.hasInterceptors;
240
+ }
241
+ intercept(interceptor) {
242
+ return this.invocationHook.intercept(interceptor);
243
+ }
244
+ invoke(target, thisArg, args, additional) {
245
+ return this.invocationHook.invoke(target, thisArg, args, additional);
246
+ }
247
+ traceInvocation(operator, target, thisArg, args, additional, callbackIndex = -1) {
248
+ return traceInvocation(
249
+ this,
250
+ operator,
251
+ target,
252
+ thisArg,
253
+ args,
254
+ additional,
255
+ callbackIndex
256
+ );
257
+ }
173
258
  subscribe(handlers) {
174
259
  for (const eventName of traceEvents) {
175
260
  const handler = handlers[eventName];
@@ -391,6 +476,60 @@ function hasTracingHookShape(value) {
391
476
  return false;
392
477
  }
393
478
  }
479
+ function hasInvocationHookShape(value) {
480
+ if (typeof value !== "object" && typeof value !== "function" || value === null) {
481
+ return false;
482
+ }
483
+ try {
484
+ const hook = value;
485
+ return value[invocationHookBrand] === GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION && typeof hook.hasInterceptors === "boolean" && typeof hook.intercept === "function" && typeof hook.invoke === "function";
486
+ } catch {
487
+ return false;
488
+ }
489
+ }
490
+ function installInvocationHook(value) {
491
+ const hasInvocationHook = hasInvocationHookShape(value);
492
+ const invocationHook = new InvocationHook();
493
+ try {
494
+ if (!hasInvocationHook) {
495
+ Object.defineProperties(value, {
496
+ [invocationHookBrand]: {
497
+ configurable: false,
498
+ enumerable: false,
499
+ value: GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION,
500
+ writable: false
501
+ },
502
+ hasInterceptors: {
503
+ configurable: false,
504
+ enumerable: false,
505
+ get: () => invocationHook.hasInterceptors
506
+ },
507
+ intercept: {
508
+ configurable: false,
509
+ enumerable: false,
510
+ value: invocationHook.intercept.bind(invocationHook),
511
+ writable: false
512
+ },
513
+ invoke: {
514
+ configurable: false,
515
+ enumerable: false,
516
+ value: invocationHook.invoke.bind(invocationHook),
517
+ writable: false
518
+ }
519
+ });
520
+ }
521
+ if (typeof value.traceInvocation !== "function") {
522
+ Object.defineProperty(value, "traceInvocation", {
523
+ configurable: false,
524
+ enumerable: false,
525
+ value: traceInvocation.bind(void 0, value),
526
+ writable: false
527
+ });
528
+ }
529
+ } catch (error) {
530
+ reportError(error);
531
+ }
532
+ }
394
533
  function isCompatibleTracingHook(value) {
395
534
  try {
396
535
  return value[hookBrand] === GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION && hasTracingHookShape(value);
@@ -477,6 +616,7 @@ function newGlobalTracingChannel(nameOrChannels) {
477
616
  return inertTracingHook;
478
617
  }
479
618
  if (isCompatibleTracingHook(existing)) {
619
+ installInvocationHook(existing);
480
620
  return existing;
481
621
  }
482
622
  if (existing !== void 0) {