braintrust 0.0.84 → 0.0.86

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