braintrust 0.0.199 → 0.0.200

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.
@@ -70,6 +70,7 @@ interface DiskCacheOptions {
70
70
  * If not specified, the cache will grow unbounded.
71
71
  */
72
72
  max?: number;
73
+ logWarnings?: boolean;
73
74
  }
74
75
  /**
75
76
  * A persistent filesystem-based cache implementation.
@@ -87,16 +88,12 @@ interface DiskCacheOptions {
87
88
  declare class DiskCache<T> {
88
89
  private readonly dir;
89
90
  private readonly max?;
91
+ private readonly logWarnings;
90
92
  /**
91
93
  * Creates a new DiskCache instance.
92
94
  * @param options - Configuration options for the cache.
93
95
  */
94
96
  constructor(options: DiskCacheOptions);
95
- /**
96
- * Gets the file path for a cache entry.
97
- * @param key - The cache key to get the path for.
98
- * @returns The full filesystem path for the cache entry.
99
- */
100
97
  private getEntryPath;
101
98
  /**
102
99
  * Retrieves a value from the cache.
@@ -104,7 +101,6 @@ declare class DiskCache<T> {
104
101
  *
105
102
  * @param key - The key to look up in the cache.
106
103
  * @returns The cached value if found, undefined otherwise.
107
- * @throws If there is an error reading from the disk cache (except for file not found).
108
104
  */
109
105
  get(key: string): Promise<T | undefined>;
110
106
  /**
@@ -115,11 +111,7 @@ declare class DiskCache<T> {
115
111
  * @param value - The value to store in the cache.
116
112
  */
117
113
  set(key: string, value: T): Promise<void>;
118
- /**
119
- * Evicts the oldest entries from the cache until it is under the maximum size.
120
- * @param entries - List of all cache entry filenames.
121
- */
122
- private evictOldest;
114
+ private evictOldestIfFull;
123
115
  }
124
116
 
125
117
  /**
@@ -1721,11 +1713,11 @@ declare const braintrustStreamChunkSchema: z.ZodUnion<[z.ZodObject<{
1721
1713
  data: z.ZodString;
1722
1714
  }, "strip", z.ZodTypeAny, {
1723
1715
  format: "code" | "global" | "graph" | "llm";
1724
- data: string;
1725
1716
  name: string;
1726
1717
  object_type: "prompt" | "tool" | "scorer" | "task" | "agent";
1727
1718
  id: string;
1728
- event: "error" | "text_delta" | "json_delta" | "progress" | "console" | "start" | "done";
1719
+ data: string;
1720
+ event: "text_delta" | "json_delta" | "error" | "progress" | "console" | "start" | "done";
1729
1721
  output_type: "completion" | "score" | "any";
1730
1722
  origin?: {
1731
1723
  object_type: "function" | "experiment" | "dataset" | "prompt" | "prompt_session" | "project_logs";
@@ -1736,11 +1728,11 @@ declare const braintrustStreamChunkSchema: z.ZodUnion<[z.ZodObject<{
1736
1728
  } | null | undefined;
1737
1729
  }, {
1738
1730
  format: "code" | "global" | "graph" | "llm";
1739
- data: string;
1740
1731
  name: string;
1741
1732
  object_type: "prompt" | "tool" | "scorer" | "task" | "agent";
1742
1733
  id: string;
1743
- event: "error" | "text_delta" | "json_delta" | "progress" | "console" | "start" | "done";
1734
+ data: string;
1735
+ event: "text_delta" | "json_delta" | "error" | "progress" | "console" | "start" | "done";
1744
1736
  output_type: "completion" | "score" | "any";
1745
1737
  origin?: {
1746
1738
  object_type: "function" | "experiment" | "dataset" | "prompt" | "prompt_session" | "project_logs";
@@ -1753,11 +1745,11 @@ declare const braintrustStreamChunkSchema: z.ZodUnion<[z.ZodObject<{
1753
1745
  }, "strip", z.ZodTypeAny, {
1754
1746
  data: {
1755
1747
  format: "code" | "global" | "graph" | "llm";
1756
- data: string;
1757
1748
  name: string;
1758
1749
  object_type: "prompt" | "tool" | "scorer" | "task" | "agent";
1759
1750
  id: string;
1760
- event: "error" | "text_delta" | "json_delta" | "progress" | "console" | "start" | "done";
1751
+ data: string;
1752
+ event: "text_delta" | "json_delta" | "error" | "progress" | "console" | "start" | "done";
1761
1753
  output_type: "completion" | "score" | "any";
1762
1754
  origin?: {
1763
1755
  object_type: "function" | "experiment" | "dataset" | "prompt" | "prompt_session" | "project_logs";
@@ -1771,11 +1763,11 @@ declare const braintrustStreamChunkSchema: z.ZodUnion<[z.ZodObject<{
1771
1763
  }, {
1772
1764
  data: {
1773
1765
  format: "code" | "global" | "graph" | "llm";
1774
- data: string;
1775
1766
  name: string;
1776
1767
  object_type: "prompt" | "tool" | "scorer" | "task" | "agent";
1777
1768
  id: string;
1778
- event: "error" | "text_delta" | "json_delta" | "progress" | "console" | "start" | "done";
1769
+ data: string;
1770
+ event: "text_delta" | "json_delta" | "error" | "progress" | "console" | "start" | "done";
1779
1771
  output_type: "completion" | "score" | "any";
1780
1772
  origin?: {
1781
1773
  object_type: "function" | "experiment" | "dataset" | "prompt" | "prompt_session" | "project_logs";
package/dist/browser.d.ts CHANGED
@@ -70,6 +70,7 @@ interface DiskCacheOptions {
70
70
  * If not specified, the cache will grow unbounded.
71
71
  */
72
72
  max?: number;
73
+ logWarnings?: boolean;
73
74
  }
74
75
  /**
75
76
  * A persistent filesystem-based cache implementation.
@@ -87,16 +88,12 @@ interface DiskCacheOptions {
87
88
  declare class DiskCache<T> {
88
89
  private readonly dir;
89
90
  private readonly max?;
91
+ private readonly logWarnings;
90
92
  /**
91
93
  * Creates a new DiskCache instance.
92
94
  * @param options - Configuration options for the cache.
93
95
  */
94
96
  constructor(options: DiskCacheOptions);
95
- /**
96
- * Gets the file path for a cache entry.
97
- * @param key - The cache key to get the path for.
98
- * @returns The full filesystem path for the cache entry.
99
- */
100
97
  private getEntryPath;
101
98
  /**
102
99
  * Retrieves a value from the cache.
@@ -104,7 +101,6 @@ declare class DiskCache<T> {
104
101
  *
105
102
  * @param key - The key to look up in the cache.
106
103
  * @returns The cached value if found, undefined otherwise.
107
- * @throws If there is an error reading from the disk cache (except for file not found).
108
104
  */
109
105
  get(key: string): Promise<T | undefined>;
110
106
  /**
@@ -115,11 +111,7 @@ declare class DiskCache<T> {
115
111
  * @param value - The value to store in the cache.
116
112
  */
117
113
  set(key: string, value: T): Promise<void>;
118
- /**
119
- * Evicts the oldest entries from the cache until it is under the maximum size.
120
- * @param entries - List of all cache entry filenames.
121
- */
122
- private evictOldest;
114
+ private evictOldestIfFull;
123
115
  }
124
116
 
125
117
  /**
@@ -1721,11 +1713,11 @@ declare const braintrustStreamChunkSchema: z.ZodUnion<[z.ZodObject<{
1721
1713
  data: z.ZodString;
1722
1714
  }, "strip", z.ZodTypeAny, {
1723
1715
  format: "code" | "global" | "graph" | "llm";
1724
- data: string;
1725
1716
  name: string;
1726
1717
  object_type: "prompt" | "tool" | "scorer" | "task" | "agent";
1727
1718
  id: string;
1728
- event: "error" | "text_delta" | "json_delta" | "progress" | "console" | "start" | "done";
1719
+ data: string;
1720
+ event: "text_delta" | "json_delta" | "error" | "progress" | "console" | "start" | "done";
1729
1721
  output_type: "completion" | "score" | "any";
1730
1722
  origin?: {
1731
1723
  object_type: "function" | "experiment" | "dataset" | "prompt" | "prompt_session" | "project_logs";
@@ -1736,11 +1728,11 @@ declare const braintrustStreamChunkSchema: z.ZodUnion<[z.ZodObject<{
1736
1728
  } | null | undefined;
1737
1729
  }, {
1738
1730
  format: "code" | "global" | "graph" | "llm";
1739
- data: string;
1740
1731
  name: string;
1741
1732
  object_type: "prompt" | "tool" | "scorer" | "task" | "agent";
1742
1733
  id: string;
1743
- event: "error" | "text_delta" | "json_delta" | "progress" | "console" | "start" | "done";
1734
+ data: string;
1735
+ event: "text_delta" | "json_delta" | "error" | "progress" | "console" | "start" | "done";
1744
1736
  output_type: "completion" | "score" | "any";
1745
1737
  origin?: {
1746
1738
  object_type: "function" | "experiment" | "dataset" | "prompt" | "prompt_session" | "project_logs";
@@ -1753,11 +1745,11 @@ declare const braintrustStreamChunkSchema: z.ZodUnion<[z.ZodObject<{
1753
1745
  }, "strip", z.ZodTypeAny, {
1754
1746
  data: {
1755
1747
  format: "code" | "global" | "graph" | "llm";
1756
- data: string;
1757
1748
  name: string;
1758
1749
  object_type: "prompt" | "tool" | "scorer" | "task" | "agent";
1759
1750
  id: string;
1760
- event: "error" | "text_delta" | "json_delta" | "progress" | "console" | "start" | "done";
1751
+ data: string;
1752
+ event: "text_delta" | "json_delta" | "error" | "progress" | "console" | "start" | "done";
1761
1753
  output_type: "completion" | "score" | "any";
1762
1754
  origin?: {
1763
1755
  object_type: "function" | "experiment" | "dataset" | "prompt" | "prompt_session" | "project_logs";
@@ -1771,11 +1763,11 @@ declare const braintrustStreamChunkSchema: z.ZodUnion<[z.ZodObject<{
1771
1763
  }, {
1772
1764
  data: {
1773
1765
  format: "code" | "global" | "graph" | "llm";
1774
- data: string;
1775
1766
  name: string;
1776
1767
  object_type: "prompt" | "tool" | "scorer" | "task" | "agent";
1777
1768
  id: string;
1778
- event: "error" | "text_delta" | "json_delta" | "progress" | "console" | "start" | "done";
1769
+ data: string;
1770
+ event: "text_delta" | "json_delta" | "error" | "progress" | "console" | "start" | "done";
1779
1771
  output_type: "completion" | "score" | "any";
1780
1772
  origin?: {
1781
1773
  object_type: "function" | "experiment" | "dataset" | "prompt" | "prompt_session" | "project_logs";
package/dist/browser.js CHANGED
@@ -396,11 +396,11 @@ function createFinalValuePassThroughStream(onFinal, onError) {
396
396
  break;
397
397
  default:
398
398
  const _type = chunkType;
399
- throw new Error(`Unknown chunk type ${_type}`);
399
+ onError(`Unknown chunk type: ${_type}`);
400
400
  }
401
401
  controller.enqueue(chunk);
402
402
  } else {
403
- throw new Error(`Unknown chunk type ${chunk}`);
403
+ onError(`Unknown chunk type ${JSON.stringify(chunk)}`);
404
404
  }
405
405
  },
406
406
  flush(controller) {
@@ -431,11 +431,12 @@ function devNullWritableStream() {
431
431
 
432
432
  // src/prompt-cache/disk-cache.ts
433
433
  function canUseDiskCache() {
434
- return !!(isomorph_default.gunzip && isomorph_default.gzip && isomorph_default.stat && isomorph_default.readFile && isomorph_default.writeFile && isomorph_default.utimes && isomorph_default.readdir && isomorph_default.mkdir && isomorph_default.unlink && isomorph_default.homedir);
434
+ return !!(isomorph_default.hash && isomorph_default.gunzip && isomorph_default.gzip && isomorph_default.stat && isomorph_default.readFile && isomorph_default.writeFile && isomorph_default.utimes && isomorph_default.readdir && isomorph_default.mkdir && isomorph_default.unlink && isomorph_default.homedir);
435
435
  }
436
436
  var DiskCache = class {
437
437
  dir;
438
438
  max;
439
+ logWarnings;
439
440
  /**
440
441
  * Creates a new DiskCache instance.
441
442
  * @param options - Configuration options for the cache.
@@ -446,14 +447,11 @@ var DiskCache = class {
446
447
  }
447
448
  this.dir = options.cacheDir;
448
449
  this.max = options.max;
450
+ this.logWarnings = options.logWarnings ?? true;
449
451
  }
450
- /**
451
- * Gets the file path for a cache entry.
452
- * @param key - The cache key to get the path for.
453
- * @returns The full filesystem path for the cache entry.
454
- */
455
452
  getEntryPath(key) {
456
- return isomorph_default.pathJoin(this.dir, key);
453
+ const hashed = isomorph_default.hash(key);
454
+ return isomorph_default.pathJoin(this.dir, hashed);
457
455
  }
458
456
  /**
459
457
  * Retrieves a value from the cache.
@@ -461,7 +459,6 @@ var DiskCache = class {
461
459
  *
462
460
  * @param key - The key to look up in the cache.
463
461
  * @returns The cached value if found, undefined otherwise.
464
- * @throws If there is an error reading from the disk cache (except for file not found).
465
462
  */
466
463
  async get(key) {
467
464
  try {
@@ -473,7 +470,10 @@ var DiskCache = class {
473
470
  if (e.code === "ENOENT") {
474
471
  return void 0;
475
472
  }
476
- throw e;
473
+ if (this.logWarnings) {
474
+ console.warn("Failed to read from disk cache", e);
475
+ }
476
+ return void 0;
477
477
  }
478
478
  }
479
479
  /**
@@ -487,33 +487,35 @@ var DiskCache = class {
487
487
  await isomorph_default.mkdir(this.dir, { recursive: true });
488
488
  const filePath = this.getEntryPath(key);
489
489
  const data = await isomorph_default.gzip(JSON.stringify(value));
490
- await isomorph_default.writeFile(filePath, data);
491
- if (this.max) {
492
- const entries = await isomorph_default.readdir(this.dir);
493
- if (entries.length > this.max) {
494
- await this.evictOldest(entries);
495
- }
490
+ try {
491
+ await isomorph_default.writeFile(filePath, data);
492
+ await this.evictOldestIfFull();
493
+ } catch (e) {
494
+ console.warn("Failed to write to disk cache", e);
495
+ return;
496
496
  }
497
497
  }
498
- /**
499
- * Evicts the oldest entries from the cache until it is under the maximum size.
500
- * @param entries - List of all cache entry filenames.
501
- */
502
- async evictOldest(entries) {
498
+ async evictOldestIfFull() {
499
+ if (!this.max) {
500
+ return;
501
+ }
502
+ const files = await isomorph_default.readdir(this.dir);
503
+ const paths = files.map((file) => isomorph_default.pathJoin(this.dir, file));
504
+ if (paths.length <= this.max) {
505
+ return;
506
+ }
503
507
  const stats = await Promise.all(
504
- entries.map(async (entry) => {
505
- const stat = await isomorph_default.stat(this.getEntryPath(entry));
508
+ paths.map(async (path) => {
509
+ const stat = await isomorph_default.stat(path);
506
510
  return {
507
- name: entry,
511
+ path,
508
512
  mtime: stat.mtime.getTime()
509
513
  };
510
514
  })
511
515
  );
512
516
  stats.sort((a, b) => a.mtime - b.mtime);
513
517
  const toRemove = stats.slice(0, stats.length - this.max);
514
- await Promise.all(
515
- toRemove.map((stat) => isomorph_default.unlink(this.getEntryPath(stat.name)))
516
- );
518
+ await Promise.all(toRemove.map((stat) => isomorph_default.unlink(stat.path)));
517
519
  }
518
520
  };
519
521
 
@@ -903,7 +905,7 @@ var BraintrustState = class _BraintrustState {
903
905
  const serializedParsed = loginSchema.safeParse(serialized);
904
906
  if (!serializedParsed.success) {
905
907
  throw new Error(
906
- `Cannot deserialize BraintrustState: ${serializedParsed.error.errors}`
908
+ `Cannot deserialize BraintrustState: ${serializedParsed.error.message}`
907
909
  );
908
910
  }
909
911
  const state = new _BraintrustState({ ...opts });
@@ -3106,17 +3108,17 @@ function extractAttachments(event, attachments) {
3106
3108
  extractAttachments(value, attachments);
3107
3109
  }
3108
3110
  }
3109
- function enrichAttachments(event) {
3111
+ function enrichAttachments(event, state) {
3110
3112
  for (const [key, value] of Object.entries(event)) {
3111
3113
  const parsedValue = import_typespecs2.attachmentReferenceSchema.safeParse(value);
3112
3114
  if (parsedValue.success) {
3113
- event[key] = new ReadonlyAttachment(parsedValue.data);
3115
+ event[key] = new ReadonlyAttachment(parsedValue.data, state);
3114
3116
  continue;
3115
3117
  }
3116
3118
  if (!(value instanceof Object)) {
3117
3119
  continue;
3118
3120
  }
3119
- enrichAttachments(value);
3121
+ enrichAttachments(value, state);
3120
3122
  }
3121
3123
  return event;
3122
3124
  }
@@ -3248,7 +3250,7 @@ var Experiment = class extends ObjectFetcher {
3248
3250
  // For type identification.
3249
3251
  kind = "experiment";
3250
3252
  constructor(state, lazyMetadata, dataset) {
3251
- super("experiment", void 0, enrichAttachments);
3253
+ super("experiment", void 0, (r) => enrichAttachments(r, state));
3252
3254
  this.lazyMetadata = lazyMetadata;
3253
3255
  this.dataset = dataset;
3254
3256
  this.lastStartTime = getCurrentUnixTimestamp();
@@ -3491,7 +3493,7 @@ var Experiment = class extends ObjectFetcher {
3491
3493
  };
3492
3494
  var ReadonlyExperiment = class extends ObjectFetcher {
3493
3495
  constructor(state, lazyMetadata) {
3494
- super("experiment", void 0, enrichAttachments);
3496
+ super("experiment", void 0, (r) => enrichAttachments(r, state));
3495
3497
  this.state = state;
3496
3498
  this.lazyMetadata = lazyMetadata;
3497
3499
  }
@@ -3804,7 +3806,7 @@ var Dataset = class extends ObjectFetcher {
3804
3806
  (r) => (
3805
3807
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
3806
3808
  (0, import_core2.ensureDatasetRecord)(
3807
- enrichAttachments(r),
3809
+ enrichAttachments(r, this.state),
3808
3810
  isLegacyDataset
3809
3811
  )
3810
3812
  ),
@@ -4359,6 +4361,16 @@ function configureBrowser() {
4359
4361
  }
4360
4362
  return process.env[name];
4361
4363
  };
4364
+ isomorph_default.hash = (data) => {
4365
+ let hash = 0;
4366
+ for (let i = 0; i < data.length; i++) {
4367
+ const char = data.charCodeAt(i);
4368
+ hash = (hash << 5) - hash + char;
4369
+ hash = hash & hash;
4370
+ }
4371
+ const hashHex = (hash >>> 0).toString(16).padStart(8, "0");
4372
+ return hashHex.repeat(8).substring(0, 64);
4373
+ };
4362
4374
  _internalSetInitialState();
4363
4375
  browserConfigured = true;
4364
4376
  }
package/dist/browser.mjs CHANGED
@@ -341,11 +341,11 @@ function createFinalValuePassThroughStream(onFinal, onError) {
341
341
  break;
342
342
  default:
343
343
  const _type = chunkType;
344
- throw new Error(`Unknown chunk type ${_type}`);
344
+ onError(`Unknown chunk type: ${_type}`);
345
345
  }
346
346
  controller.enqueue(chunk);
347
347
  } else {
348
- throw new Error(`Unknown chunk type ${chunk}`);
348
+ onError(`Unknown chunk type ${JSON.stringify(chunk)}`);
349
349
  }
350
350
  },
351
351
  flush(controller) {
@@ -376,11 +376,12 @@ function devNullWritableStream() {
376
376
 
377
377
  // src/prompt-cache/disk-cache.ts
378
378
  function canUseDiskCache() {
379
- return !!(isomorph_default.gunzip && isomorph_default.gzip && isomorph_default.stat && isomorph_default.readFile && isomorph_default.writeFile && isomorph_default.utimes && isomorph_default.readdir && isomorph_default.mkdir && isomorph_default.unlink && isomorph_default.homedir);
379
+ return !!(isomorph_default.hash && isomorph_default.gunzip && isomorph_default.gzip && isomorph_default.stat && isomorph_default.readFile && isomorph_default.writeFile && isomorph_default.utimes && isomorph_default.readdir && isomorph_default.mkdir && isomorph_default.unlink && isomorph_default.homedir);
380
380
  }
381
381
  var DiskCache = class {
382
382
  dir;
383
383
  max;
384
+ logWarnings;
384
385
  /**
385
386
  * Creates a new DiskCache instance.
386
387
  * @param options - Configuration options for the cache.
@@ -391,14 +392,11 @@ var DiskCache = class {
391
392
  }
392
393
  this.dir = options.cacheDir;
393
394
  this.max = options.max;
395
+ this.logWarnings = options.logWarnings ?? true;
394
396
  }
395
- /**
396
- * Gets the file path for a cache entry.
397
- * @param key - The cache key to get the path for.
398
- * @returns The full filesystem path for the cache entry.
399
- */
400
397
  getEntryPath(key) {
401
- return isomorph_default.pathJoin(this.dir, key);
398
+ const hashed = isomorph_default.hash(key);
399
+ return isomorph_default.pathJoin(this.dir, hashed);
402
400
  }
403
401
  /**
404
402
  * Retrieves a value from the cache.
@@ -406,7 +404,6 @@ var DiskCache = class {
406
404
  *
407
405
  * @param key - The key to look up in the cache.
408
406
  * @returns The cached value if found, undefined otherwise.
409
- * @throws If there is an error reading from the disk cache (except for file not found).
410
407
  */
411
408
  async get(key) {
412
409
  try {
@@ -418,7 +415,10 @@ var DiskCache = class {
418
415
  if (e.code === "ENOENT") {
419
416
  return void 0;
420
417
  }
421
- throw e;
418
+ if (this.logWarnings) {
419
+ console.warn("Failed to read from disk cache", e);
420
+ }
421
+ return void 0;
422
422
  }
423
423
  }
424
424
  /**
@@ -432,33 +432,35 @@ var DiskCache = class {
432
432
  await isomorph_default.mkdir(this.dir, { recursive: true });
433
433
  const filePath = this.getEntryPath(key);
434
434
  const data = await isomorph_default.gzip(JSON.stringify(value));
435
- await isomorph_default.writeFile(filePath, data);
436
- if (this.max) {
437
- const entries = await isomorph_default.readdir(this.dir);
438
- if (entries.length > this.max) {
439
- await this.evictOldest(entries);
440
- }
435
+ try {
436
+ await isomorph_default.writeFile(filePath, data);
437
+ await this.evictOldestIfFull();
438
+ } catch (e) {
439
+ console.warn("Failed to write to disk cache", e);
440
+ return;
441
441
  }
442
442
  }
443
- /**
444
- * Evicts the oldest entries from the cache until it is under the maximum size.
445
- * @param entries - List of all cache entry filenames.
446
- */
447
- async evictOldest(entries) {
443
+ async evictOldestIfFull() {
444
+ if (!this.max) {
445
+ return;
446
+ }
447
+ const files = await isomorph_default.readdir(this.dir);
448
+ const paths = files.map((file) => isomorph_default.pathJoin(this.dir, file));
449
+ if (paths.length <= this.max) {
450
+ return;
451
+ }
448
452
  const stats = await Promise.all(
449
- entries.map(async (entry) => {
450
- const stat = await isomorph_default.stat(this.getEntryPath(entry));
453
+ paths.map(async (path) => {
454
+ const stat = await isomorph_default.stat(path);
451
455
  return {
452
- name: entry,
456
+ path,
453
457
  mtime: stat.mtime.getTime()
454
458
  };
455
459
  })
456
460
  );
457
461
  stats.sort((a, b) => a.mtime - b.mtime);
458
462
  const toRemove = stats.slice(0, stats.length - this.max);
459
- await Promise.all(
460
- toRemove.map((stat) => isomorph_default.unlink(this.getEntryPath(stat.name)))
461
- );
463
+ await Promise.all(toRemove.map((stat) => isomorph_default.unlink(stat.path)));
462
464
  }
463
465
  };
464
466
 
@@ -848,7 +850,7 @@ var BraintrustState = class _BraintrustState {
848
850
  const serializedParsed = loginSchema.safeParse(serialized);
849
851
  if (!serializedParsed.success) {
850
852
  throw new Error(
851
- `Cannot deserialize BraintrustState: ${serializedParsed.error.errors}`
853
+ `Cannot deserialize BraintrustState: ${serializedParsed.error.message}`
852
854
  );
853
855
  }
854
856
  const state = new _BraintrustState({ ...opts });
@@ -3051,17 +3053,17 @@ function extractAttachments(event, attachments) {
3051
3053
  extractAttachments(value, attachments);
3052
3054
  }
3053
3055
  }
3054
- function enrichAttachments(event) {
3056
+ function enrichAttachments(event, state) {
3055
3057
  for (const [key, value] of Object.entries(event)) {
3056
3058
  const parsedValue = attachmentReferenceSchema.safeParse(value);
3057
3059
  if (parsedValue.success) {
3058
- event[key] = new ReadonlyAttachment(parsedValue.data);
3060
+ event[key] = new ReadonlyAttachment(parsedValue.data, state);
3059
3061
  continue;
3060
3062
  }
3061
3063
  if (!(value instanceof Object)) {
3062
3064
  continue;
3063
3065
  }
3064
- enrichAttachments(value);
3066
+ enrichAttachments(value, state);
3065
3067
  }
3066
3068
  return event;
3067
3069
  }
@@ -3193,7 +3195,7 @@ var Experiment = class extends ObjectFetcher {
3193
3195
  // For type identification.
3194
3196
  kind = "experiment";
3195
3197
  constructor(state, lazyMetadata, dataset) {
3196
- super("experiment", void 0, enrichAttachments);
3198
+ super("experiment", void 0, (r) => enrichAttachments(r, state));
3197
3199
  this.lazyMetadata = lazyMetadata;
3198
3200
  this.dataset = dataset;
3199
3201
  this.lastStartTime = getCurrentUnixTimestamp();
@@ -3436,7 +3438,7 @@ var Experiment = class extends ObjectFetcher {
3436
3438
  };
3437
3439
  var ReadonlyExperiment = class extends ObjectFetcher {
3438
3440
  constructor(state, lazyMetadata) {
3439
- super("experiment", void 0, enrichAttachments);
3441
+ super("experiment", void 0, (r) => enrichAttachments(r, state));
3440
3442
  this.state = state;
3441
3443
  this.lazyMetadata = lazyMetadata;
3442
3444
  }
@@ -3749,7 +3751,7 @@ var Dataset = class extends ObjectFetcher {
3749
3751
  (r) => (
3750
3752
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
3751
3753
  ensureDatasetRecord(
3752
- enrichAttachments(r),
3754
+ enrichAttachments(r, this.state),
3753
3755
  isLegacyDataset
3754
3756
  )
3755
3757
  ),
@@ -4304,6 +4306,16 @@ function configureBrowser() {
4304
4306
  }
4305
4307
  return process.env[name];
4306
4308
  };
4309
+ isomorph_default.hash = (data) => {
4310
+ let hash = 0;
4311
+ for (let i = 0; i < data.length; i++) {
4312
+ const char = data.charCodeAt(i);
4313
+ hash = (hash << 5) - hash + char;
4314
+ hash = hash & hash;
4315
+ }
4316
+ const hashHex = (hash >>> 0).toString(16).padStart(8, "0");
4317
+ return hashHex.repeat(8).substring(0, 64);
4318
+ };
4307
4319
  _internalSetInitialState();
4308
4320
  browserConfigured = true;
4309
4321
  }