braintrust 2.2.1-rc.0 → 2.2.1

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.
package/dist/cli.js CHANGED
@@ -31,14 +31,14 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
31
31
  ));
32
32
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
33
33
 
34
- // ../node_modules/.pnpm/@nodelib+fs.stat@2.0.5/node_modules/@nodelib/fs.stat/out/providers/async.js
34
+ // ../node_modules/@nodelib/fs.stat/out/providers/async.js
35
35
  var require_async = __commonJS({
36
- "../node_modules/.pnpm/@nodelib+fs.stat@2.0.5/node_modules/@nodelib/fs.stat/out/providers/async.js"(exports2) {
36
+ "../node_modules/@nodelib/fs.stat/out/providers/async.js"(exports2) {
37
37
  "use strict";
38
38
  Object.defineProperty(exports2, "__esModule", { value: true });
39
39
  exports2.read = void 0;
40
- function read(path9, settings, callback) {
41
- settings.fs.lstat(path9, (lstatError, lstat) => {
40
+ function read(path8, settings, callback) {
41
+ settings.fs.lstat(path8, (lstatError, lstat) => {
42
42
  if (lstatError !== null) {
43
43
  callFailureCallback(callback, lstatError);
44
44
  return;
@@ -47,7 +47,7 @@ var require_async = __commonJS({
47
47
  callSuccessCallback(callback, lstat);
48
48
  return;
49
49
  }
50
- settings.fs.stat(path9, (statError, stat2) => {
50
+ settings.fs.stat(path8, (statError, stat2) => {
51
51
  if (statError !== null) {
52
52
  if (settings.throwErrorOnBrokenSymbolicLink) {
53
53
  callFailureCallback(callback, statError);
@@ -73,19 +73,19 @@ var require_async = __commonJS({
73
73
  }
74
74
  });
75
75
 
76
- // ../node_modules/.pnpm/@nodelib+fs.stat@2.0.5/node_modules/@nodelib/fs.stat/out/providers/sync.js
76
+ // ../node_modules/@nodelib/fs.stat/out/providers/sync.js
77
77
  var require_sync = __commonJS({
78
- "../node_modules/.pnpm/@nodelib+fs.stat@2.0.5/node_modules/@nodelib/fs.stat/out/providers/sync.js"(exports2) {
78
+ "../node_modules/@nodelib/fs.stat/out/providers/sync.js"(exports2) {
79
79
  "use strict";
80
80
  Object.defineProperty(exports2, "__esModule", { value: true });
81
81
  exports2.read = void 0;
82
- function read(path9, settings) {
83
- const lstat = settings.fs.lstatSync(path9);
82
+ function read(path8, settings) {
83
+ const lstat = settings.fs.lstatSync(path8);
84
84
  if (!lstat.isSymbolicLink() || !settings.followSymbolicLink) {
85
85
  return lstat;
86
86
  }
87
87
  try {
88
- const stat2 = settings.fs.statSync(path9);
88
+ const stat2 = settings.fs.statSync(path8);
89
89
  if (settings.markSymbolicLink) {
90
90
  stat2.isSymbolicLink = () => true;
91
91
  }
@@ -101,9 +101,9 @@ var require_sync = __commonJS({
101
101
  }
102
102
  });
103
103
 
104
- // ../node_modules/.pnpm/@nodelib+fs.stat@2.0.5/node_modules/@nodelib/fs.stat/out/adapters/fs.js
104
+ // ../node_modules/@nodelib/fs.stat/out/adapters/fs.js
105
105
  var require_fs = __commonJS({
106
- "../node_modules/.pnpm/@nodelib+fs.stat@2.0.5/node_modules/@nodelib/fs.stat/out/adapters/fs.js"(exports2) {
106
+ "../node_modules/@nodelib/fs.stat/out/adapters/fs.js"(exports2) {
107
107
  "use strict";
108
108
  Object.defineProperty(exports2, "__esModule", { value: true });
109
109
  exports2.createFileSystemAdapter = exports2.FILE_SYSTEM_ADAPTER = void 0;
@@ -124,9 +124,9 @@ var require_fs = __commonJS({
124
124
  }
125
125
  });
126
126
 
127
- // ../node_modules/.pnpm/@nodelib+fs.stat@2.0.5/node_modules/@nodelib/fs.stat/out/settings.js
127
+ // ../node_modules/@nodelib/fs.stat/out/settings.js
128
128
  var require_settings = __commonJS({
129
- "../node_modules/.pnpm/@nodelib+fs.stat@2.0.5/node_modules/@nodelib/fs.stat/out/settings.js"(exports2) {
129
+ "../node_modules/@nodelib/fs.stat/out/settings.js"(exports2) {
130
130
  "use strict";
131
131
  Object.defineProperty(exports2, "__esModule", { value: true });
132
132
  var fs6 = require_fs();
@@ -146,9 +146,9 @@ var require_settings = __commonJS({
146
146
  }
147
147
  });
148
148
 
149
- // ../node_modules/.pnpm/@nodelib+fs.stat@2.0.5/node_modules/@nodelib/fs.stat/out/index.js
149
+ // ../node_modules/@nodelib/fs.stat/out/index.js
150
150
  var require_out = __commonJS({
151
- "../node_modules/.pnpm/@nodelib+fs.stat@2.0.5/node_modules/@nodelib/fs.stat/out/index.js"(exports2) {
151
+ "../node_modules/@nodelib/fs.stat/out/index.js"(exports2) {
152
152
  "use strict";
153
153
  Object.defineProperty(exports2, "__esModule", { value: true });
154
154
  exports2.statSync = exports2.stat = exports2.Settings = void 0;
@@ -156,17 +156,17 @@ var require_out = __commonJS({
156
156
  var sync = require_sync();
157
157
  var settings_1 = require_settings();
158
158
  exports2.Settings = settings_1.default;
159
- function stat2(path9, optionsOrSettingsOrCallback, callback) {
159
+ function stat2(path8, optionsOrSettingsOrCallback, callback) {
160
160
  if (typeof optionsOrSettingsOrCallback === "function") {
161
- async.read(path9, getSettings(), optionsOrSettingsOrCallback);
161
+ async.read(path8, getSettings(), optionsOrSettingsOrCallback);
162
162
  return;
163
163
  }
164
- async.read(path9, getSettings(optionsOrSettingsOrCallback), callback);
164
+ async.read(path8, getSettings(optionsOrSettingsOrCallback), callback);
165
165
  }
166
166
  exports2.stat = stat2;
167
- function statSync2(path9, optionsOrSettings) {
167
+ function statSync2(path8, optionsOrSettings) {
168
168
  const settings = getSettings(optionsOrSettings);
169
- return sync.read(path9, settings);
169
+ return sync.read(path8, settings);
170
170
  }
171
171
  exports2.statSync = statSync2;
172
172
  function getSettings(settingsOrOptions = {}) {
@@ -178,9 +178,9 @@ var require_out = __commonJS({
178
178
  }
179
179
  });
180
180
 
181
- // ../node_modules/.pnpm/queue-microtask@1.2.3/node_modules/queue-microtask/index.js
181
+ // ../node_modules/queue-microtask/index.js
182
182
  var require_queue_microtask = __commonJS({
183
- "../node_modules/.pnpm/queue-microtask@1.2.3/node_modules/queue-microtask/index.js"(exports2, module2) {
183
+ "../node_modules/queue-microtask/index.js"(exports2, module2) {
184
184
  "use strict";
185
185
  var promise;
186
186
  module2.exports = typeof queueMicrotask === "function" ? queueMicrotask.bind(typeof window !== "undefined" ? window : global) : (cb) => (promise || (promise = Promise.resolve())).then(cb).catch((err) => setTimeout(() => {
@@ -189,9 +189,9 @@ var require_queue_microtask = __commonJS({
189
189
  }
190
190
  });
191
191
 
192
- // ../node_modules/.pnpm/run-parallel@1.2.0/node_modules/run-parallel/index.js
192
+ // ../node_modules/run-parallel/index.js
193
193
  var require_run_parallel = __commonJS({
194
- "../node_modules/.pnpm/run-parallel@1.2.0/node_modules/run-parallel/index.js"(exports2, module2) {
194
+ "../node_modules/run-parallel/index.js"(exports2, module2) {
195
195
  "use strict";
196
196
  module2.exports = runParallel;
197
197
  var queueMicrotask2 = require_queue_microtask();
@@ -240,9 +240,9 @@ var require_run_parallel = __commonJS({
240
240
  }
241
241
  });
242
242
 
243
- // ../node_modules/.pnpm/@nodelib+fs.scandir@2.1.5/node_modules/@nodelib/fs.scandir/out/constants.js
243
+ // ../node_modules/@nodelib/fs.scandir/out/constants.js
244
244
  var require_constants = __commonJS({
245
- "../node_modules/.pnpm/@nodelib+fs.scandir@2.1.5/node_modules/@nodelib/fs.scandir/out/constants.js"(exports2) {
245
+ "../node_modules/@nodelib/fs.scandir/out/constants.js"(exports2) {
246
246
  "use strict";
247
247
  Object.defineProperty(exports2, "__esModule", { value: true });
248
248
  exports2.IS_SUPPORT_READDIR_WITH_FILE_TYPES = void 0;
@@ -260,9 +260,9 @@ var require_constants = __commonJS({
260
260
  }
261
261
  });
262
262
 
263
- // ../node_modules/.pnpm/@nodelib+fs.scandir@2.1.5/node_modules/@nodelib/fs.scandir/out/utils/fs.js
263
+ // ../node_modules/@nodelib/fs.scandir/out/utils/fs.js
264
264
  var require_fs2 = __commonJS({
265
- "../node_modules/.pnpm/@nodelib+fs.scandir@2.1.5/node_modules/@nodelib/fs.scandir/out/utils/fs.js"(exports2) {
265
+ "../node_modules/@nodelib/fs.scandir/out/utils/fs.js"(exports2) {
266
266
  "use strict";
267
267
  Object.defineProperty(exports2, "__esModule", { value: true });
268
268
  exports2.createDirentFromStats = void 0;
@@ -285,9 +285,9 @@ var require_fs2 = __commonJS({
285
285
  }
286
286
  });
287
287
 
288
- // ../node_modules/.pnpm/@nodelib+fs.scandir@2.1.5/node_modules/@nodelib/fs.scandir/out/utils/index.js
288
+ // ../node_modules/@nodelib/fs.scandir/out/utils/index.js
289
289
  var require_utils = __commonJS({
290
- "../node_modules/.pnpm/@nodelib+fs.scandir@2.1.5/node_modules/@nodelib/fs.scandir/out/utils/index.js"(exports2) {
290
+ "../node_modules/@nodelib/fs.scandir/out/utils/index.js"(exports2) {
291
291
  "use strict";
292
292
  Object.defineProperty(exports2, "__esModule", { value: true });
293
293
  exports2.fs = void 0;
@@ -296,9 +296,9 @@ var require_utils = __commonJS({
296
296
  }
297
297
  });
298
298
 
299
- // ../node_modules/.pnpm/@nodelib+fs.scandir@2.1.5/node_modules/@nodelib/fs.scandir/out/providers/common.js
299
+ // ../node_modules/@nodelib/fs.scandir/out/providers/common.js
300
300
  var require_common = __commonJS({
301
- "../node_modules/.pnpm/@nodelib+fs.scandir@2.1.5/node_modules/@nodelib/fs.scandir/out/providers/common.js"(exports2) {
301
+ "../node_modules/@nodelib/fs.scandir/out/providers/common.js"(exports2) {
302
302
  "use strict";
303
303
  Object.defineProperty(exports2, "__esModule", { value: true });
304
304
  exports2.joinPathSegments = void 0;
@@ -312,9 +312,9 @@ var require_common = __commonJS({
312
312
  }
313
313
  });
314
314
 
315
- // ../node_modules/.pnpm/@nodelib+fs.scandir@2.1.5/node_modules/@nodelib/fs.scandir/out/providers/async.js
315
+ // ../node_modules/@nodelib/fs.scandir/out/providers/async.js
316
316
  var require_async2 = __commonJS({
317
- "../node_modules/.pnpm/@nodelib+fs.scandir@2.1.5/node_modules/@nodelib/fs.scandir/out/providers/async.js"(exports2) {
317
+ "../node_modules/@nodelib/fs.scandir/out/providers/async.js"(exports2) {
318
318
  "use strict";
319
319
  Object.defineProperty(exports2, "__esModule", { value: true });
320
320
  exports2.readdir = exports2.readdirWithFileTypes = exports2.read = void 0;
@@ -384,16 +384,16 @@ var require_async2 = __commonJS({
384
384
  return;
385
385
  }
386
386
  const tasks = names.map((name) => {
387
- const path9 = common.joinPathSegments(directory, name, settings.pathSegmentSeparator);
387
+ const path8 = common.joinPathSegments(directory, name, settings.pathSegmentSeparator);
388
388
  return (done) => {
389
- fsStat.stat(path9, settings.fsStatSettings, (error2, stats) => {
389
+ fsStat.stat(path8, settings.fsStatSettings, (error2, stats) => {
390
390
  if (error2 !== null) {
391
391
  done(error2);
392
392
  return;
393
393
  }
394
394
  const entry = {
395
395
  name,
396
- path: path9,
396
+ path: path8,
397
397
  dirent: utils.fs.createDirentFromStats(name, stats)
398
398
  };
399
399
  if (settings.stats) {
@@ -422,9 +422,9 @@ var require_async2 = __commonJS({
422
422
  }
423
423
  });
424
424
 
425
- // ../node_modules/.pnpm/@nodelib+fs.scandir@2.1.5/node_modules/@nodelib/fs.scandir/out/providers/sync.js
425
+ // ../node_modules/@nodelib/fs.scandir/out/providers/sync.js
426
426
  var require_sync2 = __commonJS({
427
- "../node_modules/.pnpm/@nodelib+fs.scandir@2.1.5/node_modules/@nodelib/fs.scandir/out/providers/sync.js"(exports2) {
427
+ "../node_modules/@nodelib/fs.scandir/out/providers/sync.js"(exports2) {
428
428
  "use strict";
429
429
  Object.defineProperty(exports2, "__esModule", { value: true });
430
430
  exports2.readdir = exports2.readdirWithFileTypes = exports2.read = void 0;
@@ -481,9 +481,9 @@ var require_sync2 = __commonJS({
481
481
  }
482
482
  });
483
483
 
484
- // ../node_modules/.pnpm/@nodelib+fs.scandir@2.1.5/node_modules/@nodelib/fs.scandir/out/adapters/fs.js
484
+ // ../node_modules/@nodelib/fs.scandir/out/adapters/fs.js
485
485
  var require_fs3 = __commonJS({
486
- "../node_modules/.pnpm/@nodelib+fs.scandir@2.1.5/node_modules/@nodelib/fs.scandir/out/adapters/fs.js"(exports2) {
486
+ "../node_modules/@nodelib/fs.scandir/out/adapters/fs.js"(exports2) {
487
487
  "use strict";
488
488
  Object.defineProperty(exports2, "__esModule", { value: true });
489
489
  exports2.createFileSystemAdapter = exports2.FILE_SYSTEM_ADAPTER = void 0;
@@ -506,12 +506,12 @@ var require_fs3 = __commonJS({
506
506
  }
507
507
  });
508
508
 
509
- // ../node_modules/.pnpm/@nodelib+fs.scandir@2.1.5/node_modules/@nodelib/fs.scandir/out/settings.js
509
+ // ../node_modules/@nodelib/fs.scandir/out/settings.js
510
510
  var require_settings2 = __commonJS({
511
- "../node_modules/.pnpm/@nodelib+fs.scandir@2.1.5/node_modules/@nodelib/fs.scandir/out/settings.js"(exports2) {
511
+ "../node_modules/@nodelib/fs.scandir/out/settings.js"(exports2) {
512
512
  "use strict";
513
513
  Object.defineProperty(exports2, "__esModule", { value: true });
514
- var path9 = require("path");
514
+ var path8 = require("path");
515
515
  var fsStat = require_out();
516
516
  var fs6 = require_fs3();
517
517
  var Settings = class {
@@ -519,7 +519,7 @@ var require_settings2 = __commonJS({
519
519
  this._options = _options;
520
520
  this.followSymbolicLinks = this._getValue(this._options.followSymbolicLinks, false);
521
521
  this.fs = fs6.createFileSystemAdapter(this._options.fs);
522
- this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, path9.sep);
522
+ this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, path8.sep);
523
523
  this.stats = this._getValue(this._options.stats, false);
524
524
  this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, true);
525
525
  this.fsStatSettings = new fsStat.Settings({
@@ -536,9 +536,9 @@ var require_settings2 = __commonJS({
536
536
  }
537
537
  });
538
538
 
539
- // ../node_modules/.pnpm/@nodelib+fs.scandir@2.1.5/node_modules/@nodelib/fs.scandir/out/index.js
539
+ // ../node_modules/@nodelib/fs.scandir/out/index.js
540
540
  var require_out2 = __commonJS({
541
- "../node_modules/.pnpm/@nodelib+fs.scandir@2.1.5/node_modules/@nodelib/fs.scandir/out/index.js"(exports2) {
541
+ "../node_modules/@nodelib/fs.scandir/out/index.js"(exports2) {
542
542
  "use strict";
543
543
  Object.defineProperty(exports2, "__esModule", { value: true });
544
544
  exports2.Settings = exports2.scandirSync = exports2.scandir = void 0;
@@ -546,17 +546,17 @@ var require_out2 = __commonJS({
546
546
  var sync = require_sync2();
547
547
  var settings_1 = require_settings2();
548
548
  exports2.Settings = settings_1.default;
549
- function scandir(path9, optionsOrSettingsOrCallback, callback) {
549
+ function scandir(path8, optionsOrSettingsOrCallback, callback) {
550
550
  if (typeof optionsOrSettingsOrCallback === "function") {
551
- async.read(path9, getSettings(), optionsOrSettingsOrCallback);
551
+ async.read(path8, getSettings(), optionsOrSettingsOrCallback);
552
552
  return;
553
553
  }
554
- async.read(path9, getSettings(optionsOrSettingsOrCallback), callback);
554
+ async.read(path8, getSettings(optionsOrSettingsOrCallback), callback);
555
555
  }
556
556
  exports2.scandir = scandir;
557
- function scandirSync(path9, optionsOrSettings) {
557
+ function scandirSync(path8, optionsOrSettings) {
558
558
  const settings = getSettings(optionsOrSettings);
559
- return sync.read(path9, settings);
559
+ return sync.read(path8, settings);
560
560
  }
561
561
  exports2.scandirSync = scandirSync;
562
562
  function getSettings(settingsOrOptions = {}) {
@@ -568,9 +568,9 @@ var require_out2 = __commonJS({
568
568
  }
569
569
  });
570
570
 
571
- // ../node_modules/.pnpm/reusify@1.0.4/node_modules/reusify/reusify.js
571
+ // ../node_modules/reusify/reusify.js
572
572
  var require_reusify = __commonJS({
573
- "../node_modules/.pnpm/reusify@1.0.4/node_modules/reusify/reusify.js"(exports2, module2) {
573
+ "../node_modules/reusify/reusify.js"(exports2, module2) {
574
574
  "use strict";
575
575
  function reusify(Constructor) {
576
576
  var head = new Constructor();
@@ -599,32 +599,45 @@ var require_reusify = __commonJS({
599
599
  }
600
600
  });
601
601
 
602
- // ../node_modules/.pnpm/fastq@1.16.0/node_modules/fastq/queue.js
602
+ // ../node_modules/fastq/queue.js
603
603
  var require_queue = __commonJS({
604
- "../node_modules/.pnpm/fastq@1.16.0/node_modules/fastq/queue.js"(exports2, module2) {
604
+ "../node_modules/fastq/queue.js"(exports2, module2) {
605
605
  "use strict";
606
606
  var reusify = require_reusify();
607
- function fastqueue(context2, worker, concurrency) {
607
+ function fastqueue(context2, worker, _concurrency) {
608
608
  if (typeof context2 === "function") {
609
- concurrency = worker;
609
+ _concurrency = worker;
610
610
  worker = context2;
611
611
  context2 = null;
612
612
  }
613
- if (concurrency < 1) {
614
- throw new Error("fastqueue concurrency must be greater than 1");
613
+ if (!(_concurrency >= 1)) {
614
+ throw new Error("fastqueue concurrency must be equal to or greater than 1");
615
615
  }
616
616
  var cache = reusify(Task);
617
617
  var queueHead = null;
618
618
  var queueTail = null;
619
619
  var _running = 0;
620
- var errorHandler = null;
620
+ var errorHandler2 = null;
621
621
  var self = {
622
622
  push,
623
623
  drain: noop,
624
624
  saturated: noop,
625
625
  pause,
626
626
  paused: false,
627
- concurrency,
627
+ get concurrency() {
628
+ return _concurrency;
629
+ },
630
+ set concurrency(value) {
631
+ if (!(value >= 1)) {
632
+ throw new Error("fastqueue concurrency must be equal to or greater than 1");
633
+ }
634
+ _concurrency = value;
635
+ if (self.paused) return;
636
+ for (; queueHead && _running < _concurrency; ) {
637
+ _running++;
638
+ release();
639
+ }
640
+ },
628
641
  running,
629
642
  resume,
630
643
  idle,
@@ -634,7 +647,8 @@ var require_queue = __commonJS({
634
647
  empty: noop,
635
648
  kill,
636
649
  killAndDrain,
637
- error: error2
650
+ error: error2,
651
+ abort
638
652
  };
639
653
  return self;
640
654
  function running() {
@@ -664,7 +678,12 @@ var require_queue = __commonJS({
664
678
  function resume() {
665
679
  if (!self.paused) return;
666
680
  self.paused = false;
667
- for (var i = 0; i < self.concurrency; i++) {
681
+ if (queueHead === null) {
682
+ _running++;
683
+ release();
684
+ return;
685
+ }
686
+ for (; queueHead && _running < _concurrency; ) {
668
687
  _running++;
669
688
  release();
670
689
  }
@@ -678,8 +697,8 @@ var require_queue = __commonJS({
678
697
  current.release = release;
679
698
  current.value = value;
680
699
  current.callback = done || noop;
681
- current.errorHandler = errorHandler;
682
- if (_running === self.concurrency || self.paused) {
700
+ current.errorHandler = errorHandler2;
701
+ if (_running >= _concurrency || self.paused) {
683
702
  if (queueTail) {
684
703
  queueTail.next = current;
685
704
  queueTail = current;
@@ -699,8 +718,8 @@ var require_queue = __commonJS({
699
718
  current.release = release;
700
719
  current.value = value;
701
720
  current.callback = done || noop;
702
- current.errorHandler = errorHandler;
703
- if (_running === self.concurrency || self.paused) {
721
+ current.errorHandler = errorHandler2;
722
+ if (_running >= _concurrency || self.paused) {
704
723
  if (queueHead) {
705
724
  current.next = queueHead;
706
725
  queueHead = current;
@@ -719,7 +738,7 @@ var require_queue = __commonJS({
719
738
  cache.release(holder);
720
739
  }
721
740
  var next = queueHead;
722
- if (next) {
741
+ if (next && _running <= _concurrency) {
723
742
  if (!self.paused) {
724
743
  if (queueTail === queueHead) {
725
744
  queueTail = null;
@@ -748,8 +767,30 @@ var require_queue = __commonJS({
748
767
  self.drain();
749
768
  self.drain = noop;
750
769
  }
770
+ function abort() {
771
+ var current = queueHead;
772
+ queueHead = null;
773
+ queueTail = null;
774
+ while (current) {
775
+ var next = current.next;
776
+ var callback = current.callback;
777
+ var errorHandler3 = current.errorHandler;
778
+ var val = current.value;
779
+ var context3 = current.context;
780
+ current.value = null;
781
+ current.callback = noop;
782
+ current.errorHandler = null;
783
+ if (errorHandler3) {
784
+ errorHandler3(new Error("abort"), val);
785
+ }
786
+ callback.call(context3, new Error("abort"));
787
+ current.release(current);
788
+ current = next;
789
+ }
790
+ self.drain = noop;
791
+ }
751
792
  function error2(handler) {
752
- errorHandler = handler;
793
+ errorHandler2 = handler;
753
794
  }
754
795
  }
755
796
  function noop() {
@@ -764,20 +805,20 @@ var require_queue = __commonJS({
764
805
  var self = this;
765
806
  this.worked = function worked(err, result) {
766
807
  var callback = self.callback;
767
- var errorHandler = self.errorHandler;
808
+ var errorHandler2 = self.errorHandler;
768
809
  var val = self.value;
769
810
  self.value = null;
770
811
  self.callback = noop;
771
812
  if (self.errorHandler) {
772
- errorHandler(err, val);
813
+ errorHandler2(err, val);
773
814
  }
774
815
  callback.call(self.context, err, result);
775
816
  self.release(self);
776
817
  };
777
818
  }
778
- function queueAsPromised(context2, worker, concurrency) {
819
+ function queueAsPromised(context2, worker, _concurrency) {
779
820
  if (typeof context2 === "function") {
780
- concurrency = worker;
821
+ _concurrency = worker;
781
822
  worker = context2;
782
823
  context2 = null;
783
824
  }
@@ -786,7 +827,7 @@ var require_queue = __commonJS({
786
827
  cb(null, res);
787
828
  }, cb);
788
829
  }
789
- var queue2 = fastqueue(context2, asyncWrapper, concurrency);
830
+ var queue2 = fastqueue(context2, asyncWrapper, _concurrency);
790
831
  var pushCb = queue2.push;
791
832
  var unshiftCb = queue2.unshift;
792
833
  queue2.push = push;
@@ -820,17 +861,19 @@ var require_queue = __commonJS({
820
861
  return p;
821
862
  }
822
863
  function drained() {
823
- if (queue2.idle()) {
824
- return new Promise(function(resolve2) {
825
- resolve2();
826
- });
827
- }
828
- var previousDrain = queue2.drain;
829
864
  var p = new Promise(function(resolve2) {
830
- queue2.drain = function() {
831
- previousDrain();
832
- resolve2();
833
- };
865
+ process.nextTick(function() {
866
+ if (queue2.idle()) {
867
+ resolve2();
868
+ } else {
869
+ var previousDrain = queue2.drain;
870
+ queue2.drain = function() {
871
+ if (typeof previousDrain === "function") previousDrain();
872
+ resolve2();
873
+ queue2.drain = previousDrain;
874
+ };
875
+ }
876
+ });
834
877
  });
835
878
  return p;
836
879
  }
@@ -840,9 +883,9 @@ var require_queue = __commonJS({
840
883
  }
841
884
  });
842
885
 
843
- // ../node_modules/.pnpm/@nodelib+fs.walk@1.2.8/node_modules/@nodelib/fs.walk/out/readers/common.js
886
+ // ../node_modules/@nodelib/fs.walk/out/readers/common.js
844
887
  var require_common2 = __commonJS({
845
- "../node_modules/.pnpm/@nodelib+fs.walk@1.2.8/node_modules/@nodelib/fs.walk/out/readers/common.js"(exports2) {
888
+ "../node_modules/@nodelib/fs.walk/out/readers/common.js"(exports2) {
846
889
  "use strict";
847
890
  Object.defineProperty(exports2, "__esModule", { value: true });
848
891
  exports2.joinPathSegments = exports2.replacePathSegmentSeparator = exports2.isAppliedFilter = exports2.isFatalError = void 0;
@@ -874,9 +917,9 @@ var require_common2 = __commonJS({
874
917
  }
875
918
  });
876
919
 
877
- // ../node_modules/.pnpm/@nodelib+fs.walk@1.2.8/node_modules/@nodelib/fs.walk/out/readers/reader.js
920
+ // ../node_modules/@nodelib/fs.walk/out/readers/reader.js
878
921
  var require_reader = __commonJS({
879
- "../node_modules/.pnpm/@nodelib+fs.walk@1.2.8/node_modules/@nodelib/fs.walk/out/readers/reader.js"(exports2) {
922
+ "../node_modules/@nodelib/fs.walk/out/readers/reader.js"(exports2) {
880
923
  "use strict";
881
924
  Object.defineProperty(exports2, "__esModule", { value: true });
882
925
  var common = require_common2();
@@ -891,9 +934,9 @@ var require_reader = __commonJS({
891
934
  }
892
935
  });
893
936
 
894
- // ../node_modules/.pnpm/@nodelib+fs.walk@1.2.8/node_modules/@nodelib/fs.walk/out/readers/async.js
937
+ // ../node_modules/@nodelib/fs.walk/out/readers/async.js
895
938
  var require_async3 = __commonJS({
896
- "../node_modules/.pnpm/@nodelib+fs.walk@1.2.8/node_modules/@nodelib/fs.walk/out/readers/async.js"(exports2) {
939
+ "../node_modules/@nodelib/fs.walk/out/readers/async.js"(exports2) {
897
940
  "use strict";
898
941
  Object.defineProperty(exports2, "__esModule", { value: true });
899
942
  var events_1 = require("events");
@@ -994,9 +1037,9 @@ var require_async3 = __commonJS({
994
1037
  }
995
1038
  });
996
1039
 
997
- // ../node_modules/.pnpm/@nodelib+fs.walk@1.2.8/node_modules/@nodelib/fs.walk/out/providers/async.js
1040
+ // ../node_modules/@nodelib/fs.walk/out/providers/async.js
998
1041
  var require_async4 = __commonJS({
999
- "../node_modules/.pnpm/@nodelib+fs.walk@1.2.8/node_modules/@nodelib/fs.walk/out/providers/async.js"(exports2) {
1042
+ "../node_modules/@nodelib/fs.walk/out/providers/async.js"(exports2) {
1000
1043
  "use strict";
1001
1044
  Object.defineProperty(exports2, "__esModule", { value: true });
1002
1045
  var async_1 = require_async3();
@@ -1030,9 +1073,9 @@ var require_async4 = __commonJS({
1030
1073
  }
1031
1074
  });
1032
1075
 
1033
- // ../node_modules/.pnpm/@nodelib+fs.walk@1.2.8/node_modules/@nodelib/fs.walk/out/providers/stream.js
1076
+ // ../node_modules/@nodelib/fs.walk/out/providers/stream.js
1034
1077
  var require_stream = __commonJS({
1035
- "../node_modules/.pnpm/@nodelib+fs.walk@1.2.8/node_modules/@nodelib/fs.walk/out/providers/stream.js"(exports2) {
1078
+ "../node_modules/@nodelib/fs.walk/out/providers/stream.js"(exports2) {
1036
1079
  "use strict";
1037
1080
  Object.defineProperty(exports2, "__esModule", { value: true });
1038
1081
  var stream_1 = require("stream");
@@ -1071,9 +1114,9 @@ var require_stream = __commonJS({
1071
1114
  }
1072
1115
  });
1073
1116
 
1074
- // ../node_modules/.pnpm/@nodelib+fs.walk@1.2.8/node_modules/@nodelib/fs.walk/out/readers/sync.js
1117
+ // ../node_modules/@nodelib/fs.walk/out/readers/sync.js
1075
1118
  var require_sync3 = __commonJS({
1076
- "../node_modules/.pnpm/@nodelib+fs.walk@1.2.8/node_modules/@nodelib/fs.walk/out/readers/sync.js"(exports2) {
1119
+ "../node_modules/@nodelib/fs.walk/out/readers/sync.js"(exports2) {
1077
1120
  "use strict";
1078
1121
  Object.defineProperty(exports2, "__esModule", { value: true });
1079
1122
  var fsScandir = require_out2();
@@ -1135,9 +1178,9 @@ var require_sync3 = __commonJS({
1135
1178
  }
1136
1179
  });
1137
1180
 
1138
- // ../node_modules/.pnpm/@nodelib+fs.walk@1.2.8/node_modules/@nodelib/fs.walk/out/providers/sync.js
1181
+ // ../node_modules/@nodelib/fs.walk/out/providers/sync.js
1139
1182
  var require_sync4 = __commonJS({
1140
- "../node_modules/.pnpm/@nodelib+fs.walk@1.2.8/node_modules/@nodelib/fs.walk/out/providers/sync.js"(exports2) {
1183
+ "../node_modules/@nodelib/fs.walk/out/providers/sync.js"(exports2) {
1141
1184
  "use strict";
1142
1185
  Object.defineProperty(exports2, "__esModule", { value: true });
1143
1186
  var sync_1 = require_sync3();
@@ -1155,12 +1198,12 @@ var require_sync4 = __commonJS({
1155
1198
  }
1156
1199
  });
1157
1200
 
1158
- // ../node_modules/.pnpm/@nodelib+fs.walk@1.2.8/node_modules/@nodelib/fs.walk/out/settings.js
1201
+ // ../node_modules/@nodelib/fs.walk/out/settings.js
1159
1202
  var require_settings3 = __commonJS({
1160
- "../node_modules/.pnpm/@nodelib+fs.walk@1.2.8/node_modules/@nodelib/fs.walk/out/settings.js"(exports2) {
1203
+ "../node_modules/@nodelib/fs.walk/out/settings.js"(exports2) {
1161
1204
  "use strict";
1162
1205
  Object.defineProperty(exports2, "__esModule", { value: true });
1163
- var path9 = require("path");
1206
+ var path8 = require("path");
1164
1207
  var fsScandir = require_out2();
1165
1208
  var Settings = class {
1166
1209
  constructor(_options = {}) {
@@ -1170,7 +1213,7 @@ var require_settings3 = __commonJS({
1170
1213
  this.deepFilter = this._getValue(this._options.deepFilter, null);
1171
1214
  this.entryFilter = this._getValue(this._options.entryFilter, null);
1172
1215
  this.errorFilter = this._getValue(this._options.errorFilter, null);
1173
- this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, path9.sep);
1216
+ this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, path8.sep);
1174
1217
  this.fsScandirSettings = new fsScandir.Settings({
1175
1218
  followSymbolicLinks: this._options.followSymbolicLinks,
1176
1219
  fs: this._options.fs,
@@ -1187,9 +1230,9 @@ var require_settings3 = __commonJS({
1187
1230
  }
1188
1231
  });
1189
1232
 
1190
- // ../node_modules/.pnpm/@nodelib+fs.walk@1.2.8/node_modules/@nodelib/fs.walk/out/index.js
1233
+ // ../node_modules/@nodelib/fs.walk/out/index.js
1191
1234
  var require_out3 = __commonJS({
1192
- "../node_modules/.pnpm/@nodelib+fs.walk@1.2.8/node_modules/@nodelib/fs.walk/out/index.js"(exports2) {
1235
+ "../node_modules/@nodelib/fs.walk/out/index.js"(exports2) {
1193
1236
  "use strict";
1194
1237
  Object.defineProperty(exports2, "__esModule", { value: true });
1195
1238
  exports2.Settings = exports2.walkStream = exports2.walkSync = exports2.walk = void 0;
@@ -1206,12 +1249,12 @@ var require_out3 = __commonJS({
1206
1249
  new async_1.default(directory, getSettings(optionsOrSettingsOrCallback)).read(callback);
1207
1250
  }
1208
1251
  exports2.walk = walk2;
1209
- function walkSync2(directory, optionsOrSettings) {
1252
+ function walkSync(directory, optionsOrSettings) {
1210
1253
  const settings = getSettings(optionsOrSettings);
1211
1254
  const provider = new sync_1.default(directory, settings);
1212
1255
  return provider.read();
1213
1256
  }
1214
- exports2.walkSync = walkSync2;
1257
+ exports2.walkSync = walkSync;
1215
1258
  function walkStream(directory, optionsOrSettings) {
1216
1259
  const settings = getSettings(optionsOrSettings);
1217
1260
  const provider = new stream_1.default(directory, settings);
@@ -1232,7 +1275,7 @@ var require_package = __commonJS({
1232
1275
  "package.json"(exports2, module2) {
1233
1276
  module2.exports = {
1234
1277
  name: "braintrust",
1235
- version: "2.2.1-rc.0",
1278
+ version: "2.2.1",
1236
1279
  description: "SDK for integrating Braintrust",
1237
1280
  repository: {
1238
1281
  type: "git",
@@ -1392,15 +1435,14 @@ module.exports = __toCommonJS(cli_exports);
1392
1435
  var esbuild = __toESM(require("esbuild"));
1393
1436
  var dotenv2 = __toESM(require("dotenv"));
1394
1437
  var import_fs2 = __toESM(require("fs"));
1395
- var import_os2 = __toESM(require("os"));
1396
- var import_path6 = __toESM(require("path"));
1397
- var import_util15 = __toESM(require("util"));
1438
+ var import_os = __toESM(require("os"));
1439
+ var import_path5 = __toESM(require("path"));
1440
+ var import_util16 = __toESM(require("util"));
1398
1441
  var fsWalk = __toESM(require_out3());
1399
1442
  var import_minimatch = require("minimatch");
1400
1443
  var import_argparse = require("argparse");
1401
1444
  var import_uuid3 = require("uuid");
1402
1445
  var import_pluralize4 = __toESM(require("pluralize"));
1403
- var import_child_process = require("child_process");
1404
1446
 
1405
1447
  // src/logger.ts
1406
1448
  var import_uuid2 = require("uuid");
@@ -2097,6 +2139,10 @@ var SpanComponentsV3 = class _SpanComponentsV3 {
2097
2139
  }
2098
2140
  };
2099
2141
 
2142
+ // util/http_headers.ts
2143
+ var BT_FOUND_EXISTING_HEADER = "x-bt-found-existing";
2144
+ var BT_CURSOR_HEADER = "x-bt-cursor";
2145
+
2100
2146
  // util/type_util.ts
2101
2147
  function isObject(value) {
2102
2148
  return value instanceof Object && !(value instanceof Array);
@@ -2131,14 +2177,14 @@ function mergeDictsWithPaths({
2131
2177
  function mergeDictsWithPathsHelper({
2132
2178
  mergeInto,
2133
2179
  mergeFrom,
2134
- path: path9,
2180
+ path: path8,
2135
2181
  mergePaths
2136
2182
  }) {
2137
2183
  Object.entries(mergeFrom).forEach(([k, mergeFromV]) => {
2138
- const fullPath = path9.concat([k]);
2184
+ const fullPath = path8.concat([k]);
2139
2185
  const fullPathSerialized = JSON.stringify(fullPath);
2140
2186
  const mergeIntoV = recordFind(mergeInto, k);
2141
- const isSetUnionField = path9.length === 0 && SET_UNION_FIELDS.has(k) && !mergePaths.has(fullPathSerialized);
2187
+ const isSetUnionField = path8.length === 0 && SET_UNION_FIELDS.has(k) && !mergePaths.has(fullPathSerialized);
2142
2188
  if (isSetUnionField && isArray(mergeIntoV) && isArray(mergeFromV)) {
2143
2189
  const seen = /* @__PURE__ */ new Set();
2144
2190
  const combined = [];
@@ -2171,9 +2217,9 @@ function mergeDicts(mergeInto, mergeFrom) {
2171
2217
  function recordFind(m, k) {
2172
2218
  return m[k];
2173
2219
  }
2174
- function getObjValueByPath(row, path9) {
2220
+ function getObjValueByPath(row, path8) {
2175
2221
  let curr = row;
2176
- for (const p of path9) {
2222
+ for (const p of path8) {
2177
2223
  if (!isObjectOrArray(curr)) {
2178
2224
  return null;
2179
2225
  }
@@ -2623,6 +2669,22 @@ var SpanComponentsV4 = class _SpanComponentsV4 {
2623
2669
  return new _SpanComponentsV4(spanComponentsV4Schema.parse(jsonObj));
2624
2670
  }
2625
2671
  };
2672
+ function parseParent(parent) {
2673
+ return typeof parent === "string" ? parent : parent ? new SpanComponentsV4({
2674
+ object_type: parent.object_type === "experiment" ? 1 /* EXPERIMENT */ : parent.object_type === "playground_logs" ? 3 /* PLAYGROUND_LOGS */ : 2 /* PROJECT_LOGS */,
2675
+ object_id: parent.object_id,
2676
+ ...parent.row_ids ? {
2677
+ row_id: parent.row_ids.id,
2678
+ span_id: parent.row_ids.span_id,
2679
+ root_span_id: parent.row_ids.root_span_id
2680
+ } : {
2681
+ row_id: void 0,
2682
+ span_id: void 0,
2683
+ root_span_id: void 0
2684
+ },
2685
+ propagated_event: parent.propagated_event
2686
+ }).toStr() : void 0;
2687
+ }
2626
2688
  function makeScorerPropagatedEvent(parent) {
2627
2689
  const parentPropagatedEvent = parent ? SpanComponentsV4.fromStr(parent).data.propagated_event ?? {} : {};
2628
2690
  return mergeDicts(
@@ -3307,7 +3369,8 @@ var SpanType = import_v36.z.union([
3307
3369
  "automation",
3308
3370
  "facet",
3309
3371
  "preprocessor",
3310
- "classifier"
3372
+ "classifier",
3373
+ "review"
3311
3374
  ]),
3312
3375
  import_v36.z.null()
3313
3376
  ]);
@@ -5030,10 +5093,10 @@ var DiskCache = class {
5030
5093
  return;
5031
5094
  }
5032
5095
  const stats = await Promise.all(
5033
- paths.map(async (path9) => {
5034
- const stat2 = await isomorph_default.stat(path9);
5096
+ paths.map(async (path8) => {
5097
+ const stat2 = await isomorph_default.stat(path8);
5035
5098
  return {
5036
- path: path9,
5099
+ path: path8,
5037
5100
  mtime: stat2.mtime.getTime()
5038
5101
  };
5039
5102
  })
@@ -6016,9 +6079,9 @@ var HTTPConnection = class _HTTPConnection {
6016
6079
  this.headers["Authorization"] = `Bearer ${this.token}`;
6017
6080
  }
6018
6081
  }
6019
- async get(path9, params = void 0, config3) {
6082
+ async get(path8, params = void 0, config3) {
6020
6083
  const { headers, ...rest } = config3 || {};
6021
- const url = new URL(_urljoin(this.base_url, path9));
6084
+ const url = new URL(_urljoin(this.base_url, path8));
6022
6085
  url.search = new URLSearchParams(
6023
6086
  params ? Object.entries(params).filter(([_, v]) => v !== void 0).flatMap(
6024
6087
  ([k, v]) => v !== void 0 ? typeof v === "string" ? [[k, v]] : v.map((x) => [k, x]) : []
@@ -6039,13 +6102,13 @@ var HTTPConnection = class _HTTPConnection {
6039
6102
  })
6040
6103
  );
6041
6104
  }
6042
- async post(path9, params, config3) {
6105
+ async post(path8, params, config3) {
6043
6106
  const { headers, ...rest } = config3 || {};
6044
6107
  const this_fetch = this.fetch;
6045
6108
  const this_base_url = this.base_url;
6046
6109
  const this_headers = this.headers;
6047
6110
  return await checkResponse(
6048
- await this_fetch(_urljoin(this_base_url, path9), {
6111
+ await this_fetch(_urljoin(this_base_url, path8), {
6049
6112
  method: "POST",
6050
6113
  headers: {
6051
6114
  Accept: "application/json",
@@ -7588,6 +7651,76 @@ function init(projectOrOptions, optionalOptions) {
7588
7651
  }
7589
7652
  return ret;
7590
7653
  }
7654
+ function initDataset(projectOrOptions, optionalOptions) {
7655
+ const options = (() => {
7656
+ if (typeof projectOrOptions === "string") {
7657
+ return { ...optionalOptions, project: projectOrOptions };
7658
+ } else {
7659
+ if (optionalOptions !== void 0) {
7660
+ throw new Error(
7661
+ "Cannot specify options struct as both parameters. Must call either initDataset(project, options) or initDataset(options)."
7662
+ );
7663
+ }
7664
+ return projectOrOptions;
7665
+ }
7666
+ })();
7667
+ const {
7668
+ project,
7669
+ dataset,
7670
+ description,
7671
+ version: version2,
7672
+ appUrl,
7673
+ apiKey,
7674
+ orgName,
7675
+ fetch: fetch2,
7676
+ forceLogin,
7677
+ projectId,
7678
+ metadata,
7679
+ useOutput: legacy,
7680
+ state: stateArg,
7681
+ _internal_btql
7682
+ } = options;
7683
+ const state = stateArg ?? _globalState;
7684
+ const lazyMetadata = new LazyValue(
7685
+ async () => {
7686
+ await state.login({
7687
+ orgName,
7688
+ apiKey,
7689
+ appUrl,
7690
+ fetch: fetch2,
7691
+ forceLogin
7692
+ });
7693
+ const args = {
7694
+ org_id: state.orgId,
7695
+ project_name: project,
7696
+ project_id: projectId,
7697
+ dataset_name: dataset,
7698
+ description,
7699
+ metadata
7700
+ };
7701
+ const response = await state.appConn().post_json("api/dataset/register", args);
7702
+ return {
7703
+ project: {
7704
+ id: response.project.id,
7705
+ name: response.project.name,
7706
+ fullInfo: response.project
7707
+ },
7708
+ dataset: {
7709
+ id: response.dataset.id,
7710
+ name: response.dataset.name,
7711
+ fullInfo: response.dataset
7712
+ }
7713
+ };
7714
+ }
7715
+ );
7716
+ return new Dataset2(
7717
+ stateArg ?? _globalState,
7718
+ lazyMetadata,
7719
+ version2,
7720
+ legacy,
7721
+ _internal_btql
7722
+ );
7723
+ }
7591
7724
  async function computeLoggerMetadata(state, {
7592
7725
  project_name,
7593
7726
  project_id
@@ -7838,6 +7971,9 @@ function withCurrent(span, callback, state = void 0) {
7838
7971
  const currentState = state ?? _globalState;
7839
7972
  return currentState.contextManager.runInContext(span, () => callback(span));
7840
7973
  }
7974
+ function withParent(parent, callback, state = void 0) {
7975
+ return (state ?? _globalState).currentParent.run(parent, () => callback());
7976
+ }
7841
7977
  function _saveOrgInfo(state, org_info, org_name) {
7842
7978
  if (org_info.length === 0) {
7843
7979
  throw new LoginInvalidOrgError(
@@ -9579,7 +9715,7 @@ var BarProgressReporter = class {
9579
9715
  var import_chalk3 = __toESM(require("chalk"));
9580
9716
  var import_termi_link2 = require("termi-link");
9581
9717
 
9582
- // ../node_modules/.pnpm/async@3.2.5/node_modules/async/dist/async.mjs
9718
+ // ../node_modules/async/dist/async.mjs
9583
9719
  function initialParams(fn) {
9584
9720
  return function(...args) {
9585
9721
  var callback = args.pop();
@@ -9704,7 +9840,6 @@ function isArrayLike(value) {
9704
9840
  return value && typeof value.length === "number" && value.length >= 0 && value.length % 1 === 0;
9705
9841
  }
9706
9842
  var breakLoop = {};
9707
- var breakLoop$1 = breakLoop;
9708
9843
  function once(fn) {
9709
9844
  function wrapper(...args) {
9710
9845
  if (fn === null) return;
@@ -9796,7 +9931,7 @@ function asyncEachOfLimit(generator, limit, iteratee, callback) {
9796
9931
  canceled = true;
9797
9932
  return;
9798
9933
  }
9799
- if (result === breakLoop$1 || done && running <= 0) {
9934
+ if (result === breakLoop || done && running <= 0) {
9800
9935
  done = true;
9801
9936
  return callback(null);
9802
9937
  }
@@ -9839,7 +9974,7 @@ var eachOfLimit$2 = (limit) => {
9839
9974
  } else if (err === false) {
9840
9975
  done = true;
9841
9976
  canceled = true;
9842
- } else if (value === breakLoop$1 || done && running <= 0) {
9977
+ } else if (value === breakLoop || done && running <= 0) {
9843
9978
  done = true;
9844
9979
  return callback(null);
9845
9980
  } else if (!looping) {
@@ -9882,7 +10017,7 @@ function eachOfArrayLike(coll, iteratee, callback) {
9882
10017
  if (canceled === true) return;
9883
10018
  if (err) {
9884
10019
  callback(err);
9885
- } else if (++completed === length || value === breakLoop$1) {
10020
+ } else if (++completed === length || value === breakLoop) {
9886
10021
  callback(null);
9887
10022
  }
9888
10023
  }
@@ -10278,7 +10413,7 @@ function _createTester(check, getResult) {
10278
10413
  if (check(result) && !testResult) {
10279
10414
  testPassed = true;
10280
10415
  testResult = getResult(true, value);
10281
- return callback(null, breakLoop$1);
10416
+ return callback(null, breakLoop);
10282
10417
  }
10283
10418
  callback();
10284
10419
  });
@@ -11064,8 +11199,8 @@ function validateParametersWithJsonSchema(parameters, schema) {
11064
11199
  const validate = ajv.compile(schema);
11065
11200
  if (!validate(parameters)) {
11066
11201
  const errorMessages = validate.errors?.map((err) => {
11067
- const path9 = err.instancePath || "root";
11068
- return `${path9}: ${err.message}`;
11202
+ const path8 = err.instancePath || "root";
11203
+ return `${path8}: ${err.message}`;
11069
11204
  }).join(", ");
11070
11205
  throw Error(`Invalid parameters: ${errorMessages}`);
11071
11206
  }
@@ -11094,6 +11229,13 @@ var EvalResultWithSummary = class {
11094
11229
  };
11095
11230
  }
11096
11231
  };
11232
+ function makeEvalName(projectName, experimentName) {
11233
+ let out = projectName;
11234
+ if (experimentName) {
11235
+ out += ` [experimentName=${experimentName}]`;
11236
+ }
11237
+ return out;
11238
+ }
11097
11239
  function initExperiment(state, options = {}) {
11098
11240
  return init({
11099
11241
  state,
@@ -11128,6 +11270,118 @@ globalThis._evals = {
11128
11270
  function _initializeSpanContext() {
11129
11271
  globalThis._spanContext = { currentSpan, withCurrent, startSpan, NOOP_SPAN };
11130
11272
  }
11273
+ async function Eval(name, evaluator, reporterOrOpts) {
11274
+ const options = isEmpty2(reporterOrOpts) ? {} : typeof reporterOrOpts === "string" ? { reporter: reporterOrOpts } : "name" in reporterOrOpts ? { reporter: reporterOrOpts } : reporterOrOpts;
11275
+ let evalName = makeEvalName(name, evaluator.experimentName);
11276
+ if (globalThis._evals.evaluators[evalName]) {
11277
+ evalName = `${evalName}_${Object.keys(_evals).length}`;
11278
+ }
11279
+ if (globalThis._lazy_load) {
11280
+ globalThis._evals.evaluators[evalName] = {
11281
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
11282
+ evaluator: {
11283
+ evalName,
11284
+ projectName: name,
11285
+ ...evaluator
11286
+ },
11287
+ reporter: options.reporter
11288
+ };
11289
+ _initializeSpanContext();
11290
+ return new EvalResultWithSummary(
11291
+ {
11292
+ scores: {},
11293
+ metrics: {},
11294
+ projectName: "",
11295
+ experimentName: ""
11296
+ },
11297
+ []
11298
+ );
11299
+ }
11300
+ const progressReporter = options.progress ?? new SimpleProgressReporter();
11301
+ const shouldCollectResults = options.returnResults ?? true;
11302
+ if (typeof options.reporter === "string") {
11303
+ throw new Error(
11304
+ "Must specify a reporter object, not a name. Can only specify reporter names when running 'braintrust eval'"
11305
+ );
11306
+ }
11307
+ const resolvedReporter = options.reporter || defaultReporter;
11308
+ try {
11309
+ const { data, baseExperiment: defaultBaseExperiment } = callEvaluatorData(
11310
+ evaluator.data
11311
+ );
11312
+ const experiment = options.parent || options.noSendLogs ? null : initExperiment(evaluator.state, {
11313
+ ...evaluator.projectId ? { projectId: evaluator.projectId } : { project: name },
11314
+ experiment: evaluator.experimentName,
11315
+ description: evaluator.description,
11316
+ metadata: evaluator.metadata,
11317
+ isPublic: evaluator.isPublic,
11318
+ update: evaluator.update,
11319
+ baseExperiment: evaluator.baseExperimentName ?? defaultBaseExperiment,
11320
+ baseExperimentId: evaluator.baseExperimentId,
11321
+ gitMetadataSettings: evaluator.gitMetadataSettings,
11322
+ repoInfo: evaluator.repoInfo,
11323
+ dataset: Dataset2.isDataset(data) ? data : void 0
11324
+ });
11325
+ if (experiment && typeof process !== "undefined" && globalThis.BRAINTRUST_CONTEXT_MANAGER !== void 0) {
11326
+ await experiment._waitForId();
11327
+ }
11328
+ if (experiment && options.onStart) {
11329
+ const summary = await experiment.summarize({ summarizeScores: false });
11330
+ options.onStart(summary);
11331
+ }
11332
+ try {
11333
+ const evalDef = {
11334
+ evalName,
11335
+ projectName: name,
11336
+ ...evaluator,
11337
+ data
11338
+ };
11339
+ const enableCache = options.enableCache ?? true;
11340
+ let ret;
11341
+ if (options.parent) {
11342
+ ret = await withParent(
11343
+ options.parent,
11344
+ () => runEvaluator(
11345
+ null,
11346
+ evalDef,
11347
+ progressReporter,
11348
+ [],
11349
+ options.stream,
11350
+ options.parameters,
11351
+ shouldCollectResults,
11352
+ enableCache
11353
+ ),
11354
+ evaluator.state
11355
+ );
11356
+ } else {
11357
+ ret = await runEvaluator(
11358
+ experiment,
11359
+ evalDef,
11360
+ progressReporter,
11361
+ [],
11362
+ options.stream,
11363
+ options.parameters,
11364
+ shouldCollectResults,
11365
+ enableCache
11366
+ );
11367
+ }
11368
+ progressReporter.stop();
11369
+ resolvedReporter.reportEval(evalDef, ret, {
11370
+ verbose: true,
11371
+ jsonl: false
11372
+ });
11373
+ return ret;
11374
+ } finally {
11375
+ if (experiment) {
11376
+ await experiment.flush().catch(console.error);
11377
+ } else if (options.parent) {
11378
+ await flush().catch(console.error);
11379
+ }
11380
+ }
11381
+ } finally {
11382
+ progressReporter.stop();
11383
+ }
11384
+ }
11131
11385
  function serializeJSONWithPlainString(v) {
11132
11386
  if (typeof v === "string") {
11133
11387
  return v;
@@ -11149,21 +11403,21 @@ function parseFilters(filters) {
11149
11403
  if (equalsIdx === -1) {
11150
11404
  throw new Error(`Invalid filter ${f}`);
11151
11405
  }
11152
- const [path9, value] = [f.slice(0, equalsIdx), f.slice(equalsIdx + 1)];
11406
+ const [path8, value] = [f.slice(0, equalsIdx), f.slice(equalsIdx + 1)];
11153
11407
  let deserializedValue = deserializePlainStringAsJSON2(value).value;
11154
11408
  if (typeof deserializedValue !== "string") {
11155
11409
  deserializedValue = value;
11156
11410
  }
11157
11411
  result.push({
11158
- path: path9.split("."),
11412
+ path: path8.split("."),
11159
11413
  pattern: new RegExp(deserializedValue)
11160
11414
  });
11161
11415
  }
11162
11416
  return result;
11163
11417
  }
11164
11418
  function evaluateFilter(object, filter2) {
11165
- const { path: path9, pattern } = filter2;
11166
- const key = path9.reduce(
11419
+ const { path: path8, pattern } = filter2;
11420
+ const key = path8.reduce(
11167
11421
  (acc, p) => typeof acc === "object" && acc !== null ? (
11168
11422
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
11169
11423
  acc[p]
@@ -11656,6 +11910,120 @@ function buildLocalSummary(evaluator, results, precomputedScores) {
11656
11910
  )
11657
11911
  };
11658
11912
  }
11913
+ function reportFailures(evaluator, failingResults, { verbose, jsonl }) {
11914
+ if (failingResults.length > 0) {
11915
+ console.error(
11916
+ warning(
11917
+ `Evaluator ${evaluator.evalName} failed with ${failingResults.length} error${failingResults.length === 1 ? "" : "s"}. This evaluation ("${evaluator.evalName}") will not be fully logged.`
11918
+ )
11919
+ );
11920
+ if (jsonl) {
11921
+ console.log(
11922
+ JSON.stringify({
11923
+ evaluatorName: evaluator.evalName,
11924
+ errors: failingResults.map(
11925
+ (r) => `${r.error instanceof Error ? r.error.stack : r.error}`
11926
+ )
11927
+ })
11928
+ );
11929
+ } else {
11930
+ for (const result of failingResults) {
11931
+ logError2(result.error, verbose);
11932
+ }
11933
+ }
11934
+ if (!verbose && !jsonl) {
11935
+ console.error(warning("Add --verbose to see full stack traces."));
11936
+ }
11937
+ }
11938
+ }
11939
+ var defaultReporter = {
11940
+ name: "Braintrust default reporter",
11941
+ async reportEval(evaluator, result, { verbose, jsonl }) {
11942
+ const { results, summary } = result;
11943
+ const failingResults = results.filter(
11944
+ (r) => r.error !== void 0
11945
+ );
11946
+ if (failingResults.length > 0) {
11947
+ reportFailures(evaluator, failingResults, { verbose, jsonl });
11948
+ }
11949
+ if (jsonl) {
11950
+ isomorph_default.writeln(JSON.stringify(summary));
11951
+ } else {
11952
+ isomorph_default.writeln("Experiment summary");
11953
+ isomorph_default.writeln("==================");
11954
+ if (summary.comparisonExperimentName) {
11955
+ isomorph_default.writeln(
11956
+ `${summary.comparisonExperimentName} (baseline) <- ${summary.experimentName} (comparison)`
11957
+ );
11958
+ isomorph_default.writeln("");
11959
+ }
11960
+ const hasScores = Object.keys(summary.scores).length > 0;
11961
+ const hasMetrics = Object.keys(summary.metrics ?? {}).length > 0;
11962
+ const hasComparison = !!summary.comparisonExperimentName;
11963
+ if (hasScores || hasMetrics) {
11964
+ if (hasComparison) {
11965
+ isomorph_default.writeln(
11966
+ "Name Value Change Improvements Regressions"
11967
+ );
11968
+ isomorph_default.writeln(
11969
+ "----------------------------------------------------------------"
11970
+ );
11971
+ }
11972
+ for (const score of Object.values(summary.scores)) {
11973
+ const scorePercent = (score.score * 100).toFixed(2);
11974
+ const scoreValue = `${scorePercent}%`;
11975
+ if (hasComparison) {
11976
+ let diffString = "-";
11977
+ if (!isEmpty2(score.diff)) {
11978
+ const diffPercent = (score.diff * 100).toFixed(2);
11979
+ const diffSign = score.diff > 0 ? "+" : "";
11980
+ diffString = `${diffSign}${diffPercent}%`;
11981
+ }
11982
+ const improvements = score.improvements > 0 ? score.improvements.toString() : "-";
11983
+ const regressions = score.regressions > 0 ? score.regressions.toString() : "-";
11984
+ isomorph_default.writeln(
11985
+ `${score.name.padEnd(18)} ${scoreValue.padStart(10)} ${diffString.padStart(10)} ${improvements.padStart(12)} ${regressions.padStart(11)}`
11986
+ );
11987
+ } else {
11988
+ isomorph_default.writeln(`${score.name.padEnd(20)} ${scoreValue.padStart(15)}`);
11989
+ }
11990
+ }
11991
+ for (const metric of Object.values(summary.metrics ?? {})) {
11992
+ const fractionDigits = Number.isInteger(metric.metric) ? 0 : 2;
11993
+ const formattedValue = metric.metric.toFixed(fractionDigits);
11994
+ const metricValue = metric.unit === "$" ? `${metric.unit}${formattedValue}` : `${formattedValue}${metric.unit}`;
11995
+ if (hasComparison) {
11996
+ let diffString = "-";
11997
+ if (!isEmpty2(metric.diff)) {
11998
+ const diffPercent = (metric.diff * 100).toFixed(2);
11999
+ const diffSign = metric.diff > 0 ? "+" : "";
12000
+ diffString = `${diffSign}${diffPercent}%`;
12001
+ }
12002
+ const improvements = metric.improvements > 0 ? metric.improvements.toString() : "-";
12003
+ const regressions = metric.regressions > 0 ? metric.regressions.toString() : "-";
12004
+ isomorph_default.writeln(
12005
+ `${metric.name.padEnd(18)} ${metricValue.padStart(10)} ${diffString.padStart(10)} ${improvements.padStart(12)} ${regressions.padStart(11)}`
12006
+ );
12007
+ } else {
12008
+ isomorph_default.writeln(
12009
+ `${metric.name.padEnd(20)} ${metricValue.padStart(15)}`
12010
+ );
12011
+ }
12012
+ }
12013
+ }
12014
+ if (summary.experimentUrl) {
12015
+ isomorph_default.writeln("");
12016
+ isomorph_default.writeln(`View results for ${summary.experimentName}`);
12017
+ isomorph_default.writeln(`See results at ${summary.experimentUrl}`);
12018
+ }
12019
+ }
12020
+ isomorph_default.writeln("");
12021
+ return failingResults.length === 0;
12022
+ },
12023
+ async reportRun(evalReports) {
12024
+ return evalReports.every((r) => r);
12025
+ }
12026
+ };
11659
12027
 
11660
12028
  // src/cli/reporters/eval.ts
11661
12029
  var import_chalk2 = __toESM(require("chalk"));
@@ -12086,15 +12454,15 @@ var path2 = __toESM(require("path"));
12086
12454
 
12087
12455
  // src/cli/jest/tryRealpath.ts
12088
12456
  var import_graceful_fs = require("graceful-fs");
12089
- function tryRealpath(path9) {
12457
+ function tryRealpath(path8) {
12090
12458
  try {
12091
- path9 = import_graceful_fs.realpathSync.native(path9);
12459
+ path8 = import_graceful_fs.realpathSync.native(path8);
12092
12460
  } catch (error2) {
12093
12461
  if (error2.code !== "ENOENT" && error2.code !== "EISDIR") {
12094
12462
  throw error2;
12095
12463
  }
12096
12464
  }
12097
- return path9;
12465
+ return path8;
12098
12466
  }
12099
12467
 
12100
12468
  // src/cli/jest/nodeModulesPaths.ts
@@ -12174,12 +12542,12 @@ function loadModule({
12174
12542
  globalThis._lazy_load = true;
12175
12543
  globalThis.__inherited_braintrust_state = _internalGetGlobalState();
12176
12544
  const __filename2 = inFile;
12177
- const __dirname2 = (0, import_path.dirname)(__filename2);
12545
+ const __dirname = (0, import_path.dirname)(__filename2);
12178
12546
  new Function("require", "module", "__filename", "__dirname", moduleText)(
12179
12547
  require,
12180
12548
  module,
12181
12549
  __filename2,
12182
- __dirname2
12550
+ __dirname
12183
12551
  );
12184
12552
  return { ...globalThis._evals };
12185
12553
  });
@@ -12694,6 +13062,33 @@ var ParametersBuilder = class {
12694
13062
  return opts.schema;
12695
13063
  }
12696
13064
  };
13065
+ function serializeEvalParametersToStaticParametersSchema(parameters) {
13066
+ return Object.fromEntries(
13067
+ Object.entries(parameters).map(([name, value]) => {
13068
+ if ("type" in value && value.type === "prompt") {
13069
+ return [
13070
+ name,
13071
+ {
13072
+ type: "prompt",
13073
+ default: value.default ? promptDefinitionToPromptData(value.default) : void 0,
13074
+ description: value.description
13075
+ }
13076
+ ];
13077
+ } else {
13078
+ const schemaObj = zodToJsonSchema(value);
13079
+ return [
13080
+ name,
13081
+ {
13082
+ type: "data",
13083
+ schema: schemaObj,
13084
+ default: schemaObj.default,
13085
+ description: schemaObj.description
13086
+ }
13087
+ ];
13088
+ }
13089
+ })
13090
+ );
13091
+ }
12697
13092
  function serializeEvalParameterstoParametersSchema(parameters) {
12698
13093
  const properties = {};
12699
13094
  const required = [];
@@ -12724,6 +13119,27 @@ function serializeEvalParameterstoParametersSchema(parameters) {
12724
13119
  additionalProperties: true
12725
13120
  };
12726
13121
  }
13122
+ function serializeRemoteEvalParametersContainer(parameters) {
13123
+ if (RemoteEvalParameters.isParameters(parameters)) {
13124
+ return {
13125
+ type: "braintrust.parameters",
13126
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
13127
+ schema: parameters.schema,
13128
+ source: {
13129
+ parametersId: parameters.id,
13130
+ slug: parameters.slug,
13131
+ name: parameters.name,
13132
+ projectId: parameters.projectId,
13133
+ version: parameters.version
13134
+ }
13135
+ };
13136
+ }
13137
+ return {
13138
+ type: "braintrust.staticParameters",
13139
+ schema: serializeEvalParametersToStaticParametersSchema(parameters),
13140
+ source: null
13141
+ };
13142
+ }
12727
13143
  var ProjectNameIdMap = class {
12728
13144
  nameToId = {};
12729
13145
  idToName = {};
@@ -13396,303 +13812,543 @@ function safeStringify(obj) {
13396
13812
  }
13397
13813
  }
13398
13814
 
13399
- // src/cli/util/sse.ts
13400
- var import_net = __toESM(require("net"));
13401
- var import_os = __toESM(require("os"));
13402
- var import_path5 = __toESM(require("path"));
13403
- var import_readline = require("readline");
13404
- function buildSseSocketPath() {
13405
- const pid = process.pid;
13406
- const now2 = Date.now();
13407
- return import_path5.default.join(import_os.default.tmpdir(), `bt-eval-${pid}-${now2}.sock`);
13408
- }
13409
- function createSseServer(socketPath, onEvent) {
13410
- const server = import_net.default.createServer((socket) => {
13411
- let currentEvent = null;
13412
- let dataLines = [];
13413
- const rl = (0, import_readline.createInterface)({ input: socket });
13414
- rl.on("line", (line) => {
13415
- if (line === "") {
13416
- if (currentEvent !== null || dataLines.length > 0) {
13417
- const data = dataLines.join("\n");
13418
- dispatchSseEvent(currentEvent, data, onEvent);
13419
- currentEvent = null;
13420
- dataLines = [];
13421
- }
13422
- return;
13423
- }
13424
- if (line.startsWith("event:")) {
13425
- currentEvent = line.slice("event:".length).trim();
13426
- } else if (line.startsWith("data:")) {
13427
- dataLines.push(line.slice("data:".length).trimStart());
13815
+ // dev/server.ts
13816
+ var import_express = __toESM(require("express"));
13817
+ var import_cors = __toESM(require("cors"));
13818
+
13819
+ // dev/errorHandler.ts
13820
+ var import_v314 = require("zod/v3");
13821
+ var errorHandler = (err, req, res, next) => {
13822
+ if ("status" in err) {
13823
+ res.status(err.status).json({
13824
+ error: {
13825
+ message: err.message,
13826
+ status: err.status
13428
13827
  }
13429
13828
  });
13430
- rl.on("close", () => {
13431
- if (currentEvent !== null || dataLines.length > 0) {
13432
- const data = dataLines.join("\n");
13433
- dispatchSseEvent(currentEvent, data, onEvent);
13829
+ return;
13830
+ }
13831
+ if (err instanceof import_v314.z.ZodError) {
13832
+ res.status(400).json({
13833
+ error: {
13834
+ message: "Invalid request",
13835
+ errors: err.errors
13434
13836
  }
13435
13837
  });
13838
+ return;
13839
+ }
13840
+ console.error("Internal server error", err);
13841
+ res.status(500).json({
13842
+ error: {
13843
+ message: "Internal server error",
13844
+ status: 500
13845
+ }
13436
13846
  });
13437
- server.listen(socketPath);
13438
- return {
13439
- server,
13440
- close: () => {
13441
- server.close();
13442
- try {
13443
- require("fs").unlinkSync(socketPath);
13444
- } catch {
13847
+ };
13848
+
13849
+ // dev/authorize.ts
13850
+ var import_http_errors = __toESM(require("http-errors"));
13851
+ function authorizeRequest(req, res, next) {
13852
+ try {
13853
+ const ctx = {
13854
+ appOrigin: extractAllowedOrigin(req.headers[ORIGIN_HEADER]),
13855
+ token: void 0,
13856
+ state: void 0,
13857
+ projectId: parseHeader(req.headers, PROJECT_ID_HEADER)
13858
+ };
13859
+ if (req.headers.authorization || req.headers[BRAINTRUST_AUTH_TOKEN_HEADER]) {
13860
+ const tokenText = parseBraintrustAuthHeader(req.headers);
13861
+ if (!tokenText) {
13862
+ return next((0, import_http_errors.default)(400, "Invalid authorization token format"));
13445
13863
  }
13864
+ ctx.token = tokenText.toLowerCase() === "null" ? void 0 : tokenText;
13446
13865
  }
13447
- };
13866
+ req.ctx = ctx;
13867
+ next();
13868
+ } catch (e) {
13869
+ next(e);
13870
+ }
13448
13871
  }
13449
- function dispatchSseEvent(eventName, data, onEvent) {
13450
- const name = eventName ?? "";
13451
- switch (name) {
13452
- case "start": {
13453
- try {
13454
- const parsed = JSON.parse(data);
13455
- onEvent({ type: "start", data: parsed });
13456
- } catch {
13457
- }
13458
- break;
13459
- }
13460
- case "summary": {
13461
- try {
13462
- const parsed = JSON.parse(data);
13463
- onEvent({ type: "summary", data: parsed });
13464
- } catch {
13465
- }
13466
- break;
13467
- }
13468
- case "progress": {
13469
- try {
13470
- const parsed = JSON.parse(data);
13471
- onEvent({ type: "progress", data: parsed });
13472
- } catch {
13473
- }
13474
- break;
13475
- }
13476
- case "console": {
13477
- try {
13478
- const parsed = JSON.parse(data);
13479
- onEvent({ type: "console", data: parsed });
13480
- } catch {
13481
- }
13482
- break;
13483
- }
13484
- case "error": {
13485
- try {
13486
- const parsed = JSON.parse(data);
13487
- onEvent({ type: "error", data: parsed });
13488
- } catch {
13489
- onEvent({ type: "error", data: { message: data } });
13490
- }
13491
- break;
13872
+ var loginCache = new LRUCache({
13873
+ max: 32
13874
+ // TODO: Make this configurable
13875
+ });
13876
+ async function cachedLogin(options) {
13877
+ const key = JSON.stringify(options);
13878
+ const cached = loginCache.get(key);
13879
+ if (cached) {
13880
+ return cached;
13881
+ }
13882
+ const state = await loginToState(options);
13883
+ loginCache.set(key, state);
13884
+ return state;
13885
+ }
13886
+ function makeCheckAuthorized(allowedOrgName) {
13887
+ return async (req, _res, next) => {
13888
+ if (!req.ctx?.token) {
13889
+ return next((0, import_http_errors.default)(401, "Unauthorized"));
13492
13890
  }
13493
- case "list": {
13494
- try {
13495
- const parsed = JSON.parse(data);
13496
- onEvent({ type: "list", data: parsed });
13497
- } catch {
13891
+ try {
13892
+ const orgName = parseHeader(req.headers, "x-bt-org-name");
13893
+ if (!orgName) {
13894
+ return next((0, import_http_errors.default)(400, "Missing x-bt-org-name header"));
13498
13895
  }
13499
- break;
13500
- }
13501
- case "dev-ready": {
13502
- try {
13503
- const parsed = JSON.parse(data);
13504
- onEvent({ type: "dev-ready", data: parsed });
13505
- } catch {
13896
+ if (allowedOrgName && allowedOrgName !== orgName) {
13897
+ const errorMessage = `Org '${orgName}' is not allowed. Only org '${allowedOrgName}' is allowed.`;
13898
+ return next((0, import_http_errors.default)(403, errorMessage));
13506
13899
  }
13507
- break;
13508
- }
13509
- case "done": {
13510
- onEvent({ type: "done", data });
13511
- break;
13900
+ const state = await cachedLogin({
13901
+ apiKey: req.ctx?.token,
13902
+ orgName
13903
+ });
13904
+ req.ctx.state = state;
13905
+ next();
13906
+ } catch (e) {
13907
+ console.error("Authorization error:", e);
13908
+ return next((0, import_http_errors.default)(401, "Unauthorized"));
13512
13909
  }
13513
- default:
13514
- break;
13910
+ };
13911
+ }
13912
+ function parseBraintrustAuthHeader(headers) {
13913
+ const tokenString = parseHeader(headers, BRAINTRUST_AUTH_TOKEN_HEADER);
13914
+ return tokenString ?? parseAuthHeader(headers) ?? void 0;
13915
+ }
13916
+ function parseHeader(headers, headerName) {
13917
+ const token = headers[headerName];
13918
+ let tokenString;
13919
+ if (typeof token === "string") {
13920
+ tokenString = token;
13921
+ } else if (Array.isArray(token) && token.length > 0) {
13922
+ tokenString = token[0];
13515
13923
  }
13924
+ return tokenString;
13516
13925
  }
13517
- function findProjectRoot(startDir) {
13518
- const fs6 = require("fs");
13519
- const homeDir = require("os").homedir();
13520
- let current = import_path5.default.resolve(startDir);
13521
- let depth = 0;
13522
- const maxDepth = 8;
13523
- while (depth < maxDepth) {
13524
- if (current === "/" || current === homeDir) {
13525
- return null;
13926
+ function checkOrigin(requestOrigin, callback) {
13927
+ if (!requestOrigin) {
13928
+ return callback(null, true);
13929
+ }
13930
+ for (const origin of WHITELISTED_ORIGINS || []) {
13931
+ if (origin instanceof RegExp && origin.test(requestOrigin) || origin === requestOrigin) {
13932
+ return callback(null, requestOrigin);
13526
13933
  }
13527
- try {
13528
- const entries = fs6.readdirSync(current);
13529
- const hasPackageJson = entries.includes("package.json");
13530
- const hasLockfile = entries.includes("package-lock.json") || entries.includes("pnpm-lock.yaml") || entries.includes("yarn.lock") || entries.includes("bun.lock");
13531
- const hasGit = entries.includes(".git");
13532
- const hasDenoJson = entries.includes("deno.json") || entries.includes("deno.jsonc");
13533
- if (hasPackageJson || hasLockfile || hasGit || hasDenoJson) {
13534
- return current;
13535
- }
13536
- } catch {
13934
+ }
13935
+ return callback(null, false);
13936
+ }
13937
+ var BRAINTRUST_AUTH_TOKEN_HEADER = "x-bt-auth-token";
13938
+ var ORIGIN_HEADER = "origin";
13939
+ var PROJECT_ID_HEADER = "x-bt-project-id";
13940
+ function extractAllowedOrigin(originHeader) {
13941
+ let allowedOrigin = MAIN_ORIGIN;
13942
+ checkOrigin(originHeader, (err, origin) => {
13943
+ if (!err && originHeader && origin) {
13944
+ allowedOrigin = originHeader;
13537
13945
  }
13538
- const parent = import_path5.default.dirname(current);
13539
- if (parent === current) {
13540
- return null;
13541
- }
13542
- current = parent;
13543
- depth++;
13544
- }
13545
- return null;
13546
- }
13547
- function classifyEnvironment(projectRoot) {
13548
- const fs6 = require("fs");
13549
- const ctx = {
13550
- root: projectRoot,
13551
- hasVite: false,
13552
- hasTsNode: false,
13553
- hasTypeModule: false,
13554
- hasTsx: false,
13555
- hasBun: false,
13556
- hasDeno: false,
13557
- nodeModulesBin: import_path5.default.join(projectRoot, "node_modules", ".bin")
13558
- };
13559
- const denoJsonPath = import_path5.default.join(projectRoot, "deno.json");
13560
- const denoJsoncPath = import_path5.default.join(projectRoot, "deno.jsonc");
13561
- try {
13562
- if (fs6.existsSync(denoJsonPath) || fs6.existsSync(denoJsoncPath)) {
13563
- ctx.hasDeno = true;
13564
- return ctx;
13565
- }
13566
- } catch {
13946
+ });
13947
+ return allowedOrigin;
13948
+ }
13949
+ var MAIN_ORIGIN = "https://www.braintrust.dev";
13950
+ var WHITELISTED_ORIGINS = [
13951
+ MAIN_ORIGIN,
13952
+ "https://www.braintrustdata.com",
13953
+ new RegExp("https://.*.preview.braintrust.dev")
13954
+ ].concat(
13955
+ process.env.WHITELISTED_ORIGIN ? [process.env.WHITELISTED_ORIGIN] : []
13956
+ ).concat(
13957
+ process.env.BRAINTRUST_APP_URL ? [process.env.BRAINTRUST_APP_URL] : []
13958
+ );
13959
+ function parseAuthHeader(headers) {
13960
+ const authHeader = headers["authorization"];
13961
+ let authValue = null;
13962
+ if (Array.isArray(authHeader)) {
13963
+ authValue = authHeader[authHeader.length - 1];
13964
+ } else {
13965
+ authValue = authHeader;
13567
13966
  }
13568
- const bunLockPath = import_path5.default.join(projectRoot, "bun.lock");
13569
- try {
13570
- if (fs6.existsSync(bunLockPath)) {
13571
- ctx.hasBun = true;
13572
- return ctx;
13573
- }
13574
- } catch {
13967
+ if (!authValue) {
13968
+ return null;
13575
13969
  }
13576
- const packageJsonPath = import_path5.default.join(projectRoot, "package.json");
13577
- try {
13578
- if (fs6.existsSync(packageJsonPath)) {
13579
- const packageJson = JSON.parse(fs6.readFileSync(packageJsonPath, "utf-8"));
13580
- const allDeps = {
13581
- ...packageJson.dependencies,
13582
- ...packageJson.devDependencies
13583
- };
13584
- if (allDeps.vite || allDeps.vitest || fs6.existsSync(import_path5.default.join(projectRoot, "vite.config.ts")) || fs6.existsSync(import_path5.default.join(projectRoot, "vite.config.js")) || fs6.existsSync(import_path5.default.join(projectRoot, "vitest.config.ts")) || fs6.existsSync(import_path5.default.join(projectRoot, "vitest.config.js"))) {
13585
- ctx.hasVite = true;
13970
+ const parts = authValue.split(" ");
13971
+ if (parts.length !== 2) {
13972
+ return null;
13973
+ }
13974
+ return parts[1];
13975
+ }
13976
+ var baseAllowedHeaders = [
13977
+ "Content-Type",
13978
+ "X-Amz-Date",
13979
+ "Authorization",
13980
+ "X-Api-Key",
13981
+ "X-Amz-Security-Token",
13982
+ "x-bt-auth-token",
13983
+ "x-bt-parent",
13984
+ // These are eval-specific
13985
+ "x-bt-org-name",
13986
+ "x-bt-project-id",
13987
+ "x-bt-stream-fmt",
13988
+ "x-bt-use-cache",
13989
+ "x-stainless-os",
13990
+ "x-stainless-lang",
13991
+ "x-stainless-package-version",
13992
+ "x-stainless-runtime",
13993
+ "x-stainless-runtime-version",
13994
+ "x-stainless-arch"
13995
+ ];
13996
+
13997
+ // dev/stream.ts
13998
+ function serializeSSEEvent(event) {
13999
+ return Object.entries(event).filter(([_key, value]) => value !== void 0).map(([key, value]) => `${key}: ${value}`).join("\n") + "\n\n";
14000
+ }
14001
+
14002
+ // dev/types.ts
14003
+ var import_v315 = require("zod/v3");
14004
+ var evalBodySchema = import_v315.z.object({
14005
+ name: import_v315.z.string(),
14006
+ parameters: import_v315.z.record(import_v315.z.string(), import_v315.z.unknown()).nullish(),
14007
+ data: RunEval.shape.data,
14008
+ scores: import_v315.z.array(
14009
+ import_v315.z.object({
14010
+ function_id: FunctionId,
14011
+ name: import_v315.z.string()
14012
+ })
14013
+ ).nullish(),
14014
+ experiment_name: import_v315.z.string().nullish(),
14015
+ project_id: import_v315.z.string().nullish(),
14016
+ parent: InvokeParent.optional(),
14017
+ stream: import_v315.z.boolean().optional()
14018
+ });
14019
+ var staticParametersSchema = import_v315.z.record(
14020
+ import_v315.z.string(),
14021
+ import_v315.z.union([
14022
+ import_v315.z.object({
14023
+ type: import_v315.z.literal("prompt"),
14024
+ default: PromptData.optional(),
14025
+ description: import_v315.z.string().optional()
14026
+ }),
14027
+ import_v315.z.object({
14028
+ type: import_v315.z.literal("data"),
14029
+ schema: import_v315.z.record(import_v315.z.unknown()),
14030
+ default: import_v315.z.unknown().optional(),
14031
+ description: import_v315.z.string().optional()
14032
+ })
14033
+ ])
14034
+ );
14035
+ var parametersSchema = import_v315.z.object({
14036
+ type: import_v315.z.literal("object"),
14037
+ properties: import_v315.z.record(import_v315.z.string(), import_v315.z.record(import_v315.z.unknown())),
14038
+ required: import_v315.z.array(import_v315.z.string()).optional(),
14039
+ additionalProperties: import_v315.z.boolean().optional()
14040
+ });
14041
+ var parametersSourceSchema = import_v315.z.object({
14042
+ parametersId: import_v315.z.string().optional(),
14043
+ slug: import_v315.z.string(),
14044
+ name: import_v315.z.string(),
14045
+ projectId: import_v315.z.string().optional(),
14046
+ version: import_v315.z.string().optional()
14047
+ });
14048
+ var parametersContainerSchema = import_v315.z.object({
14049
+ type: import_v315.z.literal("braintrust.parameters"),
14050
+ schema: parametersSchema,
14051
+ source: parametersSourceSchema
14052
+ });
14053
+ var staticParametersContainerSchema = import_v315.z.object({
14054
+ type: import_v315.z.literal("braintrust.staticParameters"),
14055
+ schema: staticParametersSchema,
14056
+ source: import_v315.z.null()
14057
+ });
14058
+ var serializedParametersContainerSchema = import_v315.z.union([
14059
+ parametersContainerSchema,
14060
+ staticParametersContainerSchema,
14061
+ // keeping this type here since old versions of the SDK will still pass the unwrapped schema and we need to handle this in the app
14062
+ staticParametersSchema
14063
+ ]);
14064
+ var evaluatorDefinitionSchema = import_v315.z.object({
14065
+ parameters: serializedParametersContainerSchema.optional(),
14066
+ scores: import_v315.z.array(import_v315.z.object({ name: import_v315.z.string() })).optional()
14067
+ });
14068
+ var evaluatorDefinitionsSchema = import_v315.z.record(
14069
+ import_v315.z.string(),
14070
+ evaluatorDefinitionSchema
14071
+ );
14072
+
14073
+ // dev/server.ts
14074
+ var import_v316 = require("zod/v3");
14075
+ var import_ajv2 = require("ajv");
14076
+ function runDevServer(evaluators, opts) {
14077
+ const allEvaluators = Object.fromEntries(
14078
+ evaluators.map((evaluator) => [evaluator.evalName, evaluator])
14079
+ );
14080
+ globalThis._lazy_load = false;
14081
+ const app = (0, import_express.default)();
14082
+ app.use(import_express.default.json({ limit: "1gb" }));
14083
+ console.log("Starting server");
14084
+ app.use((req, res, next) => {
14085
+ if (req.headers["access-control-request-private-network"]) {
14086
+ res.setHeader("Access-Control-Allow-Private-Network", "true");
14087
+ }
14088
+ next();
14089
+ });
14090
+ const checkAuthorized = makeCheckAuthorized(opts.orgName);
14091
+ app.use(
14092
+ (0, import_cors.default)({
14093
+ origin: checkOrigin,
14094
+ methods: ["GET", "PATCH", "POST", "PUT", "DELETE", "OPTIONS"],
14095
+ allowedHeaders: baseAllowedHeaders,
14096
+ credentials: true,
14097
+ exposedHeaders: [
14098
+ BT_CURSOR_HEADER,
14099
+ BT_FOUND_EXISTING_HEADER,
14100
+ "x-bt-span-id",
14101
+ "x-bt-span-export"
14102
+ ],
14103
+ maxAge: 86400
14104
+ })
14105
+ );
14106
+ app.use(authorizeRequest);
14107
+ app.get("/", (req, res) => {
14108
+ res.send("Hello, world!");
14109
+ });
14110
+ app.get(
14111
+ "/list",
14112
+ checkAuthorized,
14113
+ asyncHandler(async (req, res) => {
14114
+ const evalDefs = {};
14115
+ for (const [name, evaluator] of Object.entries(allEvaluators)) {
14116
+ let parameters;
14117
+ if (evaluator.parameters) {
14118
+ const resolvedParams = await Promise.resolve(evaluator.parameters);
14119
+ parameters = serializeRemoteEvalParametersContainer(resolvedParams);
14120
+ }
14121
+ evalDefs[name] = {
14122
+ parameters,
14123
+ scores: evaluator.scores.map((score, idx) => ({
14124
+ name: scorerName(score, idx)
14125
+ }))
14126
+ };
13586
14127
  }
13587
- if (allDeps["ts-node"]) {
13588
- ctx.hasTsNode = true;
14128
+ res.json(evalDefs);
14129
+ })
14130
+ );
14131
+ app.post(
14132
+ "/eval",
14133
+ checkAuthorized,
14134
+ asyncHandler(async (req, res) => {
14135
+ const {
14136
+ name,
14137
+ parameters,
14138
+ parent,
14139
+ experiment_name,
14140
+ project_id,
14141
+ data,
14142
+ scores,
14143
+ stream
14144
+ } = evalBodySchema.parse(req.body);
14145
+ if (!req.ctx?.state) {
14146
+ res.status(500).json({ error: "Braintrust state not initialized in request" });
14147
+ return;
13589
14148
  }
13590
- if (allDeps.tsx) {
13591
- ctx.hasTsx = true;
14149
+ const state = req.ctx.state;
14150
+ const evaluator = allEvaluators[name];
14151
+ if (!evaluator) {
14152
+ res.status(404).json({ error: `Evaluator '${name}' not found` });
14153
+ return;
13592
14154
  }
13593
- if (packageJson.type === "module") {
13594
- ctx.hasTypeModule = true;
14155
+ if (evaluator.parameters) {
14156
+ try {
14157
+ await validateParameters(parameters ?? {}, evaluator.parameters);
14158
+ } catch (e) {
14159
+ console.error("Error validating parameters", e);
14160
+ if (e instanceof import_v316.z.ZodError || e instanceof import_ajv2.ValidationError || e instanceof Error) {
14161
+ res.status(400).json({
14162
+ error: e.message
14163
+ });
14164
+ return;
14165
+ }
14166
+ throw e;
14167
+ }
13595
14168
  }
13596
- }
13597
- } catch {
13598
- }
13599
- const tsconfigPath = import_path5.default.join(projectRoot, "tsconfig.json");
13600
- try {
13601
- if (fs6.existsSync(tsconfigPath)) {
13602
- const tsconfig = JSON.parse(fs6.readFileSync(tsconfigPath, "utf-8"));
13603
- if (tsconfig["ts-node"]) {
13604
- ctx.hasTsNode = true;
14169
+ const resolvedData = await getDataset(state, data);
14170
+ const evalData = callEvaluatorData(resolvedData);
14171
+ console.log("Starting eval", evaluator.evalName);
14172
+ if (stream) {
14173
+ res.setHeader("Content-Type", "text/event-stream");
14174
+ res.setHeader("Cache-Control", "no-cache");
14175
+ res.setHeader("Connection", "keep-alive");
14176
+ } else {
14177
+ res.setHeader("Content-Type", "application/json");
13605
14178
  }
13606
- }
13607
- } catch {
13608
- }
13609
- return ctx;
13610
- }
13611
- function selectRunner(ctx) {
13612
- const fs6 = require("fs");
13613
- if (ctx.hasDeno) {
13614
- const denoPath = findOnPath("deno");
13615
- if (denoPath) {
13616
- return { command: denoPath, prefixArgs: ["run", "-A"] };
13617
- }
13618
- }
13619
- if (ctx.hasBun) {
13620
- const bunPath = findOnPath("bun");
13621
- if (bunPath) {
13622
- return { command: bunPath, prefixArgs: [] };
13623
- }
13624
- const localBun = import_path5.default.join(ctx.nodeModulesBin, "bun");
13625
- try {
13626
- fs6.accessSync(localBun, fs6.constants.X_OK);
13627
- return { command: localBun, prefixArgs: [] };
13628
- } catch {
13629
- }
13630
- }
13631
- if (ctx.hasVite) {
13632
- const localViteNode = import_path5.default.join(ctx.nodeModulesBin, "vite-node");
13633
- try {
13634
- fs6.accessSync(localViteNode, fs6.constants.X_OK);
13635
- return { command: localViteNode, prefixArgs: [] };
13636
- } catch {
13637
- }
13638
- return { command: "npx", prefixArgs: ["--yes", "vite-node"] };
13639
- }
13640
- if (ctx.hasTsNode) {
13641
- const localTsNode = import_path5.default.join(ctx.nodeModulesBin, "ts-node");
13642
- try {
13643
- fs6.accessSync(localTsNode, fs6.constants.X_OK);
13644
- return { command: localTsNode, prefixArgs: [] };
13645
- } catch {
13646
- }
13647
- return { command: "npx", prefixArgs: ["--yes", "ts-node"] };
13648
- }
13649
- const localTsx = import_path5.default.join(ctx.nodeModulesBin, "tsx");
13650
- try {
13651
- fs6.accessSync(localTsx, fs6.constants.X_OK);
13652
- return { command: localTsx, prefixArgs: [] };
13653
- } catch {
13654
- }
13655
- const tsxOnPath = findOnPath("tsx");
13656
- if (tsxOnPath) {
13657
- return { command: tsxOnPath, prefixArgs: [] };
13658
- }
13659
- return { command: "npx", prefixArgs: ["--yes", "tsx"] };
14179
+ const task = async (input, hooks) => {
14180
+ const result = await evaluator.task(input, hooks);
14181
+ hooks.reportProgress({
14182
+ format: "code",
14183
+ output_type: "completion",
14184
+ event: "json_delta",
14185
+ data: JSON.stringify(result)
14186
+ });
14187
+ return result;
14188
+ };
14189
+ try {
14190
+ const summary = await Eval(
14191
+ "worker-thread",
14192
+ {
14193
+ ...evaluator,
14194
+ data: evalData.data,
14195
+ scores: evaluator.scores.concat(
14196
+ scores?.map(
14197
+ (score) => makeScorer(
14198
+ state,
14199
+ score.name,
14200
+ score.function_id,
14201
+ req.ctx?.projectId
14202
+ )
14203
+ ) ?? []
14204
+ ),
14205
+ task,
14206
+ state,
14207
+ experimentName: experiment_name ?? void 0,
14208
+ projectId: project_id ?? void 0
14209
+ },
14210
+ {
14211
+ // Avoid printing the bar to the console.
14212
+ progress: {
14213
+ start: () => {
14214
+ },
14215
+ stop: () => {
14216
+ console.log("Finished running experiment");
14217
+ },
14218
+ increment: () => {
14219
+ }
14220
+ },
14221
+ stream: (data2) => {
14222
+ if (stream) {
14223
+ res.write(
14224
+ serializeSSEEvent({
14225
+ event: "progress",
14226
+ data: JSON.stringify(data2)
14227
+ })
14228
+ );
14229
+ }
14230
+ },
14231
+ onStart: (metadata) => {
14232
+ if (stream) {
14233
+ res.write(
14234
+ serializeSSEEvent({
14235
+ event: "start",
14236
+ data: JSON.stringify(metadata)
14237
+ })
14238
+ );
14239
+ }
14240
+ },
14241
+ parent: parseParent(parent),
14242
+ parameters: parameters ?? {}
14243
+ }
14244
+ );
14245
+ if (stream) {
14246
+ res.write(
14247
+ serializeSSEEvent({
14248
+ event: "summary",
14249
+ data: JSON.stringify(summary.summary)
14250
+ })
14251
+ );
14252
+ res.write(
14253
+ serializeSSEEvent({
14254
+ event: "done",
14255
+ data: ""
14256
+ })
14257
+ );
14258
+ } else {
14259
+ res.json(summary.summary);
14260
+ }
14261
+ } catch (e) {
14262
+ console.error("Error running eval", e);
14263
+ if (stream) {
14264
+ res.write(
14265
+ serializeSSEEvent({
14266
+ event: "error",
14267
+ data: JSON.stringify(e)
14268
+ })
14269
+ );
14270
+ } else {
14271
+ res.status(500).json({ error: e });
14272
+ }
14273
+ } finally {
14274
+ res.end();
14275
+ }
14276
+ })
14277
+ );
14278
+ app.use(errorHandler);
14279
+ app.listen(opts.port, opts.host, () => {
14280
+ console.log(`Dev server running at http://${opts.host}:${opts.port}`);
14281
+ });
13660
14282
  }
13661
- function resolveRuntime(runnerOverride) {
13662
- if (runnerOverride) {
13663
- return { command: runnerOverride, prefixArgs: [] };
13664
- }
13665
- const envRunner = process.env.BT_EVAL_JS_RUNNER;
13666
- if (envRunner) {
13667
- return { command: envRunner, prefixArgs: [] };
13668
- }
13669
- const projectRoot = findProjectRoot(process.cwd());
13670
- if (!projectRoot) {
13671
- const tsxOnPath = findOnPath("tsx");
13672
- if (tsxOnPath) {
13673
- return { command: tsxOnPath, prefixArgs: [] };
13674
- }
13675
- return { command: "npx", prefixArgs: ["--yes", "tsx"] };
14283
+ var asyncHandler = (fn) => (req, res, next) => {
14284
+ Promise.resolve(fn(req, res, next)).catch(next);
14285
+ };
14286
+ async function getDataset(state, data) {
14287
+ if ("project_name" in data) {
14288
+ return initDataset({
14289
+ state,
14290
+ project: data.project_name,
14291
+ dataset: data.dataset_name,
14292
+ _internal_btql: data._internal_btql ?? void 0
14293
+ });
14294
+ } else if ("dataset_id" in data) {
14295
+ const datasetInfo = await getDatasetById({
14296
+ state,
14297
+ datasetId: data.dataset_id
14298
+ });
14299
+ return initDataset({
14300
+ state,
14301
+ projectId: datasetInfo.projectId,
14302
+ dataset: datasetInfo.dataset,
14303
+ _internal_btql: data._internal_btql ?? void 0
14304
+ });
14305
+ } else {
14306
+ return data.data;
13676
14307
  }
13677
- const ctx = classifyEnvironment(projectRoot);
13678
- return selectRunner(ctx);
13679
14308
  }
13680
- function findOnPath(binary) {
13681
- const pathEnv = process.env.PATH;
13682
- if (!pathEnv) {
13683
- return null;
13684
- }
13685
- const dirs = pathEnv.split(import_path5.default.delimiter);
13686
- for (const dir2 of dirs) {
13687
- const candidate = import_path5.default.join(dir2, binary);
13688
- try {
13689
- require("fs").accessSync(candidate);
13690
- return candidate;
13691
- } catch {
13692
- continue;
14309
+ var datasetFetchSchema = import_v316.z.object({
14310
+ project_id: import_v316.z.string(),
14311
+ name: import_v316.z.string()
14312
+ });
14313
+ async function getDatasetById({
14314
+ state,
14315
+ datasetId
14316
+ }) {
14317
+ const dataset = await state.appConn().post_json("api/dataset/get", {
14318
+ id: datasetId
14319
+ });
14320
+ const parsed = import_v316.z.array(datasetFetchSchema).parse(dataset);
14321
+ if (parsed.length === 0) {
14322
+ throw new Error(`Dataset '${datasetId}' not found`);
14323
+ }
14324
+ return { projectId: parsed[0].project_id, dataset: parsed[0].name };
14325
+ }
14326
+ function makeScorer(state, name, score, projectId) {
14327
+ const ret = async (input) => {
14328
+ const request = {
14329
+ ...score,
14330
+ input,
14331
+ parent: await getSpanParentObject().export(),
14332
+ stream: false,
14333
+ mode: "auto",
14334
+ strict: true
14335
+ };
14336
+ const headers = {
14337
+ Accept: "application/json"
14338
+ };
14339
+ if (projectId) {
14340
+ headers["x-bt-project-id"] = projectId;
13693
14341
  }
13694
- }
13695
- return null;
14342
+ const result = await state.proxyConn().post(`function/invoke`, request, {
14343
+ headers
14344
+ });
14345
+ const data = await result.json();
14346
+ return data;
14347
+ };
14348
+ Object.defineProperties(ret, {
14349
+ name: { value: `Remote eval scorer (${name})` }
14350
+ });
14351
+ return ret;
13696
14352
  }
13697
14353
 
13698
14354
  // src/cli/util/external-packages-plugin.ts
@@ -13802,6 +14458,89 @@ function addReport(evalReports, reporter, report) {
13802
14458
  }
13803
14459
  evalReports[reporter.name].results.push(report);
13804
14460
  }
14461
+ function buildWatchPluginForEvaluator(inFile, opts) {
14462
+ const evaluators = {
14463
+ evaluators: [],
14464
+ reporters: {}
14465
+ };
14466
+ const plugin = {
14467
+ name: "run-evalutator-on-end",
14468
+ setup(build2) {
14469
+ build2.onEnd(async (result) => {
14470
+ console.error(`Done building ${inFile}`);
14471
+ if (!result.outputFiles) {
14472
+ if (opts.verbose) {
14473
+ console.warn(`Failed to compile ${inFile}`);
14474
+ console.warn(result.errors);
14475
+ } else {
14476
+ console.warn(`Failed to compile ${inFile}: ${result.errors}`);
14477
+ }
14478
+ return;
14479
+ }
14480
+ const evalResult = evaluateBuildResults(inFile, result);
14481
+ if (!evalResult) {
14482
+ return;
14483
+ }
14484
+ evaluators.evaluators = evaluators.evaluators.filter(
14485
+ (e) => e.sourceFile !== inFile
14486
+ );
14487
+ for (const evaluator of Object.values(evalResult.evaluators)) {
14488
+ evaluators.evaluators.push({
14489
+ sourceFile: inFile,
14490
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
14491
+ evaluator: evaluator.evaluator,
14492
+ reporter: evaluator.reporter
14493
+ });
14494
+ }
14495
+ for (const [reporterName, reporter] of Object.entries(
14496
+ evalResult.reporters
14497
+ )) {
14498
+ evaluators.reporters[reporterName] = reporter;
14499
+ }
14500
+ const evalReports = {};
14501
+ for (const evaluatorDef of Object.values(evalResult.evaluators)) {
14502
+ const { evaluator, reporter } = evaluatorDef;
14503
+ const evalData = callEvaluatorData(evaluator.data);
14504
+ const logger = opts.noSendLogs ? null : await initExperiment2(evaluator, evalData);
14505
+ const evaluatorResult = await runEvaluator(
14506
+ logger,
14507
+ {
14508
+ ...evaluator,
14509
+ data: evalData.data
14510
+ },
14511
+ opts.progressReporter,
14512
+ opts.filters,
14513
+ void 0,
14514
+ void 0
14515
+ );
14516
+ const resolvedReporter = resolveReporter(
14517
+ reporter,
14518
+ evaluators.reporters
14519
+ // Let these accumulate across all files.
14520
+ );
14521
+ const report = resolvedReporter.reportEval(
14522
+ evaluator,
14523
+ evaluatorResult,
14524
+ {
14525
+ verbose: opts.verbose,
14526
+ jsonl: opts.jsonl
14527
+ }
14528
+ );
14529
+ addReport(evalReports, resolvedReporter, report);
14530
+ }
14531
+ for (const [reporterName, { reporter, results }] of Object.entries(
14532
+ evalReports
14533
+ )) {
14534
+ const success = await reporter.reportRun(await Promise.all(results));
14535
+ if (!success) {
14536
+ console.error(error(`Reporter ${reporterName} failed.`));
14537
+ }
14538
+ }
14539
+ });
14540
+ }
14541
+ };
14542
+ return plugin;
14543
+ }
13805
14544
  async function initFile({
13806
14545
  inFile,
13807
14546
  outFile,
@@ -13918,6 +14657,26 @@ function updateEvaluators(evaluators, buildResults, opts) {
13918
14657
  }
13919
14658
  }
13920
14659
  }
14660
+ async function runAndWatch({
14661
+ handles,
14662
+ onExit
14663
+ }) {
14664
+ const count = Object.keys(handles).length;
14665
+ console.error(`Watching ${(0, import_pluralize4.default)("file", count, true)}...`);
14666
+ Object.values(handles).map((handle) => handle.watch());
14667
+ ["SIGINT", "SIGTERM"].forEach((signal) => {
14668
+ process.on(signal, function() {
14669
+ console.error("Stopped watching.");
14670
+ for (const handle of Object.values(handles)) {
14671
+ handle.destroy();
14672
+ }
14673
+ onExit?.();
14674
+ process.exit(0);
14675
+ });
14676
+ });
14677
+ await new Promise(() => {
14678
+ });
14679
+ }
13921
14680
  async function buildEvaluators(handles, opts) {
13922
14681
  const buildPromises = Object.values(handles).map(
13923
14682
  (handle) => handle.rebuild()
@@ -14020,7 +14779,7 @@ async function runOnce(handles, opts) {
14020
14779
  return allSuccess;
14021
14780
  }
14022
14781
  function checkMatch(pathInput, include_patterns, exclude_patterns) {
14023
- const p = import_path6.default.resolve(pathInput);
14782
+ const p = import_path5.default.resolve(pathInput);
14024
14783
  if (include_patterns !== null) {
14025
14784
  let include = false;
14026
14785
  for (const pattern of include_patterns) {
@@ -14069,7 +14828,7 @@ async function collectFiles(inputPath, mode) {
14069
14828
  }
14070
14829
  files.push(inputPath);
14071
14830
  } else {
14072
- const walked = await import_util15.default.promisify(fsWalk.walk)(inputPath, {
14831
+ const walked = await import_util16.default.promisify(fsWalk.walk)(inputPath, {
14073
14832
  deepFilter: (entry) => {
14074
14833
  return checkMatch(entry.path, null, EXCLUDE);
14075
14834
  },
@@ -14104,8 +14863,8 @@ var nativeNodeModulesPlugin = {
14104
14863
  };
14105
14864
  build2.onResolve({ filter: /\.node$/ }, (args) => {
14106
14865
  try {
14107
- const path9 = require.resolve(args.path, { paths: [args.resolveDir] });
14108
- const match = path9.match(
14866
+ const path8 = require.resolve(args.path, { paths: [args.resolveDir] });
14867
+ const match = path8.match(
14109
14868
  /node_modules[/\\]((?:@[^/\\]+[/\\])?[^/\\]+)/
14110
14869
  );
14111
14870
  if (match) {
@@ -14181,7 +14940,7 @@ async function initializeHandles({
14181
14940
  );
14182
14941
  }
14183
14942
  for (const file of newFiles) {
14184
- files[import_path6.default.resolve(file)] = true;
14943
+ files[import_path5.default.resolve(file)] = true;
14185
14944
  }
14186
14945
  }
14187
14946
  if (Object.keys(files).length == 0) {
@@ -14190,15 +14949,15 @@ async function initializeHandles({
14190
14949
  );
14191
14950
  process.exit(0);
14192
14951
  }
14193
- const tmpDir = import_path6.default.join(import_os2.default.tmpdir(), `btevals-${(0, import_uuid3.v4)().slice(0, 8)}`);
14952
+ const tmpDir = import_path5.default.join(import_os.default.tmpdir(), `btevals-${(0, import_uuid3.v4)().slice(0, 8)}`);
14194
14953
  const initPromises = [];
14195
14954
  for (const file of Object.keys(files)) {
14196
- const baseName = `${import_path6.default.basename(
14955
+ const baseName = `${import_path5.default.basename(
14197
14956
  file,
14198
- import_path6.default.extname(file)
14957
+ import_path5.default.extname(file)
14199
14958
  )}-${(0, import_uuid3.v4)().slice(0, 8)}`;
14200
- const outFile = import_path6.default.join(tmpDir, `${baseName}.${OUT_EXT}`);
14201
- const bundleFile = import_path6.default.join(tmpDir, `${baseName}.bundle.js`);
14959
+ const outFile = import_path5.default.join(tmpDir, `${baseName}.${OUT_EXT}`);
14960
+ const bundleFile = import_path5.default.join(tmpDir, `${baseName}.bundle.js`);
14202
14961
  initPromises.push(
14203
14962
  initFile({
14204
14963
  inFile: file,
@@ -14217,276 +14976,6 @@ async function initializeHandles({
14217
14976
  }
14218
14977
  return handles;
14219
14978
  }
14220
- function getEvalRunnerPath() {
14221
- return import_path6.default.resolve(__dirname, "eval-runner.js");
14222
- }
14223
- function buildRunnerEnv(args) {
14224
- const env = {};
14225
- if (args.api_key) {
14226
- env.BRAINTRUST_API_KEY = args.api_key;
14227
- }
14228
- if (args.app_url) {
14229
- env.BRAINTRUST_API_URL = args.app_url;
14230
- }
14231
- if (args.org_name) {
14232
- env.BRAINTRUST_ORG_NAME = args.org_name;
14233
- }
14234
- if (args.no_send_logs) {
14235
- env.BT_EVAL_NO_SEND_LOGS = "1";
14236
- env.BT_EVAL_LOCAL = "1";
14237
- }
14238
- if (args.filter && args.filter.length > 0) {
14239
- env.BT_EVAL_FILTERS = JSON.stringify(args.filter);
14240
- }
14241
- if (args.list) {
14242
- env.BT_EVAL_LIST = "1";
14243
- }
14244
- if (args.dev) {
14245
- env.BT_EVAL_DEV = "1";
14246
- env.BT_EVAL_DEV_HOST = args.dev_host || "localhost";
14247
- env.BT_EVAL_DEV_PORT = String(args.dev_port || 8300);
14248
- if (args.dev_org_name) {
14249
- env.BT_EVAL_DEV_ORG_NAME = args.dev_org_name;
14250
- }
14251
- }
14252
- return env;
14253
- }
14254
- function resolveEvalFiles(inputFiles) {
14255
- const inputPaths = inputFiles.length > 0 ? inputFiles : ["."];
14256
- const resolved = [];
14257
- for (const inputPath of inputPaths) {
14258
- const absPath = import_path6.default.resolve(inputPath);
14259
- let stat2;
14260
- try {
14261
- stat2 = import_fs2.default.lstatSync(absPath);
14262
- } catch {
14263
- console.warn(warning2(`Cannot read ${inputPath}, skipping...`));
14264
- continue;
14265
- }
14266
- if (!stat2.isDirectory()) {
14267
- resolved.push(absPath);
14268
- } else {
14269
- const walked = fsWalk.walkSync(absPath, {
14270
- deepFilter: (entry) => checkMatch(entry.path, null, EXCLUDE),
14271
- entryFilter: (entry) => entry.dirent.isFile() && checkMatch(entry.path, INCLUDE_EVAL, EXCLUDE)
14272
- });
14273
- for (const entry of walked) {
14274
- resolved.push(entry.path);
14275
- }
14276
- }
14277
- }
14278
- return resolved;
14279
- }
14280
- function spawnEvalRunner(args, socketPath, evalFiles) {
14281
- const evalRunnerPath = getEvalRunnerPath();
14282
- const { command, prefixArgs } = resolveRuntime(args.runner);
14283
- const childArgs = [...prefixArgs, evalRunnerPath, ...evalFiles];
14284
- const childEnv = {
14285
- ...process.env,
14286
- ...buildRunnerEnv(args),
14287
- BT_EVAL_SSE_SOCK: socketPath
14288
- };
14289
- const child = (0, import_child_process.spawn)(command, childArgs, {
14290
- env: childEnv,
14291
- stdio: ["ignore", "pipe", "pipe"],
14292
- cwd: process.cwd()
14293
- });
14294
- return child;
14295
- }
14296
- async function runWithRunner(args) {
14297
- const evalFiles = resolveEvalFiles(args.files);
14298
- if (evalFiles.length === 0) {
14299
- console.warn(
14300
- warning2("No eval files were found in any of the provided paths.")
14301
- );
14302
- return true;
14303
- }
14304
- const socketPath = buildSseSocketPath();
14305
- try {
14306
- import_fs2.default.unlinkSync(socketPath);
14307
- } catch {
14308
- }
14309
- const progressReporter = args.no_progress_bars ? new SimpleProgressReporter() : new BarProgressReporter();
14310
- let success = true;
14311
- let receivedDone = false;
14312
- return new Promise((resolve2) => {
14313
- const sseServer = createSseServer(socketPath, (event) => {
14314
- switch (event.type) {
14315
- case "start": {
14316
- const summary = event.data;
14317
- const linkText = summary.experimentUrl ? (0, import_termi_link2.terminalLink)(summary.experimentUrl, summary.experimentUrl, {
14318
- fallback: (_text, url) => url
14319
- }) : "locally";
14320
- console.error(
14321
- import_chalk3.default.cyan("\u25B6") + ` Experiment ${import_chalk3.default.bold(summary.experimentName)} is running at ${linkText}`
14322
- );
14323
- break;
14324
- }
14325
- case "progress": {
14326
- handleProgress(event.data, progressReporter);
14327
- break;
14328
- }
14329
- case "summary": {
14330
- const summary = event.data;
14331
- if (args.jsonl) {
14332
- process.stdout.write(JSON.stringify(summary));
14333
- process.stdout.write("\n");
14334
- } else {
14335
- const formatted = formatExperimentSummaryFancy(
14336
- summary
14337
- );
14338
- process.stdout.write(formatted);
14339
- process.stdout.write("\n");
14340
- }
14341
- break;
14342
- }
14343
- case "console": {
14344
- if (event.data.stream === "stderr") {
14345
- console.error(event.data.message);
14346
- } else {
14347
- console.log(event.data.message);
14348
- }
14349
- break;
14350
- }
14351
- case "error": {
14352
- success = false;
14353
- console.error(import_chalk3.default.red(event.data.message));
14354
- if (args.verbose && event.data.stack) {
14355
- for (const line of event.data.stack.split("\n")) {
14356
- console.error(import_chalk3.default.gray(line));
14357
- }
14358
- }
14359
- if (event.data.message.includes("Please specify an api key")) {
14360
- console.error(
14361
- import_chalk3.default.gray(
14362
- "Hint: pass --api-key or set BRAINTRUST_API_KEY, or use --no-send-logs for local evals."
14363
- )
14364
- );
14365
- }
14366
- break;
14367
- }
14368
- case "list": {
14369
- console.log(event.data.name);
14370
- break;
14371
- }
14372
- case "dev-ready": {
14373
- console.error(
14374
- import_chalk3.default.cyan("\u25B6") + ` Dev server is running at http://${event.data.host}:${event.data.port}`
14375
- );
14376
- break;
14377
- }
14378
- case "done": {
14379
- receivedDone = true;
14380
- progressReporter.stop();
14381
- break;
14382
- }
14383
- }
14384
- });
14385
- const child = spawnEvalRunner(args, socketPath, evalFiles);
14386
- child.stdout?.on("data", (data) => {
14387
- process.stderr.write(data);
14388
- });
14389
- child.stderr?.on("data", (data) => {
14390
- process.stderr.write(data);
14391
- });
14392
- child.on("close", (code) => {
14393
- setTimeout(() => {
14394
- progressReporter.stop();
14395
- sseServer.close();
14396
- if (code !== 0 && code !== null) {
14397
- success = false;
14398
- }
14399
- resolve2(success);
14400
- }, 100);
14401
- });
14402
- child.on("error", (err) => {
14403
- console.error(import_chalk3.default.red(`Failed to start eval runner: ${err.message}`));
14404
- progressReporter.stop();
14405
- sseServer.close();
14406
- resolve2(false);
14407
- });
14408
- });
14409
- }
14410
- function handleProgress(data, progressReporter) {
14411
- let payload;
14412
- try {
14413
- payload = JSON.parse(data.data);
14414
- } catch {
14415
- return;
14416
- }
14417
- if (payload.type !== "eval_progress") {
14418
- return;
14419
- }
14420
- switch (payload.kind) {
14421
- case "start":
14422
- progressReporter.start(data.name, payload.total ?? 0);
14423
- break;
14424
- case "increment":
14425
- progressReporter.increment(data.name);
14426
- break;
14427
- case "set_total":
14428
- if (progressReporter.setTotal && payload.total !== void 0) {
14429
- progressReporter.setTotal(data.name, payload.total);
14430
- }
14431
- break;
14432
- case "stop":
14433
- break;
14434
- }
14435
- }
14436
- async function runWithWatch(args) {
14437
- const evalFiles = resolveEvalFiles(args.files);
14438
- if (evalFiles.length === 0) {
14439
- console.warn(
14440
- warning2("No eval files were found in any of the provided paths.")
14441
- );
14442
- process.exit(0);
14443
- }
14444
- const watchDirs = /* @__PURE__ */ new Set();
14445
- for (const file of evalFiles) {
14446
- watchDirs.add(import_path6.default.dirname(file));
14447
- }
14448
- console.error(`Watching ${(0, import_pluralize4.default)("file", evalFiles.length, true)}...`);
14449
- await runWithRunner(args);
14450
- let debounceTimer = null;
14451
- const watchers = [];
14452
- for (const dir2 of watchDirs) {
14453
- try {
14454
- const watcher = import_fs2.default.watch(
14455
- dir2,
14456
- { recursive: false },
14457
- (_eventType, filename) => {
14458
- if (!filename) return;
14459
- const fullPath = import_path6.default.join(dir2, filename);
14460
- if (!evalFiles.includes(fullPath)) return;
14461
- if (debounceTimer) {
14462
- clearTimeout(debounceTimer);
14463
- }
14464
- debounceTimer = setTimeout(async () => {
14465
- console.error(
14466
- import_chalk3.default.dim(`
14467
- File changed: ${filename}. Re-running...`)
14468
- );
14469
- await runWithRunner(args);
14470
- }, 300);
14471
- }
14472
- );
14473
- watchers.push(watcher);
14474
- } catch {
14475
- }
14476
- }
14477
- const cleanup = () => {
14478
- console.error("Stopped watching.");
14479
- for (const w of watchers) {
14480
- w.close();
14481
- }
14482
- process.exit(0);
14483
- };
14484
- process.on("SIGINT", cleanup);
14485
- process.on("SIGTERM", cleanup);
14486
- await new Promise(() => {
14487
- });
14488
- process.exit(0);
14489
- }
14490
14979
  async function run(args) {
14491
14980
  (0, import_env2.loadEnvConfig)(process.cwd(), true);
14492
14981
  if (args.env_file) {
@@ -14496,23 +14985,6 @@ async function run(args) {
14496
14985
  process.exit(1);
14497
14986
  }
14498
14987
  }
14499
- if (args.bundle || args.push) {
14500
- return runWithEsbuild(args);
14501
- }
14502
- if (args.list && args.watch) {
14503
- console.error(error("Cannot specify both --list and --watch."));
14504
- process.exit(1);
14505
- }
14506
- if (args.watch) {
14507
- await runWithWatch(args);
14508
- return;
14509
- }
14510
- const success = await runWithRunner(args);
14511
- if (!success) {
14512
- process.exit(1);
14513
- }
14514
- }
14515
- async function runWithEsbuild(args) {
14516
14988
  const evaluatorOpts = {
14517
14989
  verbose: args.verbose,
14518
14990
  apiKey: args.api_key,
@@ -14522,19 +14994,38 @@ async function runWithEsbuild(args) {
14522
14994
  bundle: !!args.bundle || !!args.push,
14523
14995
  setCurrent: !!args.push,
14524
14996
  terminateOnFailure: !!args.terminate_on_failure,
14525
- watch: false,
14997
+ watch: !!args.watch,
14526
14998
  jsonl: args.jsonl,
14527
14999
  progressReporter: args.no_progress_bars ? new SimpleProgressReporter() : new BarProgressReporter(),
14528
15000
  filters: args.filter ? parseFilters(args.filter) : [],
14529
- list: false
15001
+ list: !!args.list
14530
15002
  };
15003
+ if (args.list && args.watch) {
15004
+ console.error(error("Cannot specify both --list and --watch."));
15005
+ process.exit(1);
15006
+ }
15007
+ const plugins = evaluatorOpts.watch ? [
15008
+ (fileName) => buildWatchPluginForEvaluator(fileName, evaluatorOpts)
15009
+ ] : [];
14531
15010
  const handles = await initializeHandles({
14532
15011
  files: args.files,
14533
15012
  mode: "eval",
14534
15013
  tsconfig: args.tsconfig,
14535
- plugins: [],
15014
+ plugins,
14536
15015
  externalPackages: args.external_packages
14537
15016
  });
15017
+ if (args.dev) {
15018
+ const { evaluators } = await buildEvaluators(handles, evaluatorOpts);
15019
+ const allEvaluators = Object.values(evaluators.evaluators).map(
15020
+ (e) => e.evaluator
15021
+ );
15022
+ runDevServer(allEvaluators, {
15023
+ host: args.dev_host,
15024
+ port: args.dev_port,
15025
+ orgName: args.dev_org_name
15026
+ });
15027
+ return;
15028
+ }
14538
15029
  let success = true;
14539
15030
  try {
14540
15031
  if (!evaluatorOpts.noSendLogs) {
@@ -14544,7 +15035,16 @@ async function runWithEsbuild(args) {
14544
15035
  appUrl: args.app_url
14545
15036
  });
14546
15037
  }
14547
- success = await runOnce(handles, evaluatorOpts);
15038
+ if (args.watch) {
15039
+ await runAndWatch({
15040
+ handles,
15041
+ onExit: () => {
15042
+ evaluatorOpts.progressReporter.stop();
15043
+ }
15044
+ });
15045
+ } else {
15046
+ success = await runOnce(handles, evaluatorOpts);
15047
+ }
14548
15048
  } finally {
14549
15049
  for (const handle of Object.values(handles)) {
14550
15050
  await handle.destroy();
@@ -14654,10 +15154,6 @@ async function main() {
14654
15154
  help: "Only allow users that belong this to this org name to run remote evals.",
14655
15155
  type: String
14656
15156
  });
14657
- parser_run.add_argument("--runner", {
14658
- help: "JS eval runner binary (e.g. tsx, bun, ts-node). Defaults to tsx if available.",
14659
- type: String
14660
- });
14661
15157
  parser_run.set_defaults({ func: run });
14662
15158
  const parser_push = subparser.add_parser("push", {
14663
15159
  help: "Bundle prompts, tools, scorers, and other resources into Braintrust"