braintrust 3.12.0 → 3.13.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.
Files changed (49) hide show
  1. package/dev/dist/index.d.mts +25 -6
  2. package/dev/dist/index.d.ts +25 -6
  3. package/dev/dist/index.js +134 -43
  4. package/dev/dist/index.mjs +113 -22
  5. package/dist/apply-auto-instrumentation.js +170 -170
  6. package/dist/apply-auto-instrumentation.mjs +1 -1
  7. package/dist/auto-instrumentations/bundler/esbuild.cjs +1 -0
  8. package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
  9. package/dist/auto-instrumentations/bundler/next.cjs +1 -0
  10. package/dist/auto-instrumentations/bundler/next.mjs +3 -3
  11. package/dist/auto-instrumentations/bundler/rollup.cjs +1 -0
  12. package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
  13. package/dist/auto-instrumentations/bundler/vite.cjs +1 -0
  14. package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
  15. package/dist/auto-instrumentations/bundler/webpack-loader.cjs +1 -0
  16. package/dist/auto-instrumentations/bundler/webpack.cjs +1 -0
  17. package/dist/auto-instrumentations/bundler/webpack.mjs +3 -3
  18. package/dist/auto-instrumentations/{chunk-2DPA74KK.mjs → chunk-E5DUYJWK.mjs} +1 -0
  19. package/dist/auto-instrumentations/{chunk-73BZUKVI.mjs → chunk-GJOO4ESL.mjs} +1 -1
  20. package/dist/auto-instrumentations/{chunk-AFXRW7I7.mjs → chunk-WFEUJACP.mjs} +1 -1
  21. package/dist/auto-instrumentations/hook.mjs +1 -0
  22. package/dist/auto-instrumentations/index.cjs +1 -0
  23. package/dist/auto-instrumentations/index.mjs +1 -1
  24. package/dist/browser.d.mts +149 -21
  25. package/dist/browser.d.ts +149 -21
  26. package/dist/browser.js +114 -24
  27. package/dist/browser.mjs +114 -24
  28. package/dist/{chunk-BW4DF4CY.js → chunk-26JGOELH.js} +1 -0
  29. package/dist/{chunk-MSLBGITU.mjs → chunk-75IQCUB2.mjs} +1 -0
  30. package/dist/cli.js +121 -44
  31. package/dist/edge-light.d.mts +1 -1
  32. package/dist/edge-light.d.ts +1 -1
  33. package/dist/edge-light.js +114 -24
  34. package/dist/edge-light.mjs +114 -24
  35. package/dist/index.d.mts +149 -21
  36. package/dist/index.d.ts +149 -21
  37. package/dist/index.js +529 -394
  38. package/dist/index.mjs +161 -26
  39. package/dist/instrumentation/index.d.mts +40 -3
  40. package/dist/instrumentation/index.d.ts +40 -3
  41. package/dist/instrumentation/index.js +15 -2
  42. package/dist/instrumentation/index.mjs +15 -2
  43. package/dist/workerd.d.mts +1 -1
  44. package/dist/workerd.d.ts +1 -1
  45. package/dist/workerd.js +114 -24
  46. package/dist/workerd.mjs +114 -24
  47. package/package.json +3 -17
  48. package/util/dist/index.d.mts +3 -1
  49. package/util/dist/index.d.ts +3 -1
package/dist/index.mjs CHANGED
@@ -24,7 +24,7 @@ import {
24
24
  openRouterChannels,
25
25
  patchTracingChannel,
26
26
  readDisabledInstrumentationEnvConfig
27
- } from "./chunk-MSLBGITU.mjs";
27
+ } from "./chunk-75IQCUB2.mjs";
28
28
 
29
29
  // src/node/config.ts
30
30
  import { AsyncLocalStorage } from "node:async_hooks";
@@ -36,6 +36,7 @@ import * as fsSync from "node:fs";
36
36
  import * as crypto from "node:crypto";
37
37
  import { promisify } from "node:util";
38
38
  import * as zlib from "node:zlib";
39
+ import * as dotenv from "dotenv";
39
40
 
40
41
  // src/debug-logger.ts
41
42
  var PREFIX = "[braintrust]";
@@ -5580,6 +5581,19 @@ var JSONAttachment = class extends Attachment {
5580
5581
  */
5581
5582
  constructor(data, options) {
5582
5583
  const { filename = "data.json", pretty = false, state } = options ?? {};
5584
+ const deferredJsonAttachment = globalThis.__BT_DATASET_PIPELINE_DEFER_JSON_ATTACHMENT__;
5585
+ if (deferredJsonAttachment) {
5586
+ super({
5587
+ data: new Blob([]),
5588
+ filename,
5589
+ contentType: "application/json",
5590
+ state
5591
+ });
5592
+ return deferredJsonAttachment(data, {
5593
+ filename,
5594
+ pretty
5595
+ });
5596
+ }
5583
5597
  const jsonString = pretty ? JSON.stringify(data, null, 2) : JSON.stringify(data);
5584
5598
  const blob = new Blob([jsonString], { type: "application/json" });
5585
5599
  super({
@@ -7572,10 +7586,11 @@ async function login(options = {}) {
7572
7586
  async function loginToState(options = {}) {
7573
7587
  const {
7574
7588
  appUrl = isomorph_default.getEnv("BRAINTRUST_APP_URL") || "https://www.braintrust.dev",
7575
- apiKey = isomorph_default.getEnv("BRAINTRUST_API_KEY"),
7589
+ apiKey: apiKeyArg,
7576
7590
  orgName = isomorph_default.getEnv("BRAINTRUST_ORG_NAME"),
7577
7591
  fetch: fetch2 = globalThis.fetch
7578
7592
  } = options || {};
7593
+ const apiKey = apiKeyArg !== void 0 ? apiKeyArg : await isomorph_default.getBraintrustApiKey();
7579
7594
  const appPublicUrl = isomorph_default.getEnv("BRAINTRUST_APP_PUBLIC_URL") || appUrl;
7580
7595
  const state = new BraintrustState(options);
7581
7596
  state.resetLoginInfo();
@@ -8816,9 +8831,15 @@ var SpanImpl = class _SpanImpl {
8816
8831
  const cachedSpan = {
8817
8832
  input: partialRecord.input,
8818
8833
  output: partialRecord.output,
8834
+ expected: partialRecord.expected,
8835
+ error: partialRecord.error,
8836
+ scores: partialRecord.scores,
8837
+ metrics: partialRecord.metrics,
8819
8838
  metadata: partialRecord.metadata,
8839
+ tags: partialRecord.tags,
8820
8840
  span_id: this._spanId,
8821
8841
  span_parents: this._spanParents,
8842
+ is_root: this._spanId === this._rootSpanId,
8822
8843
  span_attributes: partialRecord.span_attributes
8823
8844
  };
8824
8845
  this._state.spanCache.queueWrite(
@@ -9154,6 +9175,7 @@ var Dataset2 = class extends ObjectFetcher {
9154
9175
  metadata,
9155
9176
  tags,
9156
9177
  output,
9178
+ origin,
9157
9179
  isMerge
9158
9180
  }) {
9159
9181
  return new LazyValue(async () => {
@@ -9168,6 +9190,7 @@ var Dataset2 = class extends ObjectFetcher {
9168
9190
  created: !isMerge ? (/* @__PURE__ */ new Date()).toISOString() : void 0,
9169
9191
  //if we're merging/updating an event we will not add this ts
9170
9192
  metadata,
9193
+ origin,
9171
9194
  ...!!isMerge ? {
9172
9195
  [IS_MERGE_FIELD]: true
9173
9196
  } : {}
@@ -9187,6 +9210,7 @@ var Dataset2 = class extends ObjectFetcher {
9187
9210
  * about anything else that's relevant, that you can use to help find and analyze examples later. For example, you could log the
9188
9211
  * `prompt`, example's `id`, or anything else that would be useful to slice/dice later. The values in `metadata` can be any
9189
9212
  * JSON-serializable type, but its keys must be strings.
9213
+ * @param event.origin (Optional) a reference to the source object this dataset record was derived from.
9190
9214
  * @param event.id (Optional) a unique identifier for the event. If you don't provide one, Braintrust will generate one for you.
9191
9215
  * @param event.output: (Deprecated) The output of your application. Use `expected` instead.
9192
9216
  * @returns The `id` of the logged record.
@@ -9197,7 +9221,8 @@ var Dataset2 = class extends ObjectFetcher {
9197
9221
  metadata,
9198
9222
  tags,
9199
9223
  id,
9200
- output
9224
+ output,
9225
+ origin
9201
9226
  }) {
9202
9227
  this.validateEvent({ metadata, expected, output, tags });
9203
9228
  const rowId = id || uuidv42();
@@ -9209,6 +9234,7 @@ var Dataset2 = class extends ObjectFetcher {
9209
9234
  metadata,
9210
9235
  tags,
9211
9236
  output,
9237
+ origin,
9212
9238
  isMerge: false
9213
9239
  })
9214
9240
  );
@@ -25464,11 +25490,60 @@ function configureInstrumentation(config) {
25464
25490
  }
25465
25491
 
25466
25492
  // src/node/config.ts
25493
+ var BRAINTRUST_ENV_SEARCH_PARENT_LIMIT = 64;
25467
25494
  function configureNode() {
25468
25495
  isomorph_default.buildType = "node";
25469
25496
  isomorph_default.getRepoInfo = getRepoInfo;
25470
25497
  isomorph_default.getPastNAncestors = getPastNAncestors;
25471
- isomorph_default.getEnv = (name) => process.env[name];
25498
+ isomorph_default.getEnv = (name) => {
25499
+ const value = process.env[name];
25500
+ return name === "BRAINTRUST_API_KEY" && !value?.trim() ? void 0 : value;
25501
+ };
25502
+ isomorph_default.getBraintrustApiKey = async () => {
25503
+ const value = process.env.BRAINTRUST_API_KEY;
25504
+ if (value?.trim()) {
25505
+ return value;
25506
+ }
25507
+ const envPaths = [];
25508
+ for (let dir2 = process.cwd(), depth = 0; depth <= BRAINTRUST_ENV_SEARCH_PARENT_LIMIT; dir2 = path.dirname(dir2), depth++) {
25509
+ envPaths.push(path.join(dir2, ".env.braintrust"));
25510
+ if (path.dirname(dir2) === dir2) {
25511
+ break;
25512
+ }
25513
+ }
25514
+ const pending = /* @__PURE__ */ new Map();
25515
+ envPaths.forEach((envPath, index) => {
25516
+ pending.set(
25517
+ index,
25518
+ fs.readFile(envPath, "utf8").then(
25519
+ (contents) => ({ contents, envPath, index }),
25520
+ (error) => ({ error, envPath, index })
25521
+ )
25522
+ );
25523
+ });
25524
+ const results = [];
25525
+ let nearestUnresolvedIndex = 0;
25526
+ while (pending.size > 0) {
25527
+ const result = await Promise.race(pending.values());
25528
+ pending.delete(result.index);
25529
+ results[result.index] = result;
25530
+ while (results[nearestUnresolvedIndex]) {
25531
+ const nearestResult = results[nearestUnresolvedIndex];
25532
+ if ("contents" in nearestResult) {
25533
+ const parsed = dotenv.parse(nearestResult.contents);
25534
+ const apiKey = parsed.BRAINTRUST_API_KEY;
25535
+ return apiKey?.trim() ? apiKey : void 0;
25536
+ }
25537
+ const e = nearestResult.error;
25538
+ if (typeof e === "object" && e !== null && "code" in e && e.code === "ENOENT") {
25539
+ nearestUnresolvedIndex++;
25540
+ continue;
25541
+ }
25542
+ return void 0;
25543
+ }
25544
+ }
25545
+ return void 0;
25546
+ };
25472
25547
  isomorph_default.getCallerLocation = getCallerLocation;
25473
25548
  isomorph_default.newAsyncLocalStorage = () => new AsyncLocalStorage();
25474
25549
  isomorph_default.newTracingChannel = (nameOrChannels) => diagnostics_channel.tracingChannel(nameOrChannels);
@@ -25522,6 +25597,7 @@ __export(exports_exports, {
25522
25597
  DEFAULT_FETCH_BATCH_SIZE: () => DEFAULT_FETCH_BATCH_SIZE,
25523
25598
  DEFAULT_MAX_REQUEST_SIZE: () => DEFAULT_MAX_REQUEST_SIZE,
25524
25599
  Dataset: () => Dataset2,
25600
+ DatasetPipeline: () => DatasetPipeline,
25525
25601
  ERR_PERMALINK: () => ERR_PERMALINK,
25526
25602
  Eval: () => Eval,
25527
25603
  EvalResultWithSummary: () => EvalResultWithSummary,
@@ -28780,10 +28856,12 @@ function formatExperimentSummary(summary) {
28780
28856
  // src/wrappers/shared/flush.ts
28781
28857
  async function summarizeAndFlush(experiment, options) {
28782
28858
  const shouldDisplay = options.displaySummary ?? true;
28783
- const summary = await experiment.summarize();
28784
- if (shouldDisplay) {
28785
- console.log(formatExperimentSummary(summary));
28859
+ if (!shouldDisplay) {
28860
+ await experiment.flush();
28861
+ return;
28786
28862
  }
28863
+ const summary = await experiment.summarize();
28864
+ console.log(formatExperimentSummary(summary));
28787
28865
  }
28788
28866
 
28789
28867
  // src/wrappers/vitest/flush-manager.ts
@@ -30647,8 +30725,12 @@ var waterfall$1 = awaitify(waterfall);
30647
30725
 
30648
30726
  // src/trace.ts
30649
30727
  var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
30650
- constructor(objectType, _objectId, rootSpanId, _state, spanTypeFilter) {
30651
- const filterExpr = _SpanFetcher.buildFilter(rootSpanId, spanTypeFilter);
30728
+ constructor(objectType, _objectId, rootSpanId, _state, spanTypeFilter, includeScorers = false) {
30729
+ const filterExpr = _SpanFetcher.buildFilter(
30730
+ rootSpanId,
30731
+ spanTypeFilter,
30732
+ includeScorers
30733
+ );
30652
30734
  super(objectType, void 0, void 0, {
30653
30735
  filter: filterExpr
30654
30736
  });
@@ -30657,16 +30739,17 @@ var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
30657
30739
  this._state = _state;
30658
30740
  this.spanTypeFilter = spanTypeFilter;
30659
30741
  }
30660
- static buildFilter(rootSpanId, spanTypeFilter) {
30742
+ static buildFilter(rootSpanId, spanTypeFilter, includeScorers = false) {
30661
30743
  const children = [
30662
30744
  // Base filter: root_span_id = 'value'
30663
30745
  {
30664
30746
  op: "eq",
30665
30747
  left: { op: "ident", name: ["root_span_id"] },
30666
30748
  right: { op: "literal", value: rootSpanId }
30667
- },
30668
- // Exclude span_attributes.purpose = 'score'
30669
- {
30749
+ }
30750
+ ];
30751
+ if (!includeScorers) {
30752
+ children.push({
30670
30753
  op: "or",
30671
30754
  children: [
30672
30755
  {
@@ -30679,8 +30762,8 @@ var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
30679
30762
  right: { op: "literal", value: "scorer" }
30680
30763
  }
30681
30764
  ]
30682
- }
30683
- ];
30765
+ });
30766
+ }
30684
30767
  if (spanTypeFilter && spanTypeFilter.length > 0) {
30685
30768
  children.push({
30686
30769
  op: "in",
@@ -30706,35 +30789,49 @@ var CachedSpanFetcher = class {
30706
30789
  fetchFn;
30707
30790
  constructor(objectTypeOrFetchFn, objectId, rootSpanId, getState) {
30708
30791
  if (typeof objectTypeOrFetchFn === "function") {
30709
- this.fetchFn = objectTypeOrFetchFn;
30792
+ this.fetchFn = (spanType) => objectTypeOrFetchFn(spanType);
30710
30793
  } else {
30711
30794
  const objectType = objectTypeOrFetchFn;
30712
- this.fetchFn = async (spanType) => {
30795
+ this.fetchFn = async (spanType, includeScorers) => {
30713
30796
  const state = await getState();
30714
30797
  const fetcher = new SpanFetcher(
30715
30798
  objectType,
30716
30799
  objectId,
30717
30800
  rootSpanId,
30718
30801
  state,
30719
- spanType
30802
+ spanType,
30803
+ includeScorers
30720
30804
  );
30721
30805
  const rows = await fetcher.fetchedData();
30722
- return rows.filter((row) => row.span_attributes?.purpose !== "scorer").map((row) => ({
30806
+ return rows.map((row) => ({
30723
30807
  input: row.input,
30724
30808
  output: row.output,
30809
+ expected: row.expected,
30810
+ error: row.error,
30811
+ scores: row.scores,
30812
+ metrics: row.metrics,
30725
30813
  metadata: row.metadata,
30726
30814
  span_id: row.span_id,
30727
30815
  span_parents: row.span_parents,
30816
+ is_root: row.is_root,
30728
30817
  span_attributes: row.span_attributes,
30729
30818
  id: row.id,
30730
30819
  _xact_id: row._xact_id,
30731
30820
  _pagination_key: row._pagination_key,
30732
- root_span_id: row.root_span_id
30821
+ root_span_id: row.root_span_id,
30822
+ created: row.created,
30823
+ tags: row.tags
30733
30824
  }));
30734
30825
  };
30735
30826
  }
30736
30827
  }
30737
- async getSpans({ spanType } = {}) {
30828
+ async getSpans({
30829
+ spanType,
30830
+ includeScorers = false
30831
+ } = {}) {
30832
+ if (includeScorers) {
30833
+ return this.fetchFn(spanType, true);
30834
+ }
30738
30835
  if (this.allFetched) {
30739
30836
  return this.getFromCache(spanType);
30740
30837
  }
@@ -30751,7 +30848,7 @@ var CachedSpanFetcher = class {
30751
30848
  return this.getFromCache(spanType);
30752
30849
  }
30753
30850
  async fetchSpans(spanType) {
30754
- const spans = await this.fetchFn(spanType);
30851
+ const spans = await this.fetchFn(spanType, false);
30755
30852
  for (const span of spans) {
30756
30853
  const type = span.span_attributes?.type ?? "";
30757
30854
  const existing = this.spanCache.get(type) ?? [];
@@ -30829,10 +30926,13 @@ var LocalTrace = class {
30829
30926
  * First checks the local span cache for recently logged spans, then falls
30830
30927
  * back to CachedSpanFetcher which handles BTQL fetching and caching.
30831
30928
  */
30832
- async getSpans({ spanType } = {}) {
30929
+ async getSpans({
30930
+ spanType,
30931
+ includeScorers = false
30932
+ } = {}) {
30833
30933
  const cachedSpans = this.state.spanCache.getByRootSpanId(this.rootSpanId);
30834
30934
  if (cachedSpans && cachedSpans.length > 0) {
30835
- let spans = cachedSpans.filter(
30935
+ let spans = includeScorers ? cachedSpans : cachedSpans.filter(
30836
30936
  (span) => span.span_attributes?.purpose !== "scorer"
30837
30937
  );
30838
30938
  if (spanType && spanType.length > 0) {
@@ -30843,13 +30943,19 @@ var LocalTrace = class {
30843
30943
  return spans.map((span) => ({
30844
30944
  input: span.input,
30845
30945
  output: span.output,
30946
+ expected: span.expected,
30947
+ error: span.error,
30948
+ scores: span.scores,
30949
+ metrics: span.metrics,
30846
30950
  metadata: span.metadata,
30847
30951
  span_id: span.span_id,
30848
30952
  span_parents: span.span_parents,
30849
- span_attributes: span.span_attributes
30953
+ is_root: span.is_root,
30954
+ span_attributes: span.span_attributes,
30955
+ tags: span.tags
30850
30956
  }));
30851
30957
  }
30852
- return this.cachedFetcher.getSpans({ spanType });
30958
+ return this.cachedFetcher.getSpans({ spanType, includeScorers });
30853
30959
  }
30854
30960
  /**
30855
30961
  * Get the thread (preprocessed messages) for this trace.
@@ -32038,6 +32144,34 @@ var defaultReporter = {
32038
32144
  }
32039
32145
  };
32040
32146
 
32147
+ // src/dataset-pipeline.ts
32148
+ function DatasetPipeline(definition) {
32149
+ if (!globalThis.__braintrust_dataset_pipelines) {
32150
+ globalThis.__braintrust_dataset_pipelines = [];
32151
+ }
32152
+ const storedDefinition = {
32153
+ name: definition.name,
32154
+ source: {
32155
+ projectId: definition.source.projectId,
32156
+ projectName: definition.source.projectName,
32157
+ orgName: definition.source.orgName,
32158
+ filter: definition.source.filter,
32159
+ scope: definition.source.scope ?? "span"
32160
+ },
32161
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any
32162
+ transform: definition.transform,
32163
+ target: {
32164
+ projectId: definition.target.projectId,
32165
+ projectName: definition.target.projectName,
32166
+ orgName: definition.target.orgName,
32167
+ datasetName: definition.target.datasetName,
32168
+ description: definition.target.description,
32169
+ metadata: definition.target.metadata
32170
+ }
32171
+ };
32172
+ globalThis.__braintrust_dataset_pipelines.push(storedDefinition);
32173
+ }
32174
+
32041
32175
  // src/framework2.ts
32042
32176
  import { z as z12 } from "zod/v3";
32043
32177
  var currentFilename = typeof __filename !== "undefined" ? __filename : "unknown";
@@ -32577,6 +32711,7 @@ export {
32577
32711
  DEFAULT_FETCH_BATCH_SIZE,
32578
32712
  DEFAULT_MAX_REQUEST_SIZE,
32579
32713
  Dataset2 as Dataset,
32714
+ DatasetPipeline,
32580
32715
  ERR_PERMALINK,
32581
32716
  Eval,
32582
32717
  EvalResultWithSummary,
@@ -3487,6 +3487,26 @@ declare const GitMetadataSettings: z.ZodObject<{
3487
3487
  fields?: ("dirty" | "tag" | "commit" | "branch" | "author_name" | "author_email" | "commit_message" | "commit_time" | "git_diff")[] | undefined;
3488
3488
  }>;
3489
3489
  type GitMetadataSettingsType = z.infer<typeof GitMetadataSettings>;
3490
+ declare const ObjectReference$1: z.ZodObject<{
3491
+ object_type: z.ZodEnum<["project_logs", "experiment", "dataset", "prompt", "function", "prompt_session"]>;
3492
+ object_id: z.ZodString;
3493
+ id: z.ZodString;
3494
+ _xact_id: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNull]>>;
3495
+ created: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNull]>>;
3496
+ }, "strip", z.ZodTypeAny, {
3497
+ id: string;
3498
+ object_type: "function" | "experiment" | "dataset" | "prompt" | "prompt_session" | "project_logs";
3499
+ object_id: string;
3500
+ created?: string | null | undefined;
3501
+ _xact_id?: string | null | undefined;
3502
+ }, {
3503
+ id: string;
3504
+ object_type: "function" | "experiment" | "dataset" | "prompt" | "prompt_session" | "project_logs";
3505
+ object_id: string;
3506
+ created?: string | null | undefined;
3507
+ _xact_id?: string | null | undefined;
3508
+ }>;
3509
+ type ObjectReferenceType$1 = z.infer<typeof ObjectReference$1>;
3490
3510
  declare const Prompt$1: z.ZodObject<{
3491
3511
  id: z.ZodString;
3492
3512
  _xact_id: z.ZodString;
@@ -6322,6 +6342,7 @@ declare const ObjectReference: z.ZodObject<{
6322
6342
  created?: string | null | undefined;
6323
6343
  _xact_id?: string | null | undefined;
6324
6344
  }>;
6345
+ type ObjectReferenceType = z.infer<typeof ObjectReference>;
6325
6346
 
6326
6347
  type IdField = {
6327
6348
  id: string;
@@ -6342,7 +6363,7 @@ type OtherExperimentLogFields = {
6342
6363
  metadata: Record<string, unknown>;
6343
6364
  metrics: Record<string, unknown>;
6344
6365
  datasetRecordId: string;
6345
- origin: z.infer<typeof ObjectReference>;
6366
+ origin: ObjectReferenceType;
6346
6367
  span_attributes: Record<string, unknown>;
6347
6368
  [ASYNC_SCORING_CONTROL_FIELD]: AsyncScoringControlType;
6348
6369
  [MERGE_PATHS_FIELD]: string[][];
@@ -6384,6 +6405,7 @@ type DatasetEvent = {
6384
6405
  tags?: string[];
6385
6406
  metadata?: unknown;
6386
6407
  created?: string;
6408
+ origin?: ObjectReferenceType;
6387
6409
  id: string;
6388
6410
  dataset_id: string;
6389
6411
  } & ({
@@ -6775,9 +6797,15 @@ declare class ParametersCache {
6775
6797
  interface CachedSpan {
6776
6798
  input?: unknown;
6777
6799
  output?: unknown;
6800
+ expected?: unknown;
6801
+ error?: unknown;
6802
+ scores?: Record<string, unknown>;
6803
+ metrics?: Record<string, unknown>;
6778
6804
  metadata?: Record<string, unknown>;
6805
+ tags?: string[];
6779
6806
  span_id: string;
6780
6807
  span_parents?: string[];
6808
+ is_root?: boolean | null;
6781
6809
  span_attributes?: {
6782
6810
  name?: string;
6783
6811
  type?: string;
@@ -7310,6 +7338,13 @@ interface LogOptions<IsAsyncFlush> {
7310
7338
  linkArgs?: LinkArgs;
7311
7339
  }
7312
7340
  type PromiseUnless<B, R> = B extends true ? R : Promise<Awaited<R>>;
7341
+ type DatasetPipelineDeferredJSONAttachmentHook = (data: unknown, options?: {
7342
+ filename?: string;
7343
+ pretty?: boolean;
7344
+ }) => object;
7345
+ declare global {
7346
+ var __BT_DATASET_PIPELINE_DEFER_JSON_ATTACHMENT__: DatasetPipelineDeferredJSONAttachmentHook | undefined;
7347
+ }
7313
7348
  interface ParentSpanIds {
7314
7349
  spanId: string;
7315
7350
  rootSpanId: string;
@@ -7480,7 +7515,7 @@ interface LoginOptions {
7480
7515
  */
7481
7516
  appUrl?: string;
7482
7517
  /**
7483
- * The API key to use. If the parameter is not specified, will try to use the `BRAINTRUST_API_KEY` environment variable.
7518
+ * The API key to use. If the parameter is not specified, will try to use the `BRAINTRUST_API_KEY` environment variable. In Node.js, if that is unset, will try the nearest `.env.braintrust` file in the current working directory or parent directories.
7484
7519
  */
7485
7520
  apiKey?: string;
7486
7521
  /**
@@ -7719,17 +7754,19 @@ declare class Dataset<IsLegacyDataset extends boolean = typeof DEFAULT_IS_LEGACY
7719
7754
  * about anything else that's relevant, that you can use to help find and analyze examples later. For example, you could log the
7720
7755
  * `prompt`, example's `id`, or anything else that would be useful to slice/dice later. The values in `metadata` can be any
7721
7756
  * JSON-serializable type, but its keys must be strings.
7757
+ * @param event.origin (Optional) a reference to the source object this dataset record was derived from.
7722
7758
  * @param event.id (Optional) a unique identifier for the event. If you don't provide one, Braintrust will generate one for you.
7723
7759
  * @param event.output: (Deprecated) The output of your application. Use `expected` instead.
7724
7760
  * @returns The `id` of the logged record.
7725
7761
  */
7726
- insert({ input, expected, metadata, tags, id, output, }: {
7762
+ insert({ input, expected, metadata, tags, id, output, origin, }: {
7727
7763
  readonly input?: unknown;
7728
7764
  readonly expected?: unknown;
7729
7765
  readonly tags?: string[];
7730
7766
  readonly metadata?: Record<string, unknown>;
7731
7767
  readonly id?: string;
7732
7768
  readonly output?: unknown;
7769
+ readonly origin?: ObjectReferenceType$1;
7733
7770
  }): string;
7734
7771
  /**
7735
7772
  * Update fields of a single record in the dataset. The updated fields will be batched and uploaded behind the scenes.
@@ -3487,6 +3487,26 @@ declare const GitMetadataSettings: z.ZodObject<{
3487
3487
  fields?: ("dirty" | "tag" | "commit" | "branch" | "author_name" | "author_email" | "commit_message" | "commit_time" | "git_diff")[] | undefined;
3488
3488
  }>;
3489
3489
  type GitMetadataSettingsType = z.infer<typeof GitMetadataSettings>;
3490
+ declare const ObjectReference$1: z.ZodObject<{
3491
+ object_type: z.ZodEnum<["project_logs", "experiment", "dataset", "prompt", "function", "prompt_session"]>;
3492
+ object_id: z.ZodString;
3493
+ id: z.ZodString;
3494
+ _xact_id: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNull]>>;
3495
+ created: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNull]>>;
3496
+ }, "strip", z.ZodTypeAny, {
3497
+ id: string;
3498
+ object_type: "function" | "experiment" | "dataset" | "prompt" | "prompt_session" | "project_logs";
3499
+ object_id: string;
3500
+ created?: string | null | undefined;
3501
+ _xact_id?: string | null | undefined;
3502
+ }, {
3503
+ id: string;
3504
+ object_type: "function" | "experiment" | "dataset" | "prompt" | "prompt_session" | "project_logs";
3505
+ object_id: string;
3506
+ created?: string | null | undefined;
3507
+ _xact_id?: string | null | undefined;
3508
+ }>;
3509
+ type ObjectReferenceType$1 = z.infer<typeof ObjectReference$1>;
3490
3510
  declare const Prompt$1: z.ZodObject<{
3491
3511
  id: z.ZodString;
3492
3512
  _xact_id: z.ZodString;
@@ -6322,6 +6342,7 @@ declare const ObjectReference: z.ZodObject<{
6322
6342
  created?: string | null | undefined;
6323
6343
  _xact_id?: string | null | undefined;
6324
6344
  }>;
6345
+ type ObjectReferenceType = z.infer<typeof ObjectReference>;
6325
6346
 
6326
6347
  type IdField = {
6327
6348
  id: string;
@@ -6342,7 +6363,7 @@ type OtherExperimentLogFields = {
6342
6363
  metadata: Record<string, unknown>;
6343
6364
  metrics: Record<string, unknown>;
6344
6365
  datasetRecordId: string;
6345
- origin: z.infer<typeof ObjectReference>;
6366
+ origin: ObjectReferenceType;
6346
6367
  span_attributes: Record<string, unknown>;
6347
6368
  [ASYNC_SCORING_CONTROL_FIELD]: AsyncScoringControlType;
6348
6369
  [MERGE_PATHS_FIELD]: string[][];
@@ -6384,6 +6405,7 @@ type DatasetEvent = {
6384
6405
  tags?: string[];
6385
6406
  metadata?: unknown;
6386
6407
  created?: string;
6408
+ origin?: ObjectReferenceType;
6387
6409
  id: string;
6388
6410
  dataset_id: string;
6389
6411
  } & ({
@@ -6775,9 +6797,15 @@ declare class ParametersCache {
6775
6797
  interface CachedSpan {
6776
6798
  input?: unknown;
6777
6799
  output?: unknown;
6800
+ expected?: unknown;
6801
+ error?: unknown;
6802
+ scores?: Record<string, unknown>;
6803
+ metrics?: Record<string, unknown>;
6778
6804
  metadata?: Record<string, unknown>;
6805
+ tags?: string[];
6779
6806
  span_id: string;
6780
6807
  span_parents?: string[];
6808
+ is_root?: boolean | null;
6781
6809
  span_attributes?: {
6782
6810
  name?: string;
6783
6811
  type?: string;
@@ -7310,6 +7338,13 @@ interface LogOptions<IsAsyncFlush> {
7310
7338
  linkArgs?: LinkArgs;
7311
7339
  }
7312
7340
  type PromiseUnless<B, R> = B extends true ? R : Promise<Awaited<R>>;
7341
+ type DatasetPipelineDeferredJSONAttachmentHook = (data: unknown, options?: {
7342
+ filename?: string;
7343
+ pretty?: boolean;
7344
+ }) => object;
7345
+ declare global {
7346
+ var __BT_DATASET_PIPELINE_DEFER_JSON_ATTACHMENT__: DatasetPipelineDeferredJSONAttachmentHook | undefined;
7347
+ }
7313
7348
  interface ParentSpanIds {
7314
7349
  spanId: string;
7315
7350
  rootSpanId: string;
@@ -7480,7 +7515,7 @@ interface LoginOptions {
7480
7515
  */
7481
7516
  appUrl?: string;
7482
7517
  /**
7483
- * The API key to use. If the parameter is not specified, will try to use the `BRAINTRUST_API_KEY` environment variable.
7518
+ * The API key to use. If the parameter is not specified, will try to use the `BRAINTRUST_API_KEY` environment variable. In Node.js, if that is unset, will try the nearest `.env.braintrust` file in the current working directory or parent directories.
7484
7519
  */
7485
7520
  apiKey?: string;
7486
7521
  /**
@@ -7719,17 +7754,19 @@ declare class Dataset<IsLegacyDataset extends boolean = typeof DEFAULT_IS_LEGACY
7719
7754
  * about anything else that's relevant, that you can use to help find and analyze examples later. For example, you could log the
7720
7755
  * `prompt`, example's `id`, or anything else that would be useful to slice/dice later. The values in `metadata` can be any
7721
7756
  * JSON-serializable type, but its keys must be strings.
7757
+ * @param event.origin (Optional) a reference to the source object this dataset record was derived from.
7722
7758
  * @param event.id (Optional) a unique identifier for the event. If you don't provide one, Braintrust will generate one for you.
7723
7759
  * @param event.output: (Deprecated) The output of your application. Use `expected` instead.
7724
7760
  * @returns The `id` of the logged record.
7725
7761
  */
7726
- insert({ input, expected, metadata, tags, id, output, }: {
7762
+ insert({ input, expected, metadata, tags, id, output, origin, }: {
7727
7763
  readonly input?: unknown;
7728
7764
  readonly expected?: unknown;
7729
7765
  readonly tags?: string[];
7730
7766
  readonly metadata?: Record<string, unknown>;
7731
7767
  readonly id?: string;
7732
7768
  readonly output?: unknown;
7769
+ readonly origin?: ObjectReferenceType$1;
7733
7770
  }): string;
7734
7771
  /**
7735
7772
  * Update fields of a single record in the dataset. The updated fields will be batched and uploaded behind the scenes.
@@ -125,6 +125,7 @@ var iso = {
125
125
  getRepoInfo: async (_settings) => void 0,
126
126
  getPastNAncestors: async () => [],
127
127
  getEnv: (_name) => void 0,
128
+ getBraintrustApiKey: async () => void 0,
128
129
  getCallerLocation: () => void 0,
129
130
  newAsyncLocalStorage: () => new DefaultAsyncLocalStorage(),
130
131
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -6548,10 +6549,11 @@ function initLogger(options = {}) {
6548
6549
  async function loginToState(options = {}) {
6549
6550
  const {
6550
6551
  appUrl = isomorph_default.getEnv("BRAINTRUST_APP_URL") || "https://www.braintrust.dev",
6551
- apiKey = isomorph_default.getEnv("BRAINTRUST_API_KEY"),
6552
+ apiKey: apiKeyArg,
6552
6553
  orgName = isomorph_default.getEnv("BRAINTRUST_ORG_NAME"),
6553
6554
  fetch: fetch2 = globalThis.fetch
6554
6555
  } = options || {};
6556
+ const apiKey = apiKeyArg !== void 0 ? apiKeyArg : await isomorph_default.getBraintrustApiKey();
6555
6557
  const appPublicUrl = isomorph_default.getEnv("BRAINTRUST_APP_PUBLIC_URL") || appUrl;
6556
6558
  const state = new BraintrustState(options);
6557
6559
  state.resetLoginInfo();
@@ -7482,9 +7484,15 @@ var SpanImpl = class _SpanImpl {
7482
7484
  const cachedSpan = {
7483
7485
  input: partialRecord.input,
7484
7486
  output: partialRecord.output,
7487
+ expected: partialRecord.expected,
7488
+ error: partialRecord.error,
7489
+ scores: partialRecord.scores,
7490
+ metrics: partialRecord.metrics,
7485
7491
  metadata: partialRecord.metadata,
7492
+ tags: partialRecord.tags,
7486
7493
  span_id: this._spanId,
7487
7494
  span_parents: this._spanParents,
7495
+ is_root: this._spanId === this._rootSpanId,
7488
7496
  span_attributes: partialRecord.span_attributes
7489
7497
  };
7490
7498
  this._state.spanCache.queueWrite(
@@ -7820,6 +7828,7 @@ var Dataset2 = class extends ObjectFetcher {
7820
7828
  metadata,
7821
7829
  tags,
7822
7830
  output,
7831
+ origin,
7823
7832
  isMerge
7824
7833
  }) {
7825
7834
  return new LazyValue(async () => {
@@ -7834,6 +7843,7 @@ var Dataset2 = class extends ObjectFetcher {
7834
7843
  created: !isMerge ? (/* @__PURE__ */ new Date()).toISOString() : void 0,
7835
7844
  //if we're merging/updating an event we will not add this ts
7836
7845
  metadata,
7846
+ origin,
7837
7847
  ...!!isMerge ? {
7838
7848
  [IS_MERGE_FIELD]: true
7839
7849
  } : {}
@@ -7853,6 +7863,7 @@ var Dataset2 = class extends ObjectFetcher {
7853
7863
  * about anything else that's relevant, that you can use to help find and analyze examples later. For example, you could log the
7854
7864
  * `prompt`, example's `id`, or anything else that would be useful to slice/dice later. The values in `metadata` can be any
7855
7865
  * JSON-serializable type, but its keys must be strings.
7866
+ * @param event.origin (Optional) a reference to the source object this dataset record was derived from.
7856
7867
  * @param event.id (Optional) a unique identifier for the event. If you don't provide one, Braintrust will generate one for you.
7857
7868
  * @param event.output: (Deprecated) The output of your application. Use `expected` instead.
7858
7869
  * @returns The `id` of the logged record.
@@ -7863,7 +7874,8 @@ var Dataset2 = class extends ObjectFetcher {
7863
7874
  metadata,
7864
7875
  tags,
7865
7876
  id,
7866
- output
7877
+ output,
7878
+ origin
7867
7879
  }) {
7868
7880
  this.validateEvent({ metadata, expected, output, tags });
7869
7881
  const rowId = id || (0, import_uuid2.v4)();
@@ -7875,6 +7887,7 @@ var Dataset2 = class extends ObjectFetcher {
7875
7887
  metadata,
7876
7888
  tags,
7877
7889
  output,
7890
+ origin,
7878
7891
  isMerge: false
7879
7892
  })
7880
7893
  );