braintrust 0.3.7 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/browser.js CHANGED
@@ -87,6 +87,44 @@ var Queue = (_class = class {
87
87
  }
88
88
  }, _class);
89
89
 
90
+ // src/id-gen.ts
91
+
92
+ function generateHexId(bytes) {
93
+ let result = "";
94
+ for (let i = 0; i < bytes; i++) {
95
+ result += Math.floor(Math.random() * 256).toString(16).padStart(2, "0");
96
+ }
97
+ return result;
98
+ }
99
+ var IDGenerator = class {
100
+ };
101
+ var UUIDGenerator = class extends IDGenerator {
102
+ getSpanId() {
103
+ return _uuid.v4.call(void 0, );
104
+ }
105
+ getTraceId() {
106
+ return _uuid.v4.call(void 0, );
107
+ }
108
+ shareRootSpanId() {
109
+ return true;
110
+ }
111
+ };
112
+ var OTELIDGenerator = class extends IDGenerator {
113
+ getSpanId() {
114
+ return generateHexId(8);
115
+ }
116
+ getTraceId() {
117
+ return generateHexId(16);
118
+ }
119
+ shareRootSpanId() {
120
+ return false;
121
+ }
122
+ };
123
+ function getIdGenerator() {
124
+ const useOtel = typeof process !== "undefined" && _optionalChain([process, 'access', _2 => _2.env, 'optionalAccess', _3 => _3.BRAINTRUST_OTEL_COMPAT, 'optionalAccess', _4 => _4.toLowerCase, 'call', _5 => _5()]) === "true";
125
+ return useOtel ? new OTELIDGenerator() : new UUIDGenerator();
126
+ }
127
+
90
128
  // util/db_fields.ts
91
129
  var TRANSACTION_ID_FIELD = "_xact_id";
92
130
  var IS_MERGE_FIELD = "_is_merge";
@@ -237,7 +275,7 @@ var SpanComponentsV1 = class _SpanComponentsV1 {
237
275
  return {
238
276
  objectType: this.objectType,
239
277
  objectId: this.objectId,
240
- rowIds: _optionalChain([this, 'access', _2 => _2.rowIds, 'optionalAccess', _3 => _3.toObject, 'call', _4 => _4()])
278
+ rowIds: _optionalChain([this, 'access', _6 => _6.rowIds, 'optionalAccess', _7 => _7.toObject, 'call', _8 => _8()])
241
279
  };
242
280
  }
243
281
  };
@@ -451,7 +489,7 @@ var SpanComponentsV2 = class _SpanComponentsV2 {
451
489
  objectType: this.objectType,
452
490
  objectId: this.objectId,
453
491
  computeObjectMetadataArgs: this.computeObjectMetadataArgs,
454
- rowIds: _optionalChain([this, 'access', _5 => _5.rowIds, 'optionalAccess', _6 => _6.toObject, 'call', _7 => _7()])
492
+ rowIds: _optionalChain([this, 'access', _9 => _9.rowIds, 'optionalAccess', _10 => _10.toObject, 'call', _11 => _11()])
455
493
  };
456
494
  }
457
495
  };
@@ -783,14 +821,14 @@ function depthFirstSearch(args) {
783
821
  while (events.length) {
784
822
  const { eventType, vertex, extras } = events.pop();
785
823
  if (eventType === "last") {
786
- _optionalChain([lastVisitF, 'optionalCall', _8 => _8(vertex)]);
824
+ _optionalChain([lastVisitF, 'optionalCall', _12 => _12(vertex)]);
787
825
  continue;
788
826
  }
789
827
  if (firstVisitedVertices.has(vertex)) {
790
828
  continue;
791
829
  }
792
830
  firstVisitedVertices.add(vertex);
793
- _optionalChain([firstVisitF, 'optionalCall', _9 => _9(vertex, { parentVertex: extras.parentVertex })]);
831
+ _optionalChain([firstVisitF, 'optionalCall', _13 => _13(vertex, { parentVertex: extras.parentVertex })]);
794
832
  events.push({ eventType: "last", vertex, extras: {} });
795
833
  mapAt(graph, vertex).forEach((child) => {
796
834
  events.push({
@@ -812,7 +850,7 @@ function undirectedConnectedComponents(graph) {
812
850
  let labelCounter = 0;
813
851
  const vertexLabels = /* @__PURE__ */ new Map();
814
852
  const firstVisitF = (vertex, args) => {
815
- const label = _optionalChain([args, 'optionalAccess', _10 => _10.parentVertex]) !== void 0 ? mapAt(vertexLabels, _optionalChain([args, 'optionalAccess', _11 => _11.parentVertex])) : labelCounter++;
853
+ const label = _optionalChain([args, 'optionalAccess', _14 => _14.parentVertex]) !== void 0 ? mapAt(vertexLabels, _optionalChain([args, 'optionalAccess', _15 => _15.parentVertex])) : labelCounter++;
816
854
  vertexLabels.set(vertex, label);
817
855
  };
818
856
  depthFirstSearch({ graph: directedGraph, firstVisitF });
@@ -1034,6 +1072,41 @@ function _urljoin(...parts) {
1034
1072
  ).filter((x) => x.trim() !== "").join("/");
1035
1073
  }
1036
1074
 
1075
+ // util/span_identifier_v4.ts
1076
+
1077
+ var ENCODING_VERSION_NUMBER_V4 = 4;
1078
+ var INVALID_ENCODING_ERRMSG_V4 = `SpanComponents string is not properly encoded. This library only supports encoding versions up to ${ENCODING_VERSION_NUMBER_V4}. Please make sure the SDK library used to decode the SpanComponents is at least as new as any library used to encode it.`;
1079
+ var spanComponentsV4Schema = _v3.z.object({
1080
+ object_type: spanObjectTypeV3EnumSchema,
1081
+ propagated_event: _v3.z.record(_v3.z.unknown()).nullish()
1082
+ }).and(
1083
+ _v3.z.union([
1084
+ // Must provide one or the other.
1085
+ _v3.z.object({
1086
+ object_id: _v3.z.string().nullish(),
1087
+ compute_object_metadata_args: _v3.z.optional(_v3.z.null())
1088
+ }),
1089
+ _v3.z.object({
1090
+ object_id: _v3.z.optional(_v3.z.null()),
1091
+ compute_object_metadata_args: _v3.z.record(_v3.z.unknown())
1092
+ })
1093
+ ])
1094
+ ).and(
1095
+ _v3.z.union([
1096
+ // Either all of these must be provided or none.
1097
+ _v3.z.object({
1098
+ row_id: _v3.z.string(),
1099
+ span_id: _v3.z.string(),
1100
+ root_span_id: _v3.z.string()
1101
+ }),
1102
+ _v3.z.object({
1103
+ row_id: _v3.z.optional(_v3.z.null()),
1104
+ span_id: _v3.z.optional(_v3.z.null()),
1105
+ root_span_id: _v3.z.optional(_v3.z.null())
1106
+ })
1107
+ ])
1108
+ );
1109
+
1037
1110
  // util/git_fields.ts
1038
1111
  function mergeGitMetadataSettings(s1, s2) {
1039
1112
  if (s1.collect === "all") {
@@ -3034,7 +3107,7 @@ var NoopSpan = (_class4 = class {
3034
3107
  return this;
3035
3108
  }
3036
3109
  end(args) {
3037
- return _nullishCoalesce(_optionalChain([args, 'optionalAccess', _12 => _12.endTime]), () => ( getCurrentUnixTimestamp()));
3110
+ return _nullishCoalesce(_optionalChain([args, 'optionalAccess', _16 => _16.endTime]), () => ( getCurrentUnixTimestamp()));
3038
3111
  }
3039
3112
  async export() {
3040
3113
  return "";
@@ -3058,6 +3131,20 @@ var NoopSpan = (_class4 = class {
3058
3131
  state() {
3059
3132
  return _internalGetGlobalState();
3060
3133
  }
3134
+ // Custom inspect for Node.js console.log
3135
+ [Symbol.for("nodejs.util.inspect.custom")]() {
3136
+ return `NoopSpan {
3137
+ kind: '${this.kind}',
3138
+ id: '${this.id}',
3139
+ spanId: '${this.spanId}',
3140
+ rootSpanId: '${this.rootSpanId}',
3141
+ spanParents: ${JSON.stringify(this.spanParents)}
3142
+ }`;
3143
+ }
3144
+ // Custom toString
3145
+ toString() {
3146
+ return `NoopSpan(id=${this.id}, spanId=${this.spanId})`;
3147
+ }
3061
3148
  }, _class4);
3062
3149
  var NOOP_SPAN = new NoopSpan();
3063
3150
  var NOOP_SPAN_PERMALINK = "https://braintrust.dev/noop-span";
@@ -3073,7 +3160,7 @@ var loginSchema = _zod.z.strictObject({
3073
3160
  });
3074
3161
  var stateNonce = 0;
3075
3162
  var BraintrustState = (_class5 = class _BraintrustState {
3076
- constructor(loginParams) {;_class5.prototype.__init7.call(this);_class5.prototype.__init8.call(this);_class5.prototype.__init9.call(this);_class5.prototype.__init10.call(this);_class5.prototype.__init11.call(this);_class5.prototype.__init12.call(this);_class5.prototype.__init13.call(this);_class5.prototype.__init14.call(this);_class5.prototype.__init15.call(this);_class5.prototype.__init16.call(this);_class5.prototype.__init17.call(this);_class5.prototype.__init18.call(this);_class5.prototype.__init19.call(this);
3163
+ constructor(loginParams) {;_class5.prototype.__init7.call(this);_class5.prototype.__init8.call(this);_class5.prototype.__init9.call(this);_class5.prototype.__init10.call(this);_class5.prototype.__init11.call(this);_class5.prototype.__init12.call(this);_class5.prototype.__init13.call(this);_class5.prototype.__init14.call(this);_class5.prototype.__init15.call(this);_class5.prototype.__init16.call(this);_class5.prototype.__init17.call(this);_class5.prototype.__init18.call(this);_class5.prototype.__init19.call(this);_class5.prototype.__init20.call(this);
3077
3164
  this.loginParams = loginParams;
3078
3165
  this.id = `${(/* @__PURE__ */ new Date()).toLocaleString()}-${stateNonce++}`;
3079
3166
  this.currentExperiment = void 0;
@@ -3127,6 +3214,7 @@ var BraintrustState = (_class5 = class _BraintrustState {
3127
3214
  __init18() {this._apiConn = null}
3128
3215
  __init19() {this._proxyConn = null}
3129
3216
 
3217
+ __init20() {this._idGenerator = null}
3130
3218
  resetLoginInfo() {
3131
3219
  this.appUrl = null;
3132
3220
  this.appPublicUrl = null;
@@ -3141,6 +3229,15 @@ var BraintrustState = (_class5 = class _BraintrustState {
3141
3229
  this._apiConn = null;
3142
3230
  this._proxyConn = null;
3143
3231
  }
3232
+ resetIdGenState() {
3233
+ this._idGenerator = null;
3234
+ }
3235
+ get idGenerator() {
3236
+ if (this._idGenerator === null) {
3237
+ this._idGenerator = getIdGenerator();
3238
+ }
3239
+ return this._idGenerator;
3240
+ }
3144
3241
  copyLoginInfo(other) {
3145
3242
  this.appUrl = other.appUrl;
3146
3243
  this.appPublicUrl = other.appPublicUrl;
@@ -3208,8 +3305,8 @@ var BraintrustState = (_class5 = class _BraintrustState {
3208
3305
  setFetch(fetch2) {
3209
3306
  this.loginParams.fetch = fetch2;
3210
3307
  this.fetch = fetch2;
3211
- _optionalChain([this, 'access', _13 => _13._apiConn, 'optionalAccess', _14 => _14.setFetch, 'call', _15 => _15(fetch2)]);
3212
- _optionalChain([this, 'access', _16 => _16._appConn, 'optionalAccess', _17 => _17.setFetch, 'call', _18 => _18(fetch2)]);
3308
+ _optionalChain([this, 'access', _17 => _17._apiConn, 'optionalAccess', _18 => _18.setFetch, 'call', _19 => _19(fetch2)]);
3309
+ _optionalChain([this, 'access', _20 => _20._appConn, 'optionalAccess', _21 => _21.setFetch, 'call', _22 => _22(fetch2)]);
3213
3310
  }
3214
3311
  setMaskingFunction(maskingFunction) {
3215
3312
  this.bgLogger().setMaskingFunction(maskingFunction);
@@ -3278,6 +3375,37 @@ var BraintrustState = (_class5 = class _BraintrustState {
3278
3375
  enforceQueueSizeLimit(enforce) {
3279
3376
  this._bgLogger.get().enforceQueueSizeLimit(enforce);
3280
3377
  }
3378
+ // Custom serialization to avoid logging sensitive data
3379
+ toJSON() {
3380
+ return {
3381
+ id: this.id,
3382
+ orgId: this.orgId,
3383
+ orgName: this.orgName,
3384
+ appUrl: this.appUrl,
3385
+ appPublicUrl: this.appPublicUrl,
3386
+ apiUrl: this.apiUrl,
3387
+ proxyUrl: this.proxyUrl,
3388
+ loggedIn: this.loggedIn
3389
+ // Explicitly exclude loginToken, _apiConn, _appConn, _proxyConn and other sensitive fields
3390
+ };
3391
+ }
3392
+ // Custom inspect for Node.js console.log
3393
+ [Symbol.for("nodejs.util.inspect.custom")]() {
3394
+ return `BraintrustState {
3395
+ id: '${this.id}',
3396
+ orgId: ${this.orgId ? `'${this.orgId}'` : "null"},
3397
+ orgName: ${this.orgName ? `'${this.orgName}'` : "null"},
3398
+ appUrl: ${this.appUrl ? `'${this.appUrl}'` : "null"},
3399
+ apiUrl: ${this.apiUrl ? `'${this.apiUrl}'` : "null"},
3400
+ proxyUrl: ${this.proxyUrl ? `'${this.proxyUrl}'` : "null"},
3401
+ loggedIn: ${this.loggedIn},
3402
+ loginToken: '[REDACTED]'
3403
+ }`;
3404
+ }
3405
+ // Custom toString
3406
+ toString() {
3407
+ return `BraintrustState(id=${this.id}, org=${this.orgName || "none"}, loggedIn=${this.loggedIn})`;
3408
+ }
3281
3409
  }, _class5);
3282
3410
  var _globalState;
3283
3411
  function useTestBackgroundLogger() {
@@ -3290,7 +3418,7 @@ function useTestBackgroundLogger() {
3290
3418
  return logger;
3291
3419
  }
3292
3420
  function clearTestBackgroundLogger() {
3293
- _optionalChain([_internalGetGlobalState, 'call', _19 => _19(), 'optionalAccess', _20 => _20.setOverrideBgLogger, 'call', _21 => _21(null)]);
3421
+ _optionalChain([_internalGetGlobalState, 'call', _23 => _23(), 'optionalAccess', _24 => _24.setOverrideBgLogger, 'call', _25 => _25(null)]);
3294
3422
  }
3295
3423
  function initTestExperiment(experimentName, projectName) {
3296
3424
  setInitialTestState();
@@ -3445,6 +3573,17 @@ var HTTPConnection = class _HTTPConnection {
3445
3573
  });
3446
3574
  return await resp.json();
3447
3575
  }
3576
+ // Custom inspect for Node.js console.log
3577
+ [Symbol.for("nodejs.util.inspect.custom")]() {
3578
+ return `HTTPConnection {
3579
+ base_url: '${this.base_url}',
3580
+ token: '[REDACTED]'
3581
+ }`;
3582
+ }
3583
+ // Custom toString
3584
+ toString() {
3585
+ return `HTTPConnection(${this.base_url})`;
3586
+ }
3448
3587
  };
3449
3588
  var BaseAttachment = class {
3450
3589
 
@@ -3952,9 +4091,9 @@ async function permalink(slug, opts) {
3952
4091
  if (slug === "") {
3953
4092
  return NOOP_SPAN_PERMALINK;
3954
4093
  }
3955
- const state = _nullishCoalesce(_optionalChain([opts, 'optionalAccess', _22 => _22.state]), () => ( _globalState));
4094
+ const state = _nullishCoalesce(_optionalChain([opts, 'optionalAccess', _26 => _26.state]), () => ( _globalState));
3956
4095
  const getOrgName = async () => {
3957
- if (_optionalChain([opts, 'optionalAccess', _23 => _23.orgName])) {
4096
+ if (_optionalChain([opts, 'optionalAccess', _27 => _27.orgName])) {
3958
4097
  return opts.orgName;
3959
4098
  }
3960
4099
  await state.login({});
@@ -3964,7 +4103,7 @@ async function permalink(slug, opts) {
3964
4103
  return state.orgName;
3965
4104
  };
3966
4105
  const getAppUrl = async () => {
3967
- if (_optionalChain([opts, 'optionalAccess', _24 => _24.appUrl])) {
4106
+ if (_optionalChain([opts, 'optionalAccess', _28 => _28.appUrl])) {
3968
4107
  return opts.appUrl;
3969
4108
  }
3970
4109
  await state.login({});
@@ -4051,8 +4190,8 @@ var Logger = (_class6 = class {
4051
4190
 
4052
4191
 
4053
4192
  // For type identification.
4054
- __init20() {this.kind = "logger"}
4055
- constructor(state, lazyMetadata, logOptions = {}) {;_class6.prototype.__init20.call(this);
4193
+ __init21() {this.kind = "logger"}
4194
+ constructor(state, lazyMetadata, logOptions = {}) {;_class6.prototype.__init21.call(this);
4056
4195
  this.lazyMetadata = lazyMetadata;
4057
4196
  this._asyncFlush = logOptions.asyncFlush;
4058
4197
  this.computeMetadataArgs = logOptions.computeMetadataArgs;
@@ -4094,7 +4233,7 @@ var Logger = (_class6 = class {
4094
4233
  * @returns The `id` of the logged event.
4095
4234
  */
4096
4235
  log(event, options) {
4097
- if (this.calledStartSpan && !_optionalChain([options, 'optionalAccess', _25 => _25.allowConcurrentWithSpans])) {
4236
+ if (this.calledStartSpan && !_optionalChain([options, 'optionalAccess', _29 => _29.allowConcurrentWithSpans])) {
4098
4237
  throw new Error(
4099
4238
  "Cannot run toplevel `log` method while using spans. To log to the span, call `logger.traced` and then log with `span.log`"
4100
4239
  );
@@ -4162,12 +4301,12 @@ var Logger = (_class6 = class {
4162
4301
  state: this.state,
4163
4302
  ...startSpanParentArgs({
4164
4303
  state: this.state,
4165
- parent: _optionalChain([args, 'optionalAccess', _26 => _26.parent]),
4304
+ parent: _optionalChain([args, 'optionalAccess', _30 => _30.parent]),
4166
4305
  parentObjectType: this.parentObjectType(),
4167
4306
  parentObjectId: this.lazyId,
4168
4307
  parentComputeObjectMetadataArgs: this.computeMetadataArgs,
4169
- parentSpanIds: _optionalChain([args, 'optionalAccess', _27 => _27.parentSpanIds]),
4170
- propagatedEvent: _optionalChain([args, 'optionalAccess', _28 => _28.propagatedEvent])
4308
+ parentSpanIds: _optionalChain([args, 'optionalAccess', _31 => _31.parentSpanIds]),
4309
+ propagatedEvent: _optionalChain([args, 'optionalAccess', _32 => _32.propagatedEvent])
4171
4310
  }),
4172
4311
  defaultRootType: "task" /* TASK */
4173
4312
  });
@@ -4241,9 +4380,9 @@ function constructLogs3Data(items) {
4241
4380
  function now() {
4242
4381
  return (/* @__PURE__ */ new Date()).getTime();
4243
4382
  }
4244
- var TestBackgroundLogger = (_class7 = class {constructor() { _class7.prototype.__init21.call(this);_class7.prototype.__init22.call(this); }
4245
- __init21() {this.items = []}
4246
- __init22() {this.maskingFunction = null}
4383
+ var TestBackgroundLogger = (_class7 = class {constructor() { _class7.prototype.__init22.call(this);_class7.prototype.__init23.call(this); }
4384
+ __init22() {this.items = []}
4385
+ __init23() {this.maskingFunction = null}
4247
4386
  log(items) {
4248
4387
  this.items.push(items);
4249
4388
  }
@@ -4297,26 +4436,26 @@ var BACKGROUND_LOGGER_BASE_SLEEP_TIME_S = 1;
4297
4436
  var HTTPBackgroundLogger = (_class8 = class _HTTPBackgroundLogger {
4298
4437
 
4299
4438
 
4300
- __init23() {this.activeFlush = Promise.resolve()}
4301
- __init24() {this.activeFlushResolved = true}
4302
- __init25() {this.activeFlushError = void 0}
4439
+ __init24() {this.activeFlush = Promise.resolve()}
4440
+ __init25() {this.activeFlushResolved = true}
4441
+ __init26() {this.activeFlushError = void 0}
4303
4442
 
4304
- __init26() {this.maskingFunction = null}
4305
- __init27() {this.syncFlush = false}
4443
+ __init27() {this.maskingFunction = null}
4444
+ __init28() {this.syncFlush = false}
4306
4445
  // 6 MB for the AWS lambda gateway (from our own testing).
4307
- __init28() {this.maxRequestSize = 6 * 1024 * 1024}
4308
- __init29() {this.defaultBatchSize = 100}
4309
- __init30() {this.numTries = 3}
4310
- __init31() {this.queueDropExceedingMaxsize = DEFAULT_QUEUE_SIZE}
4311
- __init32() {this.queueDropLoggingPeriod = 60}
4312
- __init33() {this.failedPublishPayloadsDir = void 0}
4313
- __init34() {this.allPublishPayloadsDir = void 0}
4314
- __init35() {this._disabled = false}
4315
- __init36() {this.queueDropLoggingState = {
4446
+ __init29() {this.maxRequestSize = 6 * 1024 * 1024}
4447
+ __init30() {this.defaultBatchSize = 100}
4448
+ __init31() {this.numTries = 3}
4449
+ __init32() {this.queueDropExceedingMaxsize = DEFAULT_QUEUE_SIZE}
4450
+ __init33() {this.queueDropLoggingPeriod = 60}
4451
+ __init34() {this.failedPublishPayloadsDir = void 0}
4452
+ __init35() {this.allPublishPayloadsDir = void 0}
4453
+ __init36() {this._disabled = false}
4454
+ __init37() {this.queueDropLoggingState = {
4316
4455
  numDropped: 0,
4317
4456
  lastLoggedTimestamp: 0
4318
4457
  }}
4319
- constructor(apiConn, opts) {;_class8.prototype.__init23.call(this);_class8.prototype.__init24.call(this);_class8.prototype.__init25.call(this);_class8.prototype.__init26.call(this);_class8.prototype.__init27.call(this);_class8.prototype.__init28.call(this);_class8.prototype.__init29.call(this);_class8.prototype.__init30.call(this);_class8.prototype.__init31.call(this);_class8.prototype.__init32.call(this);_class8.prototype.__init33.call(this);_class8.prototype.__init34.call(this);_class8.prototype.__init35.call(this);_class8.prototype.__init36.call(this);
4458
+ constructor(apiConn, opts) {;_class8.prototype.__init24.call(this);_class8.prototype.__init25.call(this);_class8.prototype.__init26.call(this);_class8.prototype.__init27.call(this);_class8.prototype.__init28.call(this);_class8.prototype.__init29.call(this);_class8.prototype.__init30.call(this);_class8.prototype.__init31.call(this);_class8.prototype.__init32.call(this);_class8.prototype.__init33.call(this);_class8.prototype.__init34.call(this);_class8.prototype.__init35.call(this);_class8.prototype.__init36.call(this);_class8.prototype.__init37.call(this);
4320
4459
  opts = _nullishCoalesce(opts, () => ( {}));
4321
4460
  this.apiConn = apiConn;
4322
4461
  const syncFlushEnv = Number(isomorph_default.getEnv("BRAINTRUST_SYNC_FLUSH"));
@@ -4405,7 +4544,7 @@ var HTTPBackgroundLogger = (_class8 = class _HTTPBackgroundLogger {
4405
4544
  this.queue.clear();
4406
4545
  return;
4407
4546
  }
4408
- const batchSize = _nullishCoalesce(_optionalChain([args, 'optionalAccess', _29 => _29.batchSize]), () => ( this.defaultBatchSize));
4547
+ const batchSize = _nullishCoalesce(_optionalChain([args, 'optionalAccess', _33 => _33.batchSize]), () => ( this.defaultBatchSize));
4409
4548
  const wrappedItems = this.queue.drain();
4410
4549
  const [allItems, attachments] = await this.unwrapLazyValues(wrappedItems);
4411
4550
  if (allItems.length === 0) {
@@ -4654,10 +4793,10 @@ Error: ${errorText}`;
4654
4793
  } catch (err) {
4655
4794
  if (err instanceof AggregateError) {
4656
4795
  for (const e of err.errors) {
4657
- _optionalChain([this, 'access', _30 => _30.onFlushError, 'optionalCall', _31 => _31(e)]);
4796
+ _optionalChain([this, 'access', _34 => _34.onFlushError, 'optionalCall', _35 => _35(e)]);
4658
4797
  }
4659
4798
  } else {
4660
- _optionalChain([this, 'access', _32 => _32.onFlushError, 'optionalCall', _33 => _33(err)]);
4799
+ _optionalChain([this, 'access', _36 => _36.onFlushError, 'optionalCall', _37 => _37(err)]);
4661
4800
  }
4662
4801
  this.activeFlushError = err;
4663
4802
  } finally {
@@ -5270,24 +5409,24 @@ async function summarize(options = {}) {
5270
5409
  return await e.summarize(options);
5271
5410
  }
5272
5411
  function currentExperiment(options) {
5273
- const state = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _34 => _34.state]), () => ( _globalState));
5412
+ const state = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _38 => _38.state]), () => ( _globalState));
5274
5413
  return state.currentExperiment;
5275
5414
  }
5276
5415
  function currentLogger(options) {
5277
- const state = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _35 => _35.state]), () => ( _globalState));
5278
- return castLogger(state.currentLogger, _optionalChain([options, 'optionalAccess', _36 => _36.asyncFlush]));
5416
+ const state = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _39 => _39.state]), () => ( _globalState));
5417
+ return castLogger(state.currentLogger, _optionalChain([options, 'optionalAccess', _40 => _40.asyncFlush]));
5279
5418
  }
5280
5419
  function currentSpan(options) {
5281
- const state = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _37 => _37.state]), () => ( _globalState));
5420
+ const state = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _41 => _41.state]), () => ( _globalState));
5282
5421
  return _nullishCoalesce(state.currentSpan.getStore(), () => ( NOOP_SPAN));
5283
5422
  }
5284
5423
  function getSpanParentObject(options) {
5285
- const state = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _38 => _38.state]), () => ( _globalState));
5424
+ const state = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _42 => _42.state]), () => ( _globalState));
5286
5425
  const parentSpan = currentSpan({ state });
5287
5426
  if (!Object.is(parentSpan, NOOP_SPAN)) {
5288
5427
  return parentSpan;
5289
5428
  }
5290
- const parentStr = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _39 => _39.parent]), () => ( state.currentParent.getStore()));
5429
+ const parentStr = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _43 => _43.parent]), () => ( state.currentParent.getStore()));
5291
5430
  if (parentStr) return SpanComponentsV3.fromStr(parentStr);
5292
5431
  const experiment = currentExperiment();
5293
5432
  if (experiment) {
@@ -5316,7 +5455,7 @@ function traced(callback, args) {
5316
5455
  const { span, isSyncFlushLogger } = startSpanAndIsLogger(args);
5317
5456
  const ret = runCatchFinally(
5318
5457
  () => {
5319
- if (_nullishCoalesce(_optionalChain([args, 'optionalAccess', _40 => _40.setCurrent]), () => ( true))) {
5458
+ if (_nullishCoalesce(_optionalChain([args, 'optionalAccess', _44 => _44.setCurrent]), () => ( true))) {
5320
5459
  return withCurrent(span, callback);
5321
5460
  } else {
5322
5461
  return callback(span);
@@ -5328,7 +5467,7 @@ function traced(callback, args) {
5328
5467
  },
5329
5468
  () => span.end()
5330
5469
  );
5331
- if (_optionalChain([args, 'optionalAccess', _41 => _41.asyncFlush]) === void 0 || _optionalChain([args, 'optionalAccess', _42 => _42.asyncFlush])) {
5470
+ if (_optionalChain([args, 'optionalAccess', _45 => _45.asyncFlush]) === void 0 || _optionalChain([args, 'optionalAccess', _46 => _46.asyncFlush])) {
5332
5471
  return ret;
5333
5472
  } else {
5334
5473
  return (async () => {
@@ -5452,14 +5591,14 @@ function wrapTraced(fn, args) {
5452
5591
  };
5453
5592
  const hasExplicitInput = args && args.event && "input" in args.event && args.event.input !== void 0;
5454
5593
  const hasExplicitOutput = args && args.event && args.event.output !== void 0;
5455
- const noTraceIO = _optionalChain([args, 'optionalAccess', _43 => _43.noTraceIO]) || hasExplicitInput || hasExplicitOutput;
5594
+ const noTraceIO = _optionalChain([args, 'optionalAccess', _47 => _47.noTraceIO]) || hasExplicitInput || hasExplicitOutput;
5456
5595
  if (isGeneratorFunction(fn)) {
5457
5596
  return wrapTracedSyncGenerator(fn, spanArgs, !!noTraceIO);
5458
5597
  }
5459
5598
  if (isAsyncGeneratorFunction(fn)) {
5460
5599
  return wrapTracedAsyncGenerator(fn, spanArgs, !!noTraceIO);
5461
5600
  }
5462
- if (_optionalChain([args, 'optionalAccess', _44 => _44.asyncFlush])) {
5601
+ if (_optionalChain([args, 'optionalAccess', _48 => _48.asyncFlush])) {
5463
5602
  return (...fnArgs) => traced((span) => {
5464
5603
  if (!hasExplicitInput) {
5465
5604
  span.log({ input: fnArgs });
@@ -5497,17 +5636,17 @@ function startSpan(args) {
5497
5636
  return startSpanAndIsLogger(args).span;
5498
5637
  }
5499
5638
  async function flush(options) {
5500
- const state = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _45 => _45.state]), () => ( _globalState));
5639
+ const state = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _49 => _49.state]), () => ( _globalState));
5501
5640
  return await state.bgLogger().flush();
5502
5641
  }
5503
5642
  function setFetch(fetch2) {
5504
5643
  _globalState.setFetch(fetch2);
5505
5644
  }
5506
5645
  function startSpanAndIsLogger(args) {
5507
- const state = _nullishCoalesce(_optionalChain([args, 'optionalAccess', _46 => _46.state]), () => ( _globalState));
5646
+ const state = _nullishCoalesce(_optionalChain([args, 'optionalAccess', _50 => _50.state]), () => ( _globalState));
5508
5647
  const parentObject = getSpanParentObject({
5509
- asyncFlush: _optionalChain([args, 'optionalAccess', _47 => _47.asyncFlush]),
5510
- parent: _optionalChain([args, 'optionalAccess', _48 => _48.parent]),
5648
+ asyncFlush: _optionalChain([args, 'optionalAccess', _51 => _51.asyncFlush]),
5649
+ parent: _optionalChain([args, 'optionalAccess', _52 => _52.parent]),
5511
5650
  state
5512
5651
  });
5513
5652
  if (parentObject instanceof SpanComponentsV3) {
@@ -5524,14 +5663,14 @@ function startSpanAndIsLogger(args) {
5524
5663
  ),
5525
5664
  parentComputeObjectMetadataArgs: _nullishCoalesce(parentObject.data.compute_object_metadata_args, () => ( void 0)),
5526
5665
  parentSpanIds,
5527
- propagatedEvent: _nullishCoalesce(_optionalChain([args, 'optionalAccess', _49 => _49.propagatedEvent]), () => ( // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
5666
+ propagatedEvent: _nullishCoalesce(_optionalChain([args, 'optionalAccess', _53 => _53.propagatedEvent]), () => ( // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
5528
5667
  (_nullishCoalesce(parentObject.data.propagated_event, () => ( void 0)))))
5529
5668
  });
5530
5669
  return {
5531
5670
  span,
5532
5671
  isSyncFlushLogger: parentObject.data.object_type === 2 /* PROJECT_LOGS */ && // Since there's no parent logger here, we're free to choose the async flush
5533
5672
  // behavior, and therefore propagate along whatever we get from the arguments
5534
- _optionalChain([args, 'optionalAccess', _50 => _50.asyncFlush]) === false
5673
+ _optionalChain([args, 'optionalAccess', _54 => _54.asyncFlush]) === false
5535
5674
  };
5536
5675
  } else {
5537
5676
  const span = parentObject.startSpan(args);
@@ -5720,10 +5859,10 @@ function extractAttachments(event, attachments) {
5720
5859
  event[key] = value.reference;
5721
5860
  continue;
5722
5861
  }
5723
- if (_optionalChain([value, 'optionalAccess', _51 => _51.type]) === BRAINTRUST_ATTACHMENT && value.key && !value.uploader) {
5862
+ if (_optionalChain([value, 'optionalAccess', _55 => _55.type]) === BRAINTRUST_ATTACHMENT && value.key && !value.uploader) {
5724
5863
  continue;
5725
5864
  }
5726
- if (_optionalChain([value, 'optionalAccess', _52 => _52.reference, 'optionalAccess', _53 => _53.type]) === BRAINTRUST_ATTACHMENT && _optionalChain([value, 'optionalAccess', _54 => _54.uploader])) {
5865
+ if (_optionalChain([value, 'optionalAccess', _56 => _56.reference, 'optionalAccess', _57 => _57.type]) === BRAINTRUST_ATTACHMENT && _optionalChain([value, 'optionalAccess', _58 => _58.uploader])) {
5727
5866
  const attachment = new Attachment({
5728
5867
  data: value.dataDebugString,
5729
5868
  filename: value.reference.filename,
@@ -5790,13 +5929,13 @@ function validateAndSanitizeExperimentLogFullArgs(event, hasDataset) {
5790
5929
  var INTERNAL_BTQL_LIMIT = 1e3;
5791
5930
  var MAX_BTQL_ITERATIONS = 1e4;
5792
5931
  var ObjectFetcher = (_class9 = class {
5793
- constructor(objectType, pinnedVersion, mutateRecord, _internal_btql) {;_class9.prototype.__init37.call(this);
5932
+ constructor(objectType, pinnedVersion, mutateRecord, _internal_btql) {;_class9.prototype.__init38.call(this);
5794
5933
  this.objectType = objectType;
5795
5934
  this.pinnedVersion = pinnedVersion;
5796
5935
  this.mutateRecord = mutateRecord;
5797
5936
  this._internal_btql = _internal_btql;
5798
5937
  }
5799
- __init37() {this._fetchedData = void 0}
5938
+ __init38() {this._fetchedData = void 0}
5800
5939
  get id() {
5801
5940
  throw new Error("ObjectFetcher subclasses must have an 'id' attribute");
5802
5941
  }
@@ -5861,7 +6000,7 @@ var ObjectFetcher = (_class9 = class {
5861
6000
  throw new Error("Too many BTQL iterations");
5862
6001
  }
5863
6002
  }
5864
- this._fetchedData = this.mutateRecord ? _optionalChain([data, 'optionalAccess', _55 => _55.map, 'call', _56 => _56(this.mutateRecord)]) : data;
6003
+ this._fetchedData = this.mutateRecord ? _optionalChain([data, 'optionalAccess', _59 => _59.map, 'call', _60 => _60(this.mutateRecord)]) : data;
5865
6004
  }
5866
6005
  return this._fetchedData || [];
5867
6006
  }
@@ -5892,9 +6031,9 @@ var Experiment2 = (_class10 = class extends ObjectFetcher {
5892
6031
 
5893
6032
 
5894
6033
  // For type identification.
5895
- __init38() {this.kind = "experiment"}
6034
+ __init39() {this.kind = "experiment"}
5896
6035
  constructor(state, lazyMetadata, dataset) {
5897
- super("experiment", void 0, (r) => enrichAttachments(r, state));_class10.prototype.__init38.call(this);;
6036
+ super("experiment", void 0, (r) => enrichAttachments(r, state));_class10.prototype.__init39.call(this);;
5898
6037
  this.lazyMetadata = lazyMetadata;
5899
6038
  this.dataset = dataset;
5900
6039
  this.lastStartTime = getCurrentUnixTimestamp();
@@ -5942,7 +6081,7 @@ var Experiment2 = (_class10 = class extends ObjectFetcher {
5942
6081
  * @returns The `id` of the logged event.
5943
6082
  */
5944
6083
  log(event, options) {
5945
- if (this.calledStartSpan && !_optionalChain([options, 'optionalAccess', _57 => _57.allowConcurrentWithSpans])) {
6084
+ if (this.calledStartSpan && !_optionalChain([options, 'optionalAccess', _61 => _61.allowConcurrentWithSpans])) {
5946
6085
  throw new Error(
5947
6086
  "Cannot run toplevel `log` method while using spans. To log to the span, call `experiment.traced` and then log with `span.log`"
5948
6087
  );
@@ -5995,12 +6134,12 @@ var Experiment2 = (_class10 = class extends ObjectFetcher {
5995
6134
  state: this.state,
5996
6135
  ...startSpanParentArgs({
5997
6136
  state: this.state,
5998
- parent: _optionalChain([args, 'optionalAccess', _58 => _58.parent]),
6137
+ parent: _optionalChain([args, 'optionalAccess', _62 => _62.parent]),
5999
6138
  parentObjectType: this.parentObjectType(),
6000
6139
  parentObjectId: this.lazyId,
6001
6140
  parentComputeObjectMetadataArgs: void 0,
6002
6141
  parentSpanIds: void 0,
6003
- propagatedEvent: _optionalChain([args, 'optionalAccess', _59 => _59.propagatedEvent])
6142
+ propagatedEvent: _optionalChain([args, 'optionalAccess', _63 => _63.propagatedEvent])
6004
6143
  }),
6005
6144
  defaultRootType: "eval" /* EVAL */
6006
6145
  });
@@ -6201,8 +6340,8 @@ var SpanImpl = (_class11 = class _SpanImpl {
6201
6340
 
6202
6341
 
6203
6342
 
6204
- __init39() {this.kind = "span"}
6205
- constructor(args) {;_class11.prototype.__init39.call(this);
6343
+ __init40() {this.kind = "span"}
6344
+ constructor(args) {;_class11.prototype.__init40.call(this);
6206
6345
  this._state = args.state;
6207
6346
  const spanAttributes = _nullishCoalesce(args.spanAttributes, () => ( {}));
6208
6347
  const rawEvent = _nullishCoalesce(args.event, () => ( {}));
@@ -6242,13 +6381,17 @@ var SpanImpl = (_class11 = class _SpanImpl {
6242
6381
  },
6243
6382
  created: (/* @__PURE__ */ new Date()).toISOString()
6244
6383
  };
6245
- this._id = _nullishCoalesce(eventId, () => ( _uuid.v4.call(void 0, )));
6246
- this._spanId = _nullishCoalesce(args.spanId, () => ( _uuid.v4.call(void 0, )));
6384
+ this._id = _nullishCoalesce(eventId, () => ( this._state.idGenerator.getSpanId()));
6385
+ this._spanId = _nullishCoalesce(args.spanId, () => ( this._state.idGenerator.getSpanId()));
6247
6386
  if (args.parentSpanIds) {
6248
6387
  this._rootSpanId = args.parentSpanIds.rootSpanId;
6249
6388
  this._spanParents = "parentSpanIds" in args.parentSpanIds ? args.parentSpanIds.parentSpanIds : [args.parentSpanIds.spanId];
6250
6389
  } else {
6251
- this._rootSpanId = this._spanId;
6390
+ if (this._state.idGenerator.shareRootSpanId()) {
6391
+ this._rootSpanId = this._spanId;
6392
+ } else {
6393
+ this._rootSpanId = this._state.idGenerator.getTraceId();
6394
+ }
6252
6395
  this._spanParents = void 0;
6253
6396
  }
6254
6397
  this.isMerge = false;
@@ -6292,10 +6435,10 @@ var SpanImpl = (_class11 = class _SpanImpl {
6292
6435
  ...serializableInternalData,
6293
6436
  [IS_MERGE_FIELD]: this.isMerge
6294
6437
  });
6295
- if (_optionalChain([partialRecord, 'access', _60 => _60.metrics, 'optionalAccess', _61 => _61.end])) {
6296
- this.loggedEndTime = _optionalChain([partialRecord, 'access', _62 => _62.metrics, 'optionalAccess', _63 => _63.end]);
6438
+ if (_optionalChain([partialRecord, 'access', _64 => _64.metrics, 'optionalAccess', _65 => _65.end])) {
6439
+ this.loggedEndTime = _optionalChain([partialRecord, 'access', _66 => _66.metrics, 'optionalAccess', _67 => _67.end]);
6297
6440
  }
6298
- if ((_nullishCoalesce(partialRecord.tags, () => ( []))).length > 0 && _optionalChain([this, 'access', _64 => _64._spanParents, 'optionalAccess', _65 => _65.length])) {
6441
+ if ((_nullishCoalesce(partialRecord.tags, () => ( []))).length > 0 && _optionalChain([this, 'access', _68 => _68._spanParents, 'optionalAccess', _69 => _69.length])) {
6299
6442
  throw new Error("Tags can only be logged to the root span");
6300
6443
  }
6301
6444
  const computeRecord = async () => ({
@@ -6340,18 +6483,18 @@ var SpanImpl = (_class11 = class _SpanImpl {
6340
6483
  );
6341
6484
  }
6342
6485
  startSpan(args) {
6343
- const parentSpanIds = _optionalChain([args, 'optionalAccess', _66 => _66.parent]) ? void 0 : { spanId: this._spanId, rootSpanId: this._rootSpanId };
6486
+ const parentSpanIds = _optionalChain([args, 'optionalAccess', _70 => _70.parent]) ? void 0 : { spanId: this._spanId, rootSpanId: this._rootSpanId };
6344
6487
  return new _SpanImpl({
6345
6488
  state: this._state,
6346
6489
  ...args,
6347
6490
  ...startSpanParentArgs({
6348
6491
  state: this._state,
6349
- parent: _optionalChain([args, 'optionalAccess', _67 => _67.parent]),
6492
+ parent: _optionalChain([args, 'optionalAccess', _71 => _71.parent]),
6350
6493
  parentObjectType: this.parentObjectType,
6351
6494
  parentObjectId: this.parentObjectId,
6352
6495
  parentComputeObjectMetadataArgs: this.parentComputeObjectMetadataArgs,
6353
6496
  parentSpanIds,
6354
- propagatedEvent: _nullishCoalesce(_optionalChain([args, 'optionalAccess', _68 => _68.propagatedEvent]), () => ( this.propagatedEvent))
6497
+ propagatedEvent: _nullishCoalesce(_optionalChain([args, 'optionalAccess', _72 => _72.propagatedEvent]), () => ( this.propagatedEvent))
6355
6498
  })
6356
6499
  });
6357
6500
  }
@@ -6365,12 +6508,12 @@ var SpanImpl = (_class11 = class _SpanImpl {
6365
6508
  ...args,
6366
6509
  ...startSpanParentArgs({
6367
6510
  state: this._state,
6368
- parent: _optionalChain([args, 'optionalAccess', _69 => _69.parent]),
6511
+ parent: _optionalChain([args, 'optionalAccess', _73 => _73.parent]),
6369
6512
  parentObjectType: this.parentObjectType,
6370
6513
  parentObjectId: this.parentObjectId,
6371
6514
  parentComputeObjectMetadataArgs: this.parentComputeObjectMetadataArgs,
6372
6515
  parentSpanIds,
6373
- propagatedEvent: _nullishCoalesce(_optionalChain([args, 'optionalAccess', _70 => _70.propagatedEvent]), () => ( this.propagatedEvent))
6516
+ propagatedEvent: _nullishCoalesce(_optionalChain([args, 'optionalAccess', _74 => _74.propagatedEvent]), () => ( this.propagatedEvent))
6374
6517
  }),
6375
6518
  spanId
6376
6519
  });
@@ -6379,7 +6522,7 @@ var SpanImpl = (_class11 = class _SpanImpl {
6379
6522
  let endTime;
6380
6523
  let internalData = {};
6381
6524
  if (!this.loggedEndTime) {
6382
- endTime = _nullishCoalesce(_optionalChain([args, 'optionalAccess', _71 => _71.endTime]), () => ( getCurrentUnixTimestamp()));
6525
+ endTime = _nullishCoalesce(_optionalChain([args, 'optionalAccess', _75 => _75.endTime]), () => ( getCurrentUnixTimestamp()));
6383
6526
  internalData = { metrics: { end: endTime } };
6384
6527
  } else {
6385
6528
  endTime = this.loggedEndTime;
@@ -6422,8 +6565,8 @@ var SpanImpl = (_class11 = class _SpanImpl {
6422
6565
  const args = this.parentComputeObjectMetadataArgs;
6423
6566
  switch (this.parentObjectType) {
6424
6567
  case 2 /* PROJECT_LOGS */: {
6425
- const projectID = _optionalChain([args, 'optionalAccess', _72 => _72.project_id]) || this.parentObjectId.getSync().value;
6426
- const projectName = _optionalChain([args, 'optionalAccess', _73 => _73.project_name]);
6568
+ const projectID = _optionalChain([args, 'optionalAccess', _76 => _76.project_id]) || this.parentObjectId.getSync().value;
6569
+ const projectName = _optionalChain([args, 'optionalAccess', _77 => _77.project_name]);
6427
6570
  if (projectID) {
6428
6571
  return `${baseUrl}/object?object_type=project_logs&object_id=${projectID}&id=${this._id}`;
6429
6572
  } else if (projectName) {
@@ -6433,7 +6576,7 @@ var SpanImpl = (_class11 = class _SpanImpl {
6433
6576
  }
6434
6577
  }
6435
6578
  case 1 /* EXPERIMENT */: {
6436
- const expID = _optionalChain([args, 'optionalAccess', _74 => _74.experiment_id]) || _optionalChain([this, 'access', _75 => _75.parentObjectId, 'optionalAccess', _76 => _76.getSync, 'call', _77 => _77(), 'optionalAccess', _78 => _78.value]);
6579
+ const expID = _optionalChain([args, 'optionalAccess', _78 => _78.experiment_id]) || _optionalChain([this, 'access', _79 => _79.parentObjectId, 'optionalAccess', _80 => _80.getSync, 'call', _81 => _81(), 'optionalAccess', _82 => _82.value]);
6437
6580
  if (!expID) {
6438
6581
  return getErrPermlink("provide-experiment-id");
6439
6582
  } else {
@@ -6459,6 +6602,20 @@ var SpanImpl = (_class11 = class _SpanImpl {
6459
6602
  state() {
6460
6603
  return this._state;
6461
6604
  }
6605
+ // Custom inspect for Node.js console.log
6606
+ [Symbol.for("nodejs.util.inspect.custom")]() {
6607
+ return `SpanImpl {
6608
+ kind: '${this.kind}',
6609
+ id: '${this.id}',
6610
+ spanId: '${this.spanId}',
6611
+ rootSpanId: '${this.rootSpanId}',
6612
+ spanParents: ${JSON.stringify(this.spanParents)}
6613
+ }`;
6614
+ }
6615
+ // Custom toString
6616
+ toString() {
6617
+ return `SpanImpl(id=${this.id}, spanId=${this.spanId})`;
6618
+ }
6462
6619
  }, _class11);
6463
6620
  function splitLoggingData({
6464
6621
  event,
@@ -6509,13 +6666,13 @@ var Dataset2 = (_class12 = class extends ObjectFetcher {
6509
6666
  )
6510
6667
  ),
6511
6668
  _internal_btql
6512
- );_class12.prototype.__init40.call(this);_class12.prototype.__init41.call(this);;
6669
+ );_class12.prototype.__init41.call(this);_class12.prototype.__init42.call(this);;
6513
6670
  this.state = state;
6514
6671
  this.lazyMetadata = lazyMetadata;
6515
6672
  }
6516
6673
 
6517
- __init40() {this.__braintrust_dataset_marker = true}
6518
- __init41() {this.newRecords = 0}
6674
+ __init41() {this.__braintrust_dataset_marker = true}
6675
+ __init42() {this.newRecords = 0}
6519
6676
  get id() {
6520
6677
  return (async () => {
6521
6678
  return (await this.lazyMetadata.get()).dataset.id;
@@ -6838,14 +6995,14 @@ function renderPromptParams(params, args, options) {
6838
6995
  return params;
6839
6996
  }
6840
6997
  var Prompt2 = (_class13 = class _Prompt {
6841
- constructor(metadata, defaults, noTrace) {;_class13.prototype.__init42.call(this);_class13.prototype.__init43.call(this);
6998
+ constructor(metadata, defaults, noTrace) {;_class13.prototype.__init43.call(this);_class13.prototype.__init44.call(this);
6842
6999
  this.metadata = metadata;
6843
7000
  this.defaults = defaults;
6844
7001
  this.noTrace = noTrace;
6845
7002
  }
6846
7003
 
6847
- __init42() {this.hasParsedPromptData = false}
6848
- __init43() {this.__braintrust_prompt_marker = true}
7004
+ __init43() {this.hasParsedPromptData = false}
7005
+ __init44() {this.__braintrust_prompt_marker = true}
6849
7006
  get id() {
6850
7007
  return this.metadata.id;
6851
7008
  }
@@ -6859,13 +7016,13 @@ var Prompt2 = (_class13 = class _Prompt {
6859
7016
  return "slug" in this.metadata ? this.metadata.slug : this.metadata.id;
6860
7017
  }
6861
7018
  get prompt() {
6862
- return _optionalChain([this, 'access', _79 => _79.getParsedPromptData, 'call', _80 => _80(), 'optionalAccess', _81 => _81.prompt]);
7019
+ return _optionalChain([this, 'access', _83 => _83.getParsedPromptData, 'call', _84 => _84(), 'optionalAccess', _85 => _85.prompt]);
6863
7020
  }
6864
7021
  get version() {
6865
7022
  return this.metadata[TRANSACTION_ID_FIELD];
6866
7023
  }
6867
7024
  get options() {
6868
- return _optionalChain([this, 'access', _82 => _82.getParsedPromptData, 'call', _83 => _83(), 'optionalAccess', _84 => _84.options]) || {};
7025
+ return _optionalChain([this, 'access', _86 => _86.getParsedPromptData, 'call', _87 => _87(), 'optionalAccess', _88 => _88.options]) || {};
6869
7026
  }
6870
7027
  get promptData() {
6871
7028
  return this.getParsedPromptData();
@@ -7016,7 +7173,7 @@ var Prompt2 = (_class13 = class _Prompt {
7016
7173
  return {
7017
7174
  type: "chat",
7018
7175
  messages,
7019
- ..._optionalChain([prompt, 'access', _85 => _85.tools, 'optionalAccess', _86 => _86.trim, 'call', _87 => _87()]) ? {
7176
+ ..._optionalChain([prompt, 'access', _89 => _89.tools, 'optionalAccess', _90 => _90.trim, 'call', _91 => _91()]) ? {
7020
7177
  tools: render(prompt.tools)
7021
7178
  } : void 0
7022
7179
  };
@@ -7126,9 +7283,15 @@ async function getPromptVersions(projectId, promptId) {
7126
7283
  );
7127
7284
  }
7128
7285
  const result = await response.json();
7129
- return _optionalChain([result, 'access', _88 => _88.data, 'optionalAccess', _89 => _89.filter, 'call', _90 => _90(
7130
- (entry) => ["upsert", "merge"].includes(_optionalChain([entry, 'access', _91 => _91.audit_data, 'optionalAccess', _92 => _92.action]))
7131
- ), 'access', _93 => _93.map, 'call', _94 => _94((entry) => prettifyXact(entry._xact_id))]) || [];
7286
+ return _optionalChain([result, 'access', _92 => _92.data, 'optionalAccess', _93 => _93.filter, 'call', _94 => _94(
7287
+ (entry) => ["upsert", "merge"].includes(_optionalChain([entry, 'access', _95 => _95.audit_data, 'optionalAccess', _96 => _96.action]))
7288
+ ), 'access', _97 => _97.map, 'call', _98 => _98((entry) => prettifyXact(entry._xact_id))]) || [];
7289
+ }
7290
+ function resetIdGenStateForTests() {
7291
+ const state = _internalGetGlobalState();
7292
+ if (state) {
7293
+ state.resetIdGenState();
7294
+ }
7132
7295
  }
7133
7296
  var _exportsForTestingOnly = {
7134
7297
  extractAttachments,
@@ -7140,7 +7303,8 @@ var _exportsForTestingOnly = {
7140
7303
  setInitialTestState,
7141
7304
  initTestExperiment,
7142
7305
  isGeneratorFunction,
7143
- isAsyncGeneratorFunction
7306
+ isAsyncGeneratorFunction,
7307
+ resetIdGenStateForTests
7144
7308
  };
7145
7309
 
7146
7310
  // src/browser-config.ts
@@ -7208,6 +7372,7 @@ __export(exports_browser_exports, {
7208
7372
  currentExperiment: () => currentExperiment,
7209
7373
  currentLogger: () => currentLogger,
7210
7374
  currentSpan: () => currentSpan,
7375
+ deepCopyEvent: () => deepCopyEvent,
7211
7376
  deserializePlainStringAsJSON: () => deserializePlainStringAsJSON,
7212
7377
  devNullWritableStream: () => devNullWritableStream,
7213
7378
  evaluatorDefinitionSchema: () => evaluatorDefinitionSchema,
@@ -7386,8 +7551,8 @@ function parseSpanFromResponseCreateParams(params) {
7386
7551
  }
7387
7552
  function parseEventFromResponseCreateResult(result) {
7388
7553
  const data = {};
7389
- if (_optionalChain([result, 'optionalAccess', _95 => _95.output]) !== void 0) {
7390
- data.output = result.output;
7554
+ if (_optionalChain([result, 'optionalAccess', _99 => _99.output]) !== void 0) {
7555
+ data.output = processImagesInOutput(result.output);
7391
7556
  }
7392
7557
  if (result) {
7393
7558
  const { output, usage, ...metadata } = result;
@@ -7395,9 +7560,38 @@ function parseEventFromResponseCreateResult(result) {
7395
7560
  data.metadata = metadata;
7396
7561
  }
7397
7562
  }
7398
- data.metrics = parseMetricsFromUsage(_optionalChain([result, 'optionalAccess', _96 => _96.usage]));
7563
+ data.metrics = parseMetricsFromUsage(_optionalChain([result, 'optionalAccess', _100 => _100.usage]));
7399
7564
  return data;
7400
7565
  }
7566
+ function processImagesInOutput(output) {
7567
+ if (Array.isArray(output)) {
7568
+ return output.map(processImagesInOutput);
7569
+ }
7570
+ if (isObject(output)) {
7571
+ if (output.type === "image_generation_call" && output.result && typeof output.result === "string") {
7572
+ const fileExtension = output.output_format || "png";
7573
+ const contentType = `image/${fileExtension}`;
7574
+ const baseFilename = output.revised_prompt && typeof output.revised_prompt === "string" ? output.revised_prompt.slice(0, 50).replace(/[^a-zA-Z0-9]/g, "_") : "generated_image";
7575
+ const filename = `${baseFilename}.${fileExtension}`;
7576
+ const binaryString = atob(output.result);
7577
+ const bytes = new Uint8Array(binaryString.length);
7578
+ for (let i = 0; i < binaryString.length; i++) {
7579
+ bytes[i] = binaryString.charCodeAt(i);
7580
+ }
7581
+ const blob = new Blob([bytes], { type: contentType });
7582
+ const attachment = new Attachment({
7583
+ data: blob,
7584
+ filename,
7585
+ contentType
7586
+ });
7587
+ return {
7588
+ ...output,
7589
+ result: attachment
7590
+ };
7591
+ }
7592
+ }
7593
+ return output;
7594
+ }
7401
7595
  function parseSpanFromResponseParseParams(params) {
7402
7596
  const spanArgs = {
7403
7597
  name: "openai.responses.parse",
@@ -7420,8 +7614,8 @@ function parseSpanFromResponseParseParams(params) {
7420
7614
  }
7421
7615
  function parseEventFromResponseParseResult(result) {
7422
7616
  const data = {};
7423
- if (_optionalChain([result, 'optionalAccess', _97 => _97.output]) !== void 0) {
7424
- data.output = result.output;
7617
+ if (_optionalChain([result, 'optionalAccess', _101 => _101.output]) !== void 0) {
7618
+ data.output = processImagesInOutput(result.output);
7425
7619
  }
7426
7620
  if (result) {
7427
7621
  const { output, usage, ...metadata } = result;
@@ -7429,7 +7623,7 @@ function parseEventFromResponseParseResult(result) {
7429
7623
  data.metadata = metadata;
7430
7624
  }
7431
7625
  }
7432
- data.metrics = parseMetricsFromUsage(_optionalChain([result, 'optionalAccess', _98 => _98.usage]));
7626
+ data.metrics = parseMetricsFromUsage(_optionalChain([result, 'optionalAccess', _102 => _102.usage]));
7433
7627
  return data;
7434
7628
  }
7435
7629
  function traceResponseCreateStream(stream, timedSpan) {
@@ -7446,7 +7640,7 @@ function traceResponseCreateStream(stream, timedSpan) {
7446
7640
  return result;
7447
7641
  }
7448
7642
  const item = result.value;
7449
- if (!item || !_optionalChain([item, 'optionalAccess', _99 => _99.type]) || !_optionalChain([item, 'optionalAccess', _100 => _100.response])) {
7643
+ if (!item || !_optionalChain([item, 'optionalAccess', _103 => _103.type]) || !_optionalChain([item, 'optionalAccess', _104 => _104.response])) {
7450
7644
  return result;
7451
7645
  }
7452
7646
  const event = parseLogFromItem(item);
@@ -7457,15 +7651,15 @@ function traceResponseCreateStream(stream, timedSpan) {
7457
7651
  };
7458
7652
  }
7459
7653
  function parseLogFromItem(item) {
7460
- if (!item || !_optionalChain([item, 'optionalAccess', _101 => _101.type]) || !_optionalChain([item, 'optionalAccess', _102 => _102.response])) {
7654
+ if (!item || !_optionalChain([item, 'optionalAccess', _105 => _105.type]) || !_optionalChain([item, 'optionalAccess', _106 => _106.response])) {
7461
7655
  return {};
7462
7656
  }
7463
7657
  const response = item.response;
7464
7658
  switch (item.type) {
7465
7659
  case "response.completed":
7466
7660
  const data = {};
7467
- if (_optionalChain([response, 'optionalAccess', _103 => _103.output]) !== void 0) {
7468
- data.output = response.output;
7661
+ if (_optionalChain([response, 'optionalAccess', _107 => _107.output]) !== void 0) {
7662
+ data.output = processImagesInOutput(response.output);
7469
7663
  }
7470
7664
  if (response) {
7471
7665
  const { usage, output, ...metadata } = response;
@@ -7473,7 +7667,7 @@ function parseLogFromItem(item) {
7473
7667
  data.metadata = metadata;
7474
7668
  }
7475
7669
  }
7476
- data.metrics = parseMetricsFromUsage(_optionalChain([response, 'optionalAccess', _104 => _104.usage]));
7670
+ data.metrics = parseMetricsFromUsage(_optionalChain([response, 'optionalAccess', _108 => _108.usage]));
7477
7671
  return data;
7478
7672
  default:
7479
7673
  return {};
@@ -7657,8 +7851,8 @@ function wrapOpenAIv4(openai) {
7657
7851
  const embeddingProxy = createEndpointProxy(openai.embeddings, wrapEmbeddings);
7658
7852
  const moderationProxy = createEndpointProxy(openai.moderations, wrapModerations);
7659
7853
  let betaProxy;
7660
- if (_optionalChain([openai, 'access', _105 => _105.beta, 'optionalAccess', _106 => _106.chat, 'optionalAccess', _107 => _107.completions, 'optionalAccess', _108 => _108.stream])) {
7661
- const betaChatCompletionProxy = new Proxy(_optionalChain([openai, 'optionalAccess', _109 => _109.beta, 'optionalAccess', _110 => _110.chat, 'access', _111 => _111.completions]), {
7854
+ if (_optionalChain([openai, 'access', _109 => _109.beta, 'optionalAccess', _110 => _110.chat, 'optionalAccess', _111 => _111.completions, 'optionalAccess', _112 => _112.stream])) {
7855
+ const betaChatCompletionProxy = new Proxy(_optionalChain([openai, 'optionalAccess', _113 => _113.beta, 'optionalAccess', _114 => _114.chat, 'access', _115 => _115.completions]), {
7662
7856
  get(target, name, receiver) {
7663
7857
  const baseVal = Reflect.get(target, name, receiver);
7664
7858
  if (name === "parse") {
@@ -7706,7 +7900,7 @@ function wrapOpenAIv4(openai) {
7706
7900
  });
7707
7901
  }
7708
7902
  function logCompletionResponse(startTime, response, span) {
7709
- const metrics = parseMetricsFromUsage(_optionalChain([response, 'optionalAccess', _112 => _112.usage]));
7903
+ const metrics = parseMetricsFromUsage(_optionalChain([response, 'optionalAccess', _116 => _116.usage]));
7710
7904
  metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
7711
7905
  span.log({
7712
7906
  output: response.choices,
@@ -7936,7 +8130,7 @@ function parseChatCompletionParams(params) {
7936
8130
  function processEmbeddingResponse(result, span) {
7937
8131
  span.log({
7938
8132
  output: { embedding_length: result.data[0].embedding.length },
7939
- metrics: parseMetricsFromUsage(_optionalChain([result, 'optionalAccess', _113 => _113.usage]))
8133
+ metrics: parseMetricsFromUsage(_optionalChain([result, 'optionalAccess', _117 => _117.usage]))
7940
8134
  });
7941
8135
  }
7942
8136
  function processModerationResponse(result, span) {
@@ -7966,10 +8160,10 @@ function postprocessStreamingResults(allResults) {
7966
8160
  if (result.usage) {
7967
8161
  metrics = {
7968
8162
  ...metrics,
7969
- ...parseMetricsFromUsage(_optionalChain([result, 'optionalAccess', _114 => _114.usage]))
8163
+ ...parseMetricsFromUsage(_optionalChain([result, 'optionalAccess', _118 => _118.usage]))
7970
8164
  };
7971
8165
  }
7972
- const delta = _optionalChain([result, 'access', _115 => _115.choices, 'optionalAccess', _116 => _116[0], 'optionalAccess', _117 => _117.delta]);
8166
+ const delta = _optionalChain([result, 'access', _119 => _119.choices, 'optionalAccess', _120 => _120[0], 'optionalAccess', _121 => _121.delta]);
7973
8167
  if (!delta) {
7974
8168
  continue;
7975
8169
  }
@@ -8165,4 +8359,5 @@ var browser_default = exports_browser_exports;
8165
8359
 
8166
8360
 
8167
8361
 
8168
- exports.Attachment = Attachment; exports.BaseAttachment = BaseAttachment; exports.BraintrustState = BraintrustState; exports.BraintrustStream = BraintrustStream; exports.Dataset = Dataset2; exports.ERR_PERMALINK = ERR_PERMALINK; exports.Experiment = Experiment2; exports.ExternalAttachment = ExternalAttachment; exports.FailedHTTPResponse = FailedHTTPResponse; exports.INTERNAL_BTQL_LIMIT = INTERNAL_BTQL_LIMIT; exports.LEGACY_CACHED_HEADER = LEGACY_CACHED_HEADER; exports.LazyValue = LazyValue; exports.Logger = Logger; exports.NOOP_SPAN = NOOP_SPAN; exports.NOOP_SPAN_PERMALINK = NOOP_SPAN_PERMALINK; exports.NoopSpan = NoopSpan; exports.Prompt = Prompt2; exports.ReadonlyAttachment = ReadonlyAttachment; exports.ReadonlyExperiment = ReadonlyExperiment; exports.SpanImpl = SpanImpl; exports.TestBackgroundLogger = TestBackgroundLogger; exports.X_CACHED_HEADER = X_CACHED_HEADER; exports._exportsForTestingOnly = _exportsForTestingOnly; exports._internalGetGlobalState = _internalGetGlobalState; exports._internalSetInitialState = _internalSetInitialState; exports.braintrustStreamChunkSchema = braintrustStreamChunkSchema; exports.createFinalValuePassThroughStream = createFinalValuePassThroughStream; exports.currentExperiment = currentExperiment; exports.currentLogger = currentLogger; exports.currentSpan = currentSpan; exports.default = browser_default; exports.deserializePlainStringAsJSON = deserializePlainStringAsJSON; exports.devNullWritableStream = devNullWritableStream; exports.evaluatorDefinitionSchema = evaluatorDefinitionSchema; exports.evaluatorDefinitionsSchema = evaluatorDefinitionsSchema; exports.flush = flush; exports.getPromptVersions = getPromptVersions; exports.getSpanParentObject = getSpanParentObject; exports.init = init; exports.initDataset = initDataset; exports.initExperiment = initExperiment; exports.initFunction = initFunction; exports.initLogger = initLogger; exports.invoke = invoke; exports.loadPrompt = loadPrompt; exports.log = log; exports.logError = logError; exports.login = login; exports.loginToState = loginToState; exports.newId = newId; exports.parseCachedHeader = parseCachedHeader; exports.permalink = permalink; exports.renderMessage = renderMessage; exports.renderPromptParams = renderPromptParams; exports.setFetch = setFetch; exports.setMaskingFunction = setMaskingFunction; exports.spanComponentsToObjectId = spanComponentsToObjectId; exports.startSpan = startSpan; exports.summarize = summarize; exports.traceable = traceable; exports.traced = traced; exports.updateSpan = updateSpan; exports.withCurrent = withCurrent; exports.withDataset = withDataset; exports.withExperiment = withExperiment; exports.withLogger = withLogger; exports.withParent = withParent; exports.wrapOpenAI = wrapOpenAI; exports.wrapOpenAIv4 = wrapOpenAIv4; exports.wrapTraced = wrapTraced;
8362
+
8363
+ exports.Attachment = Attachment; exports.BaseAttachment = BaseAttachment; exports.BraintrustState = BraintrustState; exports.BraintrustStream = BraintrustStream; exports.Dataset = Dataset2; exports.ERR_PERMALINK = ERR_PERMALINK; exports.Experiment = Experiment2; exports.ExternalAttachment = ExternalAttachment; exports.FailedHTTPResponse = FailedHTTPResponse; exports.INTERNAL_BTQL_LIMIT = INTERNAL_BTQL_LIMIT; exports.LEGACY_CACHED_HEADER = LEGACY_CACHED_HEADER; exports.LazyValue = LazyValue; exports.Logger = Logger; exports.NOOP_SPAN = NOOP_SPAN; exports.NOOP_SPAN_PERMALINK = NOOP_SPAN_PERMALINK; exports.NoopSpan = NoopSpan; exports.Prompt = Prompt2; exports.ReadonlyAttachment = ReadonlyAttachment; exports.ReadonlyExperiment = ReadonlyExperiment; exports.SpanImpl = SpanImpl; exports.TestBackgroundLogger = TestBackgroundLogger; exports.X_CACHED_HEADER = X_CACHED_HEADER; exports._exportsForTestingOnly = _exportsForTestingOnly; exports._internalGetGlobalState = _internalGetGlobalState; exports._internalSetInitialState = _internalSetInitialState; exports.braintrustStreamChunkSchema = braintrustStreamChunkSchema; exports.createFinalValuePassThroughStream = createFinalValuePassThroughStream; exports.currentExperiment = currentExperiment; exports.currentLogger = currentLogger; exports.currentSpan = currentSpan; exports.deepCopyEvent = deepCopyEvent; exports.default = browser_default; exports.deserializePlainStringAsJSON = deserializePlainStringAsJSON; exports.devNullWritableStream = devNullWritableStream; exports.evaluatorDefinitionSchema = evaluatorDefinitionSchema; exports.evaluatorDefinitionsSchema = evaluatorDefinitionsSchema; exports.flush = flush; exports.getPromptVersions = getPromptVersions; exports.getSpanParentObject = getSpanParentObject; exports.init = init; exports.initDataset = initDataset; exports.initExperiment = initExperiment; exports.initFunction = initFunction; exports.initLogger = initLogger; exports.invoke = invoke; exports.loadPrompt = loadPrompt; exports.log = log; exports.logError = logError; exports.login = login; exports.loginToState = loginToState; exports.newId = newId; exports.parseCachedHeader = parseCachedHeader; exports.permalink = permalink; exports.renderMessage = renderMessage; exports.renderPromptParams = renderPromptParams; exports.setFetch = setFetch; exports.setMaskingFunction = setMaskingFunction; exports.spanComponentsToObjectId = spanComponentsToObjectId; exports.startSpan = startSpan; exports.summarize = summarize; exports.traceable = traceable; exports.traced = traced; exports.updateSpan = updateSpan; exports.withCurrent = withCurrent; exports.withDataset = withDataset; exports.withExperiment = withExperiment; exports.withLogger = withLogger; exports.withParent = withParent; exports.wrapOpenAI = wrapOpenAI; exports.wrapOpenAIv4 = wrapOpenAIv4; exports.wrapTraced = wrapTraced;