braintrust 0.0.85 → 0.0.87

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/index.js CHANGED
@@ -3651,6 +3651,7 @@ __export(src_exports, {
3651
3651
  Eval: () => Eval,
3652
3652
  Experiment: () => Experiment,
3653
3653
  Logger: () => Logger,
3654
+ NOOP_SPAN: () => NOOP_SPAN,
3654
3655
  NoopSpan: () => NoopSpan,
3655
3656
  SpanImpl: () => SpanImpl,
3656
3657
  _internalGetGlobalState: () => _internalGetGlobalState,
@@ -3658,16 +3659,15 @@ __export(src_exports, {
3658
3659
  currentExperiment: () => currentExperiment,
3659
3660
  currentLogger: () => currentLogger,
3660
3661
  currentSpan: () => currentSpan,
3662
+ getSpanParentObject: () => getSpanParentObject,
3661
3663
  init: () => init,
3662
3664
  initDataset: () => initDataset,
3663
3665
  initLogger: () => initLogger,
3664
3666
  log: () => log,
3665
3667
  login: () => login,
3666
- noopSpan: () => noopSpan,
3667
3668
  startSpan: () => startSpan,
3668
3669
  summarize: () => summarize,
3669
3670
  traced: () => traced,
3670
- withCurrent: () => withCurrent,
3671
3671
  withDataset: () => withDataset,
3672
3672
  withExperiment: () => withExperiment,
3673
3673
  withLogger: () => withLogger,
@@ -7628,10 +7628,14 @@ var simpleGit = gitInstanceFactory;
7628
7628
  // src/gitutil.ts
7629
7629
  var COMMON_BASE_BRANCHES = ["main", "master", "develop"];
7630
7630
  async function currentRepo() {
7631
- const git = simpleGit();
7632
- if (await git.checkIsRepo()) {
7633
- return git;
7634
- } else {
7631
+ try {
7632
+ const git = simpleGit();
7633
+ if (await git.checkIsRepo()) {
7634
+ return git;
7635
+ } else {
7636
+ return null;
7637
+ }
7638
+ } catch (e) {
7635
7639
  return null;
7636
7640
  }
7637
7641
  }
@@ -7860,7 +7864,7 @@ function v4(options, buf, offset) {
7860
7864
  }
7861
7865
  var v4_default = v4;
7862
7866
 
7863
- // ../../node_modules/.pnpm/@braintrust+core@0.0.7/node_modules/@braintrust/core/dist/index.mjs
7867
+ // ../core/js/dist/index.mjs
7864
7868
  var TRANSACTION_ID_FIELD = "_xact_id";
7865
7869
  var IS_MERGE_FIELD = "_is_merge";
7866
7870
  function mergeDicts(mergeInto, mergeFrom) {
@@ -7949,12 +7953,12 @@ var NoopSpan = class {
7949
7953
  }
7950
7954
  log(_) {
7951
7955
  }
7952
- startSpan(_0, _1) {
7953
- return this;
7954
- }
7955
- traced(_0, callback, _1) {
7956
+ traced(callback, _1) {
7956
7957
  return callback(this);
7957
7958
  }
7959
+ startSpan(_1) {
7960
+ return this;
7961
+ }
7958
7962
  end(args) {
7959
7963
  return args?.endTime ?? getCurrentUnixTimestamp();
7960
7964
  }
@@ -7962,16 +7966,25 @@ var NoopSpan = class {
7962
7966
  return this.end(args);
7963
7967
  }
7964
7968
  };
7965
- var noopSpan = new NoopSpan();
7969
+ var NOOP_SPAN = new NoopSpan();
7966
7970
  var BraintrustState = class {
7967
7971
  constructor() {
7972
+ this.apiUrl = null;
7973
+ this.loginToken = null;
7974
+ this.orgId = null;
7975
+ this.orgName = null;
7976
+ this.logUrl = null;
7977
+ this.loggedIn = false;
7978
+ this._apiConn = null;
7979
+ this._logConn = null;
7968
7980
  this.id = v4_default();
7969
- this.currentExperiment = isomorph_default.newAsyncLocalStorage();
7970
- this.currentLogger = isomorph_default.newAsyncLocalStorage();
7981
+ this.currentExperiment = void 0;
7982
+ this.currentLogger = void 0;
7971
7983
  this.currentSpan = isomorph_default.newAsyncLocalStorage();
7972
- if (this.currentSpan.enterWith) {
7973
- this.currentSpan.enterWith(noopSpan);
7974
- }
7984
+ this.resetLoginInfo();
7985
+ globalThis.__inherited_braintrust_state = this;
7986
+ }
7987
+ resetLoginInfo() {
7975
7988
  this.apiUrl = null;
7976
7989
  this.loginToken = null;
7977
7990
  this.orgId = null;
@@ -7980,7 +7993,6 @@ var BraintrustState = class {
7980
7993
  this.loggedIn = false;
7981
7994
  this._apiConn = null;
7982
7995
  this._logConn = null;
7983
- globalThis.__inherited_braintrust_state = this;
7984
7996
  }
7985
7997
  apiConn() {
7986
7998
  if (!this._apiConn) {
@@ -8009,36 +8021,6 @@ function _internalSetInitialState() {
8009
8021
  _state = globalThis.__inherited_braintrust_state || new BraintrustState();
8010
8022
  }
8011
8023
  var _internalGetGlobalState = () => _state;
8012
- var UnterminatedObjectsHandler = class {
8013
- constructor() {
8014
- this.unterminatedObjects = /* @__PURE__ */ new Map();
8015
- isomorph_default.processOn("exit", () => {
8016
- this.warnUnterminated();
8017
- });
8018
- }
8019
- addUnterminated(obj, createdLocation) {
8020
- this.unterminatedObjects.set(obj, createdLocation);
8021
- }
8022
- removeUnterminated(obj) {
8023
- this.unterminatedObjects.delete(obj);
8024
- }
8025
- warnUnterminated() {
8026
- if (this.unterminatedObjects.size === 0) {
8027
- return;
8028
- }
8029
- let warningMessage = "WARNING: Did not close the following braintrust objects. We recommend running `.close` on the listed objects, or by running them inside a callback so they are closed automatically:";
8030
- this.unterminatedObjects.forEach((createdLocation, obj) => {
8031
- let msg = `
8032
- Object of type ${obj?.constructor?.name}`;
8033
- if (createdLocation) {
8034
- msg += ` created at ${JSON.stringify(createdLocation)}`;
8035
- }
8036
- warningMessage += msg;
8037
- });
8038
- console.warn(warningMessage);
8039
- }
8040
- };
8041
- var unterminatedObjects = new UnterminatedObjectsHandler();
8042
8024
  var FailedHTTPResponse = class extends Error {
8043
8025
  constructor(status, text, data = null) {
8044
8026
  super(`${status}: ${text}`);
@@ -8145,45 +8127,29 @@ var HTTPConnection = class _HTTPConnection {
8145
8127
  return await resp.json();
8146
8128
  }
8147
8129
  };
8148
- var Project = class {
8149
- constructor({ name, id }) {
8150
- this.name = name;
8151
- this.id = id;
8152
- }
8153
- async lazyInit() {
8154
- if (this.id === void 0) {
8155
- const response = await _state.apiConn().post_json("api/project/register", {
8156
- project_name: this.name || GLOBAL_PROJECT,
8157
- org_id: _state.orgId
8158
- });
8159
- this.id = response.project.id;
8160
- this.name = response.project.name;
8161
- } else if (this.name === void 0) {
8162
- const response = await _state.apiConn().get_json("api/project", {
8163
- id: this.id
8164
- });
8165
- this.name = response.name;
8166
- }
8167
- return { id: this.id, name: this.name };
8168
- }
8169
- };
8170
8130
  var Logger = class {
8171
- constructor(lazyLogin, lazyProject, logOptions = {}) {
8172
- this.loggedIn = false;
8131
+ constructor(lazyMetadata, logOptions = {}) {
8173
8132
  // For type identification.
8174
8133
  this.kind = "logger";
8175
- this._lazyLogin = lazyLogin;
8176
- this.lazyProject = lazyProject;
8134
+ this.lazyMetadata = lazyMetadata;
8177
8135
  this.logOptions = logOptions;
8178
- this.bgLogger = new BackgroundLogger();
8136
+ const logConn = this.getState().then((state) => state.logConn());
8137
+ this.bgLogger = new BackgroundLogger(logConn);
8179
8138
  this.lastStartTime = getCurrentUnixTimestamp();
8180
8139
  }
8181
- async lazyLogin() {
8182
- if (!this.loggedIn) {
8183
- await this._lazyLogin();
8184
- this.lastStartTime = getCurrentUnixTimestamp();
8185
- this.loggedIn = true;
8186
- }
8140
+ get org_id() {
8141
+ return (async () => {
8142
+ return (await this.lazyMetadata).org_id;
8143
+ })();
8144
+ }
8145
+ get project() {
8146
+ return (async () => {
8147
+ return (await this.lazyMetadata).project;
8148
+ })();
8149
+ }
8150
+ async getState() {
8151
+ await this.lazyMetadata;
8152
+ return _state;
8187
8153
  }
8188
8154
  /**
8189
8155
  * Log a single event. The event will be batched and uploaded behind the scenes if `logOptions.asyncFlush` is true.
@@ -8198,54 +8164,87 @@ var Logger = class {
8198
8164
  * @param event.id: (Optional) a unique identifier for the event. If you don't provide one, BrainTrust will generate one for you.
8199
8165
  * :returns: The `id` of the logged event.
8200
8166
  */
8201
- async log(event) {
8202
- await this.lazyLogin();
8203
- const span = await this.startSpan({ startTime: this.lastStartTime, event });
8167
+ log(event) {
8168
+ const span = this.startSpan({ startTime: this.lastStartTime, event });
8204
8169
  this.lastStartTime = span.end();
8205
- if (!this.logOptions.asyncFlush) {
8206
- await this.flush();
8170
+ const ret = span.id;
8171
+ if (this.logOptions.asyncFlush === true) {
8172
+ return ret;
8173
+ } else {
8174
+ return (async () => {
8175
+ await this.flush();
8176
+ return ret;
8177
+ })();
8178
+ }
8179
+ }
8180
+ /**
8181
+ * Create a new toplevel span underneath the logger. The name defaults to "root".
8182
+ *
8183
+ * See `Span.traced` for full details.
8184
+ */
8185
+ traced(callback, args) {
8186
+ const { setCurrent, ...argsRest } = args ?? {};
8187
+ const span = this.startSpan(argsRest);
8188
+ const ret = runFinally(
8189
+ () => {
8190
+ if (setCurrent ?? true) {
8191
+ return withCurrent(span, callback);
8192
+ } else {
8193
+ return callback(span);
8194
+ }
8195
+ },
8196
+ () => span.end()
8197
+ );
8198
+ if (this.logOptions.asyncFlush) {
8199
+ return ret;
8200
+ } else {
8201
+ return (async () => {
8202
+ const awaitedRet = await ret;
8203
+ await this.flush();
8204
+ return awaitedRet;
8205
+ })();
8207
8206
  }
8208
- return span.id;
8209
8207
  }
8210
8208
  /**
8211
- * Create a new toplevel span. The name parameter is optional and defaults to "root".
8209
+ * Lower-level alternative to `traced`, which does not automatically end the span or mark it as current.
8212
8210
  *
8213
- * See `Span.startSpan` for full details.
8211
+ * See `traced` for full details.
8214
8212
  */
8215
- async startSpan(args) {
8216
- await this.lazyLogin();
8217
- const project = await this.lazyProject.lazyInit();
8213
+ startSpan(args) {
8218
8214
  const { name, ...argsRest } = args ?? {};
8215
+ const parentIds = (async () => ({
8216
+ kind: "project_log",
8217
+ org_id: await this.org_id,
8218
+ project_id: (await this.project).id,
8219
+ log_id: "g"
8220
+ }))();
8219
8221
  return new SpanImpl({
8222
+ parentIds,
8220
8223
  bgLogger: this.bgLogger,
8221
8224
  name: name ?? "root",
8222
- ...argsRest,
8223
- rootProject: project
8225
+ ...argsRest
8224
8226
  });
8225
8227
  }
8226
- /**
8227
- * Wrapper over `Logger.startSpan`, which passes the initialized `Span` it to the given callback and ends it afterwards. See `Span.traced` for full details.
8228
- */
8229
- async traced(callback, args) {
8230
- const { setCurrent, ...argsRest } = args ?? {};
8231
- const span = await this.startSpan(argsRest);
8232
- try {
8233
- let ret = null;
8234
- return await (setCurrent ?? true ? withCurrent(span, () => callback(span)) : callback(span));
8235
- } finally {
8236
- span.end();
8237
- if (!this.logOptions.asyncFlush) {
8238
- await this.flush();
8239
- }
8240
- }
8241
- }
8242
8228
  /*
8243
8229
  * Flush any pending logs to the server.
8244
8230
  */
8245
8231
  async flush() {
8246
8232
  return await this.bgLogger.flush();
8247
8233
  }
8234
+ get asyncFlush() {
8235
+ return this.logOptions.asyncFlush;
8236
+ }
8248
8237
  };
8238
+ function castLogger(logger, asyncFlush) {
8239
+ if (logger === void 0)
8240
+ return void 0;
8241
+ if (asyncFlush && !!asyncFlush !== !!logger.asyncFlush) {
8242
+ throw new Error(
8243
+ `Asserted asyncFlush setting ${asyncFlush} does not match stored logger's setting ${logger.asyncFlush}`
8244
+ );
8245
+ }
8246
+ return logger;
8247
+ }
8249
8248
  var MaxRequestSize = 6 * 1024 * 1024;
8250
8249
  function constructJsonArray(items) {
8251
8250
  return `[${items.join(",")}]`;
@@ -8256,10 +8255,11 @@ function now() {
8256
8255
  return (/* @__PURE__ */ new Date()).getTime();
8257
8256
  }
8258
8257
  var BackgroundLogger = class {
8259
- constructor() {
8258
+ constructor(logConn) {
8260
8259
  this.items = [];
8261
8260
  this.active_flush = Promise.resolve([]);
8262
8261
  this.active_flush_resolved = true;
8262
+ this.logConn = logConn;
8263
8263
  isomorph_default.processOn("beforeExit", async () => {
8264
8264
  await this.flush();
8265
8265
  });
@@ -8273,8 +8273,9 @@ var BackgroundLogger = class {
8273
8273
  }
8274
8274
  async flush_once(batchSize = DefaultBatchSize) {
8275
8275
  this.active_flush_resolved = false;
8276
- const allItems = mergeRowBatch(this.items || []).reverse();
8276
+ const itemPromises = this.items;
8277
8277
  this.items = [];
8278
+ const allItems = mergeRowBatch(await Promise.all(itemPromises)).reverse();
8278
8279
  let postPromises = [];
8279
8280
  while (true) {
8280
8281
  const items = [];
@@ -8299,7 +8300,7 @@ var BackgroundLogger = class {
8299
8300
  for (let i = 0; i < NumRetries; i++) {
8300
8301
  const startTime = now();
8301
8302
  try {
8302
- return (await _state.logConn().post_json("logs", itemsS)).map(
8303
+ return (await (await this.logConn).post_json("logs", itemsS)).map(
8303
8304
  (res) => res.id
8304
8305
  );
8305
8306
  } catch (e) {
@@ -8340,7 +8341,7 @@ var BackgroundLogger = class {
8340
8341
  }
8341
8342
  }
8342
8343
  };
8343
- async function init(project, options = {}) {
8344
+ function init(project, options = {}) {
8344
8345
  const {
8345
8346
  experiment,
8346
8347
  description,
@@ -8351,79 +8352,129 @@ async function init(project, options = {}) {
8351
8352
  apiUrl,
8352
8353
  apiKey,
8353
8354
  orgName,
8354
- disableCache,
8355
8355
  metadata
8356
8356
  } = options || {};
8357
- await login({
8358
- orgName,
8359
- disableCache,
8360
- apiKey,
8361
- apiUrl
8362
- });
8363
- return await _initExperiment(project, {
8364
- experimentName: experiment,
8365
- description,
8366
- dataset,
8367
- update,
8368
- baseExperiment,
8369
- isPublic,
8370
- metadata
8371
- });
8372
- }
8373
- async function withExperiment(project, callback, options = {}) {
8374
- const experiment = await init(project, options);
8375
- return runFinally(
8376
- () => {
8377
- if (options.setCurrent ?? true) {
8378
- return withCurrent(experiment, () => callback(experiment));
8379
- } else {
8380
- return callback(experiment);
8357
+ const lazyMetadata = (async () => {
8358
+ await login({
8359
+ orgName,
8360
+ apiKey,
8361
+ apiUrl
8362
+ });
8363
+ const args = {
8364
+ project_name: project,
8365
+ org_id: _state.orgId
8366
+ };
8367
+ if (experiment) {
8368
+ args["experiment_name"] = experiment;
8369
+ }
8370
+ if (description) {
8371
+ args["description"] = description;
8372
+ }
8373
+ if (update) {
8374
+ args["update"] = update;
8375
+ }
8376
+ const repoStatus = await isomorph_default.getRepoStatus();
8377
+ if (repoStatus) {
8378
+ args["repo_info"] = repoStatus;
8379
+ }
8380
+ if (baseExperiment) {
8381
+ args["base_experiment"] = baseExperiment;
8382
+ } else {
8383
+ args["ancestor_commits"] = await isomorph_default.getPastNAncestors();
8384
+ }
8385
+ if (dataset !== void 0) {
8386
+ args["dataset_id"] = dataset.id;
8387
+ args["dataset_version"] = await dataset.version();
8388
+ }
8389
+ if (isPublic !== void 0) {
8390
+ args["public"] = isPublic;
8391
+ }
8392
+ if (metadata) {
8393
+ args["metadata"] = metadata;
8394
+ }
8395
+ let response = null;
8396
+ while (true) {
8397
+ try {
8398
+ response = await _state.apiConn().post_json("api/experiment/register", args);
8399
+ break;
8400
+ } catch (e) {
8401
+ if (args["base_experiment"] && `${"data" in e && e.data}`.includes("base experiment")) {
8402
+ console.warn(`Base experiment ${args["base_experiment"]} not found.`);
8403
+ delete args["base_experiment"];
8404
+ } else {
8405
+ throw e;
8406
+ }
8381
8407
  }
8382
- },
8383
- () => experiment.close()
8408
+ }
8409
+ return {
8410
+ project: {
8411
+ id: response.project.id,
8412
+ name: response.project.name,
8413
+ fullInfo: response.project
8414
+ },
8415
+ experiment: {
8416
+ id: response.experiment.id,
8417
+ name: response.experiment.name,
8418
+ fullInfo: response.experiment
8419
+ }
8420
+ };
8421
+ })();
8422
+ const ret = new Experiment(lazyMetadata, dataset);
8423
+ if (options.setCurrent ?? true) {
8424
+ _state.currentExperiment = ret;
8425
+ }
8426
+ return ret;
8427
+ }
8428
+ function withExperiment(project, callback, options = {}) {
8429
+ console.warn(
8430
+ "withExperiment is deprecated and will be removed in a future version of braintrust. Simply create the experiment with `init`."
8384
8431
  );
8432
+ const experiment = init(project, options);
8433
+ return callback(experiment);
8385
8434
  }
8386
- async function withLogger(callback, options = {}) {
8387
- const logger = initLogger(options);
8388
- return runFinally(
8389
- () => {
8390
- if (options.setCurrent ?? true) {
8391
- return withCurrent(logger, () => callback(logger));
8392
- } else {
8393
- return callback(logger);
8394
- }
8395
- },
8396
- () => logger.flush()
8435
+ function withLogger(callback, options = {}) {
8436
+ console.warn(
8437
+ "withLogger is deprecated and will be removed in a future version of braintrust. Simply create the logger with `initLogger`."
8397
8438
  );
8439
+ const logger = initLogger(options);
8440
+ return callback(logger);
8398
8441
  }
8399
- async function initDataset(project, options = {}) {
8400
- const {
8401
- dataset,
8402
- description,
8403
- version,
8404
- apiUrl,
8405
- apiKey,
8406
- orgName,
8407
- disableCache
8408
- } = options || {};
8409
- await login({
8410
- orgName,
8411
- disableCache,
8412
- apiKey,
8413
- apiUrl
8414
- });
8415
- return await _initDataset(project, {
8416
- name: dataset,
8417
- description,
8418
- version
8419
- });
8442
+ function initDataset(project, options = {}) {
8443
+ const { dataset, description, version, apiUrl, apiKey, orgName } = options || {};
8444
+ const lazyMetadata = (async () => {
8445
+ await login({
8446
+ orgName,
8447
+ apiKey,
8448
+ apiUrl
8449
+ });
8450
+ const args = {
8451
+ org_id: _state.orgId,
8452
+ project_name: project,
8453
+ dataset_name: dataset,
8454
+ description
8455
+ };
8456
+ const response = await _state.apiConn().post_json("api/dataset/register", args);
8457
+ return {
8458
+ project: {
8459
+ id: response.project.id,
8460
+ name: response.project.name,
8461
+ fullInfo: response.project
8462
+ },
8463
+ dataset: {
8464
+ id: response.dataset.id,
8465
+ name: response.dataset.name,
8466
+ fullInfo: response.dataset
8467
+ }
8468
+ };
8469
+ })();
8470
+ return new Dataset(lazyMetadata, version);
8420
8471
  }
8421
- async function withDataset(project, callback, options = {}) {
8422
- const dataset = await initDataset(project, options);
8423
- return runFinally(
8424
- () => callback(dataset),
8425
- () => dataset.close()
8472
+ function withDataset(project, callback, options = {}) {
8473
+ console.warn(
8474
+ "withDataset is deprecated and will be removed in a future version of braintrust. Simply create the dataset with `initDataset`."
8426
8475
  );
8476
+ const dataset = initDataset(project, options);
8477
+ return callback(dataset);
8427
8478
  }
8428
8479
  function initLogger(options = {}) {
8429
8480
  const {
@@ -8433,42 +8484,67 @@ function initLogger(options = {}) {
8433
8484
  apiUrl,
8434
8485
  apiKey,
8435
8486
  orgName,
8436
- disableCache
8487
+ forceLogin
8437
8488
  } = options || {};
8438
- const lazyLogin = async () => {
8489
+ const lazyMetadata = (async () => {
8439
8490
  await login({
8440
8491
  orgName,
8441
- disableCache,
8442
8492
  apiKey,
8443
- apiUrl
8493
+ apiUrl,
8494
+ forceLogin
8444
8495
  });
8445
- };
8446
- return new Logger(
8447
- lazyLogin,
8448
- new Project({
8449
- name: projectName,
8450
- id: projectId
8451
- }),
8452
- {
8453
- asyncFlush
8496
+ const org_id = _state.orgId;
8497
+ if (projectId === void 0) {
8498
+ const response = await _state.apiConn().post_json("api/project/register", {
8499
+ project_name: projectName || GLOBAL_PROJECT,
8500
+ org_id
8501
+ });
8502
+ return {
8503
+ org_id,
8504
+ project: {
8505
+ id: response.project.id,
8506
+ name: response.project.name,
8507
+ fullInfo: response.project
8508
+ }
8509
+ };
8510
+ } else if (projectName === void 0) {
8511
+ const response = await _state.apiConn().get_json("api/project", {
8512
+ id: projectId
8513
+ });
8514
+ return {
8515
+ org_id,
8516
+ project: {
8517
+ id: projectId,
8518
+ name: response.name,
8519
+ fullInfo: response.project
8520
+ }
8521
+ };
8522
+ } else {
8523
+ return {
8524
+ org_id,
8525
+ project: { id: projectId, name: projectName, fullInfo: {} }
8526
+ };
8454
8527
  }
8455
- );
8528
+ })();
8529
+ const ret = new Logger(lazyMetadata, {
8530
+ asyncFlush
8531
+ });
8532
+ if (options.setCurrent ?? true) {
8533
+ _state.currentLogger = ret;
8534
+ }
8535
+ return ret;
8456
8536
  }
8457
8537
  async function login(options = {}) {
8458
8538
  const {
8459
8539
  apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") || "https://www.braintrustdata.com",
8460
8540
  apiKey = isomorph_default.getEnv("BRAINTRUST_API_KEY"),
8461
- orgName = isomorph_default.getEnv("BRAINTRUST_ORG_NAME"),
8462
- disableCache = false
8541
+ orgName = isomorph_default.getEnv("BRAINTRUST_ORG_NAME")
8463
8542
  } = options || {};
8464
8543
  let { forceLogin = false } = options || {};
8465
- if (apiUrl != _state.apiUrl || apiKey !== void 0 && HTTPConnection.sanitize_token(apiKey) != _state.loginToken || orgName !== void 0 && orgName != _state.orgName) {
8466
- forceLogin = true;
8467
- }
8468
8544
  if (_state.loggedIn && !forceLogin) {
8469
8545
  return;
8470
8546
  }
8471
- _state = new BraintrustState();
8547
+ _state.resetLoginInfo();
8472
8548
  _state.apiUrl = apiUrl;
8473
8549
  let conn = null;
8474
8550
  if (apiKey !== void 0) {
@@ -8501,78 +8577,87 @@ async function login(options = {}) {
8501
8577
  _state.loggedIn = true;
8502
8578
  }
8503
8579
  function log(event) {
8504
- const currentExperiment2 = _state.currentExperiment.getStore();
8505
- if (!currentExperiment2) {
8580
+ console.warn(
8581
+ "braintrust.log is deprecated and will be removed in a future version of braintrust. Use `experiment.log` instead."
8582
+ );
8583
+ const e = currentExperiment();
8584
+ if (!e) {
8506
8585
  throw new Error("Not initialized. Please call init() first");
8507
8586
  }
8508
- return currentExperiment2.log(event);
8587
+ return e.log(event);
8509
8588
  }
8510
8589
  async function summarize(options = {}) {
8511
- const currentExperiment2 = _state.currentExperiment.getStore();
8512
- if (!currentExperiment2) {
8590
+ console.warn(
8591
+ "braintrust.summarize is deprecated and will be removed in a future version of braintrust. Use `experiment.summarize` instead."
8592
+ );
8593
+ const e = currentExperiment();
8594
+ if (!e) {
8513
8595
  throw new Error("Not initialized. Please call init() first");
8514
8596
  }
8515
- return await currentExperiment2.summarize(options);
8597
+ return await e.summarize(options);
8516
8598
  }
8517
8599
  function currentExperiment() {
8518
- return _state.currentExperiment.getStore();
8600
+ return _state.currentExperiment;
8519
8601
  }
8520
- function currentLogger() {
8521
- return _state.currentLogger.getStore();
8602
+ function currentLogger(options) {
8603
+ return castLogger(_state.currentLogger, options?.asyncFlush);
8522
8604
  }
8523
8605
  function currentSpan() {
8524
- return _state.currentSpan.getStore() ?? noopSpan;
8606
+ return _state.currentSpan.getStore() ?? NOOP_SPAN;
8525
8607
  }
8526
- function startSpan(args) {
8527
- const { name: nameOpt, ...argsRest } = args ?? {};
8528
- const name = (nameOpt ?? isomorph_default.getCallerLocation()?.caller_functionname) || "root";
8608
+ function getSpanParentObject(options) {
8529
8609
  const parentSpan = currentSpan();
8530
- if (!parentSpan) {
8531
- throw new Error(
8532
- "Cannot call startSpan() from outside a trace. Please wrap this code in a traced() callback."
8533
- );
8534
- }
8535
- if (!Object.is(parentSpan, noopSpan)) {
8536
- return parentSpan.startSpan(name, argsRest);
8610
+ if (!Object.is(parentSpan, NOOP_SPAN)) {
8611
+ return parentSpan;
8537
8612
  }
8538
8613
  const experiment = currentExperiment();
8539
8614
  if (experiment) {
8540
- return experiment.startSpan({ name, ...argsRest });
8615
+ return experiment;
8541
8616
  }
8542
- const logger = currentLogger();
8617
+ const logger = currentLogger(options);
8543
8618
  if (logger) {
8544
- throw new Error(
8545
- "Cannot start a span within a logger from startSpan(). Use logger.startSpan() instead."
8546
- );
8619
+ return logger;
8547
8620
  }
8548
- return noopSpan;
8621
+ return NOOP_SPAN;
8549
8622
  }
8550
8623
  function traced(callback, args) {
8551
- const span = startSpan(args);
8552
- return runFinally(
8624
+ const { span, parentObject } = startSpanReturnParent(args);
8625
+ const ret = runFinally(
8553
8626
  () => {
8554
8627
  if (args?.setCurrent ?? true) {
8555
- return withCurrent(span, () => callback(span));
8628
+ return withCurrent(span, callback);
8556
8629
  } else {
8557
8630
  return callback(span);
8558
8631
  }
8559
8632
  },
8560
8633
  () => span.end()
8561
8634
  );
8562
- }
8563
- function withCurrent(object, callback) {
8564
- if (object.kind === "experiment") {
8565
- return _state.currentExperiment.run(object, callback);
8566
- } else if (object.kind === "logger") {
8567
- return _state.currentLogger.run(object, callback);
8568
- } else if (object.kind === "span") {
8569
- return _state.currentSpan.run(object, callback);
8635
+ if (args?.asyncFlush) {
8636
+ return ret;
8570
8637
  } else {
8571
- throw new Error(
8572
- `Invalid object of type ${object.constructor.name}`
8573
- );
8638
+ return (async () => {
8639
+ const awaitedRet = await ret;
8640
+ if (parentObject.kind === "logger") {
8641
+ await parentObject.flush();
8642
+ }
8643
+ return awaitedRet;
8644
+ })();
8574
8645
  }
8575
8646
  }
8647
+ function startSpan(args) {
8648
+ return startSpanReturnParent(args).span;
8649
+ }
8650
+ function startSpanReturnParent(args) {
8651
+ const parentObject = getSpanParentObject({
8652
+ asyncFlush: args?.asyncFlush
8653
+ });
8654
+ const { name: nameOpt, ...argsRest } = args ?? {};
8655
+ const name = parentObject.kind === "span" ? nameOpt : nameOpt ?? "root";
8656
+ return { span: parentObject.startSpan({ name, ...argsRest }), parentObject };
8657
+ }
8658
+ function withCurrent(span, callback) {
8659
+ return _state.currentSpan.run(span, () => callback(span));
8660
+ }
8576
8661
  function _check_org_info(org_info, org_name) {
8577
8662
  if (org_info.length === 0) {
8578
8663
  throw new Error("This user is not part of any organizations.");
@@ -8659,83 +8744,34 @@ function validateAndSanitizeExperimentLogFullArgs(event, hasDataset) {
8659
8744
  }
8660
8745
  return event;
8661
8746
  }
8662
- async function _initExperiment(projectName, {
8663
- experimentName,
8664
- description,
8665
- dataset,
8666
- update,
8667
- baseExperiment,
8668
- isPublic,
8669
- metadata
8670
- } = {
8671
- experimentName: void 0,
8672
- description: void 0,
8673
- baseExperiment: void 0,
8674
- isPublic: false,
8675
- metadata: void 0
8676
- }) {
8677
- const args = {
8678
- project_name: projectName,
8679
- org_id: _state.orgId
8680
- };
8681
- if (experimentName) {
8682
- args["experiment_name"] = experimentName;
8683
- }
8684
- if (description) {
8685
- args["description"] = description;
8686
- }
8687
- if (update) {
8688
- args["update"] = update;
8689
- }
8690
- const repoStatus = await isomorph_default.getRepoStatus();
8691
- if (repoStatus) {
8692
- args["repo_info"] = repoStatus;
8693
- }
8694
- if (baseExperiment) {
8695
- args["base_experiment"] = baseExperiment;
8696
- } else {
8697
- args["ancestor_commits"] = await isomorph_default.getPastNAncestors();
8698
- }
8699
- if (dataset !== void 0) {
8700
- args["dataset_id"] = dataset.id;
8701
- args["dataset_version"] = await dataset.version();
8702
- }
8703
- if (isPublic !== void 0) {
8704
- args["public"] = isPublic;
8705
- }
8706
- if (metadata) {
8707
- args["metadata"] = metadata;
8708
- }
8709
- let response = null;
8710
- while (true) {
8711
- try {
8712
- response = await _state.apiConn().post_json("api/experiment/register", args);
8713
- break;
8714
- } catch (e) {
8715
- if (args["base_experiment"] && `${"data" in e && e.data}`.includes("base experiment")) {
8716
- console.warn(`Base experiment ${args["base_experiment"]} not found.`);
8717
- delete args["base_experiment"];
8718
- } else {
8719
- throw e;
8720
- }
8721
- }
8722
- }
8723
- const project = response.project;
8724
- const experiment = response.experiment;
8725
- return new Experiment(project, experiment.id, experiment.name, dataset);
8726
- }
8727
8747
  var Experiment = class {
8728
- constructor(project, id, name, dataset) {
8748
+ constructor(lazyMetadata, dataset) {
8729
8749
  // For type identification.
8730
8750
  this.kind = "experiment";
8731
- this.finished = false;
8732
- this.project = project;
8733
- this.id = id;
8734
- this.name = name;
8751
+ this.lazyMetadata = lazyMetadata;
8735
8752
  this.dataset = dataset;
8736
- this.bgLogger = new BackgroundLogger();
8753
+ const logConn = this.getState().then((state) => state.logConn());
8754
+ this.bgLogger = new BackgroundLogger(logConn);
8737
8755
  this.lastStartTime = getCurrentUnixTimestamp();
8738
- unterminatedObjects.addUnterminated(this, isomorph_default.getCallerLocation());
8756
+ }
8757
+ get id() {
8758
+ return (async () => {
8759
+ return (await this.lazyMetadata).experiment.id;
8760
+ })();
8761
+ }
8762
+ get name() {
8763
+ return (async () => {
8764
+ return (await this.lazyMetadata).experiment.name;
8765
+ })();
8766
+ }
8767
+ get project() {
8768
+ return (async () => {
8769
+ return (await this.lazyMetadata).project;
8770
+ })();
8771
+ }
8772
+ async getState() {
8773
+ await this.lazyMetadata;
8774
+ return _state;
8739
8775
  }
8740
8776
  /**
8741
8777
  * Log a single event to the experiment. The event will be batched and uploaded behind the scenes.
@@ -8753,29 +8789,15 @@ var Experiment = class {
8753
8789
  * :returns: The `id` of the logged event.
8754
8790
  */
8755
8791
  log(event) {
8756
- this.checkNotFinished();
8757
8792
  event = validateAndSanitizeExperimentLogFullArgs(event, !!this.dataset);
8758
8793
  const span = this.startSpan({ startTime: this.lastStartTime, event });
8759
8794
  this.lastStartTime = span.end();
8760
8795
  return span.id;
8761
8796
  }
8762
8797
  /**
8763
- * Create a new toplevel span. The name parameter is optional and defaults to "root".
8798
+ * Create a new toplevel span underneath the experiment. The name defaults to "root".
8764
8799
  *
8765
- * See `Span.startSpan` for full details.
8766
- */
8767
- startSpan(args) {
8768
- this.checkNotFinished();
8769
- const { name, ...argsRest } = args ?? {};
8770
- return new SpanImpl({
8771
- bgLogger: this.bgLogger,
8772
- name: name ?? "root",
8773
- ...argsRest,
8774
- rootExperiment: this
8775
- });
8776
- }
8777
- /**
8778
- * Wrapper over `Experiment.startSpan`, which passes the initialized `Span` it to the given callback and ends it afterwards. See `Span.traced` for full details.
8800
+ * See `Span.traced` for full details.
8779
8801
  */
8780
8802
  traced(callback, args) {
8781
8803
  const { setCurrent, ...argsRest } = args ?? {};
@@ -8783,7 +8805,7 @@ var Experiment = class {
8783
8805
  return runFinally(
8784
8806
  () => {
8785
8807
  if (setCurrent ?? true) {
8786
- return withCurrent(span, () => callback(span));
8808
+ return withCurrent(span, callback);
8787
8809
  } else {
8788
8810
  return callback(span);
8789
8811
  }
@@ -8791,6 +8813,25 @@ var Experiment = class {
8791
8813
  () => span.end()
8792
8814
  );
8793
8815
  }
8816
+ /**
8817
+ * Lower-level alternative to `traced`, which does not automatically end the span or mark it as current.
8818
+ *
8819
+ * See `traced` for full details.
8820
+ */
8821
+ startSpan(args) {
8822
+ const { name, ...argsRest } = args ?? {};
8823
+ const parentIds = (async () => ({
8824
+ kind: "experiment",
8825
+ project_id: (await this.project).id,
8826
+ experiment_id: await this.id
8827
+ }))();
8828
+ return new SpanImpl({
8829
+ parentIds,
8830
+ bgLogger: this.bgLogger,
8831
+ name: name ?? "root",
8832
+ ...argsRest
8833
+ });
8834
+ }
8794
8835
  /**
8795
8836
  * Summarize the experiment, including the scores (compared to the closest reference experiment) and metadata.
8796
8837
  *
@@ -8802,18 +8843,21 @@ var Experiment = class {
8802
8843
  async summarize(options = {}) {
8803
8844
  let { summarizeScores = true, comparisonExperimentId = void 0 } = options || {};
8804
8845
  await this.bgLogger.flush();
8805
- const projectUrl = `${_state.apiUrl}/app/${encodeURIComponent(
8806
- _state.orgName
8807
- )}/p/${encodeURIComponent(this.project.name)}`;
8808
- const experimentUrl = `${projectUrl}/${encodeURIComponent(this.name)}`;
8846
+ const state = await this.getState();
8847
+ const projectUrl = `${state.apiUrl}/app/${encodeURIComponent(
8848
+ state.orgName
8849
+ )}/p/${encodeURIComponent((await this.project).name)}`;
8850
+ const experimentUrl = `${projectUrl}/${encodeURIComponent(
8851
+ await this.name
8852
+ )}`;
8809
8853
  let scores = void 0;
8810
8854
  let metrics = void 0;
8811
8855
  let comparisonExperimentName = void 0;
8812
8856
  if (summarizeScores) {
8813
8857
  if (comparisonExperimentId === void 0) {
8814
- const conn = _state.logConn();
8858
+ const conn = state.logConn();
8815
8859
  const resp = await conn.get("/crud/base_experiments", {
8816
- id: this.id
8860
+ id: await this.id
8817
8861
  });
8818
8862
  const base_experiments = await resp.json();
8819
8863
  if (base_experiments.length > 0) {
@@ -8822,10 +8866,10 @@ var Experiment = class {
8822
8866
  }
8823
8867
  }
8824
8868
  if (comparisonExperimentId !== void 0) {
8825
- const results = await _state.logConn().get_json(
8869
+ const results = await state.logConn().get_json(
8826
8870
  "/experiment-comparison2",
8827
8871
  {
8828
- experiment_id: this.id,
8872
+ experiment_id: await this.id,
8829
8873
  base_experiment_id: comparisonExperimentId
8830
8874
  },
8831
8875
  3
@@ -8835,8 +8879,8 @@ var Experiment = class {
8835
8879
  }
8836
8880
  }
8837
8881
  return {
8838
- projectName: this.project.name,
8839
- experimentName: this.name,
8882
+ projectName: (await this.project).name,
8883
+ experimentName: await this.name,
8840
8884
  projectUrl,
8841
8885
  experimentUrl,
8842
8886
  comparisonExperimentName,
@@ -8845,118 +8889,99 @@ var Experiment = class {
8845
8889
  };
8846
8890
  }
8847
8891
  /**
8848
- * Finish the experiment and return its id. After calling close, you may not invoke any further methods on the experiment object.
8849
- *
8850
- * Will be invoked automatically if the experiment is wrapped in a callback passed to `braintrust.withExperiment`.
8851
- *
8852
- * @returns The experiment id.
8892
+ * Flush any pending rows to the server.
8893
+ */
8894
+ async flush() {
8895
+ return await this.bgLogger.flush();
8896
+ }
8897
+ /**
8898
+ * This function is deprecated. You can simply remove it from your code.
8853
8899
  */
8854
8900
  async close() {
8855
- this.checkNotFinished();
8856
- await this.bgLogger.flush();
8857
- this.finished = true;
8858
- unterminatedObjects.removeUnterminated(this);
8901
+ console.warn(
8902
+ "close is deprecated and will be removed in a future version of braintrust. It is now a no-op and can be removed"
8903
+ );
8859
8904
  return this.id;
8860
8905
  }
8861
- checkNotFinished() {
8862
- if (this.finished) {
8863
- throw new Error("Cannot invoke method on finished experiment");
8864
- }
8865
- }
8866
8906
  };
8867
8907
  var SpanImpl = class _SpanImpl {
8868
8908
  // root_experiment should only be specified for a root span. parent_span
8869
8909
  // should only be specified for non-root spans.
8870
8910
  constructor(args) {
8871
8911
  this.kind = "span";
8872
- this.finished = false;
8873
8912
  this.loggedEndTime = void 0;
8874
8913
  this.bgLogger = args.bgLogger;
8875
8914
  const callerLocation = isomorph_default.getCallerLocation();
8915
+ const name = (() => {
8916
+ if (args.name)
8917
+ return args.name;
8918
+ if (callerLocation) {
8919
+ const pathComponents = callerLocation.caller_filename.split("/");
8920
+ const filename = pathComponents[pathComponents.length - 1];
8921
+ return [callerLocation.caller_functionname].concat(
8922
+ filename ? [`${filename}:${callerLocation.caller_lineno}`] : []
8923
+ ).join(":");
8924
+ }
8925
+ return "subspan";
8926
+ })();
8876
8927
  this.internalData = {
8877
8928
  metrics: {
8878
8929
  start: args.startTime ?? getCurrentUnixTimestamp(),
8879
8930
  ...callerLocation
8880
8931
  },
8881
- span_attributes: { ...args.spanAttributes, name: args.name },
8932
+ span_attributes: { ...args.spanAttributes, name },
8882
8933
  created: (/* @__PURE__ */ new Date()).toISOString()
8883
8934
  };
8935
+ this.parentIds = args.parentIds;
8884
8936
  const id = args.event?.id ?? v4_default();
8885
8937
  const span_id = v4_default();
8886
- if ("rootExperiment" in args) {
8887
- this._object_info = {
8888
- id,
8889
- span_id,
8890
- root_span_id: span_id,
8891
- project_id: args.rootExperiment.project.id,
8892
- experiment_id: args.rootExperiment.id
8893
- };
8894
- } else if ("rootProject" in args) {
8895
- this._object_info = {
8896
- id,
8897
- span_id,
8898
- root_span_id: span_id,
8899
- org_id: _state.orgId,
8900
- project_id: args.rootProject.id,
8901
- log_id: "g"
8902
- };
8903
- } else if ("parentSpan" in args) {
8904
- this._object_info = {
8905
- ...args.parentSpan._object_info,
8906
- id,
8907
- span_id
8908
- };
8909
- this.internalData.span_parents = [args.parentSpan.span_id];
8910
- } else {
8911
- throw new Error("Must provide either 'rootExperiment' or 'parentSpan'");
8938
+ this.rowIds = {
8939
+ id,
8940
+ span_id,
8941
+ root_span_id: args.parentSpanInfo?.root_span_id ?? span_id
8942
+ };
8943
+ if (args.parentSpanInfo) {
8944
+ this.internalData.span_parents = [args.parentSpanInfo.span_id];
8912
8945
  }
8913
8946
  this.isMerge = false;
8914
8947
  const { id: _id, ...eventRest } = args.event ?? {};
8915
8948
  this.log(eventRest);
8916
8949
  this.isMerge = true;
8917
- unterminatedObjects.addUnterminated(this, callerLocation);
8918
8950
  }
8919
8951
  get id() {
8920
- return this._object_info.id;
8952
+ return this.rowIds.id;
8921
8953
  }
8922
8954
  get span_id() {
8923
- return this._object_info.span_id;
8955
+ return this.rowIds.span_id;
8924
8956
  }
8925
8957
  get root_span_id() {
8926
- return this._object_info.root_span_id;
8958
+ return this.rowIds.root_span_id;
8927
8959
  }
8928
8960
  log(event) {
8929
- this.checkNotFinished();
8930
8961
  const sanitized = validateAndSanitizeExperimentLogPartialArgs(event);
8931
8962
  const sanitizedAndInternalData = { ...this.internalData };
8932
8963
  mergeDicts(sanitizedAndInternalData, sanitized);
8933
- const record = {
8934
- ...sanitizedAndInternalData,
8935
- ...this._object_info,
8936
- [IS_MERGE_FIELD]: this.isMerge
8937
- };
8938
- if (record.metrics?.end) {
8939
- this.loggedEndTime = record.metrics?.end;
8940
- }
8941
8964
  this.internalData = {};
8965
+ if (sanitizedAndInternalData.metrics?.end) {
8966
+ this.loggedEndTime = sanitizedAndInternalData.metrics?.end;
8967
+ }
8968
+ const record = (async () => {
8969
+ return {
8970
+ ...sanitizedAndInternalData,
8971
+ ...this.rowIds,
8972
+ ...await this.parentIds,
8973
+ [IS_MERGE_FIELD]: this.isMerge
8974
+ };
8975
+ })();
8942
8976
  this.bgLogger.log([record]);
8943
8977
  }
8944
- startSpan(name, args) {
8945
- this.checkNotFinished();
8946
- return new _SpanImpl({
8947
- bgLogger: this.bgLogger,
8948
- name,
8949
- ...args,
8950
- parentSpan: this
8951
- });
8952
- }
8953
- traced(name, callback, args) {
8978
+ traced(callback, args) {
8954
8979
  const { setCurrent, ...argsRest } = args ?? {};
8955
- const span = this.startSpan(name, argsRest);
8980
+ const span = this.startSpan(argsRest);
8956
8981
  return runFinally(
8957
8982
  () => {
8958
8983
  if (setCurrent ?? true) {
8959
- return withCurrent(span, () => callback(span));
8984
+ return withCurrent(span, callback);
8960
8985
  } else {
8961
8986
  return callback(span);
8962
8987
  }
@@ -8964,8 +8989,18 @@ var SpanImpl = class _SpanImpl {
8964
8989
  () => span.end()
8965
8990
  );
8966
8991
  }
8992
+ startSpan(args) {
8993
+ return new _SpanImpl({
8994
+ parentIds: this.parentIds,
8995
+ bgLogger: this.bgLogger,
8996
+ parentSpanInfo: {
8997
+ span_id: this.rowIds.span_id,
8998
+ root_span_id: this.rowIds.root_span_id
8999
+ },
9000
+ ...args
9001
+ });
9002
+ }
8967
9003
  end(args) {
8968
- this.checkNotFinished();
8969
9004
  let endTime;
8970
9005
  if (!this.loggedEndTime) {
8971
9006
  endTime = args?.endTime ?? getCurrentUnixTimestamp();
@@ -8974,45 +9009,38 @@ var SpanImpl = class _SpanImpl {
8974
9009
  endTime = this.loggedEndTime;
8975
9010
  }
8976
9011
  this.log({});
8977
- this.finished = true;
8978
- unterminatedObjects.removeUnterminated(this);
8979
9012
  return endTime;
8980
9013
  }
8981
9014
  close(args) {
8982
9015
  return this.end(args);
8983
9016
  }
8984
- checkNotFinished() {
8985
- if (this.finished) {
8986
- throw new Error("Cannot invoke method on finished span");
8987
- }
8988
- }
8989
9017
  };
8990
- async function _initDataset(project_name, {
8991
- name,
8992
- description,
8993
- version
8994
- } = {}) {
8995
- const args = {
8996
- org_id: _state.orgId,
8997
- project_name,
8998
- dataset_name: name,
8999
- description
9000
- };
9001
- const response = await _state.apiConn().post_json("api/dataset/register", args);
9002
- const project = response.project;
9003
- const dataset = response.dataset;
9004
- return new Dataset(project, dataset.id, dataset.name, version);
9005
- }
9006
9018
  var Dataset = class {
9007
- constructor(project, id, name, pinnedVersion) {
9019
+ constructor(lazyMetadata, pinnedVersion) {
9008
9020
  this._fetchedData = void 0;
9009
- this.finished = false;
9010
- this.project = project;
9011
- this.id = id;
9012
- this.name = name;
9021
+ this.lazyMetadata = lazyMetadata;
9013
9022
  this.pinnedVersion = pinnedVersion;
9014
- this.logger = new BackgroundLogger();
9015
- unterminatedObjects.addUnterminated(this, isomorph_default.getCallerLocation());
9023
+ const logConn = this.getState().then((state) => state.logConn());
9024
+ this.bgLogger = new BackgroundLogger(logConn);
9025
+ }
9026
+ get id() {
9027
+ return (async () => {
9028
+ return (await this.lazyMetadata).dataset.id;
9029
+ })();
9030
+ }
9031
+ get name() {
9032
+ return (async () => {
9033
+ return (await this.lazyMetadata).dataset.name;
9034
+ })();
9035
+ }
9036
+ get project() {
9037
+ return (async () => {
9038
+ return (await this.lazyMetadata).project;
9039
+ })();
9040
+ }
9041
+ async getState() {
9042
+ await this.lazyMetadata;
9043
+ return _state;
9016
9044
  }
9017
9045
  /**
9018
9046
  * Insert a single record to the dataset. The record will be batched and uploaded behind the scenes. If you pass in an `id`,
@@ -9034,7 +9062,6 @@ var Dataset = class {
9034
9062
  metadata,
9035
9063
  id
9036
9064
  }) {
9037
- this.checkNotFinished();
9038
9065
  if (metadata !== void 0) {
9039
9066
  for (const key of Object.keys(metadata)) {
9040
9067
  if (typeof key !== "string") {
@@ -9042,29 +9069,29 @@ var Dataset = class {
9042
9069
  }
9043
9070
  }
9044
9071
  }
9045
- const args = {
9046
- id: id || v4_default(),
9072
+ const rowId = id || v4_default();
9073
+ const args = (async () => ({
9074
+ id: rowId,
9047
9075
  inputs: input,
9048
9076
  output,
9049
- project_id: this.project.id,
9050
- dataset_id: this.id,
9077
+ project_id: (await this.project).id,
9078
+ dataset_id: await this.id,
9051
9079
  created: (/* @__PURE__ */ new Date()).toISOString(),
9052
9080
  metadata
9053
- };
9054
- this.logger.log([args]);
9055
- return args.id;
9081
+ }))();
9082
+ this.bgLogger.log([args]);
9083
+ return rowId;
9056
9084
  }
9057
9085
  delete(id) {
9058
- this.checkNotFinished();
9059
- const args = {
9086
+ const args = (async () => ({
9060
9087
  id,
9061
- project_id: this.project.id,
9062
- dataset_id: this.id,
9088
+ project_id: (await this.project).id,
9089
+ dataset_id: await this.id,
9063
9090
  created: (/* @__PURE__ */ new Date()).toISOString(),
9064
9091
  _object_delete: true
9065
- };
9066
- this.logger.log([args]);
9067
- return args.id;
9092
+ }))();
9093
+ this.bgLogger.log([args]);
9094
+ return id;
9068
9095
  }
9069
9096
  /**
9070
9097
  * Summarize the dataset, including high level metrics about its size and other metadata.
@@ -9073,26 +9100,26 @@ var Dataset = class {
9073
9100
  * @returns A summary of the dataset.
9074
9101
  */
9075
9102
  async summarize(options = {}) {
9076
- this.checkNotFinished();
9077
9103
  let { summarizeData = true } = options || {};
9078
- await this.logger.flush();
9079
- const projectUrl = `${_state.apiUrl}/app/${encodeURIComponent(
9080
- _state.orgName
9081
- )}/p/${encodeURIComponent(this.project.name)}`;
9082
- const datasetUrl = `${projectUrl}/d/${encodeURIComponent(this.name)}`;
9104
+ await this.bgLogger.flush();
9105
+ const state = await this.getState();
9106
+ const projectUrl = `${state.apiUrl}/app/${encodeURIComponent(
9107
+ state.orgName
9108
+ )}/p/${encodeURIComponent((await this.project).name)}`;
9109
+ const datasetUrl = `${projectUrl}/d/${encodeURIComponent(await this.name)}`;
9083
9110
  let dataSummary = void 0;
9084
9111
  if (summarizeData) {
9085
- dataSummary = await _state.logConn().get_json(
9112
+ dataSummary = await state.logConn().get_json(
9086
9113
  "dataset-summary",
9087
9114
  {
9088
- dataset_id: this.id
9115
+ dataset_id: await this.id
9089
9116
  },
9090
9117
  3
9091
9118
  );
9092
9119
  }
9093
9120
  return {
9094
- projectName: this.project.name,
9095
- datasetName: this.name,
9121
+ projectName: (await this.project).name,
9122
+ datasetName: await this.name,
9096
9123
  projectUrl,
9097
9124
  datasetUrl,
9098
9125
  dataSummary
@@ -9117,7 +9144,6 @@ var Dataset = class {
9117
9144
  * @returns An iterator over the dataset's records.
9118
9145
  */
9119
9146
  async *fetch() {
9120
- this.checkNotFinished();
9121
9147
  const records = await this.fetchedData();
9122
9148
  for (const record of records) {
9123
9149
  yield {
@@ -9141,14 +9167,13 @@ var Dataset = class {
9141
9167
  * ```
9142
9168
  */
9143
9169
  [Symbol.asyncIterator]() {
9144
- this.checkNotFinished();
9145
9170
  return this.fetch();
9146
9171
  }
9147
9172
  async fetchedData() {
9148
- this.checkNotFinished();
9149
9173
  if (this._fetchedData === void 0) {
9150
- const resp = await _state.logConn().get("object/dataset", {
9151
- id: this.id,
9174
+ const state = await this.getState();
9175
+ const resp = await state.logConn().get("object/dataset", {
9176
+ id: await this.id,
9152
9177
  fmt: "json",
9153
9178
  version: this.pinnedVersion
9154
9179
  });
@@ -9158,11 +9183,9 @@ var Dataset = class {
9158
9183
  return this._fetchedData || [];
9159
9184
  }
9160
9185
  clearCache() {
9161
- this.checkNotFinished();
9162
9186
  this._fetchedData = void 0;
9163
9187
  }
9164
9188
  async version() {
9165
- this.checkNotFinished();
9166
9189
  if (this.pinnedVersion !== void 0) {
9167
9190
  return this.pinnedVersion;
9168
9191
  } else {
@@ -9178,24 +9201,20 @@ var Dataset = class {
9178
9201
  }
9179
9202
  }
9180
9203
  /**
9181
- * Terminate connection to the dataset and return its id. After calling close, you may not invoke any further methods on the dataset object.
9182
- *
9183
- * Will be invoked automatically if the dataset is bound as a context manager.
9184
- *
9185
- * @returns The dataset id.
9204
+ * Flush any pending rows to the server.
9205
+ */
9206
+ async flush() {
9207
+ return await this.bgLogger.flush();
9208
+ }
9209
+ /**
9210
+ * This function is deprecated. You can simply remove it from your code.
9186
9211
  */
9187
9212
  async close() {
9188
- this.checkNotFinished();
9189
- await this.logger.flush();
9190
- this.finished = true;
9191
- unterminatedObjects.removeUnterminated(this);
9213
+ console.warn(
9214
+ "close is deprecated and will be removed in a future version of braintrust. It is now a no-op and can be removed"
9215
+ );
9192
9216
  return this.id;
9193
9217
  }
9194
- checkNotFinished() {
9195
- if (this.finished) {
9196
- throw new Error("Cannot invoke method on finished dataset");
9197
- }
9198
- }
9199
9218
  };
9200
9219
 
9201
9220
  // src/node.ts
@@ -9271,28 +9290,28 @@ async function Eval(name, evaluator) {
9271
9290
  }
9272
9291
  const progressReporter = new BarProgressReporter();
9273
9292
  try {
9274
- return await withExperiment(
9275
- name,
9276
- async (experiment) => {
9277
- const ret = await runEvaluator(
9278
- experiment,
9279
- {
9280
- evalName,
9281
- projectName: name,
9282
- ...evaluator
9283
- },
9284
- progressReporter,
9285
- []
9286
- );
9287
- reportEvaluatorResult(name, ret, { verbose: true, jsonl: false });
9288
- return ret.summary;
9289
- },
9290
- {
9291
- experiment: evaluator.experimentName,
9292
- metadata: evaluator.metadata,
9293
- isPublic: evaluator.isPublic
9294
- }
9295
- );
9293
+ const experiment = init(name, {
9294
+ experiment: evaluator.experimentName,
9295
+ metadata: evaluator.metadata,
9296
+ isPublic: evaluator.isPublic,
9297
+ setCurrent: false
9298
+ });
9299
+ try {
9300
+ const ret = await runEvaluator(
9301
+ experiment,
9302
+ {
9303
+ evalName,
9304
+ projectName: name,
9305
+ ...evaluator
9306
+ },
9307
+ progressReporter,
9308
+ []
9309
+ );
9310
+ reportEvaluatorResult(name, ret, { verbose: true, jsonl: false });
9311
+ return ret.summary;
9312
+ } finally {
9313
+ experiment.flush();
9314
+ }
9296
9315
  } finally {
9297
9316
  progressReporter.stop();
9298
9317
  }
@@ -9332,30 +9351,27 @@ async function runEvaluator(experiment, evaluator, progressReporter, filters) {
9332
9351
  let output = void 0;
9333
9352
  let error2 = void 0;
9334
9353
  let scores = {};
9335
- const callback = async () => {
9354
+ const callback = async (rootSpan) => {
9336
9355
  try {
9337
9356
  const meta = (o) => metadata = { ...metadata, ...o };
9338
- await traced(
9339
- async () => {
9340
- const outputResult = evaluator.task(datum.input, {
9341
- meta,
9342
- span: currentSpan()
9343
- });
9357
+ await rootSpan.traced(
9358
+ async (span) => {
9359
+ const outputResult = evaluator.task(datum.input, { meta, span });
9344
9360
  if (outputResult instanceof Promise) {
9345
9361
  output = await outputResult;
9346
9362
  } else {
9347
9363
  output = outputResult;
9348
9364
  }
9349
- currentSpan().log({ input: datum.input, output });
9365
+ span.log({ input: datum.input, output });
9350
9366
  },
9351
9367
  { name: "task" }
9352
9368
  );
9353
- currentSpan().log({ output });
9369
+ rootSpan.log({ output });
9354
9370
  const scoringArgs = { ...datum, metadata, output };
9355
9371
  const scoreResults = await Promise.all(
9356
9372
  evaluator.scores.map(async (score, score_idx) => {
9357
- return traced(
9358
- async () => {
9373
+ return rootSpan.traced(
9374
+ async (span) => {
9359
9375
  const scoreResult = score(scoringArgs);
9360
9376
  const result = scoreResult instanceof Promise ? await scoreResult : scoreResult;
9361
9377
  const {
@@ -9363,7 +9379,7 @@ async function runEvaluator(experiment, evaluator, progressReporter, filters) {
9363
9379
  name: _,
9364
9380
  ...resultRest
9365
9381
  } = result;
9366
- currentSpan().log({
9382
+ span.log({
9367
9383
  output: resultRest,
9368
9384
  metadata: resultMetadata
9369
9385
  });
@@ -9392,7 +9408,7 @@ async function runEvaluator(experiment, evaluator, progressReporter, filters) {
9392
9408
  if (Object.keys(scoreMetadata).length > 0) {
9393
9409
  meta({ scores: scoreMetadata });
9394
9410
  }
9395
- currentSpan().log({ scores, metadata });
9411
+ rootSpan.log({ scores, metadata });
9396
9412
  } catch (e) {
9397
9413
  error2 = e;
9398
9414
  } finally {
@@ -9405,17 +9421,16 @@ async function runEvaluator(experiment, evaluator, progressReporter, filters) {
9405
9421
  error: error2
9406
9422
  };
9407
9423
  };
9408
- const rootSpan = experiment ? experiment.startSpan({
9409
- name: "eval",
9410
- event: {
9411
- input: datum.input,
9412
- expected: datum.expected
9413
- }
9414
- }) : noopSpan;
9415
- try {
9416
- return await withCurrent(rootSpan, callback);
9417
- } finally {
9418
- rootSpan.end();
9424
+ if (!experiment) {
9425
+ return await callback(NOOP_SPAN);
9426
+ } else {
9427
+ return await experiment.traced(callback, {
9428
+ name: "eval",
9429
+ event: {
9430
+ input: datum.input,
9431
+ expected: datum.expected
9432
+ }
9433
+ });
9419
9434
  }
9420
9435
  });
9421
9436
  const results = await Promise.all(evals);
@@ -9678,6 +9693,7 @@ configureNode();
9678
9693
  Eval,
9679
9694
  Experiment,
9680
9695
  Logger,
9696
+ NOOP_SPAN,
9681
9697
  NoopSpan,
9682
9698
  SpanImpl,
9683
9699
  _internalGetGlobalState,
@@ -9685,16 +9701,15 @@ configureNode();
9685
9701
  currentExperiment,
9686
9702
  currentLogger,
9687
9703
  currentSpan,
9704
+ getSpanParentObject,
9688
9705
  init,
9689
9706
  initDataset,
9690
9707
  initLogger,
9691
9708
  log,
9692
9709
  login,
9693
- noopSpan,
9694
9710
  startSpan,
9695
9711
  summarize,
9696
9712
  traced,
9697
- withCurrent,
9698
9713
  withDataset,
9699
9714
  withExperiment,
9700
9715
  withLogger,