braintrust 3.0.0 → 3.1.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.
@@ -13759,6 +13759,10 @@ interface Evaluator<Input, Output, Expected, Metadata extends BaseMetadata = Def
13759
13759
  * Optional additional metadata for the experiment.
13760
13760
  */
13761
13761
  metadata?: Record<string, unknown>;
13762
+ /**
13763
+ * Optional tags for the experiment.
13764
+ */
13765
+ tags?: string[];
13762
13766
  /**
13763
13767
  * Whether the experiment should be public. Defaults to false.
13764
13768
  */
@@ -13759,6 +13759,10 @@ interface Evaluator<Input, Output, Expected, Metadata extends BaseMetadata = Def
13759
13759
  * Optional additional metadata for the experiment.
13760
13760
  */
13761
13761
  metadata?: Record<string, unknown>;
13762
+ /**
13763
+ * Optional tags for the experiment.
13764
+ */
13765
+ tags?: string[];
13762
13766
  /**
13763
13767
  * Whether the experiment should be public. Defaults to false.
13764
13768
  */
package/dev/dist/index.js CHANGED
@@ -6288,6 +6288,7 @@ function init(projectOrOptions, optionalOptions) {
6288
6288
  forceLogin,
6289
6289
  fetch: fetch2,
6290
6290
  metadata,
6291
+ tags,
6291
6292
  gitMetadataSettings,
6292
6293
  projectId,
6293
6294
  baseExperimentId,
@@ -6400,6 +6401,10 @@ function init(projectOrOptions, optionalOptions) {
6400
6401
  if (metadata) {
6401
6402
  args["metadata"] = metadata;
6402
6403
  }
6404
+ if (tags) {
6405
+ validateTags(tags);
6406
+ args["tags"] = tags;
6407
+ }
6403
6408
  let response = null;
6404
6409
  while (true) {
6405
6410
  try {
@@ -6798,6 +6803,7 @@ function validateTags(tags) {
6798
6803
  if (seen.has(tag)) {
6799
6804
  throw new Error(`duplicate tag: ${tag}`);
6800
6805
  }
6806
+ seen.add(tag);
6801
6807
  }
6802
6808
  }
6803
6809
  function validateAndSanitizeExperimentLogPartialArgs(event) {
@@ -10089,6 +10095,7 @@ async function Eval(name, evaluator, reporterOrOpts) {
10089
10095
  experiment: evaluator.experimentName,
10090
10096
  description: evaluator.description,
10091
10097
  metadata: evaluator.metadata,
10098
+ tags: evaluator.tags,
10092
10099
  isPublic: evaluator.isPublic,
10093
10100
  update: evaluator.update,
10094
10101
  baseExperiment: _nullishCoalesce(evaluator.baseExperimentName, () => ( defaultBaseExperiment)),
@@ -6288,6 +6288,7 @@ function init(projectOrOptions, optionalOptions) {
6288
6288
  forceLogin,
6289
6289
  fetch: fetch2,
6290
6290
  metadata,
6291
+ tags,
6291
6292
  gitMetadataSettings,
6292
6293
  projectId,
6293
6294
  baseExperimentId,
@@ -6400,6 +6401,10 @@ function init(projectOrOptions, optionalOptions) {
6400
6401
  if (metadata) {
6401
6402
  args["metadata"] = metadata;
6402
6403
  }
6404
+ if (tags) {
6405
+ validateTags(tags);
6406
+ args["tags"] = tags;
6407
+ }
6403
6408
  let response = null;
6404
6409
  while (true) {
6405
6410
  try {
@@ -6798,6 +6803,7 @@ function validateTags(tags) {
6798
6803
  if (seen.has(tag)) {
6799
6804
  throw new Error(`duplicate tag: ${tag}`);
6800
6805
  }
6806
+ seen.add(tag);
6801
6807
  }
6802
6808
  }
6803
6809
  function validateAndSanitizeExperimentLogPartialArgs(event) {
@@ -10089,6 +10095,7 @@ async function Eval(name, evaluator, reporterOrOpts) {
10089
10095
  experiment: evaluator.experimentName,
10090
10096
  description: evaluator.description,
10091
10097
  metadata: evaluator.metadata,
10098
+ tags: evaluator.tags,
10092
10099
  isPublic: evaluator.isPublic,
10093
10100
  update: evaluator.update,
10094
10101
  baseExperiment: evaluator.baseExperimentName ?? defaultBaseExperiment,
@@ -19917,6 +19917,7 @@ type InitOptions<IsOpen extends boolean> = FullLoginOptions & {
19917
19917
  baseExperiment?: string;
19918
19918
  isPublic?: boolean;
19919
19919
  metadata?: Record<string, unknown>;
19920
+ tags?: string[];
19920
19921
  gitMetadataSettings?: GitMetadataSettingsType;
19921
19922
  projectId?: string;
19922
19923
  baseExperimentId?: string;
@@ -19949,6 +19950,7 @@ type InitializedExperiment<IsOpen extends boolean | undefined> = IsOpen extends
19949
19950
  * @param options.projectId The id of the project to create the experiment in. This takes precedence over `project` if specified.
19950
19951
  * @param options.baseExperimentId An optional experiment id to use as a base. If specified, the new experiment will be summarized and compared to this. This takes precedence over `baseExperiment` if specified.
19951
19952
  * @param options.repoInfo (Optional) Explicitly specify the git metadata for this experiment. This takes precedence over `gitMetadataSettings` if specified.
19953
+ * @param options.tags (Optional) A list of tags to attach to the experiment.
19952
19954
  * @returns The newly created Experiment.
19953
19955
  */
19954
19956
  declare function init<IsOpen extends boolean = false>(options: Readonly<FullInitOptions<IsOpen>>): InitializedExperiment<IsOpen>;
@@ -20340,6 +20342,7 @@ declare function setFetch(fetch: typeof globalThis.fetch): void;
20340
20342
  */
20341
20343
  declare function withCurrent<R>(span: Span, callback: (span: Span) => R, state?: BraintrustState | undefined): R;
20342
20344
  declare function withParent<R>(parent: string, callback: () => R, state?: BraintrustState | undefined): R;
20345
+ declare function validateTags(tags: readonly string[]): void;
20343
20346
  /**
20344
20347
  * Creates a deep copy of the given event. Replaces references to user objects
20345
20348
  * with placeholder strings to ensure serializability, except for
@@ -20896,6 +20899,7 @@ declare const _exportsForTestingOnly: {
20896
20899
  isGeneratorFunction: typeof isGeneratorFunction;
20897
20900
  isAsyncGeneratorFunction: typeof isAsyncGeneratorFunction;
20898
20901
  resetIdGenStateForTests: typeof resetIdGenStateForTests;
20902
+ validateTags: typeof validateTags;
20899
20903
  isomorph: Common;
20900
20904
  };
20901
20905
 
@@ -40026,6 +40030,10 @@ interface Evaluator<Input, Output, Expected, Metadata extends BaseMetadata = Def
40026
40030
  * Optional additional metadata for the experiment.
40027
40031
  */
40028
40032
  metadata?: Record<string, unknown>;
40033
+ /**
40034
+ * Optional tags for the experiment.
40035
+ */
40036
+ tags?: string[];
40029
40037
  /**
40030
40038
  * Whether the experiment should be public. Defaults to false.
40031
40039
  */
package/dist/browser.d.ts CHANGED
@@ -19917,6 +19917,7 @@ type InitOptions<IsOpen extends boolean> = FullLoginOptions & {
19917
19917
  baseExperiment?: string;
19918
19918
  isPublic?: boolean;
19919
19919
  metadata?: Record<string, unknown>;
19920
+ tags?: string[];
19920
19921
  gitMetadataSettings?: GitMetadataSettingsType;
19921
19922
  projectId?: string;
19922
19923
  baseExperimentId?: string;
@@ -19949,6 +19950,7 @@ type InitializedExperiment<IsOpen extends boolean | undefined> = IsOpen extends
19949
19950
  * @param options.projectId The id of the project to create the experiment in. This takes precedence over `project` if specified.
19950
19951
  * @param options.baseExperimentId An optional experiment id to use as a base. If specified, the new experiment will be summarized and compared to this. This takes precedence over `baseExperiment` if specified.
19951
19952
  * @param options.repoInfo (Optional) Explicitly specify the git metadata for this experiment. This takes precedence over `gitMetadataSettings` if specified.
19953
+ * @param options.tags (Optional) A list of tags to attach to the experiment.
19952
19954
  * @returns The newly created Experiment.
19953
19955
  */
19954
19956
  declare function init<IsOpen extends boolean = false>(options: Readonly<FullInitOptions<IsOpen>>): InitializedExperiment<IsOpen>;
@@ -20340,6 +20342,7 @@ declare function setFetch(fetch: typeof globalThis.fetch): void;
20340
20342
  */
20341
20343
  declare function withCurrent<R>(span: Span, callback: (span: Span) => R, state?: BraintrustState | undefined): R;
20342
20344
  declare function withParent<R>(parent: string, callback: () => R, state?: BraintrustState | undefined): R;
20345
+ declare function validateTags(tags: readonly string[]): void;
20343
20346
  /**
20344
20347
  * Creates a deep copy of the given event. Replaces references to user objects
20345
20348
  * with placeholder strings to ensure serializability, except for
@@ -20896,6 +20899,7 @@ declare const _exportsForTestingOnly: {
20896
20899
  isGeneratorFunction: typeof isGeneratorFunction;
20897
20900
  isAsyncGeneratorFunction: typeof isAsyncGeneratorFunction;
20898
20901
  resetIdGenStateForTests: typeof resetIdGenStateForTests;
20902
+ validateTags: typeof validateTags;
20899
20903
  isomorph: Common;
20900
20904
  };
20901
20905
 
@@ -40026,6 +40030,10 @@ interface Evaluator<Input, Output, Expected, Metadata extends BaseMetadata = Def
40026
40030
  * Optional additional metadata for the experiment.
40027
40031
  */
40028
40032
  metadata?: Record<string, unknown>;
40033
+ /**
40034
+ * Optional tags for the experiment.
40035
+ */
40036
+ tags?: string[];
40029
40037
  /**
40030
40038
  * Whether the experiment should be public. Defaults to false.
40031
40039
  */
package/dist/browser.js CHANGED
@@ -6429,6 +6429,7 @@ function init(projectOrOptions, optionalOptions) {
6429
6429
  forceLogin,
6430
6430
  fetch: fetch2,
6431
6431
  metadata,
6432
+ tags,
6432
6433
  gitMetadataSettings,
6433
6434
  projectId,
6434
6435
  baseExperimentId,
@@ -6541,6 +6542,10 @@ function init(projectOrOptions, optionalOptions) {
6541
6542
  if (metadata) {
6542
6543
  args["metadata"] = metadata;
6543
6544
  }
6545
+ if (tags) {
6546
+ validateTags(tags);
6547
+ args["tags"] = tags;
6548
+ }
6544
6549
  let response = null;
6545
6550
  while (true) {
6546
6551
  try {
@@ -7487,6 +7492,7 @@ function validateTags(tags) {
7487
7492
  if (seen.has(tag)) {
7488
7493
  throw new Error(`duplicate tag: ${tag}`);
7489
7494
  }
7495
+ seen.add(tag);
7490
7496
  }
7491
7497
  }
7492
7498
  function validateAndSanitizeExperimentLogPartialArgs(event) {
@@ -9211,6 +9217,7 @@ var _exportsForTestingOnly = {
9211
9217
  isGeneratorFunction,
9212
9218
  isAsyncGeneratorFunction,
9213
9219
  resetIdGenStateForTests,
9220
+ validateTags,
9214
9221
  isomorph: isomorph_default
9215
9222
  // Expose isomorph for build type detection
9216
9223
  };
@@ -10559,9 +10566,13 @@ var makeGenerateTextWrapper = (name, options, generateText, aiSDK) => {
10559
10566
  const processedInput = await processInputAttachments2(params);
10560
10567
  return traced(
10561
10568
  async (span) => {
10569
+ const { wrappedModel, getMetrics } = wrapModelAndGetMetrics(
10570
+ params.model,
10571
+ aiSDK
10572
+ );
10562
10573
  const result = await generateText({
10563
10574
  ...params,
10564
- model: wrapModel(params.model, aiSDK),
10575
+ model: wrappedModel,
10565
10576
  tools: wrapTools(params.tools)
10566
10577
  });
10567
10578
  const gatewayInfo = extractGatewayRoutingInfo(result);
@@ -10574,7 +10585,7 @@ var makeGenerateTextWrapper = (name, options, generateText, aiSDK) => {
10574
10585
  }
10575
10586
  span.log({
10576
10587
  output: await processOutput(result, options.denyOutputPaths),
10577
- metrics: extractTokenMetrics(result),
10588
+ metrics: getMetrics(result),
10578
10589
  ...Object.keys(resolvedMetadata).length > 0 ? { metadata: resolvedMetadata } : {}
10579
10590
  });
10580
10591
  return result;
@@ -10795,6 +10806,14 @@ var wrapModel = (model, ai) => {
10795
10806
  var wrapGenerateText = (generateText, options = {}, aiSDK) => {
10796
10807
  return makeGenerateTextWrapper("generateText", options, generateText, aiSDK);
10797
10808
  };
10809
+ var wrapModelAndGetMetrics = (model, aiSDK) => {
10810
+ const wrappedModel = wrapModel(model, aiSDK);
10811
+ const modelIsWrapped = wrappedModel?._braintrustWrapped === true;
10812
+ return {
10813
+ wrappedModel,
10814
+ getMetrics: (result) => modelIsWrapped ? void 0 : extractTokenMetrics(result)
10815
+ };
10816
+ };
10798
10817
  var wrapGenerateObject = (generateObject, options = {}, aiSDK) => {
10799
10818
  return async function generateObjectWrapper(allParams) {
10800
10819
  const { span_info, ...params } = allParams;
@@ -10807,9 +10826,13 @@ var wrapGenerateObject = (generateObject, options = {}, aiSDK) => {
10807
10826
  const processedInput = await processInputAttachments2(params);
10808
10827
  return traced(
10809
10828
  async (span) => {
10829
+ const { wrappedModel, getMetrics } = wrapModelAndGetMetrics(
10830
+ params.model,
10831
+ aiSDK
10832
+ );
10810
10833
  const result = await generateObject({
10811
10834
  ...params,
10812
- model: wrapModel(params.model, aiSDK),
10835
+ model: wrappedModel,
10813
10836
  tools: wrapTools(params.tools)
10814
10837
  });
10815
10838
  const output = await processOutput(result, options.denyOutputPaths);
@@ -10823,7 +10846,7 @@ var wrapGenerateObject = (generateObject, options = {}, aiSDK) => {
10823
10846
  }
10824
10847
  span.log({
10825
10848
  output,
10826
- metrics: extractTokenMetrics(result),
10849
+ metrics: getMetrics(result),
10827
10850
  ...Object.keys(resolvedMetadata).length > 0 ? { metadata: resolvedMetadata } : {}
10828
10851
  });
10829
10852
  return result;
@@ -10888,11 +10911,15 @@ var makeStreamTextWrapper = (name, options, streamText, aiSDK) => {
10888
10911
  try {
10889
10912
  const startTime = Date.now();
10890
10913
  let receivedFirst = false;
10914
+ const { wrappedModel, getMetrics } = wrapModelAndGetMetrics(
10915
+ params.model,
10916
+ aiSDK
10917
+ );
10891
10918
  const result = withCurrent(
10892
10919
  span,
10893
10920
  () => streamText({
10894
10921
  ...params,
10895
- model: wrapModel(params.model, aiSDK),
10922
+ model: wrappedModel,
10896
10923
  tools: wrapTools(params.tools),
10897
10924
  onChunk: (chunk) => {
10898
10925
  if (!receivedFirst) {
@@ -10917,7 +10944,7 @@ var makeStreamTextWrapper = (name, options, streamText, aiSDK) => {
10917
10944
  }
10918
10945
  span.log({
10919
10946
  output: await processOutput(event, options.denyOutputPaths),
10920
- metrics: extractTokenMetrics(event),
10947
+ metrics: getMetrics(event),
10921
10948
  ...Object.keys(resolvedMetadata).length > 0 ? { metadata: resolvedMetadata } : {}
10922
10949
  });
10923
10950
  span.end();
@@ -11012,11 +11039,15 @@ var wrapStreamObject = (streamObject, options = {}, aiSDK) => {
11012
11039
  try {
11013
11040
  const startTime = Date.now();
11014
11041
  let receivedFirst = false;
11042
+ const { wrappedModel, getMetrics } = wrapModelAndGetMetrics(
11043
+ params.model,
11044
+ aiSDK
11045
+ );
11015
11046
  const result = withCurrent(
11016
11047
  span,
11017
11048
  () => streamObject({
11018
11049
  ...params,
11019
- model: wrapModel(params.model, aiSDK),
11050
+ model: wrappedModel,
11020
11051
  tools: wrapTools(params.tools),
11021
11052
  onChunk: (chunk) => {
11022
11053
  if (!receivedFirst) {
@@ -11041,7 +11072,7 @@ var wrapStreamObject = (streamObject, options = {}, aiSDK) => {
11041
11072
  }
11042
11073
  span.log({
11043
11074
  output: await processOutput(event, options.denyOutputPaths),
11044
- metrics: extractTokenMetrics(event),
11075
+ metrics: getMetrics(event),
11045
11076
  ...Object.keys(resolvedMetadata).length > 0 ? { metadata: resolvedMetadata } : {}
11046
11077
  });
11047
11078
  span.end();
@@ -15635,6 +15666,7 @@ async function Eval(name, evaluator, reporterOrOpts) {
15635
15666
  experiment: evaluator.experimentName,
15636
15667
  description: evaluator.description,
15637
15668
  metadata: evaluator.metadata,
15669
+ tags: evaluator.tags,
15638
15670
  isPublic: evaluator.isPublic,
15639
15671
  update: evaluator.update,
15640
15672
  baseExperiment: evaluator.baseExperimentName ?? defaultBaseExperiment,
package/dist/browser.mjs CHANGED
@@ -6273,6 +6273,7 @@ function init(projectOrOptions, optionalOptions) {
6273
6273
  forceLogin,
6274
6274
  fetch: fetch2,
6275
6275
  metadata,
6276
+ tags,
6276
6277
  gitMetadataSettings,
6277
6278
  projectId,
6278
6279
  baseExperimentId,
@@ -6385,6 +6386,10 @@ function init(projectOrOptions, optionalOptions) {
6385
6386
  if (metadata) {
6386
6387
  args["metadata"] = metadata;
6387
6388
  }
6389
+ if (tags) {
6390
+ validateTags(tags);
6391
+ args["tags"] = tags;
6392
+ }
6388
6393
  let response = null;
6389
6394
  while (true) {
6390
6395
  try {
@@ -7331,6 +7336,7 @@ function validateTags(tags) {
7331
7336
  if (seen.has(tag)) {
7332
7337
  throw new Error(`duplicate tag: ${tag}`);
7333
7338
  }
7339
+ seen.add(tag);
7334
7340
  }
7335
7341
  }
7336
7342
  function validateAndSanitizeExperimentLogPartialArgs(event) {
@@ -9055,6 +9061,7 @@ var _exportsForTestingOnly = {
9055
9061
  isGeneratorFunction,
9056
9062
  isAsyncGeneratorFunction,
9057
9063
  resetIdGenStateForTests,
9064
+ validateTags,
9058
9065
  isomorph: isomorph_default
9059
9066
  // Expose isomorph for build type detection
9060
9067
  };
@@ -10403,9 +10410,13 @@ var makeGenerateTextWrapper = (name, options, generateText, aiSDK) => {
10403
10410
  const processedInput = await processInputAttachments2(params);
10404
10411
  return traced(
10405
10412
  async (span) => {
10413
+ const { wrappedModel, getMetrics } = wrapModelAndGetMetrics(
10414
+ params.model,
10415
+ aiSDK
10416
+ );
10406
10417
  const result = await generateText({
10407
10418
  ...params,
10408
- model: wrapModel(params.model, aiSDK),
10419
+ model: wrappedModel,
10409
10420
  tools: wrapTools(params.tools)
10410
10421
  });
10411
10422
  const gatewayInfo = extractGatewayRoutingInfo(result);
@@ -10418,7 +10429,7 @@ var makeGenerateTextWrapper = (name, options, generateText, aiSDK) => {
10418
10429
  }
10419
10430
  span.log({
10420
10431
  output: await processOutput(result, options.denyOutputPaths),
10421
- metrics: extractTokenMetrics(result),
10432
+ metrics: getMetrics(result),
10422
10433
  ...Object.keys(resolvedMetadata).length > 0 ? { metadata: resolvedMetadata } : {}
10423
10434
  });
10424
10435
  return result;
@@ -10639,6 +10650,14 @@ var wrapModel = (model, ai) => {
10639
10650
  var wrapGenerateText = (generateText, options = {}, aiSDK) => {
10640
10651
  return makeGenerateTextWrapper("generateText", options, generateText, aiSDK);
10641
10652
  };
10653
+ var wrapModelAndGetMetrics = (model, aiSDK) => {
10654
+ const wrappedModel = wrapModel(model, aiSDK);
10655
+ const modelIsWrapped = wrappedModel?._braintrustWrapped === true;
10656
+ return {
10657
+ wrappedModel,
10658
+ getMetrics: (result) => modelIsWrapped ? void 0 : extractTokenMetrics(result)
10659
+ };
10660
+ };
10642
10661
  var wrapGenerateObject = (generateObject, options = {}, aiSDK) => {
10643
10662
  return async function generateObjectWrapper(allParams) {
10644
10663
  const { span_info, ...params } = allParams;
@@ -10651,9 +10670,13 @@ var wrapGenerateObject = (generateObject, options = {}, aiSDK) => {
10651
10670
  const processedInput = await processInputAttachments2(params);
10652
10671
  return traced(
10653
10672
  async (span) => {
10673
+ const { wrappedModel, getMetrics } = wrapModelAndGetMetrics(
10674
+ params.model,
10675
+ aiSDK
10676
+ );
10654
10677
  const result = await generateObject({
10655
10678
  ...params,
10656
- model: wrapModel(params.model, aiSDK),
10679
+ model: wrappedModel,
10657
10680
  tools: wrapTools(params.tools)
10658
10681
  });
10659
10682
  const output = await processOutput(result, options.denyOutputPaths);
@@ -10667,7 +10690,7 @@ var wrapGenerateObject = (generateObject, options = {}, aiSDK) => {
10667
10690
  }
10668
10691
  span.log({
10669
10692
  output,
10670
- metrics: extractTokenMetrics(result),
10693
+ metrics: getMetrics(result),
10671
10694
  ...Object.keys(resolvedMetadata).length > 0 ? { metadata: resolvedMetadata } : {}
10672
10695
  });
10673
10696
  return result;
@@ -10732,11 +10755,15 @@ var makeStreamTextWrapper = (name, options, streamText, aiSDK) => {
10732
10755
  try {
10733
10756
  const startTime = Date.now();
10734
10757
  let receivedFirst = false;
10758
+ const { wrappedModel, getMetrics } = wrapModelAndGetMetrics(
10759
+ params.model,
10760
+ aiSDK
10761
+ );
10735
10762
  const result = withCurrent(
10736
10763
  span,
10737
10764
  () => streamText({
10738
10765
  ...params,
10739
- model: wrapModel(params.model, aiSDK),
10766
+ model: wrappedModel,
10740
10767
  tools: wrapTools(params.tools),
10741
10768
  onChunk: (chunk) => {
10742
10769
  if (!receivedFirst) {
@@ -10761,7 +10788,7 @@ var makeStreamTextWrapper = (name, options, streamText, aiSDK) => {
10761
10788
  }
10762
10789
  span.log({
10763
10790
  output: await processOutput(event, options.denyOutputPaths),
10764
- metrics: extractTokenMetrics(event),
10791
+ metrics: getMetrics(event),
10765
10792
  ...Object.keys(resolvedMetadata).length > 0 ? { metadata: resolvedMetadata } : {}
10766
10793
  });
10767
10794
  span.end();
@@ -10856,11 +10883,15 @@ var wrapStreamObject = (streamObject, options = {}, aiSDK) => {
10856
10883
  try {
10857
10884
  const startTime = Date.now();
10858
10885
  let receivedFirst = false;
10886
+ const { wrappedModel, getMetrics } = wrapModelAndGetMetrics(
10887
+ params.model,
10888
+ aiSDK
10889
+ );
10859
10890
  const result = withCurrent(
10860
10891
  span,
10861
10892
  () => streamObject({
10862
10893
  ...params,
10863
- model: wrapModel(params.model, aiSDK),
10894
+ model: wrappedModel,
10864
10895
  tools: wrapTools(params.tools),
10865
10896
  onChunk: (chunk) => {
10866
10897
  if (!receivedFirst) {
@@ -10885,7 +10916,7 @@ var wrapStreamObject = (streamObject, options = {}, aiSDK) => {
10885
10916
  }
10886
10917
  span.log({
10887
10918
  output: await processOutput(event, options.denyOutputPaths),
10888
- metrics: extractTokenMetrics(event),
10919
+ metrics: getMetrics(event),
10889
10920
  ...Object.keys(resolvedMetadata).length > 0 ? { metadata: resolvedMetadata } : {}
10890
10921
  });
10891
10922
  span.end();
@@ -15479,6 +15510,7 @@ async function Eval(name, evaluator, reporterOrOpts) {
15479
15510
  experiment: evaluator.experimentName,
15480
15511
  description: evaluator.description,
15481
15512
  metadata: evaluator.metadata,
15513
+ tags: evaluator.tags,
15482
15514
  isPublic: evaluator.isPublic,
15483
15515
  update: evaluator.update,
15484
15516
  baseExperiment: evaluator.baseExperimentName ?? defaultBaseExperiment,
package/dist/cli.js CHANGED
@@ -1275,7 +1275,7 @@ var require_package = __commonJS({
1275
1275
  "package.json"(exports2, module2) {
1276
1276
  module2.exports = {
1277
1277
  name: "braintrust",
1278
- version: "3.0.0",
1278
+ version: "3.1.0",
1279
1279
  description: "SDK for integrating Braintrust",
1280
1280
  repository: {
1281
1281
  type: "git",
@@ -7543,6 +7543,7 @@ function init(projectOrOptions, optionalOptions) {
7543
7543
  forceLogin,
7544
7544
  fetch: fetch2,
7545
7545
  metadata,
7546
+ tags,
7546
7547
  gitMetadataSettings,
7547
7548
  projectId,
7548
7549
  baseExperimentId,
@@ -7655,6 +7656,10 @@ function init(projectOrOptions, optionalOptions) {
7655
7656
  if (metadata) {
7656
7657
  args["metadata"] = metadata;
7657
7658
  }
7659
+ if (tags) {
7660
+ validateTags(tags);
7661
+ args["tags"] = tags;
7662
+ }
7658
7663
  let response = null;
7659
7664
  while (true) {
7660
7665
  try {
@@ -8053,6 +8058,7 @@ function validateTags(tags) {
8053
8058
  if (seen.has(tag)) {
8054
8059
  throw new Error(`duplicate tag: ${tag}`);
8055
8060
  }
8061
+ seen.add(tag);
8056
8062
  }
8057
8063
  }
8058
8064
  function validateAndSanitizeExperimentLogPartialArgs(event) {
@@ -11351,6 +11357,7 @@ async function Eval(name, evaluator, reporterOrOpts) {
11351
11357
  experiment: evaluator.experimentName,
11352
11358
  description: evaluator.description,
11353
11359
  metadata: evaluator.metadata,
11360
+ tags: evaluator.tags,
11354
11361
  isPublic: evaluator.isPublic,
11355
11362
  update: evaluator.update,
11356
11363
  baseExperiment: evaluator.baseExperimentName ?? defaultBaseExperiment,
@@ -14462,6 +14469,7 @@ async function initExperiment2(evaluator, evaluatorData) {
14462
14469
  experiment: evaluator.experimentName,
14463
14470
  description: evaluator.description,
14464
14471
  metadata: evaluator.metadata,
14472
+ tags: evaluator.tags,
14465
14473
  isPublic: evaluator.isPublic,
14466
14474
  update: evaluator.update,
14467
14475
  baseExperiment: evaluator.baseExperimentName ?? defaultBaseExperiment,