braintrust 3.23.1 → 3.24.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 (51) hide show
  1. package/dev/dist/index.d.mts +6 -0
  2. package/dev/dist/index.d.ts +6 -0
  3. package/dev/dist/index.js +902 -586
  4. package/dev/dist/index.mjs +320 -4
  5. package/dist/apply-auto-instrumentation.js +211 -189
  6. package/dist/apply-auto-instrumentation.mjs +23 -1
  7. package/dist/auto-instrumentations/bundler/esbuild.cjs +40 -0
  8. package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
  9. package/dist/auto-instrumentations/bundler/next.cjs +40 -0
  10. package/dist/auto-instrumentations/bundler/next.mjs +3 -3
  11. package/dist/auto-instrumentations/bundler/rollup.cjs +40 -0
  12. package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
  13. package/dist/auto-instrumentations/bundler/vite.cjs +40 -0
  14. package/dist/auto-instrumentations/bundler/vite.d.mts +1 -1
  15. package/dist/auto-instrumentations/bundler/vite.d.ts +1 -1
  16. package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
  17. package/dist/auto-instrumentations/bundler/webpack-loader.cjs +40 -0
  18. package/dist/auto-instrumentations/bundler/webpack.cjs +40 -0
  19. package/dist/auto-instrumentations/bundler/webpack.mjs +3 -3
  20. package/dist/auto-instrumentations/{chunk-KIMLYPRW.mjs → chunk-BURMPO7L.mjs} +1 -1
  21. package/dist/auto-instrumentations/{chunk-YXLNSAMJ.mjs → chunk-F43DNLPD.mjs} +40 -0
  22. package/dist/auto-instrumentations/{chunk-EXY7QCJD.mjs → chunk-GSZHTAQW.mjs} +1 -1
  23. package/dist/auto-instrumentations/hook.mjs +150 -1
  24. package/dist/auto-instrumentations/index.cjs +40 -0
  25. package/dist/auto-instrumentations/index.mjs +1 -1
  26. package/dist/browser.d.mts +131 -9
  27. package/dist/browser.d.ts +131 -9
  28. package/dist/browser.js +703 -65
  29. package/dist/browser.mjs +703 -65
  30. package/dist/{chunk-CDIKAHDZ.js → chunk-7AUY2XWX.js} +21 -1
  31. package/dist/{chunk-36IPYKMG.mjs → chunk-7F6GCRHH.mjs} +20 -0
  32. package/dist/{chunk-B6ZQIAK3.js → chunk-SU6EHKJV.js} +1085 -799
  33. package/dist/{chunk-RBXD2KYN.mjs → chunk-XE5FS7QY.mjs} +291 -5
  34. package/dist/cli.js +328 -8
  35. package/dist/edge-light.js +703 -65
  36. package/dist/edge-light.mjs +703 -65
  37. package/dist/index.d.mts +131 -9
  38. package/dist/index.d.ts +131 -9
  39. package/dist/index.js +891 -532
  40. package/dist/index.mjs +423 -64
  41. package/dist/instrumentation/index.d.mts +130 -9
  42. package/dist/instrumentation/index.d.ts +130 -9
  43. package/dist/instrumentation/index.js +601 -65
  44. package/dist/instrumentation/index.mjs +601 -65
  45. package/dist/vitest-evals-reporter.js +17 -16
  46. package/dist/vitest-evals-reporter.mjs +3 -2
  47. package/dist/workerd.js +703 -65
  48. package/dist/workerd.mjs +703 -65
  49. package/package.json +3 -3
  50. package/util/dist/index.js +4 -0
  51. package/util/dist/index.mjs +4 -0
@@ -115,6 +115,7 @@ var DefaultChannel = class {
115
115
  constructor(name) {
116
116
  this.name = name;
117
117
  }
118
+ name;
118
119
  hasSubscribers = false;
119
120
  subscribe(_subscription) {
120
121
  }
@@ -1381,6 +1382,7 @@ var SpanComponentsV3 = class _SpanComponentsV3 {
1381
1382
  constructor(data) {
1382
1383
  this.data = data;
1383
1384
  }
1385
+ data;
1384
1386
  toStr() {
1385
1387
  const jsonObj = {
1386
1388
  compute_object_metadata_args: this.data.compute_object_metadata_args || void 0,
@@ -1892,6 +1894,7 @@ var SpanComponentsV4 = class _SpanComponentsV4 {
1892
1894
  constructor(data) {
1893
1895
  this.data = data;
1894
1896
  }
1897
+ data;
1895
1898
  toStr() {
1896
1899
  const jsonObj = {
1897
1900
  compute_object_metadata_args: this.data.compute_object_metadata_args || void 0,
@@ -5138,6 +5141,97 @@ var SpanCache = class {
5138
5141
  }
5139
5142
  };
5140
5143
 
5144
+ // src/span-origin.ts
5145
+ var SDK_VERSION = true ? "3.24.0" : "0.0.0";
5146
+ function detectSpanOriginEnvironment(explicit) {
5147
+ if (explicit) return explicit;
5148
+ const envType = isomorph_default.getEnv("BRAINTRUST_ENVIRONMENT_TYPE");
5149
+ const envName = isomorph_default.getEnv("BRAINTRUST_ENVIRONMENT_NAME");
5150
+ if (envType || envName) {
5151
+ return {
5152
+ ...envType ? { type: envType } : {},
5153
+ ...envName ? { name: envName } : {}
5154
+ };
5155
+ }
5156
+ const ci = firstPresent([
5157
+ ["GITHUB_ACTIONS", "github_actions"],
5158
+ ["GITLAB_CI", "gitlab_ci"],
5159
+ ["CIRCLECI", "circleci"],
5160
+ ["BUILDKITE", "buildkite"],
5161
+ ["JENKINS_URL", "jenkins"],
5162
+ ["JENKINS_HOME", "jenkins"],
5163
+ ["TF_BUILD", "azure_pipelines"],
5164
+ ["TEAMCITY_VERSION", "teamcity"],
5165
+ ["TRAVIS", "travis"],
5166
+ ["BITBUCKET_BUILD_NUMBER", "bitbucket"]
5167
+ ]);
5168
+ if (ci) return { type: "ci", name: ci };
5169
+ if (isomorph_default.getEnv("CI")) return { type: "ci", name: "ci" };
5170
+ const earlyServer = firstPresent([
5171
+ ["VERCEL", "vercel"],
5172
+ ["NETLIFY", "netlify"]
5173
+ ]);
5174
+ if (earlyServer) return { type: "server", name: earlyServer };
5175
+ if (isomorph_default.getEnv("ECS_CONTAINER_METADATA_URI") || isomorph_default.getEnv("ECS_CONTAINER_METADATA_URI_V4")) {
5176
+ return { type: "server", name: "ecs" };
5177
+ }
5178
+ const awsExecutionEnv = isomorph_default.getEnv("AWS_EXECUTION_ENV");
5179
+ if (awsExecutionEnv?.startsWith("AWS_ECS_")) {
5180
+ return { type: "server", name: "ecs" };
5181
+ }
5182
+ if (awsExecutionEnv?.startsWith("AWS_Lambda_")) {
5183
+ return { type: "server", name: "aws_lambda" };
5184
+ }
5185
+ if (isomorph_default.getEnv("AWS_LAMBDA_FUNCTION_NAME")) {
5186
+ return { type: "server", name: "aws_lambda" };
5187
+ }
5188
+ const server = firstPresent([
5189
+ ["K_SERVICE", "cloud_run"],
5190
+ ["FUNCTION_TARGET", "gcp_functions"],
5191
+ ["KUBERNETES_SERVICE_HOST", "kubernetes"],
5192
+ ["DYNO", "heroku"],
5193
+ ["FLY_APP_NAME", "fly"],
5194
+ ["RAILWAY_ENVIRONMENT", "railway"],
5195
+ ["RENDER_SERVICE_NAME", "render"]
5196
+ ]);
5197
+ if (server) return { type: "server", name: server };
5198
+ return deploymentModeEnvironment("NODE_ENV", isomorph_default.getEnv("NODE_ENV"));
5199
+ }
5200
+ function makeSpanOrigin(instrumentationName, environment) {
5201
+ return {
5202
+ name: "braintrust.sdk.javascript",
5203
+ version: SDK_VERSION,
5204
+ instrumentation: { name: instrumentationName },
5205
+ ...environment ? { environment } : {}
5206
+ };
5207
+ }
5208
+ function mergeSpanOriginContext(context, instrumentationName, environment) {
5209
+ const next = { ...context ?? {} };
5210
+ const current = isObject2(next.span_origin) ? { ...next.span_origin } : {};
5211
+ next.span_origin = {
5212
+ ...makeSpanOrigin(instrumentationName, environment),
5213
+ ...current
5214
+ };
5215
+ return next;
5216
+ }
5217
+ function firstPresent(entries) {
5218
+ return entries.find(([key]) => Boolean(isomorph_default.getEnv(key)))?.[1];
5219
+ }
5220
+ function deploymentModeEnvironment(_key, value) {
5221
+ if (!value) return void 0;
5222
+ const normalized = value.toLowerCase();
5223
+ if (normalized === "production" || normalized === "staging") {
5224
+ return { type: "server", name: normalized };
5225
+ }
5226
+ if (normalized === "development" || normalized === "local") {
5227
+ return { type: "local", name: normalized };
5228
+ }
5229
+ return { name: value };
5230
+ }
5231
+ function isObject2(value) {
5232
+ return typeof value === "object" && value !== null && !Array.isArray(value);
5233
+ }
5234
+
5141
5235
  // src/logger.ts
5142
5236
  var BRAINTRUST_ATTACHMENT = BraintrustAttachmentReference.shape.type.value;
5143
5237
  var EXTERNAL_ATTACHMENT = ExternalAttachmentReference.shape.type.value;
@@ -5186,6 +5280,7 @@ var LoginInvalidOrgError = class extends Error {
5186
5280
  super(message);
5187
5281
  this.message = message;
5188
5282
  }
5283
+ message;
5189
5284
  };
5190
5285
  var REDACTION_FIELDS = [
5191
5286
  "input",
@@ -5201,6 +5296,8 @@ var MaskingError = class {
5201
5296
  this.fieldName = fieldName;
5202
5297
  this.errorType = errorType;
5203
5298
  }
5299
+ fieldName;
5300
+ errorType;
5204
5301
  get errorMsg() {
5205
5302
  return `ERROR: Failed to mask field '${this.fieldName}' - ${this.errorType}`;
5206
5303
  }
@@ -5410,7 +5507,9 @@ var BraintrustState = class _BraintrustState {
5410
5507
  diskCache: parametersDiskCache
5411
5508
  });
5412
5509
  this.spanCache = new SpanCache({ disabled: loginParams.disableSpanCache });
5510
+ this.spanOriginEnvironment = detectSpanOriginEnvironment();
5413
5511
  }
5512
+ loginParams;
5414
5513
  id;
5415
5514
  currentExperiment;
5416
5515
  // Note: the value of IsAsyncFlush doesn't really matter here, since we
@@ -5445,6 +5544,7 @@ var BraintrustState = class _BraintrustState {
5445
5544
  _idGenerator = null;
5446
5545
  _contextManager = null;
5447
5546
  _otelFlushCallback = null;
5547
+ spanOriginEnvironment;
5448
5548
  resetLoginInfo() {
5449
5549
  this.appUrl = null;
5450
5550
  this.appPublicUrl = null;
@@ -7798,6 +7898,7 @@ function initLogger(options = {}) {
7798
7898
  orgName,
7799
7899
  forceLogin,
7800
7900
  debugLogLevel,
7901
+ environment,
7801
7902
  fetch: fetch2,
7802
7903
  state: stateArg
7803
7904
  } = options || {};
@@ -7814,6 +7915,7 @@ function initLogger(options = {}) {
7814
7915
  };
7815
7916
  const state = stateArg ?? _globalState;
7816
7917
  state.setDebugLogLevel(debugLogLevel);
7918
+ state.spanOriginEnvironment = detectSpanOriginEnvironment(environment);
7817
7919
  state.enforceQueueSizeLimit(true);
7818
7920
  const lazyMetadata = new LazyValue(
7819
7921
  async () => {
@@ -8522,6 +8624,11 @@ var ObjectFetcher = class {
8522
8624
  this._internal_btql = _internal_btql;
8523
8625
  this._internalBrainstoreRealtime = _internalBrainstoreRealtime;
8524
8626
  }
8627
+ objectType;
8628
+ pinnedVersion;
8629
+ mutateRecord;
8630
+ _internal_btql;
8631
+ _internalBrainstoreRealtime;
8525
8632
  _fetchedData = void 0;
8526
8633
  get id() {
8527
8634
  throw new Error("ObjectFetcher subclasses must have an 'id' attribute");
@@ -8960,6 +9067,8 @@ var ReadonlyExperiment = class extends ObjectFetcher {
8960
9067
  this.state = state;
8961
9068
  this.lazyMetadata = lazyMetadata;
8962
9069
  }
9070
+ state;
9071
+ lazyMetadata;
8963
9072
  get id() {
8964
9073
  return (async () => {
8965
9074
  return (await this.lazyMetadata.get()).experiment.id;
@@ -9082,7 +9191,11 @@ var SpanImpl = class _SpanImpl {
9082
9191
  metrics: {
9083
9192
  start: args.startTime ?? getCurrentUnixTimestamp()
9084
9193
  },
9085
- context: { ...callerLocation },
9194
+ context: mergeSpanOriginContext(
9195
+ { ...callerLocation },
9196
+ "braintrust-js-logger",
9197
+ this._state.spanOriginEnvironment
9198
+ ),
9086
9199
  span_attributes: {
9087
9200
  name,
9088
9201
  type,
@@ -9456,6 +9569,7 @@ var Dataset2 = class extends ObjectFetcher {
9456
9569
  this.pinnedEnvironment = pinState?.pinnedEnvironment;
9457
9570
  this.pinnedSnapshotName = pinState?.pinnedSnapshotName;
9458
9571
  }
9572
+ state;
9459
9573
  lazyMetadata;
9460
9574
  __braintrust_dataset_marker = true;
9461
9575
  newRecords = 0;
@@ -9967,6 +10081,9 @@ var Prompt2 = class _Prompt {
9967
10081
  this.noTrace = noTrace;
9968
10082
  void this.__braintrust_prompt_marker;
9969
10083
  }
10084
+ metadata;
10085
+ defaults;
10086
+ noTrace;
9970
10087
  parsedPromptData;
9971
10088
  hasParsedPromptData = false;
9972
10089
  __braintrust_prompt_marker = true;
@@ -10204,6 +10321,7 @@ var RemoteEvalParameters = class {
10204
10321
  this.metadata = metadata;
10205
10322
  void this.__braintrust_parameters_marker;
10206
10323
  }
10324
+ metadata;
10207
10325
  __braintrust_parameters_marker = true;
10208
10326
  get id() {
10209
10327
  return this.metadata.id;
@@ -14574,6 +14692,24 @@ var aiSDKChannels = defineChannels("ai", {
14574
14692
  kind: "sync-stream"
14575
14693
  })
14576
14694
  });
14695
+ var harnessAgentChannels = defineChannels("@ai-sdk/harness", {
14696
+ generate: channel({
14697
+ channelName: "HarnessAgent.generate",
14698
+ kind: "async"
14699
+ }),
14700
+ stream: channel({
14701
+ channelName: "HarnessAgent.stream",
14702
+ kind: "async"
14703
+ }),
14704
+ continueGenerate: channel({
14705
+ channelName: "HarnessAgent.continueGenerate",
14706
+ kind: "async"
14707
+ }),
14708
+ continueStream: channel({
14709
+ channelName: "HarnessAgent.continueStream",
14710
+ kind: "async"
14711
+ })
14712
+ });
14577
14713
 
14578
14714
  // src/instrumentation/plugins/ai-sdk-plugin.ts
14579
14715
  var DEFAULT_DENY_OUTPUT_PATHS = [
@@ -14842,6 +14978,84 @@ var AISDKPlugin = class extends BasePlugin {
14842
14978
  })
14843
14979
  })
14844
14980
  );
14981
+ this.unsubscribers.push(
14982
+ traceStreamingChannel(harnessAgentChannels.generate, {
14983
+ name: "HarnessAgent.generate",
14984
+ type: "task" /* TASK */,
14985
+ extractInput: ([params], event) => prepareAISDKHarnessAgentInput(params, event.self),
14986
+ extractOutput: (result, endEvent) => processAISDKOutput(
14987
+ result,
14988
+ resolveDenyOutputPaths(endEvent, denyOutputPaths)
14989
+ ),
14990
+ extractMetrics: (result) => extractTokenMetrics(result),
14991
+ aggregateChunks: aggregateAISDKChunks
14992
+ })
14993
+ );
14994
+ this.unsubscribers.push(
14995
+ traceStreamingChannel(harnessAgentChannels.stream, {
14996
+ name: "HarnessAgent.stream",
14997
+ type: "task" /* TASK */,
14998
+ extractInput: ([params], event) => prepareAISDKHarnessAgentInput(params, event.self),
14999
+ extractOutput: (result, endEvent) => processAISDKOutput(
15000
+ result,
15001
+ resolveDenyOutputPaths(endEvent, denyOutputPaths)
15002
+ ),
15003
+ extractMetrics: (result, startTime) => ({
15004
+ ...extractTokenMetrics(result),
15005
+ ...startTime === void 0 ? {} : {
15006
+ time_to_first_token: getCurrentUnixTimestamp() - startTime
15007
+ }
15008
+ }),
15009
+ aggregateChunks: aggregateAISDKChunks,
15010
+ patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
15011
+ defaultDenyOutputPaths: denyOutputPaths,
15012
+ endEvent,
15013
+ result,
15014
+ resolvePromiseUsage: true,
15015
+ span,
15016
+ startTime
15017
+ })
15018
+ })
15019
+ );
15020
+ this.unsubscribers.push(
15021
+ traceStreamingChannel(harnessAgentChannels.continueGenerate, {
15022
+ name: "HarnessAgent.continueGenerate",
15023
+ type: "task" /* TASK */,
15024
+ extractInput: ([params], event) => prepareAISDKHarnessAgentInput(params, event.self),
15025
+ extractOutput: (result, endEvent) => processAISDKOutput(
15026
+ result,
15027
+ resolveDenyOutputPaths(endEvent, denyOutputPaths)
15028
+ ),
15029
+ extractMetrics: (result) => extractTokenMetrics(result),
15030
+ aggregateChunks: aggregateAISDKChunks
15031
+ })
15032
+ );
15033
+ this.unsubscribers.push(
15034
+ traceStreamingChannel(harnessAgentChannels.continueStream, {
15035
+ name: "HarnessAgent.continueStream",
15036
+ type: "task" /* TASK */,
15037
+ extractInput: ([params], event) => prepareAISDKHarnessAgentInput(params, event.self),
15038
+ extractOutput: (result, endEvent) => processAISDKOutput(
15039
+ result,
15040
+ resolveDenyOutputPaths(endEvent, denyOutputPaths)
15041
+ ),
15042
+ extractMetrics: (result, startTime) => ({
15043
+ ...extractTokenMetrics(result),
15044
+ ...startTime === void 0 ? {} : {
15045
+ time_to_first_token: getCurrentUnixTimestamp() - startTime
15046
+ }
15047
+ }),
15048
+ aggregateChunks: aggregateAISDKChunks,
15049
+ patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
15050
+ defaultDenyOutputPaths: denyOutputPaths,
15051
+ endEvent,
15052
+ result,
15053
+ resolvePromiseUsage: true,
15054
+ span,
15055
+ startTime
15056
+ })
15057
+ })
15058
+ );
14845
15059
  this.unsubscribers.push(
14846
15060
  traceStreamingChannel(aiSDKChannels.toolLoopAgentGenerate, {
14847
15061
  name: "ToolLoopAgent.generate",
@@ -15372,6 +15586,45 @@ function prepareAISDKCallInput(params, event, span, defaultDenyOutputPaths, chil
15372
15586
  metadata
15373
15587
  };
15374
15588
  }
15589
+ function prepareAISDKHarnessAgentInput(params, self) {
15590
+ if (isObject(self)) {
15591
+ try {
15592
+ if (isObject(self.settings)) {
15593
+ const settings = self.settings;
15594
+ if (settings.telemetry === void 0) {
15595
+ Reflect.set(self, "settings", { ...settings, telemetry: {} });
15596
+ }
15597
+ }
15598
+ } catch {
15599
+ }
15600
+ }
15601
+ const selectedInput = {};
15602
+ if (params.prompt !== void 0) {
15603
+ selectedInput.prompt = params.prompt;
15604
+ }
15605
+ if (params.messages !== void 0) {
15606
+ selectedInput.messages = params.messages;
15607
+ }
15608
+ if (params.toolApprovalContinuations !== void 0) {
15609
+ selectedInput.toolApprovalContinuations = params.toolApprovalContinuations;
15610
+ }
15611
+ const metadata = extractMetadataFromCallParams({}, self);
15612
+ if (isObject(params.session) && typeof params.session.sessionId === "string") {
15613
+ metadata.sessionId = params.session.sessionId;
15614
+ }
15615
+ if (isObject(self)) {
15616
+ if (typeof self.harnessId === "string") {
15617
+ metadata.harnessId = self.harnessId;
15618
+ }
15619
+ if (typeof self.permissionMode === "string") {
15620
+ metadata.permissionMode = self.permissionMode;
15621
+ }
15622
+ }
15623
+ return {
15624
+ input: processAISDKCallInput(selectedInput).input,
15625
+ metadata
15626
+ };
15627
+ }
15375
15628
  function prepareAISDKWorkflowAgentStreamInput(params, event, span, defaultDenyOutputPaths) {
15376
15629
  registerWorkflowAgentWrapperSpan(span);
15377
15630
  const { input } = processAISDKWorkflowAgentCallInput(params);
@@ -16219,6 +16472,7 @@ function patchAISDKStreamingResult(args) {
16219
16472
  endEvent,
16220
16473
  onComplete,
16221
16474
  result,
16475
+ resolvePromiseUsage,
16222
16476
  span,
16223
16477
  startTime
16224
16478
  } = args;
@@ -16245,6 +16499,22 @@ function patchAISDKStreamingResult(args) {
16245
16499
  outputLogged = true;
16246
16500
  try {
16247
16501
  const metrics = extractTopLevelAISDKMetrics(result, endEvent);
16502
+ if (resolvePromiseUsage) {
16503
+ try {
16504
+ const resultRecord2 = result;
16505
+ const pendingUsage = resultRecord2.totalUsage ?? resultRecord2.usage;
16506
+ if (isPromiseLike(pendingUsage)) {
16507
+ const usage = await Promise.resolve(pendingUsage);
16508
+ if (isObject(usage)) {
16509
+ Object.assign(
16510
+ metrics,
16511
+ extractTokenMetrics({ usage })
16512
+ );
16513
+ }
16514
+ }
16515
+ } catch {
16516
+ }
16517
+ }
16248
16518
  if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
16249
16519
  metrics.time_to_first_token = firstChunkTime - startTime;
16250
16520
  }
@@ -28502,6 +28772,16 @@ function cleanObject(obj) {
28502
28772
  })
28503
28773
  );
28504
28774
  }
28775
+ function normalizeTokenMetrics(obj) {
28776
+ const metrics = cleanObject(obj);
28777
+ if (metrics.total_tokens !== void 0) {
28778
+ metrics.tokens = metrics.total_tokens;
28779
+ } else if (metrics.prompt_tokens !== void 0 && metrics.completion_tokens !== void 0) {
28780
+ metrics.tokens = metrics.prompt_tokens + metrics.completion_tokens;
28781
+ }
28782
+ delete metrics.total_tokens;
28783
+ return metrics;
28784
+ }
28505
28785
  function walkGenerations(response) {
28506
28786
  const result = [];
28507
28787
  const generations = response.generations || [];
@@ -28548,7 +28828,7 @@ function getMetricsFromResponse(response) {
28548
28828
  continue;
28549
28829
  }
28550
28830
  const inputTokenDetails = usageMetadata.input_token_details;
28551
- return cleanObject({
28831
+ return normalizeTokenMetrics({
28552
28832
  total_tokens: usageMetadata.total_tokens,
28553
28833
  prompt_tokens: usageMetadata.input_tokens,
28554
28834
  completion_tokens: usageMetadata.output_tokens,
@@ -28558,7 +28838,7 @@ function getMetricsFromResponse(response) {
28558
28838
  }
28559
28839
  const llmOutput = response.llmOutput || {};
28560
28840
  const tokenUsage = isRecord(llmOutput.tokenUsage) ? llmOutput.tokenUsage : isRecord(llmOutput.estimatedTokens) ? llmOutput.estimatedTokens : {};
28561
- return cleanObject({
28841
+ return normalizeTokenMetrics({
28562
28842
  total_tokens: tokenUsage.totalTokens,
28563
28843
  prompt_tokens: tokenUsage.promptTokens,
28564
28844
  completion_tokens: tokenUsage.completionTokens
@@ -31668,7 +31948,13 @@ function configureNode() {
31668
31948
  isomorph_default.getPastNAncestors = getPastNAncestors;
31669
31949
  isomorph_default.getEnv = (name) => {
31670
31950
  const value = process.env[name];
31671
- return name === "BRAINTRUST_API_KEY" && !value?.trim() ? void 0 : value;
31951
+ if (name === "BRAINTRUST_API_KEY") {
31952
+ return value?.trim() ? value : void 0;
31953
+ }
31954
+ if ((name === "BRAINTRUST_ENVIRONMENT_TYPE" || name === "BRAINTRUST_ENVIRONMENT_NAME") && !value?.trim()) {
31955
+ return getNearestBraintrustEnvValue(name);
31956
+ }
31957
+ return value;
31672
31958
  };
31673
31959
  isomorph_default.getBraintrustApiKey = async () => {
31674
31960
  const value = process.env.BRAINTRUST_API_KEY;
@@ -31753,6 +32039,24 @@ function configureNode() {
31753
32039
  }
31754
32040
  registry.enable();
31755
32041
  }
32042
+ function getNearestBraintrustEnvValue(name) {
32043
+ for (let dir2 = process.cwd(), depth = 0; depth <= BRAINTRUST_ENV_SEARCH_PARENT_LIMIT; dir2 = path.dirname(dir2), depth++) {
32044
+ const envPath = path.join(dir2, ".env.braintrust");
32045
+ try {
32046
+ const parsed = dotenv.parse(fsSync.readFileSync(envPath, "utf8"));
32047
+ const value = parsed[name];
32048
+ return value?.trim() ? value : void 0;
32049
+ } catch (e) {
32050
+ if (typeof e !== "object" || e === null || !("code" in e) || e.code !== "ENOENT") {
32051
+ return void 0;
32052
+ }
32053
+ }
32054
+ if (path.dirname(dir2) === dir2) {
32055
+ break;
32056
+ }
32057
+ }
32058
+ return void 0;
32059
+ }
31756
32060
 
31757
32061
  // dev/server.ts
31758
32062
  import express from "express";
@@ -32897,6 +33201,10 @@ var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
32897
33201
  this._state = _state;
32898
33202
  this.spanTypeFilter = spanTypeFilter;
32899
33203
  }
33204
+ _objectId;
33205
+ rootSpanId;
33206
+ _state;
33207
+ spanTypeFilter;
32900
33208
  static buildFilter(rootSpanId, spanTypeFilter, includeScorers = false) {
32901
33209
  const children = [
32902
33210
  // Base filter: root_span_id = 'value'
@@ -33344,6 +33652,8 @@ var EvalResultWithSummary = class {
33344
33652
  this.summary = summary;
33345
33653
  this.results = results;
33346
33654
  }
33655
+ summary;
33656
+ results;
33347
33657
  /**
33348
33658
  * @deprecated Use `summary` instead.
33349
33659
  */
@@ -34636,6 +34946,7 @@ var ToolBuilder = class {
34636
34946
  constructor(project) {
34637
34947
  this.project = project;
34638
34948
  }
34949
+ project;
34639
34950
  taskCounter = 0;
34640
34951
  // This type definition is just a catch all so that the implementation can be
34641
34952
  // less specific than the two more specific declarations above.
@@ -34666,6 +34977,7 @@ var ScorerBuilder = class {
34666
34977
  constructor(project) {
34667
34978
  this.project = project;
34668
34979
  }
34980
+ project;
34669
34981
  taskCounter = 0;
34670
34982
  create(opts) {
34671
34983
  this.taskCounter++;
@@ -34725,6 +35037,7 @@ var ClassifierBuilder = class {
34725
35037
  constructor(project) {
34726
35038
  this.project = project;
34727
35039
  }
35040
+ project;
34728
35041
  taskCounter = 0;
34729
35042
  create(opts) {
34730
35043
  this.taskCounter++;
@@ -34760,6 +35073,7 @@ var CodeFunction = class {
34760
35073
  throw new Error("parameters are required if return type is defined");
34761
35074
  }
34762
35075
  }
35076
+ project;
34763
35077
  handler;
34764
35078
  name;
34765
35079
  slug;
@@ -34847,6 +35161,7 @@ var PromptBuilder = class {
34847
35161
  constructor(project) {
34848
35162
  this.project = project;
34849
35163
  }
35164
+ project;
34850
35165
  create(opts) {
34851
35166
  const toolFunctions = [];
34852
35167
  const rawTools = [];
@@ -34923,6 +35238,7 @@ var ParametersBuilder = class {
34923
35238
  constructor(project) {
34924
35239
  this.project = project;
34925
35240
  }
35241
+ project;
34926
35242
  create(opts) {
34927
35243
  const slug = opts.slug ?? slugify(opts.name, { lower: true, strict: true });
34928
35244
  const codeParameters = new CodeParameters(this.project, {