braintrust 2.2.0 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dev/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } async function _asyncNullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return await rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } async function _asyncOptionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = await fn(value); } else if (op === 'call' || op === 'optionalCall') { value = await fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4; var _class5; var _class6; var _class7; var _class8; var _class9; var _class10; var _class11; var _class12; var _class13; var _class14; var _class15; var _class16; var _class17; var _class18; var _class19;// src/node.ts
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } async function _asyncNullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return await rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } async function _asyncOptionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = await fn(value); } else if (op === 'call' || op === 'optionalCall') { value = await fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4; var _class5; var _class6; var _class7; var _class8; var _class9; var _class10; var _class11; var _class12; var _class13; var _class14; var _class15; var _class16; var _class17; var _class18; var _class19; var _class20;// src/node.ts
2
2
  var _async_hooks = require('async_hooks');
3
3
  var _path = require('path'); var path = _interopRequireWildcard(_path);
4
4
  var _promises = require('fs/promises'); var fs = _interopRequireWildcard(_promises);
@@ -326,11 +326,19 @@ function getIdGenerator() {
326
326
 
327
327
  // util/db_fields.ts
328
328
  var TRANSACTION_ID_FIELD = "_xact_id";
329
+ var OBJECT_DELETE_FIELD = "_object_delete";
329
330
  var IS_MERGE_FIELD = "_is_merge";
330
331
  var AUDIT_SOURCE_FIELD = "_audit_source";
331
332
  var AUDIT_METADATA_FIELD = "_audit_metadata";
332
333
  var VALID_SOURCES = ["app", "api", "external"];
333
- var PARENT_ID_FIELD = "_parent_id";
334
+ var OBJECT_ID_KEYS = [
335
+ "experiment_id",
336
+ "dataset_id",
337
+ "prompt_session_id",
338
+ "project_id",
339
+ "log_id",
340
+ "function_data"
341
+ ];
334
342
 
335
343
  // util/span_identifier_v3.ts
336
344
 
@@ -1005,13 +1013,6 @@ function mergeDictsWithPathsHelper({
1005
1013
  function mergeDicts(mergeInto, mergeFrom) {
1006
1014
  return mergeDictsWithPaths({ mergeInto, mergeFrom, mergePaths: [] });
1007
1015
  }
1008
- function mapAt(m, k) {
1009
- const ret = m.get(k);
1010
- if (ret === void 0) {
1011
- throw new Error(`Map does not contain key ${k}`);
1012
- }
1013
- return ret;
1014
- }
1015
1016
  function recordFind(m, k) {
1016
1017
  return m[k];
1017
1018
  }
@@ -1026,72 +1027,8 @@ function getObjValueByPath(row, path2) {
1026
1027
  return curr;
1027
1028
  }
1028
1029
 
1029
- // util/graph_util.ts
1030
- function depthFirstSearch(args) {
1031
- const { graph, firstVisitF, lastVisitF } = args;
1032
- for (const vs of graph.values()) {
1033
- for (const v of vs.values()) {
1034
- if (!graph.has(v)) {
1035
- throw new Error(`Outgoing vertex ${v} must be a key in the graph`);
1036
- }
1037
- }
1038
- }
1039
- const firstVisitedVertices = /* @__PURE__ */ new Set();
1040
- const visitationOrder = _nullishCoalesce(args.visitationOrder, () => ( [...graph.keys()]));
1041
- const events = visitationOrder.map((vertex) => ({ eventType: "first", vertex, extras: {} })).reverse();
1042
- while (events.length) {
1043
- const { eventType, vertex, extras } = events.pop();
1044
- if (eventType === "last") {
1045
- _optionalChain([lastVisitF, 'optionalCall', _17 => _17(vertex)]);
1046
- continue;
1047
- }
1048
- if (firstVisitedVertices.has(vertex)) {
1049
- continue;
1050
- }
1051
- firstVisitedVertices.add(vertex);
1052
- _optionalChain([firstVisitF, 'optionalCall', _18 => _18(vertex, { parentVertex: extras.parentVertex })]);
1053
- events.push({ eventType: "last", vertex, extras: {} });
1054
- mapAt(graph, vertex).forEach((child) => {
1055
- events.push({
1056
- eventType: "first",
1057
- vertex: child,
1058
- extras: { parentVertex: vertex }
1059
- });
1060
- });
1061
- }
1062
- }
1063
- function undirectedConnectedComponents(graph) {
1064
- const directedGraph = new Map(
1065
- [...graph.vertices].map((v) => [v, /* @__PURE__ */ new Set()])
1066
- );
1067
- for (const [i, j] of graph.edges) {
1068
- mapAt(directedGraph, i).add(j);
1069
- mapAt(directedGraph, j).add(i);
1070
- }
1071
- let labelCounter = 0;
1072
- const vertexLabels = /* @__PURE__ */ new Map();
1073
- const firstVisitF = (vertex, args) => {
1074
- const label = _optionalChain([args, 'optionalAccess', _19 => _19.parentVertex]) !== void 0 ? mapAt(vertexLabels, _optionalChain([args, 'optionalAccess', _20 => _20.parentVertex])) : labelCounter++;
1075
- vertexLabels.set(vertex, label);
1076
- };
1077
- depthFirstSearch({ graph: directedGraph, firstVisitF });
1078
- const output = Array.from({ length: labelCounter }).map(() => []);
1079
- for (const [vertex, label] of vertexLabels.entries()) {
1080
- output[label].push(vertex);
1081
- }
1082
- return output;
1083
- }
1084
- function topologicalSort(graph, visitationOrder) {
1085
- const reverseOrdering = [];
1086
- const lastVisitF = (vertex) => {
1087
- reverseOrdering.push(vertex);
1088
- };
1089
- depthFirstSearch({ graph, lastVisitF, visitationOrder });
1090
- return reverseOrdering.reverse();
1091
- }
1092
-
1093
1030
  // util/merge_row_batch.ts
1094
- function generateMergedRowKey(row, useParentIdForId) {
1031
+ function generateMergedRowKey(row) {
1095
1032
  return JSON.stringify(
1096
1033
  [
1097
1034
  "org_id",
@@ -1100,7 +1037,7 @@ function generateMergedRowKey(row, useParentIdForId) {
1100
1037
  "dataset_id",
1101
1038
  "prompt_session_id",
1102
1039
  "log_id",
1103
- _nullishCoalesce(useParentIdForId, () => ( false)) ? PARENT_ID_FIELD : "id"
1040
+ "id"
1104
1041
  ].map((k) => row[k])
1105
1042
  );
1106
1043
  }
@@ -1154,96 +1091,34 @@ function mergeRowBatch(rows) {
1154
1091
  rowGroups.set(key, row);
1155
1092
  }
1156
1093
  }
1157
- const merged = [...rowGroups.values()];
1158
- const rowToLabel = new Map(
1159
- merged.map((r, i) => [generateMergedRowKey(r), i])
1160
- );
1161
- const graph = new Map(
1162
- Array.from({ length: merged.length }).map((_, i) => [i, /* @__PURE__ */ new Set()])
1163
- );
1164
- merged.forEach((r, i) => {
1165
- const parentId = r[PARENT_ID_FIELD];
1166
- if (!parentId) {
1167
- return;
1168
- }
1169
- const parentRowKey = generateMergedRowKey(
1170
- r,
1171
- true
1172
- /* useParentIdForId */
1173
- );
1174
- const parentLabel = rowToLabel.get(parentRowKey);
1175
- if (parentLabel !== void 0) {
1176
- mapAt(graph, parentLabel).add(i);
1177
- }
1178
- });
1179
- const connectedComponents = undirectedConnectedComponents({
1180
- vertices: new Set(graph.keys()),
1181
- edges: new Set(
1182
- [...graph.entries()].flatMap(
1183
- ([k, vs]) => [...vs].map((v) => {
1184
- const ret = [k, v];
1185
- return ret;
1186
- })
1187
- )
1188
- )
1189
- });
1190
- const buckets = connectedComponents.map(
1191
- (cc) => topologicalSort(
1192
- graph,
1193
- cc
1194
- /* visitationOrder */
1195
- )
1196
- );
1197
- return buckets.map((bucket) => bucket.map((i) => merged[i]));
1094
+ return [...rowGroups.values()];
1198
1095
  }
1199
1096
  function batchItems(args) {
1200
- let { items } = args;
1097
+ const { items } = args;
1201
1098
  const batchMaxNumItems = _nullishCoalesce(args.batchMaxNumItems, () => ( Number.POSITIVE_INFINITY));
1202
1099
  const batchMaxNumBytes = _nullishCoalesce(args.batchMaxNumBytes, () => ( Number.POSITIVE_INFINITY));
1100
+ const getByteSize = args.getByteSize;
1203
1101
  const output = [];
1204
- let nextItems = [];
1205
- let batchSet = [];
1206
1102
  let batch = [];
1207
1103
  let batchLen = 0;
1208
1104
  function addToBatch(item) {
1209
1105
  batch.push(item);
1210
- batchLen += item.length;
1106
+ batchLen += getByteSize(item);
1211
1107
  }
1212
1108
  function flushBatch() {
1213
- batchSet.push(batch);
1109
+ output.push(batch);
1214
1110
  batch = [];
1215
1111
  batchLen = 0;
1216
1112
  }
1217
- while (items.length) {
1218
- for (const bucket of items) {
1219
- let i = 0;
1220
- for (const item of bucket) {
1221
- if (batch.length === 0 || item.length + batchLen < batchMaxNumBytes && batch.length < batchMaxNumItems) {
1222
- addToBatch(item);
1223
- } else if (i === 0) {
1224
- flushBatch();
1225
- addToBatch(item);
1226
- } else {
1227
- break;
1228
- }
1229
- ++i;
1230
- }
1231
- if (i < bucket.length) {
1232
- nextItems.push(bucket.slice(i));
1233
- }
1234
- if (batchLen >= batchMaxNumBytes || batch.length > batchMaxNumItems) {
1235
- flushBatch();
1236
- }
1237
- }
1238
- if (batch.length) {
1113
+ for (const item of items) {
1114
+ const itemSize = getByteSize(item);
1115
+ if (batch.length > 0 && !(itemSize + batchLen < batchMaxNumBytes && batch.length < batchMaxNumItems)) {
1239
1116
  flushBatch();
1240
1117
  }
1241
- if (batchSet.length) {
1242
- output.push(batchSet);
1243
- batchSet = [];
1244
- }
1245
- items = nextItems;
1246
- nextItems = [];
1118
+ addToBatch(item);
1119
+ }
1120
+ if (batch.length > 0) {
1121
+ flushBatch();
1247
1122
  }
1248
1123
  return output;
1249
1124
  }
@@ -1361,20 +1236,20 @@ function slugify(text, options) {
1361
1236
  \u00FF: "y"
1362
1237
  };
1363
1238
  const replacement = "-";
1364
- const trim = _optionalChain([options, 'optionalAccess', _21 => _21.trim]) !== false;
1239
+ const trim = _optionalChain([options, 'optionalAccess', _17 => _17.trim]) !== false;
1365
1240
  let slug = text.normalize().split("").reduce((result, ch) => {
1366
1241
  const mapped = charMap[ch] || ch;
1367
1242
  const appendChar = mapped === replacement ? " " : mapped;
1368
1243
  return result + appendChar.replace(/[^\w\s$*_+~.()'"!\-:@]+/g, "");
1369
1244
  }, "");
1370
- if (_optionalChain([options, 'optionalAccess', _22 => _22.strict])) {
1245
+ if (_optionalChain([options, 'optionalAccess', _18 => _18.strict])) {
1371
1246
  slug = slug.replace(/[^A-Za-z0-9\s]/g, "");
1372
1247
  }
1373
1248
  if (trim) {
1374
1249
  slug = slug.trim();
1375
1250
  }
1376
1251
  slug = slug.replace(/\s+/g, replacement);
1377
- if (_optionalChain([options, 'optionalAccess', _23 => _23.lower])) {
1252
+ if (_optionalChain([options, 'optionalAccess', _19 => _19.lower])) {
1378
1253
  slug = slug.toLowerCase();
1379
1254
  }
1380
1255
  return slug;
@@ -1841,10 +1716,15 @@ var FunctionTypeEnum = _v3.z.enum([
1841
1716
  "preprocessor",
1842
1717
  "facet",
1843
1718
  "classifier",
1844
- "tag"
1719
+ "tag",
1720
+ "parameters"
1845
1721
  ]);
1846
1722
  var NullableSavedFunctionId = _v3.z.union([
1847
- _v3.z.object({ type: _v3.z.literal("function"), id: _v3.z.string() }),
1723
+ _v3.z.object({
1724
+ type: _v3.z.literal("function"),
1725
+ id: _v3.z.string(),
1726
+ version: _v3.z.string().optional()
1727
+ }),
1848
1728
  _v3.z.object({
1849
1729
  type: _v3.z.literal("global"),
1850
1730
  name: _v3.z.string(),
@@ -1852,6 +1732,67 @@ var NullableSavedFunctionId = _v3.z.union([
1852
1732
  }),
1853
1733
  _v3.z.null()
1854
1734
  ]);
1735
+ var TopicMapReport = _v3.z.object({
1736
+ version: _v3.z.literal(1),
1737
+ created_at: _v3.z.string().optional(),
1738
+ settings: _v3.z.object({
1739
+ algorithm: _v3.z.enum(["hdbscan", "kmeans", "hierarchical"]),
1740
+ dimension_reduction: _v3.z.enum(["umap", "pca", "none"]),
1741
+ vector_field: _v3.z.string(),
1742
+ embedding_model: _v3.z.string(),
1743
+ n_clusters: _v3.z.union([_v3.z.number(), _v3.z.null()]).optional(),
1744
+ umap_dimensions: _v3.z.union([_v3.z.number(), _v3.z.null()]).optional(),
1745
+ min_cluster_size: _v3.z.union([_v3.z.number(), _v3.z.null()]).optional(),
1746
+ min_samples: _v3.z.union([_v3.z.number(), _v3.z.null()]).optional()
1747
+ }),
1748
+ query_settings: _v3.z.object({
1749
+ hierarchy_threshold: _v3.z.union([_v3.z.number(), _v3.z.null()]),
1750
+ auto_naming: _v3.z.boolean(),
1751
+ skip_cache: _v3.z.boolean(),
1752
+ viz_mode: _v3.z.enum(["bar", "scatter"]),
1753
+ naming_model: _v3.z.string()
1754
+ }).partial(),
1755
+ clusters: _v3.z.array(
1756
+ _v3.z.object({
1757
+ cluster_id: _v3.z.number(),
1758
+ parent_cluster_id: _v3.z.union([_v3.z.number(), _v3.z.null()]).optional(),
1759
+ topic_id: _v3.z.string(),
1760
+ count: _v3.z.number(),
1761
+ sample_texts: _v3.z.array(_v3.z.string()),
1762
+ samples: _v3.z.array(
1763
+ _v3.z.object({
1764
+ id: _v3.z.string(),
1765
+ text: _v3.z.string(),
1766
+ root_span_id: _v3.z.string(),
1767
+ span_id: _v3.z.string()
1768
+ })
1769
+ ),
1770
+ name: _v3.z.string().optional(),
1771
+ description: _v3.z.string().optional(),
1772
+ keywords: _v3.z.array(_v3.z.string()).optional(),
1773
+ centroid: _v3.z.array(_v3.z.number()).optional(),
1774
+ parent_id: _v3.z.union([_v3.z.number(), _v3.z.null()]).optional(),
1775
+ is_leaf: _v3.z.boolean().optional(),
1776
+ depth: _v3.z.number().optional()
1777
+ })
1778
+ ),
1779
+ embedding_points: _v3.z.array(
1780
+ _v3.z.object({
1781
+ x: _v3.z.number(),
1782
+ y: _v3.z.number(),
1783
+ cluster: _v3.z.number(),
1784
+ text: _v3.z.string().optional()
1785
+ })
1786
+ ).optional()
1787
+ });
1788
+ var TopicMapData = _v3.z.object({
1789
+ type: _v3.z.literal("topic_map"),
1790
+ source_facet: _v3.z.string(),
1791
+ embedding_model: _v3.z.string(),
1792
+ bundle_key: _v3.z.string(),
1793
+ distance_threshold: _v3.z.number().optional(),
1794
+ report: TopicMapReport.optional()
1795
+ });
1855
1796
  var BatchedFacetData = _v3.z.object({
1856
1797
  type: _v3.z.literal("batched_facet"),
1857
1798
  preprocessor: NullableSavedFunctionId.and(_v3.z.unknown()).optional(),
@@ -1860,9 +1801,17 @@ var BatchedFacetData = _v3.z.object({
1860
1801
  name: _v3.z.string(),
1861
1802
  prompt: _v3.z.string(),
1862
1803
  model: _v3.z.string().optional(),
1804
+ embedding_model: _v3.z.string().optional(),
1863
1805
  no_match_pattern: _v3.z.string().optional()
1864
1806
  })
1865
- )
1807
+ ),
1808
+ topic_maps: _v3.z.record(
1809
+ _v3.z.object({
1810
+ function_name: _v3.z.string(),
1811
+ topic_map_id: _v3.z.string().optional(),
1812
+ topic_map_data: TopicMapData
1813
+ })
1814
+ ).optional()
1866
1815
  });
1867
1816
  var BraintrustModelParams = _v3.z.object({
1868
1817
  use_cache: _v3.z.boolean(),
@@ -2073,6 +2022,18 @@ var ObjectReferenceNullish = _v3.z.union([
2073
2022
  }),
2074
2023
  _v3.z.null()
2075
2024
  ]);
2025
+ var SavedFunctionId = _v3.z.union([
2026
+ _v3.z.object({
2027
+ type: _v3.z.literal("function"),
2028
+ id: _v3.z.string(),
2029
+ version: _v3.z.string().optional()
2030
+ }),
2031
+ _v3.z.object({
2032
+ type: _v3.z.literal("global"),
2033
+ name: _v3.z.string(),
2034
+ function_type: FunctionTypeEnum.optional().default("scorer")
2035
+ })
2036
+ ]);
2076
2037
  var DatasetEvent = _v3.z.object({
2077
2038
  id: _v3.z.string(),
2078
2039
  _xact_id: _v3.z.string(),
@@ -2092,7 +2053,36 @@ var DatasetEvent = _v3.z.object({
2092
2053
  is_root: _v3.z.union([_v3.z.boolean(), _v3.z.null()]).optional(),
2093
2054
  origin: ObjectReferenceNullish.optional(),
2094
2055
  comments: _v3.z.union([_v3.z.array(_v3.z.unknown()), _v3.z.null()]).optional(),
2095
- audit_data: _v3.z.union([_v3.z.array(_v3.z.unknown()), _v3.z.null()]).optional()
2056
+ audit_data: _v3.z.union([_v3.z.array(_v3.z.unknown()), _v3.z.null()]).optional(),
2057
+ facets: _v3.z.union([_v3.z.object({}).partial().passthrough(), _v3.z.null()]).optional(),
2058
+ classifications: _v3.z.union([
2059
+ _v3.z.record(
2060
+ _v3.z.array(
2061
+ _v3.z.object({
2062
+ id: _v3.z.string(),
2063
+ label: _v3.z.string().optional(),
2064
+ confidence: _v3.z.union([_v3.z.number(), _v3.z.null()]).optional(),
2065
+ metadata: _v3.z.union([_v3.z.object({}).partial().passthrough(), _v3.z.null()]).optional(),
2066
+ source: SavedFunctionId.and(
2067
+ _v3.z.union([
2068
+ _v3.z.object({
2069
+ type: _v3.z.literal("function"),
2070
+ id: _v3.z.string(),
2071
+ version: _v3.z.string().optional()
2072
+ }),
2073
+ _v3.z.object({
2074
+ type: _v3.z.literal("global"),
2075
+ name: _v3.z.string(),
2076
+ function_type: FunctionTypeEnum.optional().default("scorer")
2077
+ }),
2078
+ _v3.z.null()
2079
+ ])
2080
+ ).optional()
2081
+ })
2082
+ )
2083
+ ),
2084
+ _v3.z.null()
2085
+ ]).optional()
2096
2086
  });
2097
2087
  var EnvVar = _v3.z.object({
2098
2088
  id: _v3.z.string().uuid(),
@@ -2169,7 +2159,8 @@ var SpanType = _v3.z.union([
2169
2159
  "automation",
2170
2160
  "facet",
2171
2161
  "preprocessor",
2172
- "classifier"
2162
+ "classifier",
2163
+ "review"
2173
2164
  ]),
2174
2165
  _v3.z.null()
2175
2166
  ]);
@@ -2210,10 +2201,43 @@ var ExperimentEvent = _v3.z.object({
2210
2201
  is_root: _v3.z.union([_v3.z.boolean(), _v3.z.null()]).optional(),
2211
2202
  origin: ObjectReferenceNullish.optional(),
2212
2203
  comments: _v3.z.union([_v3.z.array(_v3.z.unknown()), _v3.z.null()]).optional(),
2213
- audit_data: _v3.z.union([_v3.z.array(_v3.z.unknown()), _v3.z.null()]).optional()
2204
+ audit_data: _v3.z.union([_v3.z.array(_v3.z.unknown()), _v3.z.null()]).optional(),
2205
+ facets: _v3.z.union([_v3.z.object({}).partial().passthrough(), _v3.z.null()]).optional(),
2206
+ classifications: _v3.z.union([
2207
+ _v3.z.record(
2208
+ _v3.z.array(
2209
+ _v3.z.object({
2210
+ id: _v3.z.string(),
2211
+ label: _v3.z.string().optional(),
2212
+ confidence: _v3.z.union([_v3.z.number(), _v3.z.null()]).optional(),
2213
+ metadata: _v3.z.union([_v3.z.object({}).partial().passthrough(), _v3.z.null()]).optional(),
2214
+ source: SavedFunctionId.and(
2215
+ _v3.z.union([
2216
+ _v3.z.object({
2217
+ type: _v3.z.literal("function"),
2218
+ id: _v3.z.string(),
2219
+ version: _v3.z.string().optional()
2220
+ }),
2221
+ _v3.z.object({
2222
+ type: _v3.z.literal("global"),
2223
+ name: _v3.z.string(),
2224
+ function_type: FunctionTypeEnum.optional().default("scorer")
2225
+ }),
2226
+ _v3.z.null()
2227
+ ])
2228
+ ).optional()
2229
+ })
2230
+ )
2231
+ ),
2232
+ _v3.z.null()
2233
+ ]).optional()
2214
2234
  });
2215
2235
  var ExtendedSavedFunctionId = _v3.z.union([
2216
- _v3.z.object({ type: _v3.z.literal("function"), id: _v3.z.string() }),
2236
+ _v3.z.object({
2237
+ type: _v3.z.literal("function"),
2238
+ id: _v3.z.string(),
2239
+ version: _v3.z.string().optional()
2240
+ }),
2217
2241
  _v3.z.object({
2218
2242
  type: _v3.z.literal("global"),
2219
2243
  name: _v3.z.string(),
@@ -2230,6 +2254,7 @@ var FacetData = _v3.z.object({
2230
2254
  preprocessor: NullableSavedFunctionId.and(_v3.z.unknown()).optional(),
2231
2255
  prompt: _v3.z.string(),
2232
2256
  model: _v3.z.string().optional(),
2257
+ embedding_model: _v3.z.string().optional(),
2233
2258
  no_match_pattern: _v3.z.string().optional()
2234
2259
  });
2235
2260
  var PromptBlockDataNullish = _v3.z.union([
@@ -2319,14 +2344,6 @@ var PromptParserNullish = _v3.z.union([
2319
2344
  }),
2320
2345
  _v3.z.null()
2321
2346
  ]);
2322
- var SavedFunctionId = _v3.z.union([
2323
- _v3.z.object({ type: _v3.z.literal("function"), id: _v3.z.string() }),
2324
- _v3.z.object({
2325
- type: _v3.z.literal("global"),
2326
- name: _v3.z.string(),
2327
- function_type: FunctionTypeEnum.optional().default("scorer")
2328
- })
2329
- ]);
2330
2347
  var PromptDataNullish = _v3.z.union([
2331
2348
  _v3.z.object({
2332
2349
  prompt: PromptBlockDataNullish,
@@ -2377,7 +2394,8 @@ var FunctionTypeEnumNullish = _v3.z.union([
2377
2394
  "preprocessor",
2378
2395
  "facet",
2379
2396
  "classifier",
2380
- "tag"
2397
+ "tag",
2398
+ "parameters"
2381
2399
  ]),
2382
2400
  _v3.z.null()
2383
2401
  ]);
@@ -2469,7 +2487,8 @@ var FunctionData = _v3.z.union([
2469
2487
  type: _v3.z.literal("remote_eval"),
2470
2488
  endpoint: _v3.z.string(),
2471
2489
  eval_name: _v3.z.string(),
2472
- parameters: _v3.z.object({}).partial().passthrough()
2490
+ parameters: _v3.z.object({}).partial().passthrough(),
2491
+ parameters_version: _v3.z.union([_v3.z.string(), _v3.z.null()]).optional()
2473
2492
  }),
2474
2493
  _v3.z.object({
2475
2494
  type: _v3.z.literal("global"),
@@ -2478,7 +2497,18 @@ var FunctionData = _v3.z.union([
2478
2497
  config: _v3.z.union([_v3.z.object({}).partial().passthrough(), _v3.z.null()]).optional()
2479
2498
  }),
2480
2499
  FacetData,
2481
- BatchedFacetData
2500
+ BatchedFacetData,
2501
+ _v3.z.object({
2502
+ type: _v3.z.literal("parameters"),
2503
+ data: _v3.z.object({}).partial().passthrough(),
2504
+ __schema: _v3.z.object({
2505
+ type: _v3.z.literal("object"),
2506
+ properties: _v3.z.record(_v3.z.object({}).partial().passthrough()),
2507
+ required: _v3.z.array(_v3.z.string()).optional(),
2508
+ additionalProperties: _v3.z.boolean().optional()
2509
+ })
2510
+ }),
2511
+ TopicMapData.and(_v3.z.unknown())
2482
2512
  ]);
2483
2513
  var Function = _v3.z.object({
2484
2514
  id: _v3.z.string().uuid(),
@@ -2508,7 +2538,13 @@ var Function = _v3.z.object({
2508
2538
  _v3.z.null()
2509
2539
  ]).optional()
2510
2540
  });
2511
- var FunctionFormat = _v3.z.enum(["llm", "code", "global", "graph"]);
2541
+ var FunctionFormat = _v3.z.enum([
2542
+ "llm",
2543
+ "code",
2544
+ "global",
2545
+ "graph",
2546
+ "topic_map"
2547
+ ]);
2512
2548
  var PromptData = _v3.z.object({
2513
2549
  prompt: PromptBlockDataNullish,
2514
2550
  options: PromptOptionsNullish,
@@ -2591,13 +2627,14 @@ var FunctionObjectType = _v3.z.enum([
2591
2627
  "custom_view",
2592
2628
  "preprocessor",
2593
2629
  "facet",
2594
- "classifier"
2630
+ "classifier",
2631
+ "parameters"
2595
2632
  ]);
2596
2633
  var FunctionOutputType = _v3.z.enum([
2597
2634
  "completion",
2598
2635
  "score",
2599
2636
  "facet",
2600
- "tag",
2637
+ "classification",
2601
2638
  "any"
2602
2639
  ]);
2603
2640
  var GitMetadataSettings = _v3.z.object({
@@ -2633,6 +2670,10 @@ var GroupScope = _v3.z.object({
2633
2670
  idle_seconds: _v3.z.number().optional()
2634
2671
  });
2635
2672
  var IfExists = _v3.z.enum(["error", "ignore", "replace"]);
2673
+ var ImageRenderingMode = _v3.z.union([
2674
+ _v3.z.enum(["auto", "click_to_load", "blocked"]),
2675
+ _v3.z.null()
2676
+ ]);
2636
2677
  var InvokeParent = _v3.z.union([
2637
2678
  _v3.z.object({
2638
2679
  object_type: _v3.z.enum(["project_logs", "experiment", "playground_logs"]),
@@ -2725,7 +2766,8 @@ var Organization = _v3.z.object({
2725
2766
  is_universal_api: _v3.z.union([_v3.z.boolean(), _v3.z.null()]).optional(),
2726
2767
  proxy_url: _v3.z.union([_v3.z.string(), _v3.z.null()]).optional(),
2727
2768
  realtime_url: _v3.z.union([_v3.z.string(), _v3.z.null()]).optional(),
2728
- created: _v3.z.union([_v3.z.string(), _v3.z.null()]).optional()
2769
+ created: _v3.z.union([_v3.z.string(), _v3.z.null()]).optional(),
2770
+ image_rendering_mode: ImageRenderingMode.optional()
2729
2771
  });
2730
2772
  var ProjectSettings = _v3.z.union([
2731
2773
  _v3.z.object({
@@ -2866,7 +2908,36 @@ var ProjectLogsEvent = _v3.z.object({
2866
2908
  origin: ObjectReferenceNullish.optional(),
2867
2909
  comments: _v3.z.union([_v3.z.array(_v3.z.unknown()), _v3.z.null()]).optional(),
2868
2910
  audit_data: _v3.z.union([_v3.z.array(_v3.z.unknown()), _v3.z.null()]).optional(),
2869
- _async_scoring_state: _v3.z.unknown().optional()
2911
+ _async_scoring_state: _v3.z.unknown().optional(),
2912
+ facets: _v3.z.union([_v3.z.object({}).partial().passthrough(), _v3.z.null()]).optional(),
2913
+ classifications: _v3.z.union([
2914
+ _v3.z.record(
2915
+ _v3.z.array(
2916
+ _v3.z.object({
2917
+ id: _v3.z.string(),
2918
+ label: _v3.z.string().optional(),
2919
+ confidence: _v3.z.union([_v3.z.number(), _v3.z.null()]).optional(),
2920
+ metadata: _v3.z.union([_v3.z.object({}).partial().passthrough(), _v3.z.null()]).optional(),
2921
+ source: SavedFunctionId.and(
2922
+ _v3.z.union([
2923
+ _v3.z.object({
2924
+ type: _v3.z.literal("function"),
2925
+ id: _v3.z.string(),
2926
+ version: _v3.z.string().optional()
2927
+ }),
2928
+ _v3.z.object({
2929
+ type: _v3.z.literal("global"),
2930
+ name: _v3.z.string(),
2931
+ function_type: FunctionTypeEnum.optional().default("scorer")
2932
+ }),
2933
+ _v3.z.null()
2934
+ ])
2935
+ ).optional()
2936
+ })
2937
+ )
2938
+ ),
2939
+ _v3.z.null()
2940
+ ]).optional()
2870
2941
  });
2871
2942
  var ProjectScoreType = _v3.z.enum([
2872
2943
  "slider",
@@ -3168,12 +3239,15 @@ var View = _v3.z.object({
3168
3239
  "datasets",
3169
3240
  "dataset",
3170
3241
  "prompts",
3242
+ "parameters",
3171
3243
  "tools",
3172
3244
  "scorers",
3173
3245
  "classifiers",
3174
3246
  "logs",
3175
3247
  "monitor",
3176
- "for_review"
3248
+ "for_review_project_log",
3249
+ "for_review_experiments",
3250
+ "for_review_datasets"
3177
3251
  ]),
3178
3252
  name: _v3.z.string(),
3179
3253
  created: _v3.z.union([_v3.z.string(), _v3.z.null()]).optional(),
@@ -3906,6 +3980,52 @@ var PromptCache = class {
3906
3980
  }
3907
3981
  };
3908
3982
 
3983
+ // src/prompt-cache/parameters-cache.ts
3984
+ function createCacheKey2(key) {
3985
+ if (key.id) {
3986
+ return `parameters:id:${key.id}`;
3987
+ }
3988
+ const prefix = _nullishCoalesce(key.projectId, () => ( key.projectName));
3989
+ if (!prefix) {
3990
+ throw new Error("Either projectId or projectName must be provided");
3991
+ }
3992
+ if (!key.slug) {
3993
+ throw new Error("Slug must be provided when not using ID");
3994
+ }
3995
+ return `parameters:${prefix}:${key.slug}:${_nullishCoalesce(key.version, () => ( "latest"))}`;
3996
+ }
3997
+ var ParametersCache = class {
3998
+
3999
+
4000
+ constructor(options) {
4001
+ this.memoryCache = options.memoryCache;
4002
+ this.diskCache = options.diskCache;
4003
+ }
4004
+ async get(key) {
4005
+ const cacheKey = createCacheKey2(key);
4006
+ const memoryParams = this.memoryCache.get(cacheKey);
4007
+ if (memoryParams !== void 0) {
4008
+ return memoryParams;
4009
+ }
4010
+ if (this.diskCache) {
4011
+ const diskParams = await this.diskCache.get(cacheKey);
4012
+ if (!diskParams) {
4013
+ return void 0;
4014
+ }
4015
+ this.memoryCache.set(cacheKey, diskParams);
4016
+ return diskParams;
4017
+ }
4018
+ return void 0;
4019
+ }
4020
+ async set(key, value) {
4021
+ const cacheKey = createCacheKey2(key);
4022
+ this.memoryCache.set(cacheKey, value);
4023
+ if (this.diskCache) {
4024
+ await this.diskCache.set(cacheKey, value);
4025
+ }
4026
+ }
4027
+ };
4028
+
3909
4029
  // src/span-cache.ts
3910
4030
  var activeCaches = /* @__PURE__ */ new Set();
3911
4031
  var exitHandlersRegistered = false;
@@ -3927,7 +4047,7 @@ var SpanCache = (_class4 = class {
3927
4047
  // Small in-memory index tracking which rootSpanIds have data
3928
4048
  __init12() {this.rootSpanIndex = /* @__PURE__ */ new Set()}
3929
4049
  constructor(options) {;_class4.prototype.__init6.call(this);_class4.prototype.__init7.call(this);_class4.prototype.__init8.call(this);_class4.prototype.__init9.call(this);_class4.prototype.__init10.call(this);_class4.prototype.__init11.call(this);_class4.prototype.__init12.call(this);_class4.prototype.__init13.call(this);_class4.prototype.__init14.call(this);_class4.prototype.__init15.call(this);
3930
- this._explicitlyDisabled = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _24 => _24.disabled]), () => ( false));
4050
+ this._explicitlyDisabled = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _20 => _20.disabled]), () => ( false));
3931
4051
  }
3932
4052
  /**
3933
4053
  * Disable the cache at runtime. This is called automatically when
@@ -4196,7 +4316,24 @@ var SpanCache = (_class4 = class {
4196
4316
  // src/logger.ts
4197
4317
  var BRAINTRUST_ATTACHMENT = BraintrustAttachmentReference.shape.type.value;
4198
4318
  var EXTERNAL_ATTACHMENT = ExternalAttachmentReference.shape.type.value;
4319
+ var LOGS3_OVERFLOW_REFERENCE_TYPE = "logs3_overflow";
4199
4320
  var BRAINTRUST_PARAMS = Object.keys(BraintrustModelParams.shape);
4321
+ var DEFAULT_MAX_REQUEST_SIZE = 6 * 1024 * 1024;
4322
+ var parametersRowSchema = _v3.z.object({
4323
+ id: _v3.z.string().uuid(),
4324
+ _xact_id: _v3.z.string(),
4325
+ project_id: _v3.z.string().uuid(),
4326
+ name: _v3.z.string(),
4327
+ slug: _v3.z.string(),
4328
+ description: _v3.z.union([_v3.z.string(), _v3.z.null()]).optional(),
4329
+ function_type: _v3.z.literal("parameters"),
4330
+ function_data: _v3.z.object({
4331
+ type: _v3.z.literal("parameters"),
4332
+ data: _v3.z.record(_v3.z.unknown()).optional(),
4333
+ __schema: _v3.z.record(_v3.z.unknown())
4334
+ }),
4335
+ metadata: _v3.z.union([_v3.z.object({}).partial().passthrough(), _v3.z.null()]).optional()
4336
+ });
4200
4337
  var LoginInvalidOrgError = class extends Error {
4201
4338
  constructor(message) {
4202
4339
  super(message);
@@ -4294,7 +4431,7 @@ var NoopSpan = (_class5 = class {
4294
4431
  return this;
4295
4432
  }
4296
4433
  end(args) {
4297
- return _nullishCoalesce(_optionalChain([args, 'optionalAccess', _25 => _25.endTime]), () => ( getCurrentUnixTimestamp()));
4434
+ return _nullishCoalesce(_optionalChain([args, 'optionalAccess', _21 => _21.endTime]), () => ( getCurrentUnixTimestamp()));
4298
4435
  }
4299
4436
  async export() {
4300
4437
  return "";
@@ -4373,6 +4510,17 @@ var BraintrustState = (_class6 = class _BraintrustState {
4373
4510
  max: _nullishCoalesce(Number(isomorph_default.getEnv("BRAINTRUST_PROMPT_CACHE_DISK_MAX")), () => ( 1 << 20))
4374
4511
  }) : void 0;
4375
4512
  this.promptCache = new PromptCache({ memoryCache, diskCache });
4513
+ const parametersMemoryCache = new LRUCache({
4514
+ max: _nullishCoalesce(Number(isomorph_default.getEnv("BRAINTRUST_PARAMETERS_CACHE_MEMORY_MAX")), () => ( 1 << 10))
4515
+ });
4516
+ const parametersDiskCache = canUseDiskCache() ? new DiskCache({
4517
+ cacheDir: _nullishCoalesce(isomorph_default.getEnv("BRAINTRUST_PARAMETERS_CACHE_DIR"), () => ( `${_nullishCoalesce(isomorph_default.getEnv("HOME"), () => ( isomorph_default.homedir()))}/.braintrust/parameters_cache`)),
4518
+ max: _nullishCoalesce(Number(isomorph_default.getEnv("BRAINTRUST_PARAMETERS_CACHE_DISK_MAX")), () => ( 1 << 20))
4519
+ }) : void 0;
4520
+ this.parametersCache = new ParametersCache({
4521
+ memoryCache: parametersMemoryCache,
4522
+ diskCache: parametersDiskCache
4523
+ });
4376
4524
  this.spanCache = new SpanCache({ disabled: loginParams.disableSpanCache });
4377
4525
  }
4378
4526
 
@@ -4403,6 +4551,7 @@ var BraintrustState = (_class6 = class _BraintrustState {
4403
4551
  __init29() {this._proxyConn = null}
4404
4552
 
4405
4553
 
4554
+
4406
4555
  __init30() {this._idGenerator = null}
4407
4556
  __init31() {this._contextManager = null}
4408
4557
  __init32() {this._otelFlushCallback = null}
@@ -4518,8 +4667,8 @@ var BraintrustState = (_class6 = class _BraintrustState {
4518
4667
  setFetch(fetch2) {
4519
4668
  this.loginParams.fetch = fetch2;
4520
4669
  this.fetch = fetch2;
4521
- _optionalChain([this, 'access', _26 => _26._apiConn, 'optionalAccess', _27 => _27.setFetch, 'call', _28 => _28(fetch2)]);
4522
- _optionalChain([this, 'access', _29 => _29._appConn, 'optionalAccess', _30 => _30.setFetch, 'call', _31 => _31(fetch2)]);
4670
+ _optionalChain([this, 'access', _22 => _22._apiConn, 'optionalAccess', _23 => _23.setFetch, 'call', _24 => _24(fetch2)]);
4671
+ _optionalChain([this, 'access', _25 => _25._appConn, 'optionalAccess', _26 => _26.setFetch, 'call', _27 => _27(fetch2)]);
4523
4672
  }
4524
4673
  setMaskingFunction(maskingFunction) {
4525
4674
  this.bgLogger().setMaskingFunction(maskingFunction);
@@ -5196,8 +5345,8 @@ function _getOrgName(orgName) {
5196
5345
  return orgName || isomorph_default.getEnv("BRAINTRUST_ORG_NAME") || void 0;
5197
5346
  }
5198
5347
  function _getLinkBaseUrl(state, linkArgs) {
5199
- const appUrl = _getAppUrl(state.appUrl || _optionalChain([linkArgs, 'optionalAccess', _32 => _32.app_url]));
5200
- const orgName = _getOrgName(state.orgName || _optionalChain([linkArgs, 'optionalAccess', _33 => _33.org_name]));
5348
+ const appUrl = _getAppUrl(state.appUrl || _optionalChain([linkArgs, 'optionalAccess', _28 => _28.app_url]));
5349
+ const orgName = _getOrgName(state.orgName || _optionalChain([linkArgs, 'optionalAccess', _29 => _29.org_name]));
5201
5350
  if (!orgName) {
5202
5351
  return null;
5203
5352
  }
@@ -5207,9 +5356,9 @@ async function permalink(slug, opts) {
5207
5356
  if (slug === "") {
5208
5357
  return NOOP_SPAN_PERMALINK;
5209
5358
  }
5210
- const state = _nullishCoalesce(_optionalChain([opts, 'optionalAccess', _34 => _34.state]), () => ( _globalState));
5359
+ const state = _nullishCoalesce(_optionalChain([opts, 'optionalAccess', _30 => _30.state]), () => ( _globalState));
5211
5360
  const getOrgName = async () => {
5212
- if (_optionalChain([opts, 'optionalAccess', _35 => _35.orgName])) {
5361
+ if (_optionalChain([opts, 'optionalAccess', _31 => _31.orgName])) {
5213
5362
  return opts.orgName;
5214
5363
  }
5215
5364
  await state.login({});
@@ -5219,7 +5368,7 @@ async function permalink(slug, opts) {
5219
5368
  return state.orgName;
5220
5369
  };
5221
5370
  const getAppUrl = async () => {
5222
- if (_optionalChain([opts, 'optionalAccess', _36 => _36.appUrl])) {
5371
+ if (_optionalChain([opts, 'optionalAccess', _32 => _32.appUrl])) {
5223
5372
  return opts.appUrl;
5224
5373
  }
5225
5374
  await state.login({});
@@ -5354,7 +5503,7 @@ var Logger = (_class7 = class {
5354
5503
  * @returns The `id` of the logged event.
5355
5504
  */
5356
5505
  log(event, options) {
5357
- if (this.calledStartSpan && !_optionalChain([options, 'optionalAccess', _37 => _37.allowConcurrentWithSpans])) {
5506
+ if (this.calledStartSpan && !_optionalChain([options, 'optionalAccess', _33 => _33.allowConcurrentWithSpans])) {
5358
5507
  throw new Error(
5359
5508
  "Cannot run toplevel `log` method while using spans. To log to the span, call `logger.traced` and then log with `span.log`"
5360
5509
  );
@@ -5422,12 +5571,12 @@ var Logger = (_class7 = class {
5422
5571
  state: this.state,
5423
5572
  ...startSpanParentArgs({
5424
5573
  state: this.state,
5425
- parent: _optionalChain([args, 'optionalAccess', _38 => _38.parent]),
5574
+ parent: _optionalChain([args, 'optionalAccess', _34 => _34.parent]),
5426
5575
  parentObjectType: this.parentObjectType(),
5427
5576
  parentObjectId: this.lazyId,
5428
5577
  parentComputeObjectMetadataArgs: this.computeMetadataArgs,
5429
- parentSpanIds: _optionalChain([args, 'optionalAccess', _39 => _39.parentSpanIds]),
5430
- propagatedEvent: _optionalChain([args, 'optionalAccess', _40 => _40.propagatedEvent])
5578
+ parentSpanIds: _optionalChain([args, 'optionalAccess', _35 => _35.parentSpanIds]),
5579
+ propagatedEvent: _optionalChain([args, 'optionalAccess', _36 => _36.propagatedEvent])
5431
5580
  }),
5432
5581
  defaultRootType: "task" /* TASK */
5433
5582
  });
@@ -5503,8 +5652,100 @@ function castLogger(logger, asyncFlush) {
5503
5652
  }
5504
5653
  return logger;
5505
5654
  }
5655
+ var logs3OverflowUploadSchema = _v3.z.object({
5656
+ method: _v3.z.enum(["PUT", "POST"]),
5657
+ signedUrl: _v3.z.string().url(),
5658
+ headers: _v3.z.record(_v3.z.string()).optional(),
5659
+ fields: _v3.z.record(_v3.z.string()).optional(),
5660
+ key: _v3.z.string().min(1)
5661
+ });
5506
5662
  function constructLogs3Data(items) {
5507
- return `{"rows": ${constructJsonArray(items)}, "api_version": 2}`;
5663
+ return `{"rows": ${constructJsonArray(items.map((i) => i.str))}, "api_version": 2}`;
5664
+ }
5665
+ function constructLogs3OverflowRequest(key) {
5666
+ return {
5667
+ rows: {
5668
+ type: LOGS3_OVERFLOW_REFERENCE_TYPE,
5669
+ key
5670
+ },
5671
+ api_version: 2
5672
+ };
5673
+ }
5674
+ function pickLogs3OverflowObjectIds(row) {
5675
+ const objectIds = {};
5676
+ for (const key of OBJECT_ID_KEYS) {
5677
+ if (key in row) {
5678
+ objectIds[key] = row[key];
5679
+ }
5680
+ }
5681
+ return objectIds;
5682
+ }
5683
+ async function uploadLogs3OverflowPayload(upload, payload, fetchFn = fetch) {
5684
+ if (upload.method === "POST") {
5685
+ if (!upload.fields) {
5686
+ throw new Error("Missing logs3 overflow upload fields");
5687
+ }
5688
+ if (typeof FormData === "undefined" || typeof Blob === "undefined") {
5689
+ throw new Error("FormData is not available for logs3 overflow upload");
5690
+ }
5691
+ const form = new FormData();
5692
+ for (const [key, value] of Object.entries(upload.fields)) {
5693
+ form.append(key, value);
5694
+ }
5695
+ const contentType = _nullishCoalesce(upload.fields["Content-Type"], () => ( "application/json"));
5696
+ form.append("file", new Blob([payload], { type: contentType }));
5697
+ const headers2 = {};
5698
+ for (const [key, value] of Object.entries(_nullishCoalesce(upload.headers, () => ( {})))) {
5699
+ if (key.toLowerCase() !== "content-type") {
5700
+ headers2[key] = value;
5701
+ }
5702
+ }
5703
+ const response2 = await fetchFn(upload.signedUrl, {
5704
+ method: "POST",
5705
+ headers: headers2,
5706
+ body: form
5707
+ });
5708
+ if (!response2.ok) {
5709
+ const responseText = await response2.text().catch(() => "");
5710
+ throw new Error(
5711
+ `Failed to upload logs3 overflow payload: ${response2.status} ${responseText}`
5712
+ );
5713
+ }
5714
+ return;
5715
+ }
5716
+ const headers = { ..._nullishCoalesce(upload.headers, () => ( {})) };
5717
+ addAzureBlobHeaders(headers, upload.signedUrl);
5718
+ const response = await fetchFn(upload.signedUrl, {
5719
+ method: "PUT",
5720
+ headers,
5721
+ body: payload
5722
+ });
5723
+ if (!response.ok) {
5724
+ const responseText = await response.text().catch(() => "");
5725
+ throw new Error(
5726
+ `Failed to upload logs3 overflow payload: ${response.status} ${responseText}`
5727
+ );
5728
+ }
5729
+ }
5730
+ function stringifyWithOverflowMeta(item) {
5731
+ const str = JSON.stringify(item);
5732
+ const record = item;
5733
+ return {
5734
+ str,
5735
+ overflowMeta: {
5736
+ object_ids: pickLogs3OverflowObjectIds(record),
5737
+ is_delete: record[OBJECT_DELETE_FIELD] === true,
5738
+ input_row: {
5739
+ byte_size: utf8ByteLength(str)
5740
+ }
5741
+ }
5742
+ };
5743
+ }
5744
+ function utf8ByteLength(value) {
5745
+ if (typeof TextEncoder !== "undefined") {
5746
+ return new TextEncoder().encode(value).length;
5747
+ }
5748
+ return value.length;
5508
5749
  }
5509
5750
  function now() {
5510
5751
  return (/* @__PURE__ */ new Date()).getTime();
@@ -5519,21 +5760,21 @@ var HTTPBackgroundLogger = (_class8 = class _HTTPBackgroundLogger {
5519
5760
 
5520
5761
  __init37() {this.maskingFunction = null}
5521
5762
  __init38() {this.syncFlush = false}
5522
- // 6 MB for the AWS lambda gateway (from our own testing).
5523
- __init39() {this.maxRequestSize = 6 * 1024 * 1024}
5524
- __init40() {this.defaultBatchSize = 100}
5525
- __init41() {this.numTries = 3}
5526
- __init42() {this.queueDropExceedingMaxsize = DEFAULT_QUEUE_SIZE}
5527
- __init43() {this.queueDropLoggingPeriod = 60}
5528
- __init44() {this.failedPublishPayloadsDir = void 0}
5529
- __init45() {this.allPublishPayloadsDir = void 0}
5530
- __init46() {this.flushChunkSize = 25}
5531
- __init47() {this._disabled = false}
5532
- __init48() {this.queueDropLoggingState = {
5763
+ __init39() {this.maxRequestSizeOverride = null}
5764
+ __init40() {this._maxRequestSizePromise = null}
5765
+ __init41() {this.defaultBatchSize = 100}
5766
+ __init42() {this.numTries = 3}
5767
+ __init43() {this.queueDropExceedingMaxsize = DEFAULT_QUEUE_SIZE}
5768
+ __init44() {this.queueDropLoggingPeriod = 60}
5769
+ __init45() {this.failedPublishPayloadsDir = void 0}
5770
+ __init46() {this.allPublishPayloadsDir = void 0}
5771
+ __init47() {this.flushChunkSize = 25}
5772
+ __init48() {this._disabled = false}
5773
+ __init49() {this.queueDropLoggingState = {
5533
5774
  numDropped: 0,
5534
5775
  lastLoggedTimestamp: 0
5535
5776
  }}
5536
- constructor(apiConn, opts) {;_class8.prototype.__init34.call(this);_class8.prototype.__init35.call(this);_class8.prototype.__init36.call(this);_class8.prototype.__init37.call(this);_class8.prototype.__init38.call(this);_class8.prototype.__init39.call(this);_class8.prototype.__init40.call(this);_class8.prototype.__init41.call(this);_class8.prototype.__init42.call(this);_class8.prototype.__init43.call(this);_class8.prototype.__init44.call(this);_class8.prototype.__init45.call(this);_class8.prototype.__init46.call(this);_class8.prototype.__init47.call(this);_class8.prototype.__init48.call(this);
5777
+ constructor(apiConn, opts) {;_class8.prototype.__init34.call(this);_class8.prototype.__init35.call(this);_class8.prototype.__init36.call(this);_class8.prototype.__init37.call(this);_class8.prototype.__init38.call(this);_class8.prototype.__init39.call(this);_class8.prototype.__init40.call(this);_class8.prototype.__init41.call(this);_class8.prototype.__init42.call(this);_class8.prototype.__init43.call(this);_class8.prototype.__init44.call(this);_class8.prototype.__init45.call(this);_class8.prototype.__init46.call(this);_class8.prototype.__init47.call(this);_class8.prototype.__init48.call(this);_class8.prototype.__init49.call(this);
5537
5778
  opts = _nullishCoalesce(opts, () => ( {}));
5538
5779
  this.apiConn = apiConn;
5539
5780
  const syncFlushEnv = Number(isomorph_default.getEnv("BRAINTRUST_SYNC_FLUSH"));
@@ -5548,7 +5789,7 @@ var HTTPBackgroundLogger = (_class8 = class _HTTPBackgroundLogger {
5548
5789
  }
5549
5790
  const maxRequestSizeEnv = Number(isomorph_default.getEnv("BRAINTRUST_MAX_REQUEST_SIZE"));
5550
5791
  if (!isNaN(maxRequestSizeEnv)) {
5551
- this.maxRequestSize = maxRequestSizeEnv;
5792
+ this.maxRequestSizeOverride = maxRequestSizeEnv;
5552
5793
  }
5553
5794
  const numTriesEnv = Number(isomorph_default.getEnv("BRAINTRUST_NUM_RETRIES"));
5554
5795
  if (!isNaN(numTriesEnv)) {
@@ -5610,6 +5851,30 @@ var HTTPBackgroundLogger = (_class8 = class _HTTPBackgroundLogger {
5610
5851
  }
5611
5852
  }
5612
5853
  }
5854
+ getMaxRequestSize() {
5855
+ if (!this._maxRequestSizePromise) {
5856
+ this._maxRequestSizePromise = (async () => {
5857
+ let serverLimit = null;
5858
+ try {
5859
+ const conn = await this.apiConn.get();
5860
+ const versionInfo = await conn.get_json("version");
5861
+ serverLimit = _nullishCoalesce(_v3.z.object({ logs3_payload_max_bytes: _v3.z.number().nullish() }).parse(versionInfo).logs3_payload_max_bytes, () => ( null));
5862
+ } catch (e) {
5863
+ console.warn("Failed to fetch version info for payload limit:", e);
5864
+ }
5865
+ const validServerLimit = serverLimit !== null && serverLimit > 0 ? serverLimit : null;
5866
+ const canUseOverflow = validServerLimit !== null;
5867
+ let maxRequestSize = DEFAULT_MAX_REQUEST_SIZE;
5868
+ if (this.maxRequestSizeOverride !== null) {
5869
+ maxRequestSize = validServerLimit !== null ? Math.min(this.maxRequestSizeOverride, validServerLimit) : this.maxRequestSizeOverride;
5870
+ } else if (validServerLimit !== null) {
5871
+ maxRequestSize = validServerLimit;
5872
+ }
5873
+ return { maxRequestSize, canUseOverflow };
5874
+ })();
5875
+ }
5876
+ return this._maxRequestSizePromise;
5877
+ }
5613
5878
  async flush() {
5614
5879
  if (this.syncFlush) {
5615
5880
  this.triggerActiveFlush();
@@ -5628,7 +5893,7 @@ var HTTPBackgroundLogger = (_class8 = class _HTTPBackgroundLogger {
5628
5893
  this.queue.clear();
5629
5894
  return;
5630
5895
  }
5631
- const batchSize = _nullishCoalesce(_optionalChain([args, 'optionalAccess', _41 => _41.batchSize]), () => ( this.defaultBatchSize));
5896
+ const batchSize = _nullishCoalesce(_optionalChain([args, 'optionalAccess', _37 => _37.batchSize]), () => ( this.defaultBatchSize));
5632
5897
  const wrappedItems = this.queue.drain();
5633
5898
  if (wrappedItems.length === 0) {
5634
5899
  return;
@@ -5653,33 +5918,33 @@ var HTTPBackgroundLogger = (_class8 = class _HTTPBackgroundLogger {
5653
5918
  if (allItems.length === 0) {
5654
5919
  return;
5655
5920
  }
5656
- const allItemsStr = allItems.map(
5657
- (bucket) => bucket.map((item) => JSON.stringify(item))
5921
+ const allItemsWithMeta = allItems.map(
5922
+ (item) => stringifyWithOverflowMeta(item)
5658
5923
  );
5659
- const batchSets = batchItems({
5660
- items: allItemsStr,
5924
+ const maxRequestSizeResult = await this.getMaxRequestSize();
5925
+ const batches = batchItems({
5926
+ items: allItemsWithMeta,
5661
5927
  batchMaxNumItems: batchSize,
5662
- batchMaxNumBytes: this.maxRequestSize / 2
5928
+ batchMaxNumBytes: maxRequestSizeResult.maxRequestSize / 2,
5929
+ getByteSize: (item) => item.str.length
5663
5930
  });
5664
- for (const batchSet of batchSets) {
5665
- const postPromises = batchSet.map(
5666
- (batch) => (async () => {
5667
- try {
5668
- await this.submitLogsRequest(batch);
5669
- return { type: "success" };
5670
- } catch (e) {
5671
- return { type: "error", value: e };
5672
- }
5673
- })()
5931
+ const postPromises = batches.map(
5932
+ (batch) => (async () => {
5933
+ try {
5934
+ await this.submitLogsRequest(batch, maxRequestSizeResult);
5935
+ return { type: "success" };
5936
+ } catch (e) {
5937
+ return { type: "error", value: e };
5938
+ }
5939
+ })()
5940
+ );
5941
+ const results = await Promise.all(postPromises);
5942
+ const failingResultErrors = results.map((r) => r.type === "success" ? void 0 : r.value).filter((r) => r !== void 0);
5943
+ if (failingResultErrors.length) {
5944
+ throw new AggregateError(
5945
+ failingResultErrors,
5946
+ `Encountered the following errors while logging:`
5674
5947
  );
5675
- const results = await Promise.all(postPromises);
5676
- const failingResultErrors = results.map((r) => r.type === "success" ? void 0 : r.value).filter((r) => r !== void 0);
5677
- if (failingResultErrors.length) {
5678
- throw new AggregateError(
5679
- failingResultErrors,
5680
- `Encountered the following errors while logging:`
5681
- );
5682
- }
5683
5948
  }
5684
5949
  const attachmentErrors = [];
5685
5950
  for (const attachment of attachments) {
@@ -5709,32 +5974,30 @@ var HTTPBackgroundLogger = (_class8 = class _HTTPBackgroundLogger {
5709
5974
  items.forEach((item) => extractAttachments(item, attachments));
5710
5975
  let mergedItems = mergeRowBatch(items);
5711
5976
  if (this.maskingFunction) {
5712
- mergedItems = mergedItems.map(
5713
- (batch) => batch.map((item) => {
5714
- const maskedItem = { ...item };
5715
- for (const field of REDACTION_FIELDS) {
5716
- if (item[field] !== void 0) {
5717
- const maskedValue = applyMaskingToField(
5718
- this.maskingFunction,
5719
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
5720
- item[field],
5721
- field
5722
- );
5723
- if (maskedValue instanceof MaskingError) {
5724
- delete maskedItem[field];
5725
- if (maskedItem.error) {
5726
- maskedItem.error = `${maskedItem.error}; ${maskedValue.errorMsg}`;
5727
- } else {
5728
- maskedItem.error = maskedValue.errorMsg;
5729
- }
5977
+ mergedItems = mergedItems.map((item) => {
5978
+ const maskedItem = { ...item };
5979
+ for (const field of REDACTION_FIELDS) {
5980
+ if (item[field] !== void 0) {
5981
+ const maskedValue = applyMaskingToField(
5982
+ this.maskingFunction,
5983
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5984
+ item[field],
5985
+ field
5986
+ );
5987
+ if (maskedValue instanceof MaskingError) {
5988
+ delete maskedItem[field];
5989
+ if (maskedItem.error) {
5990
+ maskedItem.error = `${maskedItem.error}; ${maskedValue.errorMsg}`;
5730
5991
  } else {
5731
- maskedItem[field] = maskedValue;
5992
+ maskedItem.error = maskedValue.errorMsg;
5732
5993
  }
5994
+ } else {
5995
+ maskedItem[field] = maskedValue;
5733
5996
  }
5734
5997
  }
5735
- return maskedItem;
5736
- })
5737
- );
5998
+ }
5999
+ return maskedItem;
6000
+ });
5738
6001
  }
5739
6002
  return [mergedItems, attachments];
5740
6003
  } catch (e) {
@@ -5761,20 +6024,73 @@ var HTTPBackgroundLogger = (_class8 = class _HTTPBackgroundLogger {
5761
6024
  }
5762
6025
  throw new Error("Impossible");
5763
6026
  }
5764
- async submitLogsRequest(items) {
6027
+ async requestLogs3OverflowUpload(conn, args) {
6028
+ let response;
6029
+ try {
6030
+ response = await conn.post_json("logs3/overflow", {
6031
+ content_type: "application/json",
6032
+ size_bytes: args.sizeBytes,
6033
+ rows: args.rows
6034
+ });
6035
+ } catch (error) {
6036
+ const errorStr = JSON.stringify(error);
6037
+ throw new Error(
6038
+ `Failed to request logs3 overflow upload URL: ${errorStr}`
6039
+ );
6040
+ }
6041
+ try {
6042
+ return logs3OverflowUploadSchema.parse(response);
6043
+ } catch (error) {
6044
+ if (error instanceof _v3.ZodError) {
6045
+ const errorStr = JSON.stringify(error.flatten());
6046
+ throw new Error(`Invalid response from API server: ${errorStr}`);
6047
+ }
6048
+ throw error;
6049
+ }
6050
+ }
6051
+ async _uploadLogs3OverflowPayload(conn, upload, payload) {
6052
+ await uploadLogs3OverflowPayload(upload, payload, conn.fetch.bind(conn));
6053
+ }
6054
+ async submitLogsRequest(items, {
6055
+ maxRequestSize,
6056
+ canUseOverflow
6057
+ }) {
5765
6058
  const conn = await this.apiConn.get();
5766
6059
  const dataStr = constructLogs3Data(items);
6060
+ const payloadBytes = utf8ByteLength(dataStr);
6061
+ const useOverflow = canUseOverflow && payloadBytes > maxRequestSize;
5767
6062
  if (this.allPublishPayloadsDir) {
5768
6063
  await _HTTPBackgroundLogger.writePayloadToDir({
5769
6064
  payloadDir: this.allPublishPayloadsDir,
5770
6065
  payload: dataStr
5771
6066
  });
5772
6067
  }
6068
+ let overflowUpload = null;
6069
+ const overflowRows = useOverflow ? items.map((item) => item.overflowMeta) : null;
5773
6070
  for (let i = 0; i < this.numTries; i++) {
5774
6071
  const startTime = now();
5775
6072
  let error = void 0;
5776
6073
  try {
5777
- await conn.post_json("logs3", dataStr);
6074
+ if (overflowRows) {
6075
+ if (!overflowUpload) {
6076
+ const currentUpload = await this.requestLogs3OverflowUpload(conn, {
6077
+ rows: overflowRows,
6078
+ sizeBytes: payloadBytes
6079
+ });
6080
+ await this._uploadLogs3OverflowPayload(
6081
+ conn,
6082
+ currentUpload,
6083
+ dataStr
6084
+ );
6085
+ overflowUpload = currentUpload;
6086
+ }
6087
+ await conn.post_json(
6088
+ "logs3",
6089
+ constructLogs3OverflowRequest(overflowUpload.key)
6090
+ );
6091
+ } else {
6092
+ await conn.post_json("logs3", dataStr);
6093
+ }
5778
6094
  } catch (e) {
5779
6095
  error = e;
5780
6096
  }
@@ -5790,7 +6106,7 @@ var HTTPBackgroundLogger = (_class8 = class _HTTPBackgroundLogger {
5790
6106
  return `${error}`;
5791
6107
  }
5792
6108
  })();
5793
- const errMsg = `log request failed. Elapsed time: ${(now() - startTime) / 1e3} seconds. Payload size: ${dataStr.length}.${retryingText}
6109
+ const errMsg = `log request failed. Elapsed time: ${(now() - startTime) / 1e3} seconds. Payload size: ${payloadBytes}.${retryingText}
5794
6110
  Error: ${errorText}`;
5795
6111
  if (!isRetrying && this.failedPublishPayloadsDir) {
5796
6112
  await _HTTPBackgroundLogger.writePayloadToDir({
@@ -5844,7 +6160,7 @@ Error: ${errorText}`;
5844
6160
  try {
5845
6161
  const [allItems, allAttachments] = await this.unwrapLazyValues(wrappedItems);
5846
6162
  const dataStr = constructLogs3Data(
5847
- allItems.map((x) => JSON.stringify(x))
6163
+ allItems.map((x) => stringifyWithOverflowMeta(x))
5848
6164
  );
5849
6165
  const attachmentStr = JSON.stringify(
5850
6166
  allAttachments.map((a) => a.debugInfo())
@@ -5893,10 +6209,10 @@ Error: ${errorText}`;
5893
6209
  } catch (err) {
5894
6210
  if (err instanceof AggregateError) {
5895
6211
  for (const e of err.errors) {
5896
- _optionalChain([this, 'access', _42 => _42.onFlushError, 'optionalCall', _43 => _43(e)]);
6212
+ _optionalChain([this, 'access', _38 => _38.onFlushError, 'optionalCall', _39 => _39(e)]);
5897
6213
  }
5898
6214
  } else {
5899
- _optionalChain([this, 'access', _44 => _44.onFlushError, 'optionalCall', _45 => _45(err)]);
6215
+ _optionalChain([this, 'access', _40 => _40.onFlushError, 'optionalCall', _41 => _41(err)]);
5900
6216
  }
5901
6217
  this.activeFlushError = err;
5902
6218
  } finally {
@@ -6302,24 +6618,24 @@ async function loginToState(options = {}) {
6302
6618
  return state;
6303
6619
  }
6304
6620
  function currentExperiment(options) {
6305
- const state = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _46 => _46.state]), () => ( _globalState));
6621
+ const state = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _42 => _42.state]), () => ( _globalState));
6306
6622
  return state.currentExperiment;
6307
6623
  }
6308
6624
  function currentLogger(options) {
6309
- const state = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _47 => _47.state]), () => ( _globalState));
6310
- return castLogger(state.currentLogger, _optionalChain([options, 'optionalAccess', _48 => _48.asyncFlush]));
6625
+ const state = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _43 => _43.state]), () => ( _globalState));
6626
+ return castLogger(state.currentLogger, _optionalChain([options, 'optionalAccess', _44 => _44.asyncFlush]));
6311
6627
  }
6312
6628
  function currentSpan(options) {
6313
- const state = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _49 => _49.state]), () => ( _globalState));
6629
+ const state = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _45 => _45.state]), () => ( _globalState));
6314
6630
  return _nullishCoalesce(state.contextManager.getCurrentSpan(), () => ( NOOP_SPAN));
6315
6631
  }
6316
6632
  function getSpanParentObject(options) {
6317
- const state = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _50 => _50.state]), () => ( _globalState));
6633
+ const state = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _46 => _46.state]), () => ( _globalState));
6318
6634
  const parentSpan = currentSpan({ state });
6319
6635
  if (!Object.is(parentSpan, NOOP_SPAN)) {
6320
6636
  return parentSpan;
6321
6637
  }
6322
- const parentStr = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _51 => _51.parent]), () => ( state.currentParent.getStore()));
6638
+ const parentStr = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _47 => _47.parent]), () => ( state.currentParent.getStore()));
6323
6639
  if (parentStr) return getSpanComponentsClass().fromStr(parentStr);
6324
6640
  const experiment = currentExperiment();
6325
6641
  if (experiment) {
@@ -6348,7 +6664,7 @@ function traced(callback, args) {
6348
6664
  const { span, isSyncFlushLogger } = startSpanAndIsLogger(args);
6349
6665
  const ret = runCatchFinally(
6350
6666
  () => {
6351
- if (_nullishCoalesce(_optionalChain([args, 'optionalAccess', _52 => _52.setCurrent]), () => ( true))) {
6667
+ if (_nullishCoalesce(_optionalChain([args, 'optionalAccess', _48 => _48.setCurrent]), () => ( true))) {
6352
6668
  return withCurrent(span, callback);
6353
6669
  } else {
6354
6670
  return callback(span);
@@ -6360,7 +6676,7 @@ function traced(callback, args) {
6360
6676
  },
6361
6677
  () => span.end()
6362
6678
  );
6363
- if (_optionalChain([args, 'optionalAccess', _53 => _53.asyncFlush]) === void 0 || _optionalChain([args, 'optionalAccess', _54 => _54.asyncFlush])) {
6679
+ if (_optionalChain([args, 'optionalAccess', _49 => _49.asyncFlush]) === void 0 || _optionalChain([args, 'optionalAccess', _50 => _50.asyncFlush])) {
6364
6680
  return ret;
6365
6681
  } else {
6366
6682
  return (async () => {
@@ -6376,14 +6692,14 @@ function startSpan(args) {
6376
6692
  return startSpanAndIsLogger(args).span;
6377
6693
  }
6378
6694
  async function flush(options) {
6379
- const state = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _55 => _55.state]), () => ( _globalState));
6695
+ const state = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _51 => _51.state]), () => ( _globalState));
6380
6696
  return await state.bgLogger().flush();
6381
6697
  }
6382
6698
  function startSpanAndIsLogger(args) {
6383
- const state = _nullishCoalesce(_optionalChain([args, 'optionalAccess', _56 => _56.state]), () => ( _globalState));
6699
+ const state = _nullishCoalesce(_optionalChain([args, 'optionalAccess', _52 => _52.state]), () => ( _globalState));
6384
6700
  const parentObject = getSpanParentObject({
6385
- asyncFlush: _optionalChain([args, 'optionalAccess', _57 => _57.asyncFlush]),
6386
- parent: _optionalChain([args, 'optionalAccess', _58 => _58.parent]),
6701
+ asyncFlush: _optionalChain([args, 'optionalAccess', _53 => _53.asyncFlush]),
6702
+ parent: _optionalChain([args, 'optionalAccess', _54 => _54.parent]),
6387
6703
  state
6388
6704
  });
6389
6705
  if (parentObject instanceof SpanComponentsV3 || parentObject instanceof SpanComponentsV4) {
@@ -6400,14 +6716,14 @@ function startSpanAndIsLogger(args) {
6400
6716
  ),
6401
6717
  parentComputeObjectMetadataArgs: _nullishCoalesce(parentObject.data.compute_object_metadata_args, () => ( void 0)),
6402
6718
  parentSpanIds,
6403
- propagatedEvent: _nullishCoalesce(_optionalChain([args, 'optionalAccess', _59 => _59.propagatedEvent]), () => ( // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
6719
+ propagatedEvent: _nullishCoalesce(_optionalChain([args, 'optionalAccess', _55 => _55.propagatedEvent]), () => ( // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
6404
6720
  (_nullishCoalesce(parentObject.data.propagated_event, () => ( void 0)))))
6405
6721
  });
6406
6722
  return {
6407
6723
  span,
6408
6724
  isSyncFlushLogger: parentObject.data.object_type === 2 /* PROJECT_LOGS */ && // Since there's no parent logger here, we're free to choose the async flush
6409
6725
  // behavior, and therefore propagate along whatever we get from the arguments
6410
- _optionalChain([args, 'optionalAccess', _60 => _60.asyncFlush]) === false
6726
+ _optionalChain([args, 'optionalAccess', _56 => _56.asyncFlush]) === false
6411
6727
  };
6412
6728
  } else {
6413
6729
  const span = parentObject.startSpan(args);
@@ -6553,10 +6869,10 @@ function extractAttachments(event, attachments) {
6553
6869
  event[key] = value.reference;
6554
6870
  continue;
6555
6871
  }
6556
- if (_optionalChain([value, 'optionalAccess', _61 => _61.type]) === BRAINTRUST_ATTACHMENT && value.key && !value.uploader) {
6872
+ if (_optionalChain([value, 'optionalAccess', _57 => _57.type]) === BRAINTRUST_ATTACHMENT && value.key && !value.uploader) {
6557
6873
  continue;
6558
6874
  }
6559
- if (_optionalChain([value, 'optionalAccess', _62 => _62.reference, 'optionalAccess', _63 => _63.type]) === BRAINTRUST_ATTACHMENT && _optionalChain([value, 'optionalAccess', _64 => _64.uploader])) {
6875
+ if (_optionalChain([value, 'optionalAccess', _58 => _58.reference, 'optionalAccess', _59 => _59.type]) === BRAINTRUST_ATTACHMENT && _optionalChain([value, 'optionalAccess', _60 => _60.uploader])) {
6560
6876
  const attachment = new Attachment({
6561
6877
  data: value.dataDebugString,
6562
6878
  filename: value.reference.filename,
@@ -6623,13 +6939,13 @@ function validateAndSanitizeExperimentLogFullArgs(event, hasDataset) {
6623
6939
  var DEFAULT_FETCH_BATCH_SIZE = 1e3;
6624
6940
  var MAX_BTQL_ITERATIONS = 1e4;
6625
6941
  var ObjectFetcher = (_class9 = class {
6626
- constructor(objectType, pinnedVersion, mutateRecord, _internal_btql) {;_class9.prototype.__init49.call(this);
6942
+ constructor(objectType, pinnedVersion, mutateRecord, _internal_btql) {;_class9.prototype.__init50.call(this);
6627
6943
  this.objectType = objectType;
6628
6944
  this.pinnedVersion = pinnedVersion;
6629
6945
  this.mutateRecord = mutateRecord;
6630
6946
  this._internal_btql = _internal_btql;
6631
6947
  }
6632
- __init49() {this._fetchedData = void 0}
6948
+ __init50() {this._fetchedData = void 0}
6633
6949
  get id() {
6634
6950
  throw new Error("ObjectFetcher subclasses must have an 'id' attribute");
6635
6951
  }
@@ -6707,7 +7023,7 @@ var ObjectFetcher = (_class9 = class {
6707
7023
  }
6708
7024
  return;
6709
7025
  }
6710
- for await (const record of this.fetchRecordsFromApi(_optionalChain([options, 'optionalAccess', _65 => _65.batchSize]))) {
7026
+ for await (const record of this.fetchRecordsFromApi(_optionalChain([options, 'optionalAccess', _61 => _61.batchSize]))) {
6711
7027
  yield record;
6712
7028
  }
6713
7029
  }
@@ -6717,7 +7033,7 @@ var ObjectFetcher = (_class9 = class {
6717
7033
  async fetchedData(options) {
6718
7034
  if (this._fetchedData === void 0) {
6719
7035
  const data = [];
6720
- for await (const record of this.fetchRecordsFromApi(_optionalChain([options, 'optionalAccess', _66 => _66.batchSize]))) {
7036
+ for await (const record of this.fetchRecordsFromApi(_optionalChain([options, 'optionalAccess', _62 => _62.batchSize]))) {
6721
7037
  data.push(record);
6722
7038
  }
6723
7039
  this._fetchedData = data;
@@ -6750,9 +7066,9 @@ var Experiment2 = (_class10 = class extends ObjectFetcher {
6750
7066
 
6751
7067
 
6752
7068
  // For type identification.
6753
- __init50() {this.kind = "experiment"}
7069
+ __init51() {this.kind = "experiment"}
6754
7070
  constructor(state, lazyMetadata, dataset) {
6755
- super("experiment", void 0, (r) => enrichAttachments(r, state));_class10.prototype.__init50.call(this);;
7071
+ super("experiment", void 0, (r) => enrichAttachments(r, state));_class10.prototype.__init51.call(this);;
6756
7072
  this.lazyMetadata = lazyMetadata;
6757
7073
  this.dataset = dataset;
6758
7074
  this.lastStartTime = getCurrentUnixTimestamp();
@@ -6812,7 +7128,7 @@ var Experiment2 = (_class10 = class extends ObjectFetcher {
6812
7128
  * @returns The `id` of the logged event.
6813
7129
  */
6814
7130
  log(event, options) {
6815
- if (this.calledStartSpan && !_optionalChain([options, 'optionalAccess', _67 => _67.allowConcurrentWithSpans])) {
7131
+ if (this.calledStartSpan && !_optionalChain([options, 'optionalAccess', _63 => _63.allowConcurrentWithSpans])) {
6816
7132
  throw new Error(
6817
7133
  "Cannot run toplevel `log` method while using spans. To log to the span, call `experiment.traced` and then log with `span.log`"
6818
7134
  );
@@ -6865,12 +7181,12 @@ var Experiment2 = (_class10 = class extends ObjectFetcher {
6865
7181
  state: this.state,
6866
7182
  ...startSpanParentArgs({
6867
7183
  state: this.state,
6868
- parent: _optionalChain([args, 'optionalAccess', _68 => _68.parent]),
7184
+ parent: _optionalChain([args, 'optionalAccess', _64 => _64.parent]),
6869
7185
  parentObjectType: this.parentObjectType(),
6870
7186
  parentObjectId: this.lazyId,
6871
7187
  parentComputeObjectMetadataArgs: void 0,
6872
7188
  parentSpanIds: void 0,
6873
- propagatedEvent: _optionalChain([args, 'optionalAccess', _69 => _69.propagatedEvent])
7189
+ propagatedEvent: _optionalChain([args, 'optionalAccess', _65 => _65.propagatedEvent])
6874
7190
  }),
6875
7191
  defaultRootType: "eval" /* EVAL */
6876
7192
  });
@@ -7105,8 +7421,8 @@ var SpanImpl = (_class11 = class _SpanImpl {
7105
7421
 
7106
7422
 
7107
7423
 
7108
- __init51() {this.kind = "span"}
7109
- constructor(args) {;_class11.prototype.__init51.call(this);
7424
+ __init52() {this.kind = "span"}
7425
+ constructor(args) {;_class11.prototype.__init52.call(this);
7110
7426
  this._state = args.state;
7111
7427
  const spanAttributes = _nullishCoalesce(args.spanAttributes, () => ( {}));
7112
7428
  const rawEvent = _nullishCoalesce(args.event, () => ( {}));
@@ -7208,8 +7524,8 @@ var SpanImpl = (_class11 = class _SpanImpl {
7208
7524
  ...serializableInternalData,
7209
7525
  [IS_MERGE_FIELD]: this.isMerge
7210
7526
  });
7211
- if (_optionalChain([partialRecord, 'access', _70 => _70.metrics, 'optionalAccess', _71 => _71.end])) {
7212
- this.loggedEndTime = _optionalChain([partialRecord, 'access', _72 => _72.metrics, 'optionalAccess', _73 => _73.end]);
7527
+ if (_optionalChain([partialRecord, 'access', _66 => _66.metrics, 'optionalAccess', _67 => _67.end])) {
7528
+ this.loggedEndTime = _optionalChain([partialRecord, 'access', _68 => _68.metrics, 'optionalAccess', _69 => _69.end]);
7213
7529
  }
7214
7530
  if (this.parentObjectType === 1 /* EXPERIMENT */) {
7215
7531
  const cachedSpan = {
@@ -7268,18 +7584,18 @@ var SpanImpl = (_class11 = class _SpanImpl {
7268
7584
  );
7269
7585
  }
7270
7586
  startSpan(args) {
7271
- const parentSpanIds = _optionalChain([args, 'optionalAccess', _74 => _74.parent]) ? void 0 : { spanId: this._spanId, rootSpanId: this._rootSpanId };
7587
+ const parentSpanIds = _optionalChain([args, 'optionalAccess', _70 => _70.parent]) ? void 0 : { spanId: this._spanId, rootSpanId: this._rootSpanId };
7272
7588
  return new _SpanImpl({
7273
7589
  state: this._state,
7274
7590
  ...args,
7275
7591
  ...startSpanParentArgs({
7276
7592
  state: this._state,
7277
- parent: _optionalChain([args, 'optionalAccess', _75 => _75.parent]),
7593
+ parent: _optionalChain([args, 'optionalAccess', _71 => _71.parent]),
7278
7594
  parentObjectType: this.parentObjectType,
7279
7595
  parentObjectId: this.parentObjectId,
7280
7596
  parentComputeObjectMetadataArgs: this.parentComputeObjectMetadataArgs,
7281
7597
  parentSpanIds,
7282
- propagatedEvent: _nullishCoalesce(_optionalChain([args, 'optionalAccess', _76 => _76.propagatedEvent]), () => ( this.propagatedEvent))
7598
+ propagatedEvent: _nullishCoalesce(_optionalChain([args, 'optionalAccess', _72 => _72.propagatedEvent]), () => ( this.propagatedEvent))
7283
7599
  })
7284
7600
  });
7285
7601
  }
@@ -7293,12 +7609,12 @@ var SpanImpl = (_class11 = class _SpanImpl {
7293
7609
  ...args,
7294
7610
  ...startSpanParentArgs({
7295
7611
  state: this._state,
7296
- parent: _optionalChain([args, 'optionalAccess', _77 => _77.parent]),
7612
+ parent: _optionalChain([args, 'optionalAccess', _73 => _73.parent]),
7297
7613
  parentObjectType: this.parentObjectType,
7298
7614
  parentObjectId: this.parentObjectId,
7299
7615
  parentComputeObjectMetadataArgs: this.parentComputeObjectMetadataArgs,
7300
7616
  parentSpanIds,
7301
- propagatedEvent: _nullishCoalesce(_optionalChain([args, 'optionalAccess', _78 => _78.propagatedEvent]), () => ( this.propagatedEvent))
7617
+ propagatedEvent: _nullishCoalesce(_optionalChain([args, 'optionalAccess', _74 => _74.propagatedEvent]), () => ( this.propagatedEvent))
7302
7618
  }),
7303
7619
  spanId
7304
7620
  });
@@ -7307,7 +7623,7 @@ var SpanImpl = (_class11 = class _SpanImpl {
7307
7623
  let endTime;
7308
7624
  let internalData = {};
7309
7625
  if (!this.loggedEndTime) {
7310
- endTime = _nullishCoalesce(_optionalChain([args, 'optionalAccess', _79 => _79.endTime]), () => ( getCurrentUnixTimestamp()));
7626
+ endTime = _nullishCoalesce(_optionalChain([args, 'optionalAccess', _75 => _75.endTime]), () => ( getCurrentUnixTimestamp()));
7311
7627
  internalData = { metrics: { end: endTime } };
7312
7628
  } else {
7313
7629
  endTime = this.loggedEndTime;
@@ -7358,8 +7674,8 @@ var SpanImpl = (_class11 = class _SpanImpl {
7358
7674
  const args = this.parentComputeObjectMetadataArgs;
7359
7675
  switch (this.parentObjectType) {
7360
7676
  case 2 /* PROJECT_LOGS */: {
7361
- const projectID = _optionalChain([args, 'optionalAccess', _80 => _80.project_id]) || this.parentObjectId.getSync().value;
7362
- const projectName = _optionalChain([args, 'optionalAccess', _81 => _81.project_name]);
7677
+ const projectID = _optionalChain([args, 'optionalAccess', _76 => _76.project_id]) || this.parentObjectId.getSync().value;
7678
+ const projectName = _optionalChain([args, 'optionalAccess', _77 => _77.project_name]);
7363
7679
  if (projectID) {
7364
7680
  return `${baseUrl}/object?object_type=project_logs&object_id=${projectID}&id=${this._id}`;
7365
7681
  } else if (projectName) {
@@ -7369,7 +7685,7 @@ var SpanImpl = (_class11 = class _SpanImpl {
7369
7685
  }
7370
7686
  }
7371
7687
  case 1 /* EXPERIMENT */: {
7372
- const expID = _optionalChain([args, 'optionalAccess', _82 => _82.experiment_id]) || _optionalChain([this, 'access', _83 => _83.parentObjectId, 'optionalAccess', _84 => _84.getSync, 'call', _85 => _85(), 'optionalAccess', _86 => _86.value]);
7688
+ const expID = _optionalChain([args, 'optionalAccess', _78 => _78.experiment_id]) || _optionalChain([this, 'access', _79 => _79.parentObjectId, 'optionalAccess', _80 => _80.getSync, 'call', _81 => _81(), 'optionalAccess', _82 => _82.value]);
7373
7689
  if (!expID) {
7374
7690
  return getErrPermlink("provide-experiment-id");
7375
7691
  } else {
@@ -7459,13 +7775,13 @@ var Dataset2 = (_class12 = class extends ObjectFetcher {
7459
7775
  )
7460
7776
  ),
7461
7777
  _internal_btql
7462
- );_class12.prototype.__init52.call(this);_class12.prototype.__init53.call(this);;
7778
+ );_class12.prototype.__init53.call(this);_class12.prototype.__init54.call(this);;
7463
7779
  this.state = state;
7464
7780
  this.lazyMetadata = lazyMetadata;
7465
7781
  }
7466
7782
 
7467
- __init52() {this.__braintrust_dataset_marker = true}
7468
- __init53() {this.newRecords = 0}
7783
+ __init53() {this.__braintrust_dataset_marker = true}
7784
+ __init54() {this.newRecords = 0}
7469
7785
  get id() {
7470
7786
  return (async () => {
7471
7787
  return (await this.lazyMetadata.get()).dataset.id;
@@ -7819,14 +8135,14 @@ function renderPromptParams(params, args, options = {}) {
7819
8135
  return params;
7820
8136
  }
7821
8137
  var Prompt2 = (_class13 = class _Prompt {
7822
- constructor(metadata, defaults, noTrace) {;_class13.prototype.__init54.call(this);_class13.prototype.__init55.call(this);
8138
+ constructor(metadata, defaults, noTrace) {;_class13.prototype.__init55.call(this);_class13.prototype.__init56.call(this);
7823
8139
  this.metadata = metadata;
7824
8140
  this.defaults = defaults;
7825
8141
  this.noTrace = noTrace;
7826
8142
  }
7827
8143
 
7828
- __init54() {this.hasParsedPromptData = false}
7829
- __init55() {this.__braintrust_prompt_marker = true}
8144
+ __init55() {this.hasParsedPromptData = false}
8145
+ __init56() {this.__braintrust_prompt_marker = true}
7830
8146
  get id() {
7831
8147
  return this.metadata.id;
7832
8148
  }
@@ -7840,16 +8156,16 @@ var Prompt2 = (_class13 = class _Prompt {
7840
8156
  return "slug" in this.metadata ? this.metadata.slug : this.metadata.id;
7841
8157
  }
7842
8158
  get prompt() {
7843
- return _optionalChain([this, 'access', _87 => _87.getParsedPromptData, 'call', _88 => _88(), 'optionalAccess', _89 => _89.prompt]);
8159
+ return _optionalChain([this, 'access', _83 => _83.getParsedPromptData, 'call', _84 => _84(), 'optionalAccess', _85 => _85.prompt]);
7844
8160
  }
7845
8161
  get version() {
7846
8162
  return this.metadata[TRANSACTION_ID_FIELD];
7847
8163
  }
7848
8164
  get options() {
7849
- return _optionalChain([this, 'access', _90 => _90.getParsedPromptData, 'call', _91 => _91(), 'optionalAccess', _92 => _92.options]) || {};
8165
+ return _optionalChain([this, 'access', _86 => _86.getParsedPromptData, 'call', _87 => _87(), 'optionalAccess', _88 => _88.options]) || {};
7850
8166
  }
7851
8167
  get templateFormat() {
7852
- return _optionalChain([this, 'access', _93 => _93.getParsedPromptData, 'call', _94 => _94(), 'optionalAccess', _95 => _95.template_format]);
8168
+ return _optionalChain([this, 'access', _89 => _89.getParsedPromptData, 'call', _90 => _90(), 'optionalAccess', _91 => _91.template_format]);
7853
8169
  }
7854
8170
  get promptData() {
7855
8171
  return this.getParsedPromptData();
@@ -8009,7 +8325,7 @@ var Prompt2 = (_class13 = class _Prompt {
8009
8325
  return {
8010
8326
  type: "chat",
8011
8327
  messages,
8012
- ..._optionalChain([prompt, 'access', _96 => _96.tools, 'optionalAccess', _97 => _97.trim, 'call', _98 => _98()]) ? {
8328
+ ..._optionalChain([prompt, 'access', _92 => _92.tools, 'optionalAccess', _93 => _93.trim, 'call', _94 => _94()]) ? {
8013
8329
  tools: render(prompt.tools)
8014
8330
  } : void 0
8015
8331
  };
@@ -8054,18 +8370,67 @@ var Prompt2 = (_class13 = class _Prompt {
8054
8370
  );
8055
8371
  }
8056
8372
  }, _class13);
8057
- var TEST_API_KEY = "___TEST_API_KEY__THIS_IS_NOT_REAL___";
8058
-
8059
- // src/node.ts
8060
- var _util = require('util');
8061
- var _zlib = require('zlib'); var zlib = _interopRequireWildcard(_zlib);
8062
- function configureNode() {
8063
- isomorph_default.getRepoInfo = getRepoInfo;
8064
- isomorph_default.getPastNAncestors = getPastNAncestors;
8065
- isomorph_default.getEnv = (name) => process.env[name];
8066
- isomorph_default.getCallerLocation = getCallerLocation;
8067
- isomorph_default.newAsyncLocalStorage = () => new (0, _async_hooks.AsyncLocalStorage)();
8068
- isomorph_default.processOn = (event, handler) => {
8373
+ var RemoteEvalParameters = (_class14 = class {
8374
+ constructor(metadata) {;_class14.prototype.__init57.call(this);
8375
+ this.metadata = metadata;
8376
+ }
8377
+ __init57() {this.__braintrust_parameters_marker = true}
8378
+ get id() {
8379
+ return this.metadata.id;
8380
+ }
8381
+ get projectId() {
8382
+ return this.metadata.project_id;
8383
+ }
8384
+ get name() {
8385
+ return this.metadata.name;
8386
+ }
8387
+ get slug() {
8388
+ return this.metadata.slug;
8389
+ }
8390
+ get version() {
8391
+ return this.metadata[TRANSACTION_ID_FIELD];
8392
+ }
8393
+ get schema() {
8394
+ return this.metadata.function_data.__schema;
8395
+ }
8396
+ get data() {
8397
+ return _nullishCoalesce(this.metadata.function_data.data, () => ( {}));
8398
+ }
8399
+ validate(data) {
8400
+ if (typeof data !== "object" || data === null) {
8401
+ return false;
8402
+ }
8403
+ const schemaProps = this.schema.properties;
8404
+ if (typeof schemaProps !== "object" || schemaProps === null) {
8405
+ return true;
8406
+ }
8407
+ for (const key of Object.keys(schemaProps)) {
8408
+ if (!(key in data)) {
8409
+ const required = Array.isArray(this.schema.required) ? this.schema.required : [];
8410
+ if (required.includes(key)) {
8411
+ return false;
8412
+ }
8413
+ }
8414
+ }
8415
+ return true;
8416
+ }
8417
+ static isParameters(x) {
8418
+ return typeof x === "object" && x !== null && "__braintrust_parameters_marker" in x && // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
8419
+ x.__braintrust_parameters_marker === true;
8420
+ }
8421
+ }, _class14);
8422
+ var TEST_API_KEY = "___TEST_API_KEY__THIS_IS_NOT_REAL___";
8423
+
8424
+ // src/node.ts
8425
+ var _util = require('util');
8426
+ var _zlib = require('zlib'); var zlib = _interopRequireWildcard(_zlib);
8427
+ function configureNode() {
8428
+ isomorph_default.getRepoInfo = getRepoInfo;
8429
+ isomorph_default.getPastNAncestors = getPastNAncestors;
8430
+ isomorph_default.getEnv = (name) => process.env[name];
8431
+ isomorph_default.getCallerLocation = getCallerLocation;
8432
+ isomorph_default.newAsyncLocalStorage = () => new (0, _async_hooks.AsyncLocalStorage)();
8433
+ isomorph_default.processOn = (event, handler) => {
8069
8434
  process.on(event, handler);
8070
8435
  };
8071
8436
  isomorph_default.basename = path.basename;
@@ -9133,6 +9498,85 @@ function waterfall(tasks, callback) {
9133
9498
  }
9134
9499
  var waterfall$1 = awaitify(waterfall);
9135
9500
 
9501
+ // src/functions/invoke.ts
9502
+ async function invoke(args) {
9503
+ const {
9504
+ orgName,
9505
+ apiKey,
9506
+ appUrl,
9507
+ forceLogin,
9508
+ fetch: fetch2,
9509
+ input,
9510
+ messages,
9511
+ parent: parentArg,
9512
+ metadata,
9513
+ tags,
9514
+ state: stateArg,
9515
+ stream,
9516
+ mode,
9517
+ schema,
9518
+ strict,
9519
+ projectId,
9520
+ ...functionIdArgs
9521
+ } = args;
9522
+ const state = _nullishCoalesce(stateArg, () => ( _internalGetGlobalState()));
9523
+ await state.login({
9524
+ orgName,
9525
+ apiKey,
9526
+ appUrl,
9527
+ forceLogin,
9528
+ fetch: fetch2
9529
+ });
9530
+ const parent = parentArg ? typeof parentArg === "string" ? parentArg : await parentArg.export() : await getSpanParentObject().export();
9531
+ const functionId = FunctionId.safeParse({
9532
+ function_id: functionIdArgs.function_id,
9533
+ project_name: functionIdArgs.projectName,
9534
+ slug: functionIdArgs.slug,
9535
+ global_function: functionIdArgs.globalFunction,
9536
+ function_type: functionIdArgs.functionType,
9537
+ prompt_session_id: functionIdArgs.promptSessionId,
9538
+ prompt_session_function_id: functionIdArgs.promptSessionFunctionId,
9539
+ version: functionIdArgs.version
9540
+ });
9541
+ if (!functionId.success) {
9542
+ throw new Error(
9543
+ `Invalid function ID arguments: ${functionId.error.message}`
9544
+ );
9545
+ }
9546
+ const request = {
9547
+ ...functionId.data,
9548
+ input,
9549
+ messages,
9550
+ parent,
9551
+ metadata,
9552
+ tags,
9553
+ stream,
9554
+ mode,
9555
+ strict
9556
+ };
9557
+ const headers = {
9558
+ Accept: stream ? "text/event-stream" : "application/json"
9559
+ };
9560
+ if (projectId) {
9561
+ headers["x-bt-project-id"] = projectId;
9562
+ }
9563
+ if (orgName) {
9564
+ headers["x-bt-org-name"] = orgName;
9565
+ }
9566
+ const resp = await state.proxyConn().post(`function/invoke`, request, {
9567
+ headers
9568
+ });
9569
+ if (stream) {
9570
+ if (!resp.body) {
9571
+ throw new Error("Received empty stream body");
9572
+ }
9573
+ return new BraintrustStream(resp.body);
9574
+ } else {
9575
+ const data = await resp.json();
9576
+ return schema ? schema.parse(data) : data;
9577
+ }
9578
+ }
9579
+
9136
9580
  // src/trace.ts
9137
9581
  var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
9138
9582
  constructor(objectType, _objectId, rootSpanId, _state, spanTypeFilter) {
@@ -9188,11 +9632,11 @@ var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
9188
9632
  return this._state;
9189
9633
  }
9190
9634
  };
9191
- var CachedSpanFetcher = (_class14 = class {
9192
- __init56() {this.spanCache = /* @__PURE__ */ new Map()}
9193
- __init57() {this.allFetched = false}
9635
+ var CachedSpanFetcher = (_class15 = class {
9636
+ __init58() {this.spanCache = /* @__PURE__ */ new Map()}
9637
+ __init59() {this.allFetched = false}
9194
9638
 
9195
- constructor(objectTypeOrFetchFn, objectId, rootSpanId, getState) {;_class14.prototype.__init56.call(this);_class14.prototype.__init57.call(this);
9639
+ constructor(objectTypeOrFetchFn, objectId, rootSpanId, getState) {;_class15.prototype.__init58.call(this);_class15.prototype.__init59.call(this);
9196
9640
  if (typeof objectTypeOrFetchFn === "function") {
9197
9641
  this.fetchFn = objectTypeOrFetchFn;
9198
9642
  } else {
@@ -9207,7 +9651,7 @@ var CachedSpanFetcher = (_class14 = class {
9207
9651
  spanType
9208
9652
  );
9209
9653
  const rows = await fetcher.fetchedData();
9210
- return rows.filter((row) => _optionalChain([row, 'access', _99 => _99.span_attributes, 'optionalAccess', _100 => _100.purpose]) !== "scorer").map((row) => ({
9654
+ return rows.filter((row) => _optionalChain([row, 'access', _95 => _95.span_attributes, 'optionalAccess', _96 => _96.purpose]) !== "scorer").map((row) => ({
9211
9655
  input: row.input,
9212
9656
  output: row.output,
9213
9657
  metadata: row.metadata,
@@ -9241,7 +9685,7 @@ var CachedSpanFetcher = (_class14 = class {
9241
9685
  async fetchSpans(spanType) {
9242
9686
  const spans = await this.fetchFn(spanType);
9243
9687
  for (const span of spans) {
9244
- const type = _nullishCoalesce(_optionalChain([span, 'access', _101 => _101.span_attributes, 'optionalAccess', _102 => _102.type]), () => ( ""));
9688
+ const type = _nullishCoalesce(_optionalChain([span, 'access', _97 => _97.span_attributes, 'optionalAccess', _98 => _98.type]), () => ( ""));
9245
9689
  const existing = _nullishCoalesce(this.spanCache.get(type), () => ( []));
9246
9690
  existing.push(span);
9247
9691
  this.spanCache.set(type, existing);
@@ -9258,23 +9702,24 @@ var CachedSpanFetcher = (_class14 = class {
9258
9702
  }
9259
9703
  return result;
9260
9704
  }
9261
- }, _class14);
9262
- var LocalTrace = (_class15 = class {
9705
+ }, _class15);
9706
+ var LocalTrace = (_class16 = class {
9263
9707
 
9264
9708
 
9265
9709
 
9266
9710
 
9267
9711
 
9268
- __init58() {this.spansFlushed = false}
9269
- __init59() {this.spansFlushPromise = null}
9712
+ __init60() {this.spansFlushed = false}
9713
+ __init61() {this.spansFlushPromise = null}
9270
9714
 
9715
+ __init62() {this.threadCache = /* @__PURE__ */ new Map()}
9271
9716
  constructor({
9272
9717
  objectType,
9273
9718
  objectId,
9274
9719
  rootSpanId,
9275
9720
  ensureSpansFlushed,
9276
9721
  state
9277
- }) {;_class15.prototype.__init58.call(this);_class15.prototype.__init59.call(this);
9722
+ }) {;_class16.prototype.__init60.call(this);_class16.prototype.__init61.call(this);_class16.prototype.__init62.call(this);
9278
9723
  this.objectType = objectType;
9279
9724
  this.objectId = objectId;
9280
9725
  this.rootSpanId = rootSpanId;
@@ -9320,11 +9765,11 @@ var LocalTrace = (_class15 = class {
9320
9765
  const cachedSpans = this.state.spanCache.getByRootSpanId(this.rootSpanId);
9321
9766
  if (cachedSpans && cachedSpans.length > 0) {
9322
9767
  let spans = cachedSpans.filter(
9323
- (span) => _optionalChain([span, 'access', _103 => _103.span_attributes, 'optionalAccess', _104 => _104.purpose]) !== "scorer"
9768
+ (span) => _optionalChain([span, 'access', _99 => _99.span_attributes, 'optionalAccess', _100 => _100.purpose]) !== "scorer"
9324
9769
  );
9325
9770
  if (spanType && spanType.length > 0) {
9326
9771
  spans = spans.filter(
9327
- (span) => spanType.includes(_nullishCoalesce(_optionalChain([span, 'access', _105 => _105.span_attributes, 'optionalAccess', _106 => _106.type]), () => ( "")))
9772
+ (span) => spanType.includes(_nullishCoalesce(_optionalChain([span, 'access', _101 => _101.span_attributes, 'optionalAccess', _102 => _102.type]), () => ( "")))
9328
9773
  );
9329
9774
  }
9330
9775
  return spans.map((span) => ({
@@ -9338,6 +9783,36 @@ var LocalTrace = (_class15 = class {
9338
9783
  }
9339
9784
  return this.cachedFetcher.getSpans({ spanType });
9340
9785
  }
9786
+ /**
9787
+ * Get the thread (preprocessed messages) for this trace.
9788
+ * Calls the API with the project_default preprocessor (which falls back to "thread").
9789
+ */
9790
+ async getThread(options) {
9791
+ const cacheKey = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _103 => _103.preprocessor]), () => ( "project_default"));
9792
+ if (!this.threadCache.has(cacheKey)) {
9793
+ const promise = this.fetchThread(options);
9794
+ this.threadCache.set(cacheKey, promise);
9795
+ }
9796
+ return this.threadCache.get(cacheKey);
9797
+ }
9798
+ async fetchThread(options) {
9799
+ await this.ensureSpansReady();
9800
+ await this.state.login({});
9801
+ const result = await invoke({
9802
+ globalFunction: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _104 => _104.preprocessor]), () => ( "project_default")),
9803
+ functionType: "preprocessor",
9804
+ input: {
9805
+ trace_ref: {
9806
+ object_type: this.objectType,
9807
+ object_id: this.objectId,
9808
+ root_span_id: this.rootSpanId
9809
+ }
9810
+ },
9811
+ mode: "json",
9812
+ state: this.state
9813
+ });
9814
+ return Array.isArray(result) ? result : [];
9815
+ }
9341
9816
  async ensureSpansReady() {
9342
9817
  if (this.spansFlushed || !this.ensureSpansFlushed) {
9343
9818
  return;
@@ -9355,7 +9830,7 @@ var LocalTrace = (_class15 = class {
9355
9830
  }
9356
9831
  await this.spansFlushPromise;
9357
9832
  }
9358
- }, _class15);
9833
+ }, _class16);
9359
9834
 
9360
9835
  // src/reporters/progress.ts
9361
9836
  var SimpleProgressReporter = class {
@@ -9372,662 +9847,385 @@ var SimpleProgressReporter = class {
9372
9847
 
9373
9848
  // src/eval-parameters.ts
9374
9849
 
9850
+ var _ajv = require('ajv'); var _ajv2 = _interopRequireDefault(_ajv);
9375
9851
 
9376
- // src/framework2.ts
9852
+ // src/prompt-schemas.ts
9377
9853
 
9378
- var currentFilename = typeof __filename !== "undefined" ? __filename : "unknown";
9379
- var ProjectBuilder = class {
9380
- create(opts) {
9381
- return new Project2(opts);
9854
+ var promptContentsSchema = _v3.z.union([
9855
+ _v3.z.object({
9856
+ prompt: _v3.z.string()
9857
+ }),
9858
+ _v3.z.object({
9859
+ messages: _v3.z.array(ChatCompletionMessageParam)
9860
+ })
9861
+ ]);
9862
+ var promptDefinitionSchema = promptContentsSchema.and(
9863
+ _v3.z.object({
9864
+ model: _v3.z.string(),
9865
+ params: ModelParams.optional(),
9866
+ templateFormat: _v3.z.enum(["mustache", "nunjucks", "none"]).optional()
9867
+ })
9868
+ );
9869
+ var promptDefinitionWithToolsSchema = promptDefinitionSchema.and(
9870
+ _v3.z.object({
9871
+ tools: _v3.z.array(ToolFunctionDefinition).optional()
9872
+ })
9873
+ );
9874
+ function promptDefinitionToPromptData(promptDefinition, rawTools) {
9875
+ const promptBlock = "messages" in promptDefinition ? {
9876
+ type: "chat",
9877
+ messages: promptDefinition.messages,
9878
+ tools: rawTools && rawTools.length > 0 ? JSON.stringify(rawTools) : void 0
9879
+ } : {
9880
+ type: "completion",
9881
+ content: promptDefinition.prompt
9882
+ };
9883
+ return {
9884
+ prompt: promptBlock,
9885
+ options: {
9886
+ model: promptDefinition.model,
9887
+ params: promptDefinition.params
9888
+ },
9889
+ ...promptDefinition.templateFormat ? { template_format: promptDefinition.templateFormat } : {}
9890
+ };
9891
+ }
9892
+
9893
+ // src/eval-parameters.ts
9894
+ var evalParametersSchema = _v3.z.record(
9895
+ _v3.z.string(),
9896
+ _v3.z.union([
9897
+ _v3.z.object({
9898
+ type: _v3.z.literal("prompt"),
9899
+ default: promptDefinitionWithToolsSchema.optional(),
9900
+ description: _v3.z.string().optional()
9901
+ }),
9902
+ _v3.z.instanceof(_v3.z.ZodType)
9903
+ // For Zod schemas
9904
+ ])
9905
+ );
9906
+ async function validateParameters(parameters, parameterSchema) {
9907
+ let resolvedSchema = parameterSchema;
9908
+ if (resolvedSchema instanceof Promise) {
9909
+ resolvedSchema = await resolvedSchema;
9910
+ }
9911
+ if (resolvedSchema === void 0 || resolvedSchema === null) {
9912
+ return parameters;
9913
+ }
9914
+ if (RemoteEvalParameters.isParameters(resolvedSchema)) {
9915
+ const mergedParameters = parameters && Object.keys(parameters).length > 0 ? {
9916
+ ...resolvedSchema.data,
9917
+ ...parameters
9918
+ } : resolvedSchema.data;
9919
+ return validateParametersWithJsonSchema(
9920
+ mergedParameters,
9921
+ resolvedSchema.schema
9922
+ );
9382
9923
  }
9383
- };
9384
- var projects = new ProjectBuilder();
9385
- var Project2 = (_class16 = class {
9386
-
9387
-
9388
-
9389
-
9390
-
9391
- __init60() {this._publishableCodeFunctions = []}
9392
- __init61() {this._publishablePrompts = []}
9393
- constructor(args) {;_class16.prototype.__init60.call(this);_class16.prototype.__init61.call(this);
9394
- _initializeSpanContext();
9395
- this.name = "name" in args ? args.name : void 0;
9396
- this.id = "id" in args ? args.id : void 0;
9397
- this.tools = new ToolBuilder(this);
9398
- this.prompts = new PromptBuilder(this);
9399
- this.scorers = new ScorerBuilder(this);
9924
+ return validateParametersWithZod(
9925
+ parameters,
9926
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
9927
+ resolvedSchema
9928
+ );
9929
+ }
9930
+ function validateParametersWithZod(parameters, parameterSchema) {
9931
+ return Object.fromEntries(
9932
+ Object.entries(parameterSchema).map(([name, schema]) => {
9933
+ const value = parameters[name];
9934
+ try {
9935
+ if ("type" in schema && schema.type === "prompt") {
9936
+ const promptData = value ? PromptData.parse(value) : schema.default ? promptDefinitionToPromptData(
9937
+ schema.default,
9938
+ schema.default.tools
9939
+ ) : void 0;
9940
+ if (!promptData) {
9941
+ throw new Error(`Parameter '${name}' is required`);
9942
+ }
9943
+ return [name, Prompt2.fromPromptData(name, promptData)];
9944
+ } else {
9945
+ const schemaCasted = schema;
9946
+ return [name, schemaCasted.parse(value)];
9947
+ }
9948
+ } catch (e) {
9949
+ console.error("Error validating parameter", name, e);
9950
+ throw Error(
9951
+ `Invalid parameter '${name}': ${e instanceof Error ? e.message : String(e)}`
9952
+ );
9953
+ }
9954
+ })
9955
+ );
9956
+ }
9957
+ function validateParametersWithJsonSchema(parameters, schema) {
9958
+ const ajv = new (0, _ajv2.default)({ coerceTypes: true, useDefaults: true, strict: false });
9959
+ const validate = ajv.compile(schema);
9960
+ if (!validate(parameters)) {
9961
+ const errorMessages = _optionalChain([validate, 'access', _105 => _105.errors, 'optionalAccess', _106 => _106.map, 'call', _107 => _107((err) => {
9962
+ const path2 = err.instancePath || "root";
9963
+ return `${path2}: ${err.message}`;
9964
+ }), 'access', _108 => _108.join, 'call', _109 => _109(", ")]);
9965
+ throw Error(`Invalid parameters: ${errorMessages}`);
9400
9966
  }
9401
- addPrompt(prompt) {
9402
- this._publishablePrompts.push(prompt);
9403
- if (globalThis._lazy_load) {
9404
- globalThis._evals.prompts.push(prompt);
9405
- }
9967
+ return parameters;
9968
+ }
9969
+
9970
+ // src/framework.ts
9971
+ var EvalResultWithSummary = class {
9972
+ constructor(summary, results) {
9973
+ this.summary = summary;
9974
+ this.results = results;
9406
9975
  }
9407
- addCodeFunction(fn) {
9408
- this._publishableCodeFunctions.push(fn);
9409
- if (globalThis._lazy_load) {
9410
- globalThis._evals.functions.push(fn);
9411
- }
9976
+ /**
9977
+ * @deprecated Use `summary` instead.
9978
+ */
9979
+ toString() {
9980
+ return JSON.stringify(this.summary);
9412
9981
  }
9413
- async publish() {
9414
- if (globalThis._lazy_load) {
9415
- console.warn("publish() is a no-op when running `braintrust push`.");
9416
- return;
9417
- }
9418
- await login();
9419
- const projectMap = new ProjectNameIdMap();
9420
- const functionDefinitions = [];
9421
- if (this._publishableCodeFunctions.length > 0) {
9422
- console.warn(
9423
- "Code functions cannot be published directly. Use `braintrust push` instead."
9424
- );
9425
- }
9426
- if (this._publishablePrompts.length > 0) {
9427
- for (const prompt of this._publishablePrompts) {
9428
- const functionDefinition = await prompt.toFunctionDefinition(projectMap);
9429
- functionDefinitions.push(functionDefinition);
9430
- }
9431
- }
9432
- await _internalGetGlobalState().apiConn().post_json("insert-functions", {
9433
- functions: functionDefinitions
9434
- });
9982
+ [Symbol.for("nodejs.util.inspect.custom")]() {
9983
+ return `EvalResultWithSummary(summary="...", results=[...])`;
9435
9984
  }
9436
- }, _class16);
9437
- var ToolBuilder = (_class17 = class {
9438
- constructor(project) {;_class17.prototype.__init62.call(this);
9439
- this.project = project;
9985
+ toJSON() {
9986
+ return {
9987
+ summary: this.summary,
9988
+ results: this.results
9989
+ };
9440
9990
  }
9441
- __init62() {this.taskCounter = 0}
9442
- // This type definition is just a catch all so that the implementation can be
9443
- // less specific than the two more specific declarations above.
9444
- create(opts) {
9445
- this.taskCounter++;
9446
- opts = _nullishCoalesce(opts, () => ( {}));
9447
- const { handler, name, slug, parameters, returns, ...rest } = opts;
9448
- let resolvedName = _nullishCoalesce(name, () => ( handler.name));
9449
- if (resolvedName.trim().length === 0) {
9450
- resolvedName = `Tool ${isomorph_default.basename(currentFilename)} ${this.taskCounter}`;
9451
- }
9452
- const tool = new CodeFunction(this.project, {
9453
- handler,
9454
- name: resolvedName,
9455
- slug: _nullishCoalesce(slug, () => ( slugify(resolvedName, { lower: true, strict: true }))),
9456
- type: "tool",
9457
- // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/consistent-type-assertions
9458
- parameters,
9459
- // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/consistent-type-assertions
9460
- returns,
9461
- ...rest
9462
- });
9463
- this.project.addCodeFunction(tool);
9464
- return tool;
9991
+ };
9992
+ function makeEvalName(projectName, experimentName) {
9993
+ let out = projectName;
9994
+ if (experimentName) {
9995
+ out += ` [experimentName=${experimentName}]`;
9465
9996
  }
9466
- }, _class17);
9467
- var ScorerBuilder = (_class18 = class {
9468
- constructor(project) {;_class18.prototype.__init63.call(this);
9469
- this.project = project;
9997
+ return out;
9998
+ }
9999
+ function initExperiment(state, options = {}) {
10000
+ return init({
10001
+ state,
10002
+ ...options,
10003
+ setCurrent: false
10004
+ });
10005
+ }
10006
+ function callEvaluatorData(data) {
10007
+ const dataResult = typeof data === "function" ? data() : data;
10008
+ let baseExperiment = void 0;
10009
+ if ("_type" in dataResult && dataResult._type === "BaseExperiment") {
10010
+ baseExperiment = dataResult.name;
9470
10011
  }
9471
- __init63() {this.taskCounter = 0}
9472
- create(opts) {
9473
- this.taskCounter++;
9474
- let resolvedName = opts.name;
9475
- if (!resolvedName && "handler" in opts) {
9476
- resolvedName = opts.handler.name;
10012
+ return {
10013
+ data: dataResult,
10014
+ baseExperiment
10015
+ };
10016
+ }
10017
+ function isAsyncIterable2(value) {
10018
+ return typeof value === "object" && value !== null && typeof value[Symbol.asyncIterator] === "function";
10019
+ }
10020
+ function isIterable(value) {
10021
+ return typeof value === "object" && value !== null && typeof value[Symbol.iterator] === "function";
10022
+ }
10023
+ globalThis._evals = {
10024
+ functions: [],
10025
+ prompts: [],
10026
+ parameters: [],
10027
+ evaluators: {},
10028
+ reporters: {}
10029
+ };
10030
+ function _initializeSpanContext() {
10031
+ globalThis._spanContext = { currentSpan, withCurrent, startSpan, NOOP_SPAN };
10032
+ }
10033
+ async function Eval(name, evaluator, reporterOrOpts) {
10034
+ const options = isEmpty2(reporterOrOpts) ? {} : typeof reporterOrOpts === "string" ? { reporter: reporterOrOpts } : "name" in reporterOrOpts ? { reporter: reporterOrOpts } : reporterOrOpts;
10035
+ let evalName = makeEvalName(name, evaluator.experimentName);
10036
+ if (globalThis._evals.evaluators[evalName]) {
10037
+ evalName = `${evalName}_${Object.keys(_evals).length}`;
10038
+ }
10039
+ if (globalThis._lazy_load) {
10040
+ globalThis._evals.evaluators[evalName] = {
10041
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
10042
+ evaluator: {
10043
+ evalName,
10044
+ projectName: name,
10045
+ ...evaluator
10046
+ },
10047
+ reporter: options.reporter
10048
+ };
10049
+ _initializeSpanContext();
10050
+ return new EvalResultWithSummary(
10051
+ {
10052
+ scores: {},
10053
+ metrics: {},
10054
+ projectName: "",
10055
+ experimentName: ""
10056
+ },
10057
+ []
10058
+ );
10059
+ }
10060
+ const progressReporter = _nullishCoalesce(options.progress, () => ( new SimpleProgressReporter()));
10061
+ const shouldCollectResults = _nullishCoalesce(options.returnResults, () => ( true));
10062
+ if (typeof options.reporter === "string") {
10063
+ throw new Error(
10064
+ "Must specify a reporter object, not a name. Can only specify reporter names when running 'braintrust eval'"
10065
+ );
10066
+ }
10067
+ const resolvedReporter = options.reporter || defaultReporter;
10068
+ try {
10069
+ const { data, baseExperiment: defaultBaseExperiment } = callEvaluatorData(
10070
+ evaluator.data
10071
+ );
10072
+ const experiment = options.parent || options.noSendLogs ? null : initExperiment(evaluator.state, {
10073
+ ...evaluator.projectId ? { projectId: evaluator.projectId } : { project: name },
10074
+ experiment: evaluator.experimentName,
10075
+ description: evaluator.description,
10076
+ metadata: evaluator.metadata,
10077
+ isPublic: evaluator.isPublic,
10078
+ update: evaluator.update,
10079
+ baseExperiment: _nullishCoalesce(evaluator.baseExperimentName, () => ( defaultBaseExperiment)),
10080
+ baseExperimentId: evaluator.baseExperimentId,
10081
+ gitMetadataSettings: evaluator.gitMetadataSettings,
10082
+ repoInfo: evaluator.repoInfo,
10083
+ dataset: Dataset2.isDataset(data) ? data : void 0
10084
+ });
10085
+ if (experiment && typeof process !== "undefined" && globalThis.BRAINTRUST_CONTEXT_MANAGER !== void 0) {
10086
+ await experiment._waitForId();
9477
10087
  }
9478
- if (!resolvedName || resolvedName.trim().length === 0) {
9479
- resolvedName = `Scorer ${isomorph_default.basename(currentFilename)} ${this.taskCounter}`;
10088
+ if (experiment && options.onStart) {
10089
+ const summary = await experiment.summarize({ summarizeScores: false });
10090
+ options.onStart(summary);
9480
10091
  }
9481
- const slug = _nullishCoalesce(opts.slug, () => ( slugify(resolvedName, { lower: true, strict: true })));
9482
- if ("handler" in opts) {
9483
- const scorer = new CodeFunction(this.project, {
9484
- ...opts,
9485
- name: resolvedName,
9486
- slug,
9487
- type: "scorer"
9488
- });
9489
- this.project.addCodeFunction(scorer);
9490
- } else {
9491
- const promptBlock = "messages" in opts ? {
9492
- type: "chat",
9493
- messages: opts.messages
9494
- } : {
9495
- type: "completion",
9496
- content: opts.prompt
9497
- };
9498
- const promptData = {
9499
- prompt: promptBlock,
9500
- options: {
9501
- model: opts.model,
9502
- params: opts.params
9503
- },
9504
- parser: {
9505
- type: "llm_classifier",
9506
- use_cot: opts.useCot,
9507
- choice_scores: opts.choiceScores
9508
- }
10092
+ try {
10093
+ const evalDef = {
10094
+ evalName,
10095
+ projectName: name,
10096
+ ...evaluator,
10097
+ data
9509
10098
  };
9510
- const codePrompt = new CodePrompt(
9511
- this.project,
9512
- promptData,
9513
- [],
9514
- {
9515
- ...opts,
9516
- name: resolvedName,
9517
- slug
9518
- },
9519
- "scorer"
9520
- );
9521
- this.project.addPrompt(codePrompt);
10099
+ const enableCache = _nullishCoalesce(options.enableCache, () => ( true));
10100
+ let ret;
10101
+ if (options.parent) {
10102
+ ret = await withParent(
10103
+ options.parent,
10104
+ () => runEvaluator(
10105
+ null,
10106
+ evalDef,
10107
+ progressReporter,
10108
+ [],
10109
+ options.stream,
10110
+ options.parameters,
10111
+ shouldCollectResults,
10112
+ enableCache
10113
+ ),
10114
+ evaluator.state
10115
+ );
10116
+ } else {
10117
+ ret = await runEvaluator(
10118
+ experiment,
10119
+ evalDef,
10120
+ progressReporter,
10121
+ [],
10122
+ options.stream,
10123
+ options.parameters,
10124
+ shouldCollectResults,
10125
+ enableCache
10126
+ );
10127
+ }
10128
+ progressReporter.stop();
10129
+ resolvedReporter.reportEval(evalDef, ret, {
10130
+ verbose: true,
10131
+ jsonl: false
10132
+ });
10133
+ return ret;
10134
+ } finally {
10135
+ if (experiment) {
10136
+ await experiment.flush().catch(console.error);
10137
+ } else if (options.parent) {
10138
+ await flush().catch(console.error);
10139
+ }
9522
10140
  }
10141
+ } finally {
10142
+ progressReporter.stop();
9523
10143
  }
9524
- }, _class18);
9525
- var CodeFunction = class {
9526
- constructor(project, opts) {
9527
- this.project = project;
9528
- this.handler = opts.handler;
9529
- this.name = opts.name;
9530
- this.slug = opts.slug;
9531
- this.description = opts.description;
9532
- this.type = opts.type;
9533
- this.ifExists = opts.ifExists;
9534
- this.metadata = opts.metadata;
9535
- this.parameters = opts.parameters;
9536
- this.returns = opts.returns;
9537
- if (this.returns && !this.parameters) {
9538
- throw new Error("parameters are required if return type is defined");
9539
- }
10144
+ }
10145
+ function serializeJSONWithPlainString(v) {
10146
+ if (typeof v === "string") {
10147
+ return v;
10148
+ } else {
10149
+ return JSON.stringify(v);
9540
10150
  }
9541
-
9542
-
9543
-
9544
-
9545
-
9546
-
9547
-
9548
-
9549
-
9550
- key() {
9551
- return JSON.stringify([
9552
- _nullishCoalesce(this.project.id, () => ( "")),
9553
- _nullishCoalesce(this.project.name, () => ( "")),
9554
- this.slug
9555
- ]);
10151
+ }
10152
+ function evaluateFilter(object, filter2) {
10153
+ const { path: path2, pattern } = filter2;
10154
+ const key = path2.reduce(
10155
+ (acc, p) => typeof acc === "object" && acc !== null ? (
10156
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
10157
+ acc[p]
10158
+ ) : void 0,
10159
+ object
10160
+ );
10161
+ if (key === void 0) {
10162
+ return false;
9556
10163
  }
9557
- };
9558
- var CodePrompt = class {
9559
-
9560
-
9561
-
9562
-
9563
-
9564
-
9565
-
9566
-
9567
-
9568
-
9569
- constructor(project, prompt, toolFunctions, opts, functionType) {
9570
- this.project = project;
9571
- this.name = opts.name;
9572
- this.slug = opts.slug;
9573
- this.prompt = prompt;
9574
- this.toolFunctions = toolFunctions;
9575
- this.ifExists = opts.ifExists;
9576
- this.description = opts.description;
9577
- this.id = opts.id;
9578
- this.functionType = functionType;
9579
- this.metadata = opts.metadata;
9580
- }
9581
- async toFunctionDefinition(projectNameToId) {
9582
- const prompt_data = {
9583
- ...this.prompt
9584
- };
9585
- if (this.toolFunctions.length > 0) {
9586
- const resolvableToolFunctions = await Promise.all(
9587
- this.toolFunctions.map(async (fn) => {
9588
- if ("slug" in fn) {
9589
- return {
9590
- type: "slug",
9591
- project_id: await projectNameToId.resolve(fn.project),
9592
- slug: fn.slug
9593
- };
9594
- } else {
9595
- return fn;
9596
- }
9597
- })
9598
- );
9599
- prompt_data.tool_functions = // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
9600
- resolvableToolFunctions;
9601
- }
9602
- return {
9603
- project_id: await projectNameToId.resolve(this.project),
9604
- name: this.name,
9605
- slug: this.slug,
9606
- description: _nullishCoalesce(this.description, () => ( "")),
9607
- function_data: {
9608
- type: "prompt"
9609
- },
9610
- function_type: this.functionType,
9611
- prompt_data,
9612
- if_exists: this.ifExists,
9613
- metadata: this.metadata
9614
- };
9615
- }
9616
- };
9617
- var promptContentsSchema = _v3.z.union([
9618
- _v3.z.object({
9619
- prompt: _v3.z.string()
9620
- }),
9621
- _v3.z.object({
9622
- messages: _v3.z.array(ChatCompletionMessageParam)
9623
- })
9624
- ]);
9625
- var promptDefinitionSchema = promptContentsSchema.and(
9626
- _v3.z.object({
9627
- model: _v3.z.string(),
9628
- params: ModelParams.optional(),
9629
- templateFormat: _v3.z.enum(["mustache", "nunjucks", "none"]).optional()
9630
- })
9631
- );
9632
- var promptDefinitionWithToolsSchema = promptDefinitionSchema.and(
9633
- _v3.z.object({
9634
- tools: _v3.z.array(ToolFunctionDefinition).optional()
9635
- })
9636
- );
9637
- var PromptBuilder = class {
9638
- constructor(project) {
9639
- this.project = project;
9640
- }
9641
- create(opts) {
9642
- const toolFunctions = [];
9643
- const rawTools = [];
9644
- for (const tool of _nullishCoalesce(opts.tools, () => ( []))) {
9645
- if (tool instanceof CodeFunction) {
9646
- toolFunctions.push(tool);
9647
- } else if ("type" in tool && !("function" in tool)) {
9648
- toolFunctions.push(tool);
9649
- } else {
9650
- rawTools.push(tool);
9651
- }
9652
- }
9653
- const slug = _nullishCoalesce(opts.slug, () => ( slugify(opts.name, { lower: true, strict: true })));
9654
- const promptData = promptDefinitionToPromptData(opts, rawTools);
9655
- const promptRow = {
9656
- id: opts.id,
9657
- _xact_id: opts.version ? loadPrettyXact(opts.version) : void 0,
9658
- name: opts.name,
9659
- slug,
9660
- prompt_data: promptData,
9661
- ...this.project.id !== void 0 ? { project_id: this.project.id } : {}
9662
- };
9663
- const prompt = new Prompt2(
9664
- promptRow,
9665
- {},
9666
- // It doesn't make sense to specify defaults here.
9667
- _nullishCoalesce(opts.noTrace, () => ( false))
9668
- );
9669
- const codePrompt = new CodePrompt(this.project, promptData, toolFunctions, {
9670
- ...opts,
9671
- slug
9672
- });
9673
- this.project.addPrompt(codePrompt);
9674
- return prompt;
9675
- }
9676
- };
9677
- function promptDefinitionToPromptData(promptDefinition, rawTools) {
9678
- const promptBlock = "messages" in promptDefinition ? {
9679
- type: "chat",
9680
- messages: promptDefinition.messages,
9681
- tools: rawTools && rawTools.length > 0 ? JSON.stringify(rawTools) : void 0
9682
- } : {
9683
- type: "completion",
9684
- content: promptDefinition.prompt
9685
- };
9686
- return {
9687
- prompt: promptBlock,
9688
- options: {
9689
- model: promptDefinition.model,
9690
- params: promptDefinition.params
9691
- },
9692
- ...promptDefinition.templateFormat ? { template_format: promptDefinition.templateFormat } : {}
9693
- };
10164
+ return pattern.test(serializeJSONWithPlainString(key));
9694
10165
  }
9695
- var ProjectNameIdMap = (_class19 = class {constructor() { _class19.prototype.__init64.call(this);_class19.prototype.__init65.call(this); }
9696
- __init64() {this.nameToId = {}}
9697
- __init65() {this.idToName = {}}
9698
- async getId(projectName) {
9699
- if (!(projectName in this.nameToId)) {
9700
- const response = await _internalGetGlobalState().appConn().post_json("api/project/register", {
9701
- project_name: projectName
9702
- });
9703
- const result = _v3.z.object({
9704
- project: Project
9705
- }).parse(response);
9706
- const projectId = result.project.id;
9707
- this.nameToId[projectName] = projectId;
9708
- this.idToName[projectId] = projectName;
9709
- }
9710
- return this.nameToId[projectName];
10166
+ function scorerName(scorer, scorer_idx) {
10167
+ return scorer.name || `scorer_${scorer_idx}`;
10168
+ }
10169
+ async function runEvaluator(experiment, evaluator, progressReporter, filters, stream, parameters, collectResults = true, enableCache = true) {
10170
+ return await runEvaluatorInternal(
10171
+ experiment,
10172
+ evaluator,
10173
+ progressReporter,
10174
+ filters,
10175
+ stream,
10176
+ parameters,
10177
+ collectResults,
10178
+ enableCache
10179
+ );
10180
+ }
10181
+ async function runEvaluatorInternal(experiment, evaluator, progressReporter, filters, stream, parameters, collectResults, enableCache) {
10182
+ if (enableCache) {
10183
+ _optionalChain([(_nullishCoalesce(evaluator.state, () => ( _internalGetGlobalState()))), 'optionalAccess', _110 => _110.spanCache, 'optionalAccess', _111 => _111.start, 'call', _112 => _112()]);
9711
10184
  }
9712
- async getName(projectId) {
9713
- if (!(projectId in this.idToName)) {
9714
- const response = await _internalGetGlobalState().appConn().post_json("api/project/get", {
9715
- id: projectId
9716
- });
9717
- const result = _v3.z.array(Project).nonempty().parse(response);
9718
- const projectName = result[0].name;
9719
- this.idToName[projectId] = projectName;
9720
- this.nameToId[projectName] = projectId;
10185
+ try {
10186
+ if (typeof evaluator.data === "string") {
10187
+ throw new Error("Unimplemented: string data paths");
9721
10188
  }
9722
- return this.idToName[projectId];
9723
- }
9724
- async resolve(project) {
9725
- if (project.id) {
9726
- return project.id;
10189
+ let dataResult = typeof evaluator.data === "function" ? evaluator.data() : evaluator.data;
10190
+ parameters = await validateParameters(
10191
+ _nullishCoalesce(parameters, () => ( {})),
10192
+ evaluator.parameters
10193
+ );
10194
+ if ("_type" in dataResult) {
10195
+ if (dataResult._type !== "BaseExperiment") {
10196
+ throw new Error("Invalid _type");
10197
+ }
10198
+ if (!experiment) {
10199
+ throw new Error(
10200
+ "Cannot use BaseExperiment() without connecting to Braintrust (you most likely set --no-send-logs)"
10201
+ );
10202
+ }
10203
+ let name = dataResult.name;
10204
+ if (isEmpty2(name)) {
10205
+ const baseExperiment = await experiment.fetchBaseExperiment();
10206
+ if (!baseExperiment) {
10207
+ throw new Error("BaseExperiment() failed to fetch base experiment");
10208
+ }
10209
+ name = baseExperiment.name;
10210
+ }
10211
+ dataResult = initExperiment(evaluator.state, {
10212
+ ...evaluator.projectId ? { projectId: evaluator.projectId } : { project: evaluator.projectName },
10213
+ experiment: name,
10214
+ open: true
10215
+ }).asDataset();
9727
10216
  }
9728
- return this.getId(project.name);
9729
- }
9730
- }, _class19);
9731
-
9732
- // src/eval-parameters.ts
9733
- var evalParametersSchema = _v3.z.record(
9734
- _v3.z.string(),
9735
- _v3.z.union([
9736
- _v3.z.object({
9737
- type: _v3.z.literal("prompt"),
9738
- default: promptDefinitionWithToolsSchema.optional(),
9739
- description: _v3.z.string().optional()
9740
- }),
9741
- _v3.z.instanceof(_v3.z.ZodType)
9742
- // For Zod schemas
9743
- ])
9744
- );
9745
- function validateParameters(parameters, parameterSchema) {
9746
- return Object.fromEntries(
9747
- Object.entries(parameterSchema).map(([name, schema]) => {
9748
- const value = parameters[name];
9749
- try {
9750
- if ("type" in schema && schema.type === "prompt") {
9751
- const promptData = value ? PromptData.parse(value) : schema.default ? promptDefinitionToPromptData(
9752
- schema.default,
9753
- schema.default.tools
9754
- ) : void 0;
9755
- if (!promptData) {
9756
- throw new Error(`Parameter '${name}' is required`);
10217
+ const resolvedDataResult = dataResult instanceof Promise ? await dataResult : dataResult;
10218
+ const dataIterable = (() => {
10219
+ if (isAsyncIterable2(resolvedDataResult)) {
10220
+ return resolvedDataResult;
10221
+ }
10222
+ if (Array.isArray(resolvedDataResult) || isIterable(resolvedDataResult)) {
10223
+ const iterable = resolvedDataResult;
10224
+ return (async function* () {
10225
+ for (const datum of iterable) {
10226
+ yield datum;
9757
10227
  }
9758
- return [name, Prompt2.fromPromptData(name, promptData)];
9759
- } else {
9760
- const schemaCasted = schema;
9761
- return [name, schemaCasted.parse(value)];
9762
- }
9763
- } catch (e) {
9764
- console.error("Error validating parameter", name, e);
9765
- throw Error(
9766
- `Invalid parameter '${name}': ${e instanceof Error ? e.message : String(e)}`
9767
- );
9768
- }
9769
- })
9770
- );
9771
- }
9772
-
9773
- // src/framework.ts
9774
- var EvalResultWithSummary = class {
9775
- constructor(summary, results) {
9776
- this.summary = summary;
9777
- this.results = results;
9778
- }
9779
- /**
9780
- * @deprecated Use `summary` instead.
9781
- */
9782
- toString() {
9783
- return JSON.stringify(this.summary);
9784
- }
9785
- [Symbol.for("nodejs.util.inspect.custom")]() {
9786
- return `EvalResultWithSummary(summary="...", results=[...])`;
9787
- }
9788
- toJSON() {
9789
- return {
9790
- summary: this.summary,
9791
- results: this.results
9792
- };
9793
- }
9794
- };
9795
- function makeEvalName(projectName, experimentName) {
9796
- let out = projectName;
9797
- if (experimentName) {
9798
- out += ` [experimentName=${experimentName}]`;
9799
- }
9800
- return out;
9801
- }
9802
- function initExperiment(state, options = {}) {
9803
- return init({
9804
- state,
9805
- ...options,
9806
- setCurrent: false
9807
- });
9808
- }
9809
- function callEvaluatorData(data) {
9810
- const dataResult = typeof data === "function" ? data() : data;
9811
- let baseExperiment = void 0;
9812
- if ("_type" in dataResult && dataResult._type === "BaseExperiment") {
9813
- baseExperiment = dataResult.name;
9814
- }
9815
- return {
9816
- data: dataResult,
9817
- baseExperiment
9818
- };
9819
- }
9820
- function isAsyncIterable2(value) {
9821
- return typeof value === "object" && value !== null && typeof value[Symbol.asyncIterator] === "function";
9822
- }
9823
- function isIterable(value) {
9824
- return typeof value === "object" && value !== null && typeof value[Symbol.iterator] === "function";
9825
- }
9826
- globalThis._evals = {
9827
- functions: [],
9828
- prompts: [],
9829
- evaluators: {},
9830
- reporters: {}
9831
- };
9832
- function _initializeSpanContext() {
9833
- globalThis._spanContext = { currentSpan, withCurrent, startSpan, NOOP_SPAN };
9834
- }
9835
- async function Eval(name, evaluator, reporterOrOpts) {
9836
- const options = isEmpty2(reporterOrOpts) ? {} : typeof reporterOrOpts === "string" ? { reporter: reporterOrOpts } : "name" in reporterOrOpts ? { reporter: reporterOrOpts } : reporterOrOpts;
9837
- let evalName = makeEvalName(name, evaluator.experimentName);
9838
- if (globalThis._evals.evaluators[evalName]) {
9839
- evalName = `${evalName}_${Object.keys(_evals).length}`;
9840
- }
9841
- if (globalThis._lazy_load) {
9842
- globalThis._evals.evaluators[evalName] = {
9843
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
9844
- evaluator: {
9845
- evalName,
9846
- projectName: name,
9847
- ...evaluator
9848
- },
9849
- reporter: options.reporter
9850
- };
9851
- _initializeSpanContext();
9852
- return new EvalResultWithSummary(
9853
- {
9854
- scores: {},
9855
- metrics: {},
9856
- projectName: "",
9857
- experimentName: ""
9858
- },
9859
- []
9860
- );
9861
- }
9862
- const progressReporter = _nullishCoalesce(options.progress, () => ( new SimpleProgressReporter()));
9863
- const shouldCollectResults = _nullishCoalesce(options.returnResults, () => ( true));
9864
- if (typeof options.reporter === "string") {
9865
- throw new Error(
9866
- "Must specify a reporter object, not a name. Can only specify reporter names when running 'braintrust eval'"
9867
- );
9868
- }
9869
- const resolvedReporter = options.reporter || defaultReporter;
9870
- try {
9871
- const { data, baseExperiment: defaultBaseExperiment } = callEvaluatorData(
9872
- evaluator.data
9873
- );
9874
- const experiment = options.parent || options.noSendLogs ? null : initExperiment(evaluator.state, {
9875
- ...evaluator.projectId ? { projectId: evaluator.projectId } : { project: name },
9876
- experiment: evaluator.experimentName,
9877
- description: evaluator.description,
9878
- metadata: evaluator.metadata,
9879
- isPublic: evaluator.isPublic,
9880
- update: evaluator.update,
9881
- baseExperiment: _nullishCoalesce(evaluator.baseExperimentName, () => ( defaultBaseExperiment)),
9882
- baseExperimentId: evaluator.baseExperimentId,
9883
- gitMetadataSettings: evaluator.gitMetadataSettings,
9884
- repoInfo: evaluator.repoInfo,
9885
- dataset: Dataset2.isDataset(data) ? data : void 0
9886
- });
9887
- if (experiment && typeof process !== "undefined" && globalThis.BRAINTRUST_CONTEXT_MANAGER !== void 0) {
9888
- await experiment._waitForId();
9889
- }
9890
- if (experiment && options.onStart) {
9891
- const summary = await experiment.summarize({ summarizeScores: false });
9892
- options.onStart(summary);
9893
- }
9894
- try {
9895
- const evalDef = {
9896
- evalName,
9897
- projectName: name,
9898
- ...evaluator,
9899
- data
9900
- };
9901
- const enableCache = _nullishCoalesce(options.enableCache, () => ( true));
9902
- let ret;
9903
- if (options.parent) {
9904
- ret = await withParent(
9905
- options.parent,
9906
- () => runEvaluator(
9907
- null,
9908
- evalDef,
9909
- progressReporter,
9910
- [],
9911
- options.stream,
9912
- options.parameters,
9913
- shouldCollectResults,
9914
- enableCache
9915
- ),
9916
- evaluator.state
9917
- );
9918
- } else {
9919
- ret = await runEvaluator(
9920
- experiment,
9921
- evalDef,
9922
- progressReporter,
9923
- [],
9924
- options.stream,
9925
- options.parameters,
9926
- shouldCollectResults,
9927
- enableCache
9928
- );
9929
- }
9930
- progressReporter.stop();
9931
- resolvedReporter.reportEval(evalDef, ret, {
9932
- verbose: true,
9933
- jsonl: false
9934
- });
9935
- return ret;
9936
- } finally {
9937
- if (experiment) {
9938
- await experiment.flush().catch(console.error);
9939
- } else if (options.parent) {
9940
- await flush().catch(console.error);
9941
- }
9942
- }
9943
- } finally {
9944
- progressReporter.stop();
9945
- }
9946
- }
9947
- function serializeJSONWithPlainString(v) {
9948
- if (typeof v === "string") {
9949
- return v;
9950
- } else {
9951
- return JSON.stringify(v);
9952
- }
9953
- }
9954
- function evaluateFilter(object, filter2) {
9955
- const { path: path2, pattern } = filter2;
9956
- const key = path2.reduce(
9957
- (acc, p) => typeof acc === "object" && acc !== null ? (
9958
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
9959
- acc[p]
9960
- ) : void 0,
9961
- object
9962
- );
9963
- if (key === void 0) {
9964
- return false;
9965
- }
9966
- return pattern.test(serializeJSONWithPlainString(key));
9967
- }
9968
- function scorerName(scorer, scorer_idx) {
9969
- return scorer.name || `scorer_${scorer_idx}`;
9970
- }
9971
- async function runEvaluator(experiment, evaluator, progressReporter, filters, stream, parameters, collectResults = true, enableCache = true) {
9972
- return await runEvaluatorInternal(
9973
- experiment,
9974
- evaluator,
9975
- progressReporter,
9976
- filters,
9977
- stream,
9978
- parameters,
9979
- collectResults,
9980
- enableCache
9981
- );
9982
- }
9983
- async function runEvaluatorInternal(experiment, evaluator, progressReporter, filters, stream, parameters, collectResults, enableCache) {
9984
- if (enableCache) {
9985
- _optionalChain([(_nullishCoalesce(evaluator.state, () => ( _internalGetGlobalState()))), 'optionalAccess', _107 => _107.spanCache, 'optionalAccess', _108 => _108.start, 'call', _109 => _109()]);
9986
- }
9987
- try {
9988
- if (typeof evaluator.data === "string") {
9989
- throw new Error("Unimplemented: string data paths");
9990
- }
9991
- let dataResult = typeof evaluator.data === "function" ? evaluator.data() : evaluator.data;
9992
- parameters = validateParameters(
9993
- _nullishCoalesce(parameters, () => ( {})),
9994
- _nullishCoalesce(evaluator.parameters, () => ( {}))
9995
- );
9996
- if ("_type" in dataResult) {
9997
- if (dataResult._type !== "BaseExperiment") {
9998
- throw new Error("Invalid _type");
9999
- }
10000
- if (!experiment) {
10001
- throw new Error(
10002
- "Cannot use BaseExperiment() without connecting to Braintrust (you most likely set --no-send-logs)"
10003
- );
10004
- }
10005
- let name = dataResult.name;
10006
- if (isEmpty2(name)) {
10007
- const baseExperiment = await experiment.fetchBaseExperiment();
10008
- if (!baseExperiment) {
10009
- throw new Error("BaseExperiment() failed to fetch base experiment");
10010
- }
10011
- name = baseExperiment.name;
10012
- }
10013
- dataResult = initExperiment(evaluator.state, {
10014
- ...evaluator.projectId ? { projectId: evaluator.projectId } : { project: evaluator.projectName },
10015
- experiment: name,
10016
- open: true
10017
- }).asDataset();
10018
- }
10019
- const resolvedDataResult = dataResult instanceof Promise ? await dataResult : dataResult;
10020
- const dataIterable = (() => {
10021
- if (isAsyncIterable2(resolvedDataResult)) {
10022
- return resolvedDataResult;
10023
- }
10024
- if (Array.isArray(resolvedDataResult) || isIterable(resolvedDataResult)) {
10025
- const iterable = resolvedDataResult;
10026
- return (async function* () {
10027
- for (const datum of iterable) {
10028
- yield datum;
10029
- }
10030
- })();
10228
+ })();
10031
10229
  }
10032
10230
  throw new Error(
10033
10231
  "Evaluator data must be an array, iterable, or async iterable"
@@ -10093,7 +10291,7 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
10093
10291
  objectType: parentComponents ? spanObjectTypeV3ToTypedString(
10094
10292
  parentComponents.data.object_type
10095
10293
  ) : "experiment",
10096
- objectId: await _asyncNullishCoalesce(await _asyncOptionalChain([parentComponents, 'optionalAccess', async _110 => _110.data, 'access', async _111 => _111.object_id]), async () => ( (experimentIdPromise ? await _asyncNullishCoalesce(await experimentIdPromise, async () => ( "")) : ""))),
10294
+ objectId: await _asyncNullishCoalesce(await _asyncOptionalChain([parentComponents, 'optionalAccess', async _113 => _113.data, 'access', async _114 => _114.object_id]), async () => ( (experimentIdPromise ? await _asyncNullishCoalesce(await experimentIdPromise, async () => ( "")) : ""))),
10097
10295
  rootSpanId: rootSpan.rootSpanId,
10098
10296
  ensureSpansFlushed,
10099
10297
  state
@@ -10119,10 +10317,10 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
10119
10317
  span,
10120
10318
  parameters: _nullishCoalesce(parameters, () => ( {})),
10121
10319
  reportProgress: (event) => {
10122
- _optionalChain([stream, 'optionalCall', _112 => _112({
10320
+ _optionalChain([stream, 'optionalCall', _115 => _115({
10123
10321
  ...event,
10124
10322
  id: rootSpan.id,
10125
- origin: _optionalChain([baseEvent, 'access', _113 => _113.event, 'optionalAccess', _114 => _114.origin]),
10323
+ origin: _optionalChain([baseEvent, 'access', _116 => _116.event, 'optionalAccess', _117 => _117.origin]),
10126
10324
  name: evaluator.evalName,
10127
10325
  object_type: "task"
10128
10326
  })]);
@@ -10150,6 +10348,9 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
10150
10348
  } else {
10151
10349
  rootSpan.log({ output, metadata, expected });
10152
10350
  }
10351
+ if (evaluator.flushBeforeScoring) {
10352
+ await rootSpan.flush();
10353
+ }
10153
10354
  const scoringArgs = {
10154
10355
  input: datum.input,
10155
10356
  expected: "expected" in datum ? datum.expected : void 0,
@@ -10283,7 +10484,7 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
10283
10484
  metadata,
10284
10485
  scores: mergedScores,
10285
10486
  error,
10286
- origin: _optionalChain([baseEvent, 'access', _115 => _115.event, 'optionalAccess', _116 => _116.origin])
10487
+ origin: _optionalChain([baseEvent, 'access', _118 => _118.event, 'optionalAccess', _119 => _119.origin])
10287
10488
  });
10288
10489
  }
10289
10490
  };
@@ -10316,7 +10517,7 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
10316
10517
  break;
10317
10518
  }
10318
10519
  scheduledTrials++;
10319
- _optionalChain([progressReporter, 'access', _117 => _117.setTotal, 'optionalCall', _118 => _118(evaluator.evalName, scheduledTrials)]);
10520
+ _optionalChain([progressReporter, 'access', _120 => _120.setTotal, 'optionalCall', _121 => _121(evaluator.evalName, scheduledTrials)]);
10320
10521
  q.push({ datum, trialIndex });
10321
10522
  }
10322
10523
  }
@@ -10378,427 +10579,918 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
10378
10579
  collectedResults.length = 0;
10379
10580
  }
10380
10581
  }
10381
- const summary = experiment ? await experiment.summarize({
10382
- summarizeScores: evaluator.summarizeScores
10383
- }) : buildLocalSummary(
10384
- evaluator,
10385
- collectResults ? collectedResults : [],
10386
- _nullishCoalesce(localScoreAccumulator, () => ( void 0))
10387
- );
10388
- return new EvalResultWithSummary(
10389
- summary,
10390
- collectResults ? collectedResults : []
10391
- );
10392
- } finally {
10393
- if (enableCache) {
10394
- const spanCache = _optionalChain([(_nullishCoalesce(evaluator.state, () => ( _internalGetGlobalState()))), 'optionalAccess', _119 => _119.spanCache]);
10395
- _optionalChain([spanCache, 'optionalAccess', _120 => _120.dispose, 'call', _121 => _121()]);
10396
- _optionalChain([spanCache, 'optionalAccess', _122 => _122.stop, 'call', _123 => _123()]);
10582
+ const summary = experiment ? await experiment.summarize({
10583
+ summarizeScores: evaluator.summarizeScores
10584
+ }) : buildLocalSummary(
10585
+ evaluator,
10586
+ collectResults ? collectedResults : [],
10587
+ _nullishCoalesce(localScoreAccumulator, () => ( void 0))
10588
+ );
10589
+ return new EvalResultWithSummary(
10590
+ summary,
10591
+ collectResults ? collectedResults : []
10592
+ );
10593
+ } finally {
10594
+ if (enableCache) {
10595
+ const spanCache = _optionalChain([(_nullishCoalesce(evaluator.state, () => ( _internalGetGlobalState()))), 'optionalAccess', _122 => _122.spanCache]);
10596
+ _optionalChain([spanCache, 'optionalAccess', _123 => _123.dispose, 'call', _124 => _124()]);
10597
+ _optionalChain([spanCache, 'optionalAccess', _125 => _125.stop, 'call', _126 => _126()]);
10598
+ }
10599
+ }
10600
+ }
10601
+ var warning = (text) => `Warning: ${text}`;
10602
+ function logError2(e, verbose) {
10603
+ if (!verbose) {
10604
+ console.error(`${e}`);
10605
+ } else {
10606
+ console.error(e);
10607
+ }
10608
+ }
10609
+ function accumulateScores(accumulator, scores) {
10610
+ for (const [name, score] of Object.entries(scores)) {
10611
+ if (score === null || score === void 0) {
10612
+ continue;
10613
+ }
10614
+ const existing = _nullishCoalesce(accumulator[name], () => ( { total: 0, count: 0 }));
10615
+ accumulator[name] = {
10616
+ total: existing.total + score,
10617
+ count: existing.count + 1
10618
+ };
10619
+ }
10620
+ }
10621
+ function ensureScoreAccumulator(results) {
10622
+ const accumulator = {};
10623
+ for (const result of results) {
10624
+ accumulateScores(accumulator, result.scores);
10625
+ }
10626
+ return accumulator;
10627
+ }
10628
+ function buildLocalSummary(evaluator, results, precomputedScores) {
10629
+ const scoresByName = _nullishCoalesce(precomputedScores, () => ( ensureScoreAccumulator(results)));
10630
+ return {
10631
+ projectName: evaluator.projectName,
10632
+ experimentName: evaluator.evalName,
10633
+ scores: Object.fromEntries(
10634
+ Object.entries(scoresByName).map(([name, { total, count }]) => [
10635
+ name,
10636
+ {
10637
+ name,
10638
+ score: count === 0 ? 0 : total / count,
10639
+ improvements: 0,
10640
+ regressions: 0
10641
+ }
10642
+ ])
10643
+ )
10644
+ };
10645
+ }
10646
+ function reportFailures(evaluator, failingResults, { verbose, jsonl }) {
10647
+ if (failingResults.length > 0) {
10648
+ console.error(
10649
+ warning(
10650
+ `Evaluator ${evaluator.evalName} failed with ${failingResults.length} error${failingResults.length === 1 ? "" : "s"}. This evaluation ("${evaluator.evalName}") will not be fully logged.`
10651
+ )
10652
+ );
10653
+ if (jsonl) {
10654
+ console.log(
10655
+ JSON.stringify({
10656
+ evaluatorName: evaluator.evalName,
10657
+ errors: failingResults.map(
10658
+ (r) => `${r.error instanceof Error ? r.error.stack : r.error}`
10659
+ )
10660
+ })
10661
+ );
10662
+ } else {
10663
+ for (const result of failingResults) {
10664
+ logError2(result.error, verbose);
10665
+ }
10666
+ }
10667
+ if (!verbose && !jsonl) {
10668
+ console.error(warning("Add --verbose to see full stack traces."));
10669
+ }
10670
+ }
10671
+ }
10672
+ var defaultReporter = {
10673
+ name: "Braintrust default reporter",
10674
+ async reportEval(evaluator, result, { verbose, jsonl }) {
10675
+ const { results, summary } = result;
10676
+ const failingResults = results.filter(
10677
+ (r) => r.error !== void 0
10678
+ );
10679
+ if (failingResults.length > 0) {
10680
+ reportFailures(evaluator, failingResults, { verbose, jsonl });
10681
+ }
10682
+ if (jsonl) {
10683
+ isomorph_default.writeln(JSON.stringify(summary));
10684
+ } else {
10685
+ isomorph_default.writeln("Experiment summary");
10686
+ isomorph_default.writeln("==================");
10687
+ if (summary.comparisonExperimentName) {
10688
+ isomorph_default.writeln(
10689
+ `${summary.comparisonExperimentName} (baseline) <- ${summary.experimentName} (comparison)`
10690
+ );
10691
+ isomorph_default.writeln("");
10692
+ }
10693
+ const hasScores = Object.keys(summary.scores).length > 0;
10694
+ const hasMetrics = Object.keys(_nullishCoalesce(summary.metrics, () => ( {}))).length > 0;
10695
+ const hasComparison = !!summary.comparisonExperimentName;
10696
+ if (hasScores || hasMetrics) {
10697
+ if (hasComparison) {
10698
+ isomorph_default.writeln(
10699
+ "Name Value Change Improvements Regressions"
10700
+ );
10701
+ isomorph_default.writeln(
10702
+ "----------------------------------------------------------------"
10703
+ );
10704
+ }
10705
+ for (const score of Object.values(summary.scores)) {
10706
+ const scorePercent = (score.score * 100).toFixed(2);
10707
+ const scoreValue = `${scorePercent}%`;
10708
+ if (hasComparison) {
10709
+ let diffString = "-";
10710
+ if (!isEmpty2(score.diff)) {
10711
+ const diffPercent = (score.diff * 100).toFixed(2);
10712
+ const diffSign = score.diff > 0 ? "+" : "";
10713
+ diffString = `${diffSign}${diffPercent}%`;
10714
+ }
10715
+ const improvements = score.improvements > 0 ? score.improvements.toString() : "-";
10716
+ const regressions = score.regressions > 0 ? score.regressions.toString() : "-";
10717
+ isomorph_default.writeln(
10718
+ `${score.name.padEnd(18)} ${scoreValue.padStart(10)} ${diffString.padStart(10)} ${improvements.padStart(12)} ${regressions.padStart(11)}`
10719
+ );
10720
+ } else {
10721
+ isomorph_default.writeln(`${score.name.padEnd(20)} ${scoreValue.padStart(15)}`);
10722
+ }
10723
+ }
10724
+ for (const metric of Object.values(_nullishCoalesce(summary.metrics, () => ( {})))) {
10725
+ const fractionDigits = Number.isInteger(metric.metric) ? 0 : 2;
10726
+ const formattedValue = metric.metric.toFixed(fractionDigits);
10727
+ const metricValue = metric.unit === "$" ? `${metric.unit}${formattedValue}` : `${formattedValue}${metric.unit}`;
10728
+ if (hasComparison) {
10729
+ let diffString = "-";
10730
+ if (!isEmpty2(metric.diff)) {
10731
+ const diffPercent = (metric.diff * 100).toFixed(2);
10732
+ const diffSign = metric.diff > 0 ? "+" : "";
10733
+ diffString = `${diffSign}${diffPercent}%`;
10734
+ }
10735
+ const improvements = metric.improvements > 0 ? metric.improvements.toString() : "-";
10736
+ const regressions = metric.regressions > 0 ? metric.regressions.toString() : "-";
10737
+ isomorph_default.writeln(
10738
+ `${metric.name.padEnd(18)} ${metricValue.padStart(10)} ${diffString.padStart(10)} ${improvements.padStart(12)} ${regressions.padStart(11)}`
10739
+ );
10740
+ } else {
10741
+ isomorph_default.writeln(
10742
+ `${metric.name.padEnd(20)} ${metricValue.padStart(15)}`
10743
+ );
10744
+ }
10745
+ }
10746
+ }
10747
+ if (summary.experimentUrl) {
10748
+ isomorph_default.writeln("");
10749
+ isomorph_default.writeln(`View results for ${summary.experimentName}`);
10750
+ isomorph_default.writeln(`See results at ${summary.experimentUrl}`);
10751
+ }
10752
+ }
10753
+ isomorph_default.writeln("");
10754
+ return failingResults.length === 0;
10755
+ },
10756
+ async reportRun(evalReports) {
10757
+ return evalReports.every((r) => r);
10758
+ }
10759
+ };
10760
+
10761
+ // dev/errorHandler.ts
10762
+
10763
+ var errorHandler = (err, req, res, next) => {
10764
+ if ("status" in err) {
10765
+ res.status(err.status).json({
10766
+ error: {
10767
+ message: err.message,
10768
+ status: err.status
10769
+ }
10770
+ });
10771
+ return;
10772
+ }
10773
+ if (err instanceof _v3.z.ZodError) {
10774
+ res.status(400).json({
10775
+ error: {
10776
+ message: "Invalid request",
10777
+ errors: err.errors
10778
+ }
10779
+ });
10780
+ return;
10781
+ }
10782
+ console.error("Internal server error", err);
10783
+ res.status(500).json({
10784
+ error: {
10785
+ message: "Internal server error",
10786
+ status: 500
10787
+ }
10788
+ });
10789
+ };
10790
+
10791
+ // dev/authorize.ts
10792
+ var _httperrors = require('http-errors'); var _httperrors2 = _interopRequireDefault(_httperrors);
10793
+ function authorizeRequest(req, res, next) {
10794
+ try {
10795
+ const ctx = {
10796
+ appOrigin: extractAllowedOrigin(req.headers[ORIGIN_HEADER]),
10797
+ token: void 0,
10798
+ state: void 0,
10799
+ projectId: parseHeader(req.headers, PROJECT_ID_HEADER)
10800
+ };
10801
+ if (req.headers.authorization || req.headers[BRAINTRUST_AUTH_TOKEN_HEADER]) {
10802
+ const tokenText = parseBraintrustAuthHeader(req.headers);
10803
+ if (!tokenText) {
10804
+ return next(_httperrors2.default.call(void 0, 400, "Invalid authorization token format"));
10805
+ }
10806
+ ctx.token = tokenText.toLowerCase() === "null" ? void 0 : tokenText;
10807
+ }
10808
+ req.ctx = ctx;
10809
+ next();
10810
+ } catch (e) {
10811
+ next(e);
10812
+ }
10813
+ }
10814
+ var loginCache = new LRUCache({
10815
+ max: 32
10816
+ // TODO: Make this configurable
10817
+ });
10818
+ async function cachedLogin(options) {
10819
+ const key = JSON.stringify(options);
10820
+ const cached = loginCache.get(key);
10821
+ if (cached) {
10822
+ return cached;
10823
+ }
10824
+ const state = await loginToState(options);
10825
+ loginCache.set(key, state);
10826
+ return state;
10827
+ }
10828
+ function makeCheckAuthorized(allowedOrgName) {
10829
+ return async (req, _res, next) => {
10830
+ if (!_optionalChain([req, 'access', _127 => _127.ctx, 'optionalAccess', _128 => _128.token])) {
10831
+ return next(_httperrors2.default.call(void 0, 401, "Unauthorized"));
10832
+ }
10833
+ try {
10834
+ const orgName = parseHeader(req.headers, "x-bt-org-name");
10835
+ if (!orgName) {
10836
+ return next(_httperrors2.default.call(void 0, 400, "Missing x-bt-org-name header"));
10837
+ }
10838
+ if (allowedOrgName && allowedOrgName !== orgName) {
10839
+ const errorMessage = `Org '${orgName}' is not allowed. Only org '${allowedOrgName}' is allowed.`;
10840
+ return next(_httperrors2.default.call(void 0, 403, errorMessage));
10841
+ }
10842
+ const state = await cachedLogin({
10843
+ apiKey: _optionalChain([req, 'access', _129 => _129.ctx, 'optionalAccess', _130 => _130.token]),
10844
+ orgName
10845
+ });
10846
+ req.ctx.state = state;
10847
+ next();
10848
+ } catch (e) {
10849
+ console.error("Authorization error:", e);
10850
+ return next(_httperrors2.default.call(void 0, 401, "Unauthorized"));
10851
+ }
10852
+ };
10853
+ }
10854
+ function parseBraintrustAuthHeader(headers) {
10855
+ const tokenString = parseHeader(headers, BRAINTRUST_AUTH_TOKEN_HEADER);
10856
+ return _nullishCoalesce(_nullishCoalesce(tokenString, () => ( parseAuthHeader(headers))), () => ( void 0));
10857
+ }
10858
+ function parseHeader(headers, headerName) {
10859
+ const token = headers[headerName];
10860
+ let tokenString;
10861
+ if (typeof token === "string") {
10862
+ tokenString = token;
10863
+ } else if (Array.isArray(token) && token.length > 0) {
10864
+ tokenString = token[0];
10865
+ }
10866
+ return tokenString;
10867
+ }
10868
+ function checkOrigin(requestOrigin, callback) {
10869
+ if (!requestOrigin) {
10870
+ return callback(null, true);
10871
+ }
10872
+ for (const origin of WHITELISTED_ORIGINS || []) {
10873
+ if (origin instanceof RegExp && origin.test(requestOrigin) || origin === requestOrigin) {
10874
+ return callback(null, requestOrigin);
10875
+ }
10876
+ }
10877
+ return callback(null, false);
10878
+ }
10879
+ var BRAINTRUST_AUTH_TOKEN_HEADER = "x-bt-auth-token";
10880
+ var ORIGIN_HEADER = "origin";
10881
+ var PROJECT_ID_HEADER = "x-bt-project-id";
10882
+ function extractAllowedOrigin(originHeader) {
10883
+ let allowedOrigin = MAIN_ORIGIN;
10884
+ checkOrigin(originHeader, (err, origin) => {
10885
+ if (!err && originHeader && origin) {
10886
+ allowedOrigin = originHeader;
10887
+ }
10888
+ });
10889
+ return allowedOrigin;
10890
+ }
10891
+ var MAIN_ORIGIN = "https://www.braintrust.dev";
10892
+ var WHITELISTED_ORIGINS = [
10893
+ MAIN_ORIGIN,
10894
+ "https://www.braintrustdata.com",
10895
+ new RegExp("https://.*.preview.braintrust.dev")
10896
+ ].concat(
10897
+ process.env.WHITELISTED_ORIGIN ? [process.env.WHITELISTED_ORIGIN] : []
10898
+ ).concat(
10899
+ process.env.BRAINTRUST_APP_URL ? [process.env.BRAINTRUST_APP_URL] : []
10900
+ );
10901
+ function parseAuthHeader(headers) {
10902
+ const authHeader = headers["authorization"];
10903
+ let authValue = null;
10904
+ if (Array.isArray(authHeader)) {
10905
+ authValue = authHeader[authHeader.length - 1];
10906
+ } else {
10907
+ authValue = authHeader;
10908
+ }
10909
+ if (!authValue) {
10910
+ return null;
10911
+ }
10912
+ const parts = authValue.split(" ");
10913
+ if (parts.length !== 2) {
10914
+ return null;
10915
+ }
10916
+ return parts[1];
10917
+ }
10918
+ var baseAllowedHeaders = [
10919
+ "Content-Type",
10920
+ "X-Amz-Date",
10921
+ "Authorization",
10922
+ "X-Api-Key",
10923
+ "X-Amz-Security-Token",
10924
+ "x-bt-auth-token",
10925
+ "x-bt-parent",
10926
+ // These are eval-specific
10927
+ "x-bt-org-name",
10928
+ "x-bt-project-id",
10929
+ "x-bt-stream-fmt",
10930
+ "x-bt-use-cache",
10931
+ "x-stainless-os",
10932
+ "x-stainless-lang",
10933
+ "x-stainless-package-version",
10934
+ "x-stainless-runtime",
10935
+ "x-stainless-runtime-version",
10936
+ "x-stainless-arch"
10937
+ ];
10938
+
10939
+ // dev/stream.ts
10940
+ function serializeSSEEvent(event) {
10941
+ return Object.entries(event).filter(([_key, value]) => value !== void 0).map(([key, value]) => `${key}: ${value}`).join("\n") + "\n\n";
10942
+ }
10943
+
10944
+ // dev/types.ts
10945
+
10946
+ var evalBodySchema = _v3.z.object({
10947
+ name: _v3.z.string(),
10948
+ parameters: _v3.z.record(_v3.z.string(), _v3.z.unknown()).nullish(),
10949
+ data: RunEval.shape.data,
10950
+ scores: _v3.z.array(
10951
+ _v3.z.object({
10952
+ function_id: FunctionId,
10953
+ name: _v3.z.string()
10954
+ })
10955
+ ).nullish(),
10956
+ experiment_name: _v3.z.string().nullish(),
10957
+ project_id: _v3.z.string().nullish(),
10958
+ parent: InvokeParent.optional(),
10959
+ stream: _v3.z.boolean().optional()
10960
+ });
10961
+ var staticParametersSchema = _v3.z.record(
10962
+ _v3.z.string(),
10963
+ _v3.z.union([
10964
+ _v3.z.object({
10965
+ type: _v3.z.literal("prompt"),
10966
+ default: PromptData.optional(),
10967
+ description: _v3.z.string().optional()
10968
+ }),
10969
+ _v3.z.object({
10970
+ type: _v3.z.literal("data"),
10971
+ schema: _v3.z.record(_v3.z.unknown()),
10972
+ default: _v3.z.unknown().optional(),
10973
+ description: _v3.z.string().optional()
10974
+ })
10975
+ ])
10976
+ );
10977
+ var parametersSchema = _v3.z.object({
10978
+ type: _v3.z.literal("object"),
10979
+ properties: _v3.z.record(_v3.z.string(), _v3.z.record(_v3.z.unknown())),
10980
+ required: _v3.z.array(_v3.z.string()).optional(),
10981
+ additionalProperties: _v3.z.boolean().optional()
10982
+ });
10983
+ var parametersSourceSchema = _v3.z.object({
10984
+ parametersId: _v3.z.string().optional(),
10985
+ slug: _v3.z.string(),
10986
+ name: _v3.z.string(),
10987
+ projectId: _v3.z.string().optional(),
10988
+ version: _v3.z.string().optional()
10989
+ });
10990
+ var parametersContainerSchema = _v3.z.object({
10991
+ type: _v3.z.literal("braintrust.parameters"),
10992
+ schema: parametersSchema,
10993
+ source: parametersSourceSchema
10994
+ });
10995
+ var staticParametersContainerSchema = _v3.z.object({
10996
+ type: _v3.z.literal("braintrust.staticParameters"),
10997
+ schema: staticParametersSchema,
10998
+ source: _v3.z.null()
10999
+ });
11000
+ var serializedParametersContainerSchema = _v3.z.union([
11001
+ parametersContainerSchema,
11002
+ staticParametersContainerSchema,
11003
+ // keeping this type here since old versions of the SDK will still pass the unwrapped schema and we need to handle this in the app
11004
+ staticParametersSchema
11005
+ ]);
11006
+ var evaluatorDefinitionSchema = _v3.z.object({
11007
+ parameters: serializedParametersContainerSchema.optional(),
11008
+ scores: _v3.z.array(_v3.z.object({ name: _v3.z.string() })).optional()
11009
+ });
11010
+ var evaluatorDefinitionsSchema = _v3.z.record(
11011
+ _v3.z.string(),
11012
+ evaluatorDefinitionSchema
11013
+ );
11014
+
11015
+ // dev/server.ts
11016
+
11017
+
11018
+
11019
+ // src/framework2.ts
11020
+
11021
+
11022
+ // src/zod/utils.ts
11023
+ var _zodtojsonschema = require('zod-to-json-schema');
11024
+ var _v4 = require('zod/v4'); var z42 = _interopRequireWildcard(_v4);
11025
+ function isZodV4(zodObject) {
11026
+ return typeof zodObject === "object" && zodObject !== null && "_zod" in zodObject && zodObject._zod !== void 0;
11027
+ }
11028
+ function zodToJsonSchema(schema) {
11029
+ if (isZodV4(schema)) {
11030
+ return z42.toJSONSchema(schema, {
11031
+ target: "draft-7"
11032
+ });
11033
+ }
11034
+ return _zodtojsonschema.zodToJsonSchema.call(void 0, schema);
11035
+ }
11036
+
11037
+ // src/framework2.ts
11038
+ var currentFilename = typeof __filename !== "undefined" ? __filename : "unknown";
11039
+ var ProjectBuilder = class {
11040
+ create(opts) {
11041
+ return new Project2(opts);
11042
+ }
11043
+ };
11044
+ var projects = new ProjectBuilder();
11045
+ var Project2 = (_class17 = class {
11046
+
11047
+
11048
+
11049
+
11050
+
11051
+
11052
+ __init63() {this._publishableCodeFunctions = []}
11053
+ __init64() {this._publishablePrompts = []}
11054
+ __init65() {this._publishableParameters = []}
11055
+ constructor(args) {;_class17.prototype.__init63.call(this);_class17.prototype.__init64.call(this);_class17.prototype.__init65.call(this);
11056
+ _initializeSpanContext();
11057
+ this.name = "name" in args ? args.name : void 0;
11058
+ this.id = "id" in args ? args.id : void 0;
11059
+ this.tools = new ToolBuilder(this);
11060
+ this.prompts = new PromptBuilder(this);
11061
+ this.parameters = new ParametersBuilder(this);
11062
+ this.scorers = new ScorerBuilder(this);
11063
+ }
11064
+ addPrompt(prompt) {
11065
+ this._publishablePrompts.push(prompt);
11066
+ if (globalThis._lazy_load) {
11067
+ globalThis._evals.prompts.push(prompt);
11068
+ }
11069
+ }
11070
+ addParameters(parameters) {
11071
+ this._publishableParameters.push(parameters);
11072
+ if (globalThis._lazy_load) {
11073
+ if (globalThis._evals.parameters == null)
11074
+ globalThis._evals.parameters = [];
11075
+ globalThis._evals.parameters.push(parameters);
10397
11076
  }
10398
11077
  }
10399
- }
10400
- var warning = (text) => `Warning: ${text}`;
10401
- function logError2(e, verbose) {
10402
- if (!verbose) {
10403
- console.error(`${e}`);
10404
- } else {
10405
- console.error(e);
11078
+ addCodeFunction(fn) {
11079
+ this._publishableCodeFunctions.push(fn);
11080
+ if (globalThis._lazy_load) {
11081
+ globalThis._evals.functions.push(fn);
11082
+ }
10406
11083
  }
10407
- }
10408
- function accumulateScores(accumulator, scores) {
10409
- for (const [name, score] of Object.entries(scores)) {
10410
- if (score === null || score === void 0) {
10411
- continue;
11084
+ async publish() {
11085
+ if (globalThis._lazy_load) {
11086
+ console.warn("publish() is a no-op when running `braintrust push`.");
11087
+ return;
10412
11088
  }
10413
- const existing = _nullishCoalesce(accumulator[name], () => ( { total: 0, count: 0 }));
10414
- accumulator[name] = {
10415
- total: existing.total + score,
10416
- count: existing.count + 1
10417
- };
11089
+ await login();
11090
+ const projectMap = new ProjectNameIdMap();
11091
+ const functionDefinitions = [];
11092
+ if (this._publishableCodeFunctions.length > 0) {
11093
+ console.warn(
11094
+ "Code functions cannot be published directly. Use `braintrust push` instead."
11095
+ );
11096
+ }
11097
+ if (this._publishablePrompts.length > 0) {
11098
+ for (const prompt of this._publishablePrompts) {
11099
+ const functionDefinition = await prompt.toFunctionDefinition(projectMap);
11100
+ functionDefinitions.push(functionDefinition);
11101
+ }
11102
+ }
11103
+ await _internalGetGlobalState().apiConn().post_json("insert-functions", {
11104
+ functions: functionDefinitions
11105
+ });
10418
11106
  }
10419
- }
10420
- function ensureScoreAccumulator(results) {
10421
- const accumulator = {};
10422
- for (const result of results) {
10423
- accumulateScores(accumulator, result.scores);
11107
+ }, _class17);
11108
+ var ToolBuilder = (_class18 = class {
11109
+ constructor(project) {;_class18.prototype.__init66.call(this);
11110
+ this.project = project;
10424
11111
  }
10425
- return accumulator;
10426
- }
10427
- function buildLocalSummary(evaluator, results, precomputedScores) {
10428
- const scoresByName = _nullishCoalesce(precomputedScores, () => ( ensureScoreAccumulator(results)));
10429
- return {
10430
- projectName: evaluator.projectName,
10431
- experimentName: evaluator.evalName,
10432
- scores: Object.fromEntries(
10433
- Object.entries(scoresByName).map(([name, { total, count }]) => [
10434
- name,
10435
- {
10436
- name,
10437
- score: count === 0 ? 0 : total / count,
10438
- improvements: 0,
10439
- regressions: 0
11112
+ __init66() {this.taskCounter = 0}
11113
+ // This type definition is just a catch all so that the implementation can be
11114
+ // less specific than the two more specific declarations above.
11115
+ create(opts) {
11116
+ this.taskCounter++;
11117
+ opts = _nullishCoalesce(opts, () => ( {}));
11118
+ const { handler, name, slug, parameters, returns, ...rest } = opts;
11119
+ let resolvedName = _nullishCoalesce(name, () => ( handler.name));
11120
+ if (resolvedName.trim().length === 0) {
11121
+ resolvedName = `Tool ${isomorph_default.basename(currentFilename)} ${this.taskCounter}`;
11122
+ }
11123
+ const tool = new CodeFunction(this.project, {
11124
+ handler,
11125
+ name: resolvedName,
11126
+ slug: _nullishCoalesce(slug, () => ( slugify(resolvedName, { lower: true, strict: true }))),
11127
+ type: "tool",
11128
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/consistent-type-assertions
11129
+ parameters,
11130
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/consistent-type-assertions
11131
+ returns,
11132
+ ...rest
11133
+ });
11134
+ this.project.addCodeFunction(tool);
11135
+ return tool;
11136
+ }
11137
+ }, _class18);
11138
+ var ScorerBuilder = (_class19 = class {
11139
+ constructor(project) {;_class19.prototype.__init67.call(this);
11140
+ this.project = project;
11141
+ }
11142
+ __init67() {this.taskCounter = 0}
11143
+ create(opts) {
11144
+ this.taskCounter++;
11145
+ let resolvedName = opts.name;
11146
+ if (!resolvedName && "handler" in opts) {
11147
+ resolvedName = opts.handler.name;
11148
+ }
11149
+ if (!resolvedName || resolvedName.trim().length === 0) {
11150
+ resolvedName = `Scorer ${isomorph_default.basename(currentFilename)} ${this.taskCounter}`;
11151
+ }
11152
+ const slug = _nullishCoalesce(opts.slug, () => ( slugify(resolvedName, { lower: true, strict: true })));
11153
+ if ("handler" in opts) {
11154
+ const scorer = new CodeFunction(this.project, {
11155
+ ...opts,
11156
+ name: resolvedName,
11157
+ slug,
11158
+ type: "scorer"
11159
+ });
11160
+ this.project.addCodeFunction(scorer);
11161
+ } else {
11162
+ const promptBlock = "messages" in opts ? {
11163
+ type: "chat",
11164
+ messages: opts.messages
11165
+ } : {
11166
+ type: "completion",
11167
+ content: opts.prompt
11168
+ };
11169
+ const promptData = {
11170
+ prompt: promptBlock,
11171
+ options: {
11172
+ model: opts.model,
11173
+ params: opts.params
11174
+ },
11175
+ parser: {
11176
+ type: "llm_classifier",
11177
+ use_cot: opts.useCot,
11178
+ choice_scores: opts.choiceScores
10440
11179
  }
10441
- ])
10442
- )
10443
- };
10444
- }
10445
- function reportFailures(evaluator, failingResults, { verbose, jsonl }) {
10446
- if (failingResults.length > 0) {
10447
- console.error(
10448
- warning(
10449
- `Evaluator ${evaluator.evalName} failed with ${failingResults.length} error${failingResults.length === 1 ? "" : "s"}. This evaluation ("${evaluator.evalName}") will not be fully logged.`
10450
- )
10451
- );
10452
- if (jsonl) {
10453
- console.log(
10454
- JSON.stringify({
10455
- evaluatorName: evaluator.evalName,
10456
- errors: failingResults.map(
10457
- (r) => `${r.error instanceof Error ? r.error.stack : r.error}`
10458
- )
10459
- })
11180
+ };
11181
+ const codePrompt = new CodePrompt(
11182
+ this.project,
11183
+ promptData,
11184
+ [],
11185
+ {
11186
+ ...opts,
11187
+ name: resolvedName,
11188
+ slug
11189
+ },
11190
+ "scorer"
10460
11191
  );
10461
- } else {
10462
- for (const result of failingResults) {
10463
- logError2(result.error, verbose);
10464
- }
11192
+ this.project.addPrompt(codePrompt);
10465
11193
  }
10466
- if (!verbose && !jsonl) {
10467
- console.error(warning("Add --verbose to see full stack traces."));
11194
+ }
11195
+ }, _class19);
11196
+ var CodeFunction = class {
11197
+ constructor(project, opts) {
11198
+ this.project = project;
11199
+ this.handler = opts.handler;
11200
+ this.name = opts.name;
11201
+ this.slug = opts.slug;
11202
+ this.description = opts.description;
11203
+ this.type = opts.type;
11204
+ this.ifExists = opts.ifExists;
11205
+ this.metadata = opts.metadata;
11206
+ this.parameters = opts.parameters;
11207
+ this.returns = opts.returns;
11208
+ if (this.returns && !this.parameters) {
11209
+ throw new Error("parameters are required if return type is defined");
10468
11210
  }
10469
11211
  }
10470
- }
10471
- var defaultReporter = {
10472
- name: "Braintrust default reporter",
10473
- async reportEval(evaluator, result, { verbose, jsonl }) {
10474
- const { results, summary } = result;
10475
- const failingResults = results.filter(
10476
- (r) => r.error !== void 0
10477
- );
10478
- if (failingResults.length > 0) {
10479
- reportFailures(evaluator, failingResults, { verbose, jsonl });
10480
- }
10481
- if (jsonl) {
10482
- isomorph_default.writeln(JSON.stringify(summary));
10483
- } else {
10484
- isomorph_default.writeln("Experiment summary");
10485
- isomorph_default.writeln("==================");
10486
- if (summary.comparisonExperimentName) {
10487
- isomorph_default.writeln(
10488
- `${summary.comparisonExperimentName} (baseline) <- ${summary.experimentName} (comparison)`
10489
- );
10490
- isomorph_default.writeln("");
10491
- }
10492
- const hasScores = Object.keys(summary.scores).length > 0;
10493
- const hasMetrics = Object.keys(_nullishCoalesce(summary.metrics, () => ( {}))).length > 0;
10494
- const hasComparison = !!summary.comparisonExperimentName;
10495
- if (hasScores || hasMetrics) {
10496
- if (hasComparison) {
10497
- isomorph_default.writeln(
10498
- "Name Value Change Improvements Regressions"
10499
- );
10500
- isomorph_default.writeln(
10501
- "----------------------------------------------------------------"
10502
- );
10503
- }
10504
- for (const score of Object.values(summary.scores)) {
10505
- const scorePercent = (score.score * 100).toFixed(2);
10506
- const scoreValue = `${scorePercent}%`;
10507
- if (hasComparison) {
10508
- let diffString = "-";
10509
- if (!isEmpty2(score.diff)) {
10510
- const diffPercent = (score.diff * 100).toFixed(2);
10511
- const diffSign = score.diff > 0 ? "+" : "";
10512
- diffString = `${diffSign}${diffPercent}%`;
10513
- }
10514
- const improvements = score.improvements > 0 ? score.improvements.toString() : "-";
10515
- const regressions = score.regressions > 0 ? score.regressions.toString() : "-";
10516
- isomorph_default.writeln(
10517
- `${score.name.padEnd(18)} ${scoreValue.padStart(10)} ${diffString.padStart(10)} ${improvements.padStart(12)} ${regressions.padStart(11)}`
10518
- );
10519
- } else {
10520
- isomorph_default.writeln(`${score.name.padEnd(20)} ${scoreValue.padStart(15)}`);
10521
- }
10522
- }
10523
- for (const metric of Object.values(_nullishCoalesce(summary.metrics, () => ( {})))) {
10524
- const fractionDigits = Number.isInteger(metric.metric) ? 0 : 2;
10525
- const formattedValue = metric.metric.toFixed(fractionDigits);
10526
- const metricValue = metric.unit === "$" ? `${metric.unit}${formattedValue}` : `${formattedValue}${metric.unit}`;
10527
- if (hasComparison) {
10528
- let diffString = "-";
10529
- if (!isEmpty2(metric.diff)) {
10530
- const diffPercent = (metric.diff * 100).toFixed(2);
10531
- const diffSign = metric.diff > 0 ? "+" : "";
10532
- diffString = `${diffSign}${diffPercent}%`;
10533
- }
10534
- const improvements = metric.improvements > 0 ? metric.improvements.toString() : "-";
10535
- const regressions = metric.regressions > 0 ? metric.regressions.toString() : "-";
10536
- isomorph_default.writeln(
10537
- `${metric.name.padEnd(18)} ${metricValue.padStart(10)} ${diffString.padStart(10)} ${improvements.padStart(12)} ${regressions.padStart(11)}`
10538
- );
11212
+
11213
+
11214
+
11215
+
11216
+
11217
+
11218
+
11219
+
11220
+
11221
+ key() {
11222
+ return JSON.stringify([
11223
+ _nullishCoalesce(this.project.id, () => ( "")),
11224
+ _nullishCoalesce(this.project.name, () => ( "")),
11225
+ this.slug
11226
+ ]);
11227
+ }
11228
+ };
11229
+ var CodePrompt = class {
11230
+
11231
+
11232
+
11233
+
11234
+
11235
+
11236
+
11237
+
11238
+
11239
+
11240
+ constructor(project, prompt, toolFunctions, opts, functionType) {
11241
+ this.project = project;
11242
+ this.name = opts.name;
11243
+ this.slug = opts.slug;
11244
+ this.prompt = prompt;
11245
+ this.toolFunctions = toolFunctions;
11246
+ this.ifExists = opts.ifExists;
11247
+ this.description = opts.description;
11248
+ this.id = opts.id;
11249
+ this.functionType = functionType;
11250
+ this.metadata = opts.metadata;
11251
+ }
11252
+ async toFunctionDefinition(projectNameToId) {
11253
+ const prompt_data = {
11254
+ ...this.prompt
11255
+ };
11256
+ if (this.toolFunctions.length > 0) {
11257
+ const resolvableToolFunctions = await Promise.all(
11258
+ this.toolFunctions.map(async (fn) => {
11259
+ if ("slug" in fn) {
11260
+ return {
11261
+ type: "slug",
11262
+ project_id: await projectNameToId.resolve(fn.project),
11263
+ slug: fn.slug
11264
+ };
10539
11265
  } else {
10540
- isomorph_default.writeln(
10541
- `${metric.name.padEnd(20)} ${metricValue.padStart(15)}`
10542
- );
11266
+ return fn;
10543
11267
  }
10544
- }
10545
- }
10546
- if (summary.experimentUrl) {
10547
- isomorph_default.writeln("");
10548
- isomorph_default.writeln(`View results for ${summary.experimentName}`);
10549
- isomorph_default.writeln(`See results at ${summary.experimentUrl}`);
10550
- }
11268
+ })
11269
+ );
11270
+ prompt_data.tool_functions = // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
11271
+ resolvableToolFunctions;
10551
11272
  }
10552
- isomorph_default.writeln("");
10553
- return failingResults.length === 0;
10554
- },
10555
- async reportRun(evalReports) {
10556
- return evalReports.every((r) => r);
11273
+ return {
11274
+ project_id: await projectNameToId.resolve(this.project),
11275
+ name: this.name,
11276
+ slug: this.slug,
11277
+ description: _nullishCoalesce(this.description, () => ( "")),
11278
+ function_data: {
11279
+ type: "prompt"
11280
+ },
11281
+ function_type: this.functionType,
11282
+ prompt_data,
11283
+ if_exists: this.ifExists,
11284
+ metadata: this.metadata
11285
+ };
10557
11286
  }
10558
11287
  };
10559
-
10560
- // dev/errorHandler.ts
10561
-
10562
- var errorHandler = (err, req, res, next) => {
10563
- if ("status" in err) {
10564
- res.status(err.status).json({
10565
- error: {
10566
- message: err.message,
10567
- status: err.status
10568
- }
10569
- });
10570
- return;
11288
+ var PromptBuilder = class {
11289
+ constructor(project) {
11290
+ this.project = project;
10571
11291
  }
10572
- if (err instanceof _v3.z.ZodError) {
10573
- res.status(400).json({
10574
- error: {
10575
- message: "Invalid request",
10576
- errors: err.errors
11292
+ create(opts) {
11293
+ const toolFunctions = [];
11294
+ const rawTools = [];
11295
+ for (const tool of _nullishCoalesce(opts.tools, () => ( []))) {
11296
+ if (tool instanceof CodeFunction) {
11297
+ toolFunctions.push(tool);
11298
+ } else if ("type" in tool && !("function" in tool)) {
11299
+ toolFunctions.push(tool);
11300
+ } else {
11301
+ rawTools.push(tool);
10577
11302
  }
11303
+ }
11304
+ const slug = _nullishCoalesce(opts.slug, () => ( slugify(opts.name, { lower: true, strict: true })));
11305
+ const promptData = promptDefinitionToPromptData(opts, rawTools);
11306
+ const promptRow = {
11307
+ id: opts.id,
11308
+ _xact_id: opts.version ? loadPrettyXact(opts.version) : void 0,
11309
+ name: opts.name,
11310
+ slug,
11311
+ prompt_data: promptData,
11312
+ ...this.project.id !== void 0 ? { project_id: this.project.id } : {}
11313
+ };
11314
+ const prompt = new Prompt2(
11315
+ promptRow,
11316
+ {},
11317
+ // It doesn't make sense to specify defaults here.
11318
+ _nullishCoalesce(opts.noTrace, () => ( false))
11319
+ );
11320
+ const codePrompt = new CodePrompt(this.project, promptData, toolFunctions, {
11321
+ ...opts,
11322
+ slug
10578
11323
  });
10579
- return;
11324
+ this.project.addPrompt(codePrompt);
11325
+ return prompt;
10580
11326
  }
10581
- console.error("Internal server error", err);
10582
- res.status(500).json({
10583
- error: {
10584
- message: "Internal server error",
10585
- status: 500
10586
- }
10587
- });
10588
11327
  };
10589
-
10590
- // dev/authorize.ts
10591
- var _httperrors = require('http-errors'); var _httperrors2 = _interopRequireDefault(_httperrors);
10592
- function authorizeRequest(req, res, next) {
10593
- try {
10594
- const ctx = {
10595
- appOrigin: extractAllowedOrigin(req.headers[ORIGIN_HEADER]),
10596
- token: void 0,
10597
- state: void 0,
10598
- projectId: parseHeader(req.headers, PROJECT_ID_HEADER)
11328
+ var CodeParameters = class {
11329
+
11330
+
11331
+
11332
+
11333
+
11334
+
11335
+
11336
+ constructor(project, opts) {
11337
+ this.project = project;
11338
+ this.name = opts.name;
11339
+ this.slug = opts.slug;
11340
+ this.description = opts.description;
11341
+ this.schema = opts.schema;
11342
+ this.ifExists = opts.ifExists;
11343
+ this.metadata = opts.metadata;
11344
+ }
11345
+ async toFunctionDefinition(projectNameToId) {
11346
+ return {
11347
+ project_id: await projectNameToId.resolve(this.project),
11348
+ name: this.name,
11349
+ slug: this.slug,
11350
+ description: _nullishCoalesce(this.description, () => ( "")),
11351
+ function_type: "parameters",
11352
+ function_data: {
11353
+ type: "parameters",
11354
+ data: {},
11355
+ __schema: serializeEvalParameterstoParametersSchema(this.schema)
11356
+ },
11357
+ if_exists: this.ifExists,
11358
+ metadata: this.metadata
10599
11359
  };
10600
- if (req.headers.authorization || req.headers[BRAINTRUST_AUTH_TOKEN_HEADER]) {
10601
- const tokenText = parseBraintrustAuthHeader(req.headers);
10602
- if (!tokenText) {
10603
- return next(_httperrors2.default.call(void 0, 400, "Invalid authorization token format"));
10604
- }
10605
- ctx.token = tokenText.toLowerCase() === "null" ? void 0 : tokenText;
10606
- }
10607
- req.ctx = ctx;
10608
- next();
10609
- } catch (e) {
10610
- next(e);
10611
11360
  }
10612
- }
10613
- var loginCache = new LRUCache({
10614
- max: 32
10615
- // TODO: Make this configurable
10616
- });
10617
- async function cachedLogin(options) {
10618
- const key = JSON.stringify(options);
10619
- const cached = loginCache.get(key);
10620
- if (cached) {
10621
- return cached;
11361
+ };
11362
+ var ParametersBuilder = class {
11363
+ constructor(project) {
11364
+ this.project = project;
10622
11365
  }
10623
- const state = await loginToState(options);
10624
- loginCache.set(key, state);
10625
- return state;
11366
+ create(opts) {
11367
+ const slug = _nullishCoalesce(opts.slug, () => ( slugify(opts.name, { lower: true, strict: true })));
11368
+ const codeParameters = new CodeParameters(this.project, {
11369
+ name: opts.name,
11370
+ slug,
11371
+ description: opts.description,
11372
+ schema: opts.schema,
11373
+ ifExists: opts.ifExists,
11374
+ metadata: opts.metadata
11375
+ });
11376
+ this.project.addParameters(codeParameters);
11377
+ return opts.schema;
11378
+ }
11379
+ };
11380
+ function serializeEvalParametersToStaticParametersSchema(parameters) {
11381
+ return Object.fromEntries(
11382
+ Object.entries(parameters).map(([name, value]) => {
11383
+ if ("type" in value && value.type === "prompt") {
11384
+ return [
11385
+ name,
11386
+ {
11387
+ type: "prompt",
11388
+ default: value.default ? promptDefinitionToPromptData(value.default) : void 0,
11389
+ description: value.description
11390
+ }
11391
+ ];
11392
+ } else {
11393
+ const schemaObj = zodToJsonSchema(value);
11394
+ return [
11395
+ name,
11396
+ {
11397
+ type: "data",
11398
+ schema: schemaObj,
11399
+ default: schemaObj.default,
11400
+ description: schemaObj.description
11401
+ }
11402
+ ];
11403
+ }
11404
+ })
11405
+ );
10626
11406
  }
10627
- function makeCheckAuthorized(allowedOrgName) {
10628
- return async (req, _res, next) => {
10629
- if (!_optionalChain([req, 'access', _124 => _124.ctx, 'optionalAccess', _125 => _125.token])) {
10630
- return next(_httperrors2.default.call(void 0, 401, "Unauthorized"));
10631
- }
10632
- try {
10633
- const orgName = parseHeader(req.headers, "x-bt-org-name");
10634
- if (!orgName) {
10635
- return next(_httperrors2.default.call(void 0, 400, "Missing x-bt-org-name header"));
11407
+ function serializeEvalParameterstoParametersSchema(parameters) {
11408
+ const properties = {};
11409
+ const required = [];
11410
+ for (const [name, value] of Object.entries(parameters)) {
11411
+ if ("type" in value && value.type === "prompt") {
11412
+ const defaultPromptData = value.default ? promptDefinitionToPromptData(value.default) : void 0;
11413
+ properties[name] = {
11414
+ type: "object",
11415
+ "x-bt-type": "prompt",
11416
+ ...value.description ? { description: value.description } : {},
11417
+ ...defaultPromptData ? { default: defaultPromptData } : {}
11418
+ };
11419
+ if (!defaultPromptData) {
11420
+ required.push(name);
10636
11421
  }
10637
- if (allowedOrgName && allowedOrgName !== orgName) {
10638
- const errorMessage = `Org '${orgName}' is not allowed. Only org '${allowedOrgName}' is allowed.`;
10639
- return next(_httperrors2.default.call(void 0, 403, errorMessage));
11422
+ } else {
11423
+ const schemaObj = zodToJsonSchema(value);
11424
+ properties[name] = schemaObj;
11425
+ if (!("default" in schemaObj)) {
11426
+ required.push(name);
10640
11427
  }
10641
- const state = await cachedLogin({
10642
- apiKey: _optionalChain([req, 'access', _126 => _126.ctx, 'optionalAccess', _127 => _127.token]),
10643
- orgName
10644
- });
10645
- req.ctx.state = state;
10646
- next();
10647
- } catch (e) {
10648
- console.error("Authorization error:", e);
10649
- return next(_httperrors2.default.call(void 0, 401, "Unauthorized"));
10650
11428
  }
11429
+ }
11430
+ return {
11431
+ type: "object",
11432
+ properties,
11433
+ ...required.length > 0 ? { required } : {},
11434
+ additionalProperties: true
10651
11435
  };
10652
11436
  }
10653
- function parseBraintrustAuthHeader(headers) {
10654
- const tokenString = parseHeader(headers, BRAINTRUST_AUTH_TOKEN_HEADER);
10655
- return _nullishCoalesce(_nullishCoalesce(tokenString, () => ( parseAuthHeader(headers))), () => ( void 0));
10656
- }
10657
- function parseHeader(headers, headerName) {
10658
- const token = headers[headerName];
10659
- let tokenString;
10660
- if (typeof token === "string") {
10661
- tokenString = token;
10662
- } else if (Array.isArray(token) && token.length > 0) {
10663
- tokenString = token[0];
11437
+ function serializeRemoteEvalParametersContainer(parameters) {
11438
+ if (RemoteEvalParameters.isParameters(parameters)) {
11439
+ return {
11440
+ type: "braintrust.parameters",
11441
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
11442
+ schema: parameters.schema,
11443
+ source: {
11444
+ parametersId: parameters.id,
11445
+ slug: parameters.slug,
11446
+ name: parameters.name,
11447
+ projectId: parameters.projectId,
11448
+ version: parameters.version
11449
+ }
11450
+ };
10664
11451
  }
10665
- return tokenString;
11452
+ return {
11453
+ type: "braintrust.staticParameters",
11454
+ schema: serializeEvalParametersToStaticParametersSchema(parameters),
11455
+ source: null
11456
+ };
10666
11457
  }
10667
- function checkOrigin(requestOrigin, callback) {
10668
- if (!requestOrigin) {
10669
- return callback(null, true);
10670
- }
10671
- for (const origin of WHITELISTED_ORIGINS || []) {
10672
- if (origin instanceof RegExp && origin.test(requestOrigin) || origin === requestOrigin) {
10673
- return callback(null, requestOrigin);
11458
+ var ProjectNameIdMap = (_class20 = class {constructor() { _class20.prototype.__init68.call(this);_class20.prototype.__init69.call(this); }
11459
+ __init68() {this.nameToId = {}}
11460
+ __init69() {this.idToName = {}}
11461
+ async getId(projectName) {
11462
+ if (!(projectName in this.nameToId)) {
11463
+ const response = await _internalGetGlobalState().appConn().post_json("api/project/register", {
11464
+ project_name: projectName
11465
+ });
11466
+ const result = _v3.z.object({
11467
+ project: Project
11468
+ }).parse(response);
11469
+ const projectId = result.project.id;
11470
+ this.nameToId[projectName] = projectId;
11471
+ this.idToName[projectId] = projectName;
10674
11472
  }
11473
+ return this.nameToId[projectName];
10675
11474
  }
10676
- return callback(null, false);
10677
- }
10678
- var BRAINTRUST_AUTH_TOKEN_HEADER = "x-bt-auth-token";
10679
- var ORIGIN_HEADER = "origin";
10680
- var PROJECT_ID_HEADER = "x-bt-project-id";
10681
- function extractAllowedOrigin(originHeader) {
10682
- let allowedOrigin = MAIN_ORIGIN;
10683
- checkOrigin(originHeader, (err, origin) => {
10684
- if (!err && originHeader && origin) {
10685
- allowedOrigin = originHeader;
11475
+ async getName(projectId) {
11476
+ if (!(projectId in this.idToName)) {
11477
+ const response = await _internalGetGlobalState().appConn().post_json("api/project/get", {
11478
+ id: projectId
11479
+ });
11480
+ const result = _v3.z.array(Project).nonempty().parse(response);
11481
+ const projectName = result[0].name;
11482
+ this.idToName[projectId] = projectName;
11483
+ this.nameToId[projectName] = projectId;
10686
11484
  }
10687
- });
10688
- return allowedOrigin;
10689
- }
10690
- var MAIN_ORIGIN = "https://www.braintrust.dev";
10691
- var WHITELISTED_ORIGINS = [
10692
- MAIN_ORIGIN,
10693
- "https://www.braintrustdata.com",
10694
- new RegExp("https://.*.preview.braintrust.dev")
10695
- ].concat(
10696
- process.env.WHITELISTED_ORIGIN ? [process.env.WHITELISTED_ORIGIN] : []
10697
- ).concat(
10698
- process.env.BRAINTRUST_APP_URL ? [process.env.BRAINTRUST_APP_URL] : []
10699
- );
10700
- function parseAuthHeader(headers) {
10701
- const authHeader = headers["authorization"];
10702
- let authValue = null;
10703
- if (Array.isArray(authHeader)) {
10704
- authValue = authHeader[authHeader.length - 1];
10705
- } else {
10706
- authValue = authHeader;
10707
- }
10708
- if (!authValue) {
10709
- return null;
10710
- }
10711
- const parts = authValue.split(" ");
10712
- if (parts.length !== 2) {
10713
- return null;
11485
+ return this.idToName[projectId];
10714
11486
  }
10715
- return parts[1];
10716
- }
10717
- var baseAllowedHeaders = [
10718
- "Content-Type",
10719
- "X-Amz-Date",
10720
- "Authorization",
10721
- "X-Api-Key",
10722
- "X-Amz-Security-Token",
10723
- "x-bt-auth-token",
10724
- "x-bt-parent",
10725
- // These are eval-specific
10726
- "x-bt-org-name",
10727
- "x-bt-project-id",
10728
- "x-bt-stream-fmt",
10729
- "x-bt-use-cache",
10730
- "x-stainless-os",
10731
- "x-stainless-lang",
10732
- "x-stainless-package-version",
10733
- "x-stainless-runtime",
10734
- "x-stainless-runtime-version",
10735
- "x-stainless-arch"
10736
- ];
10737
-
10738
- // dev/stream.ts
10739
- function serializeSSEEvent(event) {
10740
- return Object.entries(event).filter(([_key, value]) => value !== void 0).map(([key, value]) => `${key}: ${value}`).join("\n") + "\n\n";
10741
- }
10742
-
10743
- // dev/types.ts
10744
-
10745
- var evalBodySchema = _v3.z.object({
10746
- name: _v3.z.string(),
10747
- parameters: _v3.z.record(_v3.z.string(), _v3.z.unknown()).nullish(),
10748
- data: RunEval.shape.data,
10749
- scores: _v3.z.array(
10750
- _v3.z.object({
10751
- function_id: FunctionId,
10752
- name: _v3.z.string()
10753
- })
10754
- ).nullish(),
10755
- experiment_name: _v3.z.string().nullish(),
10756
- project_id: _v3.z.string().nullish(),
10757
- parent: InvokeParent.optional(),
10758
- stream: _v3.z.boolean().optional()
10759
- });
10760
- var evalParametersSerializedSchema = _v3.z.record(
10761
- _v3.z.string(),
10762
- _v3.z.union([
10763
- _v3.z.object({
10764
- type: _v3.z.literal("prompt"),
10765
- default: PromptData.optional(),
10766
- description: _v3.z.string().optional()
10767
- }),
10768
- _v3.z.object({
10769
- type: _v3.z.literal("data"),
10770
- schema: _v3.z.record(_v3.z.unknown()),
10771
- // JSON Schema
10772
- default: _v3.z.unknown().optional(),
10773
- description: _v3.z.string().optional()
10774
- })
10775
- ])
10776
- );
10777
- var evaluatorDefinitionSchema = _v3.z.object({
10778
- parameters: evalParametersSerializedSchema.optional()
10779
- });
10780
- var evaluatorDefinitionsSchema = _v3.z.record(
10781
- _v3.z.string(),
10782
- evaluatorDefinitionSchema
10783
- );
10784
-
10785
- // dev/server.ts
10786
-
10787
-
10788
- // src/zod/utils.ts
10789
- var _zodtojsonschema = require('zod-to-json-schema');
10790
- var _v4 = require('zod/v4'); var z42 = _interopRequireWildcard(_v4);
10791
- function isZodV4(zodObject) {
10792
- return typeof zodObject === "object" && zodObject !== null && "_zod" in zodObject && zodObject._zod !== void 0;
10793
- }
10794
- function zodToJsonSchema(schema) {
10795
- if (isZodV4(schema)) {
10796
- return z42.toJSONSchema(schema, {
10797
- target: "draft-7"
10798
- });
11487
+ async resolve(project) {
11488
+ if (project.id) {
11489
+ return project.id;
11490
+ }
11491
+ return this.getId(project.name);
10799
11492
  }
10800
- return _zodtojsonschema.zodToJsonSchema.call(void 0, schema);
10801
- }
11493
+ }, _class20);
10802
11494
 
10803
11495
  // dev/server.ts
10804
11496
  function runDevServer(evaluators, opts) {
@@ -10835,20 +11527,27 @@ function runDevServer(evaluators, opts) {
10835
11527
  app.get("/", (req, res) => {
10836
11528
  res.send("Hello, world!");
10837
11529
  });
10838
- app.get("/list", checkAuthorized, (req, res) => {
10839
- const evalDefs = Object.fromEntries(
10840
- Object.entries(allEvaluators).map(([name, evaluator]) => [
10841
- name,
10842
- {
10843
- parameters: evaluator.parameters ? makeEvalParametersSchema(evaluator.parameters) : void 0,
11530
+ app.get(
11531
+ "/list",
11532
+ checkAuthorized,
11533
+ asyncHandler(async (req, res) => {
11534
+ const evalDefs = {};
11535
+ for (const [name, evaluator] of Object.entries(allEvaluators)) {
11536
+ let parameters;
11537
+ if (evaluator.parameters) {
11538
+ const resolvedParams = await Promise.resolve(evaluator.parameters);
11539
+ parameters = serializeRemoteEvalParametersContainer(resolvedParams);
11540
+ }
11541
+ evalDefs[name] = {
11542
+ parameters,
10844
11543
  scores: evaluator.scores.map((score, idx) => ({
10845
11544
  name: scorerName(score, idx)
10846
11545
  }))
10847
- }
10848
- ])
10849
- );
10850
- res.json(evalDefs);
10851
- });
11546
+ };
11547
+ }
11548
+ res.json(evalDefs);
11549
+ })
11550
+ );
10852
11551
  app.post(
10853
11552
  "/eval",
10854
11553
  checkAuthorized,
@@ -10863,7 +11562,7 @@ function runDevServer(evaluators, opts) {
10863
11562
  scores,
10864
11563
  stream
10865
11564
  } = evalBodySchema.parse(req.body);
10866
- if (!_optionalChain([req, 'access', _128 => _128.ctx, 'optionalAccess', _129 => _129.state])) {
11565
+ if (!_optionalChain([req, 'access', _131 => _131.ctx, 'optionalAccess', _132 => _132.state])) {
10867
11566
  res.status(500).json({ error: "Braintrust state not initialized in request" });
10868
11567
  return;
10869
11568
  }
@@ -10873,18 +11572,12 @@ function runDevServer(evaluators, opts) {
10873
11572
  res.status(404).json({ error: `Evaluator '${name}' not found` });
10874
11573
  return;
10875
11574
  }
10876
- if (evaluator.parameters && Object.keys(evaluator.parameters).length > 0) {
11575
+ if (evaluator.parameters) {
10877
11576
  try {
10878
- if (!evaluator.parameters) {
10879
- res.status(400).json({
10880
- error: `Evaluator '${name}' does not accept parameters`
10881
- });
10882
- return;
10883
- }
10884
- validateParameters(_nullishCoalesce(parameters, () => ( {})), evaluator.parameters);
11577
+ await validateParameters(_nullishCoalesce(parameters, () => ( {})), evaluator.parameters);
10885
11578
  } catch (e) {
10886
11579
  console.error("Error validating parameters", e);
10887
- if (e instanceof _v3.z.ZodError || e instanceof Error) {
11580
+ if (e instanceof _v3.z.ZodError || e instanceof _ajv.ValidationError || e instanceof Error) {
10888
11581
  res.status(400).json({
10889
11582
  error: e.message
10890
11583
  });
@@ -10920,12 +11613,12 @@ function runDevServer(evaluators, opts) {
10920
11613
  ...evaluator,
10921
11614
  data: evalData.data,
10922
11615
  scores: evaluator.scores.concat(
10923
- _nullishCoalesce(_optionalChain([scores, 'optionalAccess', _130 => _130.map, 'call', _131 => _131(
11616
+ _nullishCoalesce(_optionalChain([scores, 'optionalAccess', _133 => _133.map, 'call', _134 => _134(
10924
11617
  (score) => makeScorer(
10925
11618
  state,
10926
11619
  score.name,
10927
11620
  score.function_id,
10928
- _optionalChain([req, 'access', _132 => _132.ctx, 'optionalAccess', _133 => _133.projectId])
11621
+ _optionalChain([req, 'access', _135 => _135.ctx, 'optionalAccess', _136 => _136.projectId])
10929
11622
  )
10930
11623
  )]), () => ( []))
10931
11624
  ),
@@ -11077,33 +11770,6 @@ function makeScorer(state, name, score, projectId) {
11077
11770
  });
11078
11771
  return ret;
11079
11772
  }
11080
- function makeEvalParametersSchema(parameters) {
11081
- return Object.fromEntries(
11082
- Object.entries(parameters).map(([name, value]) => {
11083
- if ("type" in value && value.type === "prompt") {
11084
- return [
11085
- name,
11086
- {
11087
- type: "prompt",
11088
- default: value.default ? promptDefinitionToPromptData(value.default) : void 0,
11089
- description: value.description
11090
- }
11091
- ];
11092
- } else {
11093
- const schemaObj = zodToJsonSchema(value);
11094
- return [
11095
- name,
11096
- {
11097
- type: "data",
11098
- schema: schemaObj,
11099
- default: schemaObj.default,
11100
- description: schemaObj.description
11101
- }
11102
- ];
11103
- }
11104
- })
11105
- );
11106
- }
11107
11773
 
11108
11774
  // dev/index.ts
11109
11775
  configureNode();