@axlsdk/studio 0.23.2 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/{chunk-Z374DI7D.js → chunk-PFPLZQ5X.js} +672 -62
- package/dist/chunk-PFPLZQ5X.js.map +1 -0
- package/dist/cli.cjs +670 -60
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/client/assets/index-CuWKncEa.js +320 -0
- package/dist/client/assets/index-DinaGVe2.css +1 -0
- package/dist/client/index.html +2 -2
- package/dist/middleware.cjs +670 -60
- package/dist/middleware.cjs.map +1 -1
- package/dist/middleware.js +1 -1
- package/dist/server/index.cjs +670 -60
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +28 -0
- package/dist/server/index.d.ts +28 -0
- package/dist/server/index.js +1 -1
- package/package.json +4 -4
- package/dist/chunk-Z374DI7D.js.map +0 -1
- package/dist/client/assets/index-7nGvwNtb.js +0 -318
- package/dist/client/assets/index-Bc4iQdXy.css +0 -1
package/dist/server/index.cjs
CHANGED
|
@@ -134,42 +134,177 @@ function sanitizeRichInputFailure(event) {
|
|
|
134
134
|
}
|
|
135
135
|
return event;
|
|
136
136
|
}
|
|
137
|
+
var MEASURED_METADATA_KEYS = /* @__PURE__ */ new Set([
|
|
138
|
+
"models",
|
|
139
|
+
"modelCallCounts",
|
|
140
|
+
"workflows",
|
|
141
|
+
"workflowCallCounts",
|
|
142
|
+
"tokens",
|
|
143
|
+
"agentCalls"
|
|
144
|
+
]);
|
|
145
|
+
function redactItemMetadata(metadata) {
|
|
146
|
+
if (!metadata) return metadata;
|
|
147
|
+
const out = {};
|
|
148
|
+
for (const [key, value] of Object.entries(metadata)) {
|
|
149
|
+
out[key] = MEASURED_METADATA_KEYS.has(key) ? value : REDACTED;
|
|
150
|
+
}
|
|
151
|
+
return out;
|
|
152
|
+
}
|
|
153
|
+
function projectItemFailure(failure) {
|
|
154
|
+
if (!failure || typeof failure !== "object") return void 0;
|
|
155
|
+
const f = failure;
|
|
156
|
+
if (typeof f.name !== "string") return void 0;
|
|
157
|
+
return {
|
|
158
|
+
name: f.name,
|
|
159
|
+
...typeof f.provider === "string" ? { provider: f.provider } : {},
|
|
160
|
+
...typeof f.status === "number" && Number.isFinite(f.status) ? { status: f.status } : {},
|
|
161
|
+
...typeof f.retryable === "boolean" ? { retryable: f.retryable } : {},
|
|
162
|
+
...typeof f.requestId === "string" ? { requestId: f.requestId } : {}
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
function isPlainObject(value) {
|
|
166
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
167
|
+
}
|
|
168
|
+
function redactScorerDetail(detail) {
|
|
169
|
+
if (!isPlainObject(detail)) return REDACTED;
|
|
170
|
+
const d = detail;
|
|
171
|
+
return {
|
|
172
|
+
score: d.score,
|
|
173
|
+
...d.duration !== void 0 ? { duration: d.duration } : {},
|
|
174
|
+
...d.cost !== void 0 ? { cost: d.cost } : {},
|
|
175
|
+
// `skipped` is a structural boolean (the `applies` predicate verdict),
|
|
176
|
+
// not user/LLM content — preserve it so the client's N/A chip renders.
|
|
177
|
+
...d.skipped !== void 0 ? { skipped: d.skipped } : {},
|
|
178
|
+
// `outcome` and `accounting` are structural (a classification and a set
|
|
179
|
+
// of counts), so they survive redaction the way `skipped` does — without
|
|
180
|
+
// them a compliance-mode reader cannot tell a judge that was stopped on
|
|
181
|
+
// budget from one that scored 0.
|
|
182
|
+
...d.outcome !== void 0 ? { outcome: d.outcome } : {},
|
|
183
|
+
...d.accounting !== void 0 ? { accounting: d.accounting } : {},
|
|
184
|
+
// `diagnostics` survives for the same reason `accounting` does: it is a
|
|
185
|
+
// list of operation ids and statuses, not content.
|
|
186
|
+
...d.diagnostics !== void 0 ? { diagnostics: d.diagnostics } : {}
|
|
187
|
+
// metadata deliberately omitted — may contain LLM scorer reasoning
|
|
188
|
+
};
|
|
189
|
+
}
|
|
137
190
|
function redactEvalItem(item) {
|
|
191
|
+
if (!isPlainObject(item)) return REDACTED;
|
|
192
|
+
const { failure, ...rest } = item;
|
|
193
|
+
const typed = item;
|
|
194
|
+
const projectedFailure = failure !== void 0 ? projectItemFailure(failure) : void 0;
|
|
138
195
|
const scrubbed = {
|
|
139
|
-
...
|
|
196
|
+
...rest,
|
|
197
|
+
...projectedFailure ? { failure: projectedFailure } : {},
|
|
140
198
|
input: REDACTED,
|
|
141
199
|
output: REDACTED,
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
200
|
+
// `diagnostics` is spread through untouched on purpose: it holds operation
|
|
201
|
+
// IDs, kinds, turn/attempt indexes and a status — pointers into an artifact,
|
|
202
|
+
// never content. The records themselves are redacted by the core rule at
|
|
203
|
+
// both write time and delivery time (`redactRecordLine`).
|
|
204
|
+
...typed.metadata !== void 0 ? {
|
|
205
|
+
metadata: isPlainObject(typed.metadata) ? redactItemMetadata(typed.metadata) : REDACTED
|
|
206
|
+
} : {},
|
|
207
|
+
...typed.annotations !== void 0 ? { annotations: REDACTED } : {},
|
|
208
|
+
...typed.error !== void 0 ? { error: REDACTED } : {},
|
|
209
|
+
...typed.scorerErrors !== void 0 ? {
|
|
210
|
+
scorerErrors: Array.isArray(typed.scorerErrors) ? typed.scorerErrors.map(() => REDACTED) : REDACTED
|
|
211
|
+
} : {},
|
|
212
|
+
// `callerReport.metadata` is whatever the workflow callback returned — free-
|
|
213
|
+
// form user content, exactly like `output`, so it is dropped rather than
|
|
214
|
+
// masked (same treatment as scorer metadata below). Its sibling `cost` is a
|
|
215
|
+
// plain number and stays. (`outcome` and `accounting` are spread through
|
|
216
|
+
// untouched: both are structural counts and classifications, no content.)
|
|
217
|
+
...typed.callerReport !== void 0 ? {
|
|
218
|
+
callerReport: isPlainObject(typed.callerReport) ? typeof typed.callerReport.cost === "number" ? { cost: typed.callerReport.cost } : {} : REDACTED
|
|
219
|
+
} : {}
|
|
220
|
+
};
|
|
221
|
+
if (typed.scoreDetails !== void 0) {
|
|
222
|
+
if (isPlainObject(typed.scoreDetails)) {
|
|
223
|
+
const detailsOut = {};
|
|
224
|
+
for (const [name, detail] of Object.entries(typed.scoreDetails)) {
|
|
225
|
+
detailsOut[name] = redactScorerDetail(detail);
|
|
226
|
+
}
|
|
227
|
+
scrubbed.scoreDetails = detailsOut;
|
|
228
|
+
} else {
|
|
229
|
+
scrubbed.scoreDetails = REDACTED;
|
|
158
230
|
}
|
|
159
|
-
scrubbed.scoreDetails = detailsOut;
|
|
160
231
|
}
|
|
161
232
|
return scrubbed;
|
|
162
233
|
}
|
|
163
234
|
function redactEvalResult(result, redact) {
|
|
164
235
|
if (!redact) return result;
|
|
165
|
-
|
|
166
|
-
|
|
236
|
+
return redactResultShape(result);
|
|
237
|
+
}
|
|
238
|
+
function redactResultShape(result) {
|
|
239
|
+
const scrubbedMetadata = redactResultMetadata(result.metadata);
|
|
240
|
+
const hasMultiRun = "_multiRun" in result;
|
|
241
|
+
const multiRun = result._multiRun;
|
|
167
242
|
return {
|
|
168
243
|
...result,
|
|
169
244
|
metadata: scrubbedMetadata,
|
|
170
|
-
items: result.items.map(redactEvalItem)
|
|
245
|
+
items: Array.isArray(result.items) ? result.items.map(redactEvalItem) : REDACTED,
|
|
246
|
+
...hasMultiRun && multiRun !== void 0 ? {
|
|
247
|
+
_multiRun: isPlainObject(multiRun) ? redactMultiRun(multiRun) : REDACTED
|
|
248
|
+
} : {}
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
function redactResultMetadata(metadata) {
|
|
252
|
+
const meta3 = metadata;
|
|
253
|
+
return isPlainObject(meta3) && typeof meta3.batchFailure === "string" ? { ...meta3, batchFailure: REDACTED } : metadata;
|
|
254
|
+
}
|
|
255
|
+
function redactMultiRun(multiRun) {
|
|
256
|
+
const { allRuns } = multiRun;
|
|
257
|
+
return {
|
|
258
|
+
...multiRun,
|
|
259
|
+
...allRuns !== void 0 ? {
|
|
260
|
+
allRuns: Array.isArray(allRuns) ? allRuns.map(
|
|
261
|
+
(run) => isPlainObject(run) && Array.isArray(run.items) ? redactResultShape(run) : REDACTED
|
|
262
|
+
) : REDACTED
|
|
263
|
+
} : {},
|
|
264
|
+
...typeof multiRun.batchFailure === "string" ? { batchFailure: REDACTED } : {}
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
function redactEvalComparison(comparison, redact) {
|
|
268
|
+
if (!redact) return comparison;
|
|
269
|
+
const maskInput = (r) => ({ ...r, input: REDACTED });
|
|
270
|
+
const side = (s) => ({
|
|
271
|
+
...s,
|
|
272
|
+
metadata: redactResultMetadata(s.metadata)
|
|
273
|
+
});
|
|
274
|
+
return {
|
|
275
|
+
...comparison,
|
|
276
|
+
baseline: side(comparison.baseline),
|
|
277
|
+
candidate: side(comparison.candidate),
|
|
278
|
+
regressions: comparison.regressions.map(maskInput),
|
|
279
|
+
improvements: comparison.improvements.map(maskInput)
|
|
171
280
|
};
|
|
172
281
|
}
|
|
282
|
+
function redactRecordLine(line, redact) {
|
|
283
|
+
if (!redact) return line;
|
|
284
|
+
let parsed;
|
|
285
|
+
try {
|
|
286
|
+
parsed = JSON.parse(line);
|
|
287
|
+
} catch {
|
|
288
|
+
const stub = {
|
|
289
|
+
v: 1,
|
|
290
|
+
phase: "end",
|
|
291
|
+
operationId: "unknown",
|
|
292
|
+
kind: "chat",
|
|
293
|
+
transportAttempts: 1,
|
|
294
|
+
provider: "unknown",
|
|
295
|
+
model: "unknown",
|
|
296
|
+
termination: "the stored record could not be parsed",
|
|
297
|
+
captured: {
|
|
298
|
+
fidelity: "runtime_request",
|
|
299
|
+
redacted: true,
|
|
300
|
+
truncated: true,
|
|
301
|
+
omitted: ["record"]
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
return JSON.stringify(stub);
|
|
305
|
+
}
|
|
306
|
+
return JSON.stringify((0, import_axl.redactCapturedRequest)(parsed));
|
|
307
|
+
}
|
|
173
308
|
function redactEvalHistoryEntry(entry, redact) {
|
|
174
309
|
if (!redact) return entry;
|
|
175
310
|
return {
|
|
@@ -946,7 +1081,50 @@ function reduceCost(acc, event) {
|
|
|
946
1081
|
};
|
|
947
1082
|
}
|
|
948
1083
|
function emptyEvalTrendData() {
|
|
949
|
-
return { byEval: {}, totalRuns: 0, totalCost: 0 };
|
|
1084
|
+
return { byEval: {}, totalRuns: 0, totalCost: 0, totalCostCompleteness: "complete" };
|
|
1085
|
+
}
|
|
1086
|
+
function worse(a, b) {
|
|
1087
|
+
if (a === "unverified" || b === "unverified") return "unverified";
|
|
1088
|
+
if (a === "incomplete" || b === "incomplete") return "incomplete";
|
|
1089
|
+
return "complete";
|
|
1090
|
+
}
|
|
1091
|
+
function extractAccounting(data) {
|
|
1092
|
+
const result = data ?? {};
|
|
1093
|
+
const accounting = result.accounting;
|
|
1094
|
+
if (!accounting || typeof accounting !== "object") {
|
|
1095
|
+
return { cost: usable(extractCost(data)), completeness: "unverified", budgetStopped: false };
|
|
1096
|
+
}
|
|
1097
|
+
const completeness = accounting.completeness === "complete" || accounting.completeness === "incomplete" ? accounting.completeness : "unverified";
|
|
1098
|
+
const knownCost = usable(accounting.knownCost);
|
|
1099
|
+
const summary = result.summary;
|
|
1100
|
+
return {
|
|
1101
|
+
cost: knownCost,
|
|
1102
|
+
completeness,
|
|
1103
|
+
budgetStopped: isBudgetStopped(accounting.budget?.status, summary?.coverage)
|
|
1104
|
+
};
|
|
1105
|
+
}
|
|
1106
|
+
function usable(value) {
|
|
1107
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : 0;
|
|
1108
|
+
}
|
|
1109
|
+
function refusedWork(coverage) {
|
|
1110
|
+
if (!coverage || typeof coverage !== "object") return 0;
|
|
1111
|
+
const { items, scorers } = coverage;
|
|
1112
|
+
let refused = count(items, "budget_skipped") + count(items, "budget_interrupted");
|
|
1113
|
+
if (scorers && typeof scorers === "object") {
|
|
1114
|
+
for (const s of Object.values(scorers)) {
|
|
1115
|
+
refused += count(s, "budget_skipped") + count(s, "budget_interrupted");
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
return refused;
|
|
1119
|
+
}
|
|
1120
|
+
function count(block, key) {
|
|
1121
|
+
if (!block || typeof block !== "object") return 0;
|
|
1122
|
+
const value = block[key];
|
|
1123
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
|
|
1124
|
+
}
|
|
1125
|
+
function isBudgetStopped(status, coverage) {
|
|
1126
|
+
if (status !== "closed") return false;
|
|
1127
|
+
return refusedWork(coverage) > 0;
|
|
950
1128
|
}
|
|
951
1129
|
function extractScores(data) {
|
|
952
1130
|
if (!data || typeof data !== "object") return {};
|
|
@@ -1013,7 +1191,7 @@ function computeScoreStats(runs) {
|
|
|
1013
1191
|
}
|
|
1014
1192
|
function reduceEvalTrends(acc, entry) {
|
|
1015
1193
|
const scores = extractScores(entry.data);
|
|
1016
|
-
const cost =
|
|
1194
|
+
const { cost, completeness, budgetStopped } = extractAccounting(entry.data);
|
|
1017
1195
|
const model = extractModel(entry.data);
|
|
1018
1196
|
const duration3 = extractDuration(entry.data);
|
|
1019
1197
|
const metadata = entry.data?.metadata;
|
|
@@ -1024,6 +1202,8 @@ function reduceEvalTrends(acc, entry) {
|
|
|
1024
1202
|
id: entry.id,
|
|
1025
1203
|
scores,
|
|
1026
1204
|
cost,
|
|
1205
|
+
completeness,
|
|
1206
|
+
...budgetStopped ? { budgetStopped: true } : {},
|
|
1027
1207
|
...model !== void 0 ? { model } : {},
|
|
1028
1208
|
...duration3 !== void 0 ? { duration: duration3 } : {},
|
|
1029
1209
|
...runGroupId !== void 0 ? { runGroupId } : {},
|
|
@@ -1042,12 +1222,15 @@ function reduceEvalTrends(acc, entry) {
|
|
|
1042
1222
|
scoreMean: mean,
|
|
1043
1223
|
scoreStd: std,
|
|
1044
1224
|
costTotal: (prev?.costTotal ?? 0) + cost,
|
|
1225
|
+
costCompleteness: worse(prev?.costCompleteness ?? "complete", completeness),
|
|
1226
|
+
budgetStoppedRuns: (prev?.budgetStoppedRuns ?? 0) + (budgetStopped ? 1 : 0),
|
|
1045
1227
|
runCount: (prev?.runCount ?? 0) + 1
|
|
1046
1228
|
};
|
|
1047
1229
|
return {
|
|
1048
1230
|
byEval,
|
|
1049
1231
|
totalRuns: acc.totalRuns + 1,
|
|
1050
|
-
totalCost: acc.totalCost + cost
|
|
1232
|
+
totalCost: acc.totalCost + cost,
|
|
1233
|
+
totalCostCompleteness: worse(acc.totalCostCompleteness ?? "complete", completeness)
|
|
1051
1234
|
};
|
|
1052
1235
|
}
|
|
1053
1236
|
var MAX_DURATIONS = 200;
|
|
@@ -1369,21 +1552,32 @@ var executions_default = createExecutionRoutes();
|
|
|
1369
1552
|
|
|
1370
1553
|
// src/server/routes/sessions.ts
|
|
1371
1554
|
var import_hono4 = require("hono");
|
|
1555
|
+
function mediaFields(source) {
|
|
1556
|
+
const bytes = source.type === "bytes" ? source.data.byteLength : source.type === "base64" ? Math.floor(source.data.length * 3 / 4) - (source.data.endsWith("==") ? 2 : source.data.endsWith("=") ? 1 : 0) : void 0;
|
|
1557
|
+
return {
|
|
1558
|
+
source: source.type,
|
|
1559
|
+
...source.mediaType ? { mediaType: source.mediaType } : {},
|
|
1560
|
+
...bytes !== void 0 ? { bytes } : {}
|
|
1561
|
+
};
|
|
1562
|
+
}
|
|
1372
1563
|
function describeStudioInput(content) {
|
|
1373
1564
|
if (typeof content === "string") return void 0;
|
|
1374
1565
|
return {
|
|
1375
1566
|
parts: content.map((part) => {
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1567
|
+
switch (part.type) {
|
|
1568
|
+
case "text":
|
|
1569
|
+
return { type: "text", characters: part.text.length };
|
|
1570
|
+
case "image":
|
|
1571
|
+
return { type: "image", ...mediaFields(part.source) };
|
|
1572
|
+
case "audio":
|
|
1573
|
+
return { type: "audio", ...mediaFields(part.source) };
|
|
1574
|
+
default: {
|
|
1575
|
+
const unreachable = part;
|
|
1576
|
+
throw new Error(
|
|
1577
|
+
`unsupported model input part: ${String(unreachable.type)}`
|
|
1578
|
+
);
|
|
1579
|
+
}
|
|
1580
|
+
}
|
|
1387
1581
|
})
|
|
1388
1582
|
};
|
|
1389
1583
|
}
|
|
@@ -1737,6 +1931,184 @@ function createCostRoutes(costAggregator) {
|
|
|
1737
1931
|
// src/server/routes/evals.ts
|
|
1738
1932
|
var import_node_crypto = require("crypto");
|
|
1739
1933
|
var import_hono10 = require("hono");
|
|
1934
|
+
|
|
1935
|
+
// src/server/eval-import.ts
|
|
1936
|
+
var ITEM_OUTCOMES = [
|
|
1937
|
+
"completed",
|
|
1938
|
+
"failed",
|
|
1939
|
+
"cancelled",
|
|
1940
|
+
"budget_skipped",
|
|
1941
|
+
"budget_interrupted"
|
|
1942
|
+
];
|
|
1943
|
+
var SCORER_OUTCOMES = [
|
|
1944
|
+
"scored",
|
|
1945
|
+
"failed",
|
|
1946
|
+
"skipped",
|
|
1947
|
+
"cancelled",
|
|
1948
|
+
"budget_skipped",
|
|
1949
|
+
"budget_interrupted"
|
|
1950
|
+
];
|
|
1951
|
+
var EPSILON = 1e-9;
|
|
1952
|
+
function isFiniteNonNegative(value) {
|
|
1953
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0;
|
|
1954
|
+
}
|
|
1955
|
+
function isCount(value) {
|
|
1956
|
+
return isFiniteNonNegative(value) && Number.isInteger(value);
|
|
1957
|
+
}
|
|
1958
|
+
function isValidImportedBudget(value) {
|
|
1959
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
1960
|
+
const b = value;
|
|
1961
|
+
if (!isFiniteNonNegative(b.limit)) return false;
|
|
1962
|
+
if (!isFiniteNonNegative(b.knownSpend)) return false;
|
|
1963
|
+
if (!isFiniteNonNegative(b.knownOvershoot)) return false;
|
|
1964
|
+
if (b.status !== "open" && b.status !== "closed") return false;
|
|
1965
|
+
if (b.closedBy !== void 0 && b.closedBy !== "case" && b.closedBy !== "scorer" && b.closedBy !== "operation") {
|
|
1966
|
+
return false;
|
|
1967
|
+
}
|
|
1968
|
+
if (b.knownSpend >= b.limit !== (b.status === "closed")) return false;
|
|
1969
|
+
const expected = Math.max(0, b.knownSpend - b.limit);
|
|
1970
|
+
return Math.abs(b.knownOvershoot - expected) <= EPSILON;
|
|
1971
|
+
}
|
|
1972
|
+
function isValidImportedCoverage(value) {
|
|
1973
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
1974
|
+
const c = value;
|
|
1975
|
+
if (!c.items || typeof c.items !== "object" || Array.isArray(c.items)) return false;
|
|
1976
|
+
const items = c.items;
|
|
1977
|
+
for (const key of ITEM_OUTCOMES) {
|
|
1978
|
+
if (!isCount(items[key])) return false;
|
|
1979
|
+
}
|
|
1980
|
+
if (!c.scorers || typeof c.scorers !== "object" || Array.isArray(c.scorers)) return false;
|
|
1981
|
+
for (const bucket of Object.values(c.scorers)) {
|
|
1982
|
+
if (!bucket || typeof bucket !== "object" || Array.isArray(bucket)) return false;
|
|
1983
|
+
const counts = bucket;
|
|
1984
|
+
for (const key of SCORER_OUTCOMES) {
|
|
1985
|
+
if (!isCount(counts[key])) return false;
|
|
1986
|
+
}
|
|
1987
|
+
}
|
|
1988
|
+
return true;
|
|
1989
|
+
}
|
|
1990
|
+
function isValidImportedItemErrorRate(value) {
|
|
1991
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
1992
|
+
const r = value;
|
|
1993
|
+
const { failed, attempted, rate, limit, exceeded } = r;
|
|
1994
|
+
if (!isCount(failed) || !isCount(attempted) || failed > attempted) return false;
|
|
1995
|
+
if (!isFiniteNonNegative(limit) || limit > 1) return false;
|
|
1996
|
+
if (typeof rate !== "number" || typeof exceeded !== "boolean") return false;
|
|
1997
|
+
const expectedRate = attempted > 0 ? failed / attempted : 0;
|
|
1998
|
+
if (Math.abs(rate - expectedRate) > EPSILON) return false;
|
|
1999
|
+
return exceeded === (attempted > 0 && rate > limit);
|
|
2000
|
+
}
|
|
2001
|
+
function isValidImportedMultiRun(value) {
|
|
2002
|
+
if (!isPlainRecord(value)) return false;
|
|
2003
|
+
const { allRuns } = value;
|
|
2004
|
+
if (allRuns === void 0) return true;
|
|
2005
|
+
if (!Array.isArray(allRuns)) return false;
|
|
2006
|
+
return allRuns.every(
|
|
2007
|
+
(run) => isPlainRecord(run) && Array.isArray(run.items) && run.items.every(isPlainRecord)
|
|
2008
|
+
);
|
|
2009
|
+
}
|
|
2010
|
+
function isPlainRecord(value) {
|
|
2011
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2012
|
+
}
|
|
2013
|
+
function sumOf(record2) {
|
|
2014
|
+
if (record2 === void 0) return 0;
|
|
2015
|
+
if (record2 === null || typeof record2 !== "object" || Array.isArray(record2)) return void 0;
|
|
2016
|
+
let total = 0;
|
|
2017
|
+
for (const value of Object.values(record2)) {
|
|
2018
|
+
if (!isFiniteNonNegative(value)) return void 0;
|
|
2019
|
+
total += value;
|
|
2020
|
+
}
|
|
2021
|
+
return total;
|
|
2022
|
+
}
|
|
2023
|
+
function allNumeric(record2) {
|
|
2024
|
+
if (record2 === void 0) return true;
|
|
2025
|
+
if (record2 === null || typeof record2 !== "object" || Array.isArray(record2)) return false;
|
|
2026
|
+
return Object.values(record2).every(
|
|
2027
|
+
(value) => typeof value === "number" && Number.isFinite(value)
|
|
2028
|
+
);
|
|
2029
|
+
}
|
|
2030
|
+
function isValidImportedAccounting(value) {
|
|
2031
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
2032
|
+
const a = value;
|
|
2033
|
+
if (a.version !== 1) return false;
|
|
2034
|
+
if (a.currency !== "USD") return false;
|
|
2035
|
+
if (!isFiniteNonNegative(a.knownCost)) return false;
|
|
2036
|
+
if (a.completeness !== "complete" && a.completeness !== "incomplete" && a.completeness !== "unverified") {
|
|
2037
|
+
return false;
|
|
2038
|
+
}
|
|
2039
|
+
if (!allNumeric(a.reasons)) return false;
|
|
2040
|
+
if (!allNumeric(a.usage)) return false;
|
|
2041
|
+
const ops = a.operations;
|
|
2042
|
+
if (!ops || typeof ops !== "object") return false;
|
|
2043
|
+
for (const key of ["total", "settled", "unknown", "denied"]) {
|
|
2044
|
+
if (!isFiniteNonNegative(ops[key])) return false;
|
|
2045
|
+
}
|
|
2046
|
+
if (!allNumeric(ops.byKind)) return false;
|
|
2047
|
+
if (ops.total !== ops.settled + ops.unknown) return false;
|
|
2048
|
+
if (a.completeness === "unverified") return true;
|
|
2049
|
+
const provenanceTotal = sumOf(a.provenance);
|
|
2050
|
+
if (provenanceTotal === void 0) return false;
|
|
2051
|
+
if (Math.abs(provenanceTotal - a.knownCost) > EPSILON) return false;
|
|
2052
|
+
const breakdown = a.breakdown;
|
|
2053
|
+
if (!breakdown || typeof breakdown !== "object") return false;
|
|
2054
|
+
const breakdownTotal = sumOf({
|
|
2055
|
+
generation: breakdown.generation,
|
|
2056
|
+
judging: breakdown.judging,
|
|
2057
|
+
external: breakdown.external
|
|
2058
|
+
});
|
|
2059
|
+
if (breakdownTotal === void 0) return false;
|
|
2060
|
+
if (Math.abs(breakdownTotal - a.knownCost) > EPSILON) return false;
|
|
2061
|
+
return true;
|
|
2062
|
+
}
|
|
2063
|
+
function importedAccountingIsTrustworthy(result) {
|
|
2064
|
+
if (!result || typeof result !== "object") return false;
|
|
2065
|
+
const r = result;
|
|
2066
|
+
if (r.accounting !== void 0 && !isValidImportedAccounting(r.accounting)) return false;
|
|
2067
|
+
const budget = r.accounting?.budget;
|
|
2068
|
+
if (budget !== void 0 && !isValidImportedBudget(budget)) return false;
|
|
2069
|
+
const coverage = r.summary?.coverage;
|
|
2070
|
+
if (coverage !== void 0 && !isValidImportedCoverage(coverage)) return false;
|
|
2071
|
+
if (!Array.isArray(r.items)) return true;
|
|
2072
|
+
for (const item of r.items) {
|
|
2073
|
+
if (!item || typeof item !== "object") continue;
|
|
2074
|
+
const i = item;
|
|
2075
|
+
if (i.accounting !== void 0 && !isValidImportedAccounting(i.accounting)) return false;
|
|
2076
|
+
if (i.scoreDetails && typeof i.scoreDetails === "object") {
|
|
2077
|
+
for (const detail of Object.values(i.scoreDetails)) {
|
|
2078
|
+
const d = detail;
|
|
2079
|
+
if (d?.accounting !== void 0 && !isValidImportedAccounting(d.accounting)) return false;
|
|
2080
|
+
}
|
|
2081
|
+
}
|
|
2082
|
+
}
|
|
2083
|
+
return true;
|
|
2084
|
+
}
|
|
2085
|
+
function stripAccounting(result) {
|
|
2086
|
+
const copy = structuredClone(result);
|
|
2087
|
+
delete copy.accounting;
|
|
2088
|
+
const summary = copy.summary;
|
|
2089
|
+
if (summary && typeof summary === "object") {
|
|
2090
|
+
delete summary.coverage;
|
|
2091
|
+
}
|
|
2092
|
+
const items = copy.items;
|
|
2093
|
+
if (Array.isArray(items)) {
|
|
2094
|
+
for (const item of items) {
|
|
2095
|
+
if (!item || typeof item !== "object") continue;
|
|
2096
|
+
const i = item;
|
|
2097
|
+
delete i.accounting;
|
|
2098
|
+
const details = i.scoreDetails;
|
|
2099
|
+
if (details && typeof details === "object") {
|
|
2100
|
+
for (const detail of Object.values(details)) {
|
|
2101
|
+
if (detail && typeof detail === "object") {
|
|
2102
|
+
delete detail.accounting;
|
|
2103
|
+
}
|
|
2104
|
+
}
|
|
2105
|
+
}
|
|
2106
|
+
}
|
|
2107
|
+
}
|
|
2108
|
+
return copy;
|
|
2109
|
+
}
|
|
2110
|
+
|
|
2111
|
+
// src/server/routes/evals.ts
|
|
1740
2112
|
function createEvalRoutes(connMgr, evalLoader) {
|
|
1741
2113
|
const app5 = new import_hono10.Hono();
|
|
1742
2114
|
const activeRuns = /* @__PURE__ */ new Map();
|
|
@@ -1784,6 +2156,7 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
1784
2156
|
let runs = 1;
|
|
1785
2157
|
let stream = false;
|
|
1786
2158
|
let captureTraces = false;
|
|
2159
|
+
let captureRequests = false;
|
|
1787
2160
|
try {
|
|
1788
2161
|
const body = await c.req.json().catch(() => ({}));
|
|
1789
2162
|
if (typeof body.runs === "number" && Number.isFinite(body.runs) && body.runs > 1) {
|
|
@@ -1795,6 +2168,9 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
1795
2168
|
if (body.captureTraces === true) {
|
|
1796
2169
|
captureTraces = true;
|
|
1797
2170
|
}
|
|
2171
|
+
if (body.captureRequests === true) {
|
|
2172
|
+
captureRequests = true;
|
|
2173
|
+
}
|
|
1798
2174
|
} catch {
|
|
1799
2175
|
}
|
|
1800
2176
|
if (stream) {
|
|
@@ -1818,6 +2194,7 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
1818
2194
|
metadata: { runGroupId, runIndex: r, batchAttempted: runs },
|
|
1819
2195
|
signal: ac.signal,
|
|
1820
2196
|
captureTraces,
|
|
2197
|
+
captureRequests,
|
|
1821
2198
|
onProgress: (event) => {
|
|
1822
2199
|
if (event.type === "run_done") return;
|
|
1823
2200
|
connMgr.broadcastWithWildcard(`eval:${evalRunId}`, {
|
|
@@ -1890,6 +2267,7 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
1890
2267
|
const result = await runtime.runRegisteredEval(name, {
|
|
1891
2268
|
signal: ac.signal,
|
|
1892
2269
|
captureTraces,
|
|
2270
|
+
captureRequests,
|
|
1893
2271
|
onProgress: (event) => {
|
|
1894
2272
|
if (event.type === "run_done") return;
|
|
1895
2273
|
connMgr.broadcastWithWildcard(`eval:${evalRunId}`, event);
|
|
@@ -1921,7 +2299,8 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
1921
2299
|
try {
|
|
1922
2300
|
const result2 = await runtime.runRegisteredEval(name, {
|
|
1923
2301
|
metadata: { runGroupId, runIndex: r, batchAttempted: runs },
|
|
1924
|
-
captureTraces
|
|
2302
|
+
captureTraces,
|
|
2303
|
+
captureRequests
|
|
1925
2304
|
});
|
|
1926
2305
|
results.push(result2);
|
|
1927
2306
|
} catch (err) {
|
|
@@ -1937,11 +2316,14 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
1937
2316
|
const partial2 = results.length < runs;
|
|
1938
2317
|
const failureMsg = runFailure ? redactErrorMessage(runFailure, redactOn) || String(runFailure) || void 0 : void 0;
|
|
1939
2318
|
const aggDegraded = unionDegradedScorers(results);
|
|
2319
|
+
const worstItemRate = worstItemErrorRate(results);
|
|
2320
|
+
const { modelTiming: _runOneModelTiming, ...firstSummary } = first.summary;
|
|
1940
2321
|
const result = {
|
|
1941
2322
|
...first,
|
|
1942
2323
|
summary: {
|
|
1943
|
-
...
|
|
1944
|
-
...aggDegraded.length > 0 ? { degraded: aggDegraded } : {}
|
|
2324
|
+
...firstSummary,
|
|
2325
|
+
...aggDegraded.length > 0 ? { degraded: aggDegraded } : {},
|
|
2326
|
+
...worstItemRate ? { itemErrorRate: worstItemRate } : {}
|
|
1945
2327
|
},
|
|
1946
2328
|
_multiRun: {
|
|
1947
2329
|
aggregate,
|
|
@@ -1959,7 +2341,10 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
1959
2341
|
data: redactEvalResult(result, redactOn)
|
|
1960
2342
|
});
|
|
1961
2343
|
} else {
|
|
1962
|
-
const result = await runtime.runRegisteredEval(name, {
|
|
2344
|
+
const result = await runtime.runRegisteredEval(name, {
|
|
2345
|
+
captureTraces,
|
|
2346
|
+
captureRequests
|
|
2347
|
+
});
|
|
1963
2348
|
return c.json({
|
|
1964
2349
|
ok: true,
|
|
1965
2350
|
data: redactEvalResult(result, redactOn)
|
|
@@ -1972,6 +2357,106 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
1972
2357
|
);
|
|
1973
2358
|
}
|
|
1974
2359
|
});
|
|
2360
|
+
async function resolveDiagnostics(runtime, id) {
|
|
2361
|
+
const entry = await runtime.getEvalResult(id);
|
|
2362
|
+
const artifactId = entry?.data?.diagnostics?.artifactId;
|
|
2363
|
+
return typeof artifactId === "string" && artifactId !== "" ? { artifactId } : void 0;
|
|
2364
|
+
}
|
|
2365
|
+
app5.get("/evals/:id/diagnostics", async (c) => {
|
|
2366
|
+
const runtime = c.get("runtime");
|
|
2367
|
+
const id = c.req.param("id");
|
|
2368
|
+
const resolved = await resolveDiagnostics(runtime, id);
|
|
2369
|
+
if (!resolved) {
|
|
2370
|
+
return c.json(
|
|
2371
|
+
{
|
|
2372
|
+
ok: false,
|
|
2373
|
+
error: {
|
|
2374
|
+
code: "NOT_FOUND",
|
|
2375
|
+
message: `Eval result "${id}" has no captured requests`
|
|
2376
|
+
}
|
|
2377
|
+
},
|
|
2378
|
+
404
|
|
2379
|
+
);
|
|
2380
|
+
}
|
|
2381
|
+
const opened = await runtime.openDiagnosticArtifact(resolved.artifactId);
|
|
2382
|
+
if (!opened) {
|
|
2383
|
+
return c.json(
|
|
2384
|
+
{
|
|
2385
|
+
ok: false,
|
|
2386
|
+
error: {
|
|
2387
|
+
code: "NOT_FOUND",
|
|
2388
|
+
message: `Captured requests for eval result "${id}" are no longer available`
|
|
2389
|
+
}
|
|
2390
|
+
},
|
|
2391
|
+
404
|
|
2392
|
+
);
|
|
2393
|
+
}
|
|
2394
|
+
return c.json({
|
|
2395
|
+
ok: true,
|
|
2396
|
+
data: {
|
|
2397
|
+
artifactId: opened.manifest.artifactId,
|
|
2398
|
+
status: opened.manifest.status,
|
|
2399
|
+
...opened.manifest.reason !== void 0 ? { reason: opened.manifest.reason } : {},
|
|
2400
|
+
records: opened.manifest.records,
|
|
2401
|
+
bytes: opened.manifest.bytes,
|
|
2402
|
+
fidelity: opened.manifest.fidelity,
|
|
2403
|
+
redaction: opened.manifest.redaction,
|
|
2404
|
+
...opened.manifest.expiresAt !== void 0 ? { expiresAt: opened.manifest.expiresAt } : {},
|
|
2405
|
+
...opened.manifest.copiedFrom !== void 0 ? { copiedFrom: opened.manifest.copiedFrom } : {}
|
|
2406
|
+
}
|
|
2407
|
+
});
|
|
2408
|
+
});
|
|
2409
|
+
app5.get("/evals/:id/diagnostics/records", async (c) => {
|
|
2410
|
+
const runtime = c.get("runtime");
|
|
2411
|
+
const redactOn = runtime.isRedactEnabled();
|
|
2412
|
+
const id = c.req.param("id");
|
|
2413
|
+
const resolved = await resolveDiagnostics(runtime, id);
|
|
2414
|
+
const opened = resolved ? await runtime.openDiagnosticArtifact(resolved.artifactId) : void 0;
|
|
2415
|
+
if (!opened) {
|
|
2416
|
+
return c.json(
|
|
2417
|
+
{
|
|
2418
|
+
ok: false,
|
|
2419
|
+
error: {
|
|
2420
|
+
code: "NOT_FOUND",
|
|
2421
|
+
message: `Captured requests for eval result "${id}" are not available`
|
|
2422
|
+
}
|
|
2423
|
+
},
|
|
2424
|
+
404
|
|
2425
|
+
);
|
|
2426
|
+
}
|
|
2427
|
+
let cancelled = false;
|
|
2428
|
+
const lines = opened.lines[Symbol.asyncIterator]();
|
|
2429
|
+
return new Response(
|
|
2430
|
+
new ReadableStream({
|
|
2431
|
+
async start(controller) {
|
|
2432
|
+
const encoder = new TextEncoder();
|
|
2433
|
+
try {
|
|
2434
|
+
for (; ; ) {
|
|
2435
|
+
const next = await lines.next();
|
|
2436
|
+
if (next.done || cancelled) break;
|
|
2437
|
+
controller.enqueue(encoder.encode(`${redactRecordLine(next.value, redactOn)}
|
|
2438
|
+
`));
|
|
2439
|
+
}
|
|
2440
|
+
if (!cancelled) controller.close();
|
|
2441
|
+
} catch (error48) {
|
|
2442
|
+
if (!cancelled) controller.error(error48);
|
|
2443
|
+
} finally {
|
|
2444
|
+
await lines.return?.().catch(() => void 0);
|
|
2445
|
+
}
|
|
2446
|
+
},
|
|
2447
|
+
cancel() {
|
|
2448
|
+
cancelled = true;
|
|
2449
|
+
}
|
|
2450
|
+
}),
|
|
2451
|
+
{
|
|
2452
|
+
status: 200,
|
|
2453
|
+
headers: {
|
|
2454
|
+
"Content-Type": "application/x-ndjson; charset=utf-8",
|
|
2455
|
+
"Cache-Control": "no-store"
|
|
2456
|
+
}
|
|
2457
|
+
}
|
|
2458
|
+
);
|
|
2459
|
+
});
|
|
1975
2460
|
app5.post("/evals/runs/:evalRunId/cancel", (c) => {
|
|
1976
2461
|
const evalRunId = c.req.param("evalRunId");
|
|
1977
2462
|
const ac = activeRuns.get(evalRunId);
|
|
@@ -1991,6 +2476,7 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
1991
2476
|
const redactOn = runtime.isRedactEnabled();
|
|
1992
2477
|
const name = c.req.param("name");
|
|
1993
2478
|
const body = await c.req.json();
|
|
2479
|
+
const captureRequests = body.captureRequests === true;
|
|
1994
2480
|
if (!body.resultId || typeof body.resultId !== "string") {
|
|
1995
2481
|
return c.json(
|
|
1996
2482
|
{ ok: false, error: { code: "BAD_REQUEST", message: "resultId is required" } },
|
|
@@ -2004,8 +2490,7 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
2004
2490
|
404
|
|
2005
2491
|
);
|
|
2006
2492
|
}
|
|
2007
|
-
const
|
|
2008
|
-
const historyEntry = history.find((h) => h.id === body.resultId);
|
|
2493
|
+
const historyEntry = await runtime.getEvalResult(body.resultId);
|
|
2009
2494
|
if (!historyEntry) {
|
|
2010
2495
|
return c.json(
|
|
2011
2496
|
{ ok: false, error: { code: "NOT_FOUND", message: `Result "${body.resultId}" not found` } },
|
|
@@ -2018,7 +2503,8 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
2018
2503
|
const result = await rescore(
|
|
2019
2504
|
historyEntry.data,
|
|
2020
2505
|
config2.scorers,
|
|
2021
|
-
runtime
|
|
2506
|
+
runtime,
|
|
2507
|
+
captureRequests ? { captureRequests: true } : void 0
|
|
2022
2508
|
);
|
|
2023
2509
|
await runtime.saveEvalResult({
|
|
2024
2510
|
id: result.id,
|
|
@@ -2072,8 +2558,13 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
2072
2558
|
400
|
|
2073
2559
|
);
|
|
2074
2560
|
}
|
|
2075
|
-
const
|
|
2076
|
-
const
|
|
2561
|
+
const idsOf = (v) => Array.isArray(v) ? v : [v];
|
|
2562
|
+
const requested = /* @__PURE__ */ new Set([...idsOf(body.baselineId), ...idsOf(body.candidateId)]);
|
|
2563
|
+
const byId = /* @__PURE__ */ new Map();
|
|
2564
|
+
for (const id of requested) {
|
|
2565
|
+
const entry = await runtime.getEvalResult(id);
|
|
2566
|
+
if (entry) byId.set(id, entry.data);
|
|
2567
|
+
}
|
|
2077
2568
|
const missing = [];
|
|
2078
2569
|
const resolveOne = (id) => {
|
|
2079
2570
|
const data = byId.get(id);
|
|
@@ -2109,7 +2600,10 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
2109
2600
|
}
|
|
2110
2601
|
try {
|
|
2111
2602
|
const result = await runtime.evalCompare(baseline, candidate, body.options);
|
|
2112
|
-
return c.json({
|
|
2603
|
+
return c.json({
|
|
2604
|
+
ok: true,
|
|
2605
|
+
data: redactEvalComparison(result, redactOn)
|
|
2606
|
+
});
|
|
2113
2607
|
} catch (err) {
|
|
2114
2608
|
return c.json(
|
|
2115
2609
|
{
|
|
@@ -2177,6 +2671,26 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
2177
2671
|
const workflowsFromMeta = Array.isArray(metadataObj.workflows) ? metadataObj.workflows : [];
|
|
2178
2672
|
const primaryWorkflow = workflowsFromMeta.find((w) => typeof w === "string");
|
|
2179
2673
|
const evalName = trim(body.eval) ?? trim(primaryWorkflow) ?? trim(firstResult.workflow) ?? "imported";
|
|
2674
|
+
let readAccounting;
|
|
2675
|
+
let validateRequestSidecar;
|
|
2676
|
+
try {
|
|
2677
|
+
({ readAccounting, validateRequestSidecar } = await import("@axlsdk/eval"));
|
|
2678
|
+
} catch {
|
|
2679
|
+
readAccounting = void 0;
|
|
2680
|
+
validateRequestSidecar = void 0;
|
|
2681
|
+
}
|
|
2682
|
+
let sidecarLines;
|
|
2683
|
+
if (body.requests !== void 0 && body.requests !== null) {
|
|
2684
|
+
if (!validateRequestSidecar) {
|
|
2685
|
+
return bad("importing captured requests requires @axlsdk/eval to be installed");
|
|
2686
|
+
}
|
|
2687
|
+
const validation = validateRequestSidecar(body.requests);
|
|
2688
|
+
if (!validation.ok) return bad(validation.reason);
|
|
2689
|
+
sidecarLines = validation.lines;
|
|
2690
|
+
}
|
|
2691
|
+
if (sidecarLines && validatedResults.length > 1) {
|
|
2692
|
+
return bad("a requests sidecar can only accompany a single result");
|
|
2693
|
+
}
|
|
2180
2694
|
const timestamp = Date.now();
|
|
2181
2695
|
const imported = [];
|
|
2182
2696
|
for (const r of validatedResults) {
|
|
@@ -2186,6 +2700,42 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
2186
2700
|
id,
|
|
2187
2701
|
metadata: typeof r.metadata === "object" && r.metadata != null ? r.metadata : {}
|
|
2188
2702
|
};
|
|
2703
|
+
if (entry.accounting === void 0) {
|
|
2704
|
+
if (entry.summary?.coverage !== void 0 && !isValidImportedCoverage(entry.summary.coverage)) {
|
|
2705
|
+
delete entry.summary.coverage;
|
|
2706
|
+
entry.metadata.importedAccounting = "invalid";
|
|
2707
|
+
}
|
|
2708
|
+
if (readAccounting) {
|
|
2709
|
+
entry.accounting = readAccounting(entry);
|
|
2710
|
+
}
|
|
2711
|
+
} else if (importedAccountingIsTrustworthy(entry)) {
|
|
2712
|
+
entry.metadata.importedAccounting = "declared";
|
|
2713
|
+
} else {
|
|
2714
|
+
const stripped = stripAccounting(entry);
|
|
2715
|
+
entry.accounting = readAccounting ? readAccounting(stripped) : void 0;
|
|
2716
|
+
entry.items = stripped.items;
|
|
2717
|
+
entry.summary = stripped.summary;
|
|
2718
|
+
entry.metadata.importedAccounting = "invalid";
|
|
2719
|
+
}
|
|
2720
|
+
if (entry.summary?.itemErrorRate !== void 0 && !isValidImportedItemErrorRate(entry.summary.itemErrorRate)) {
|
|
2721
|
+
delete entry.summary.itemErrorRate;
|
|
2722
|
+
entry.metadata.importedItemErrorRate = "invalid";
|
|
2723
|
+
}
|
|
2724
|
+
const multiRun = entry._multiRun;
|
|
2725
|
+
if (multiRun !== void 0 && !isValidImportedMultiRun(multiRun)) {
|
|
2726
|
+
delete entry._multiRun;
|
|
2727
|
+
entry.metadata.importedMultiRun = "invalid";
|
|
2728
|
+
}
|
|
2729
|
+
if (sidecarLines) {
|
|
2730
|
+
entry.diagnostics = await restageImportedRequests(runtime, id, sidecarLines);
|
|
2731
|
+
} else if (entry.diagnostics) {
|
|
2732
|
+
entry.diagnostics = {
|
|
2733
|
+
...entry.diagnostics,
|
|
2734
|
+
artifactId: "",
|
|
2735
|
+
status: "unavailable",
|
|
2736
|
+
reason: "imported without its captured-request sidecar"
|
|
2737
|
+
};
|
|
2738
|
+
}
|
|
2189
2739
|
await runtime.saveEvalResult({ id, eval: evalName, timestamp, data: entry });
|
|
2190
2740
|
imported.push({ id, eval: evalName, timestamp });
|
|
2191
2741
|
}
|
|
@@ -2194,12 +2744,72 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
2194
2744
|
}
|
|
2195
2745
|
return c.json({ ok: true, data: { imported } });
|
|
2196
2746
|
});
|
|
2747
|
+
async function restageImportedRequests(runtime, ownerId, lines) {
|
|
2748
|
+
let stagedId;
|
|
2749
|
+
try {
|
|
2750
|
+
const staged = await runtime.stageDiagnosticArtifact({ kind: "eval", id: ownerId });
|
|
2751
|
+
stagedId = staged.artifactId;
|
|
2752
|
+
let bytes = 0;
|
|
2753
|
+
let allRedacted = lines.length > 0;
|
|
2754
|
+
for (const line of lines) {
|
|
2755
|
+
await staged.sink.append(line);
|
|
2756
|
+
bytes += Buffer.byteLength(line, "utf-8");
|
|
2757
|
+
if (allRedacted) {
|
|
2758
|
+
try {
|
|
2759
|
+
allRedacted = JSON.parse(line).captured?.redacted === true;
|
|
2760
|
+
} catch {
|
|
2761
|
+
allRedacted = false;
|
|
2762
|
+
}
|
|
2763
|
+
}
|
|
2764
|
+
}
|
|
2765
|
+
const manifest = await runtime.finalizeDiagnosticArtifact(
|
|
2766
|
+
staged.artifactId,
|
|
2767
|
+
"complete",
|
|
2768
|
+
void 0,
|
|
2769
|
+
allRedacted ? "applied" : "none"
|
|
2770
|
+
);
|
|
2771
|
+
return {
|
|
2772
|
+
version: 1,
|
|
2773
|
+
artifactId: manifest.artifactId,
|
|
2774
|
+
fidelity: "runtime_request",
|
|
2775
|
+
status: manifest.status,
|
|
2776
|
+
records: lines.length,
|
|
2777
|
+
bytes,
|
|
2778
|
+
redaction: manifest.redaction
|
|
2779
|
+
};
|
|
2780
|
+
} catch (error48) {
|
|
2781
|
+
if (stagedId !== void 0) {
|
|
2782
|
+
await runtime.rollbackDiagnosticArtifact(stagedId).catch(() => void 0);
|
|
2783
|
+
}
|
|
2784
|
+
return {
|
|
2785
|
+
version: 1,
|
|
2786
|
+
artifactId: "",
|
|
2787
|
+
fidelity: "runtime_request",
|
|
2788
|
+
status: "unavailable",
|
|
2789
|
+
reason: `captured requests could not be stored: ${error48 instanceof Error ? error48.message : String(error48)}`,
|
|
2790
|
+
records: 0,
|
|
2791
|
+
bytes: 0,
|
|
2792
|
+
redaction: "none"
|
|
2793
|
+
};
|
|
2794
|
+
}
|
|
2795
|
+
}
|
|
2197
2796
|
function closeActiveRuns() {
|
|
2198
2797
|
for (const ac of activeRuns.values()) ac.abort();
|
|
2199
2798
|
activeRuns.clear();
|
|
2200
2799
|
}
|
|
2201
2800
|
return { app: app5, closeActiveRuns };
|
|
2202
2801
|
}
|
|
2802
|
+
function worstItemErrorRate(results) {
|
|
2803
|
+
let worst;
|
|
2804
|
+
let runsExceeded = 0;
|
|
2805
|
+
for (const run of results) {
|
|
2806
|
+
const r = run.summary?.itemErrorRate;
|
|
2807
|
+
if (!r) continue;
|
|
2808
|
+
if (r.exceeded) runsExceeded++;
|
|
2809
|
+
if (!worst || r.rate > worst.rate) worst = r;
|
|
2810
|
+
}
|
|
2811
|
+
return worst ? { ...worst, runsExceeded } : void 0;
|
|
2812
|
+
}
|
|
2203
2813
|
function unionDegradedScorers(results) {
|
|
2204
2814
|
const byScorer = /* @__PURE__ */ new Map();
|
|
2205
2815
|
for (const run of results) {
|
|
@@ -2210,8 +2820,8 @@ function unionDegradedScorers(results) {
|
|
|
2210
2820
|
if (!existing) {
|
|
2211
2821
|
byScorer.set(d.scorer, { ...d, runsAffected: 1 });
|
|
2212
2822
|
} else {
|
|
2213
|
-
const
|
|
2214
|
-
byScorer.set(d.scorer, { ...
|
|
2823
|
+
const worse2 = d.rate > existing.rate ? d : existing;
|
|
2824
|
+
byScorer.set(d.scorer, { ...worse2, runsAffected: existing.runsAffected + 1 });
|
|
2215
2825
|
}
|
|
2216
2826
|
}
|
|
2217
2827
|
}
|
|
@@ -2851,7 +3461,7 @@ __export(util_exports, {
|
|
|
2851
3461
|
getSizableOrigin: () => getSizableOrigin,
|
|
2852
3462
|
hexToUint8Array: () => hexToUint8Array,
|
|
2853
3463
|
isObject: () => isObject,
|
|
2854
|
-
isPlainObject: () =>
|
|
3464
|
+
isPlainObject: () => isPlainObject2,
|
|
2855
3465
|
issue: () => issue,
|
|
2856
3466
|
joinValues: () => joinValues,
|
|
2857
3467
|
jsonStringifyReplacer: () => jsonStringifyReplacer,
|
|
@@ -3035,7 +3645,7 @@ var allowsEval = cached(() => {
|
|
|
3035
3645
|
return false;
|
|
3036
3646
|
}
|
|
3037
3647
|
});
|
|
3038
|
-
function
|
|
3648
|
+
function isPlainObject2(o) {
|
|
3039
3649
|
if (isObject(o) === false)
|
|
3040
3650
|
return false;
|
|
3041
3651
|
const ctor = o.constructor;
|
|
@@ -3052,7 +3662,7 @@ function isPlainObject(o) {
|
|
|
3052
3662
|
return true;
|
|
3053
3663
|
}
|
|
3054
3664
|
function shallowClone(o) {
|
|
3055
|
-
if (
|
|
3665
|
+
if (isPlainObject2(o))
|
|
3056
3666
|
return { ...o };
|
|
3057
3667
|
if (Array.isArray(o))
|
|
3058
3668
|
return [...o];
|
|
@@ -3245,7 +3855,7 @@ function omit(schema, mask) {
|
|
|
3245
3855
|
return clone(schema, def);
|
|
3246
3856
|
}
|
|
3247
3857
|
function extend(schema, shape) {
|
|
3248
|
-
if (!
|
|
3858
|
+
if (!isPlainObject2(shape)) {
|
|
3249
3859
|
throw new Error("Invalid input to extend: expected a plain object");
|
|
3250
3860
|
}
|
|
3251
3861
|
const checks = schema._zod.def.checks;
|
|
@@ -3268,7 +3878,7 @@ function extend(schema, shape) {
|
|
|
3268
3878
|
return clone(schema, def);
|
|
3269
3879
|
}
|
|
3270
3880
|
function safeExtend(schema, shape) {
|
|
3271
|
-
if (!
|
|
3881
|
+
if (!isPlainObject2(shape)) {
|
|
3272
3882
|
throw new Error("Invalid input to safeExtend: expected a plain object");
|
|
3273
3883
|
}
|
|
3274
3884
|
const def = mergeDefs(schema._zod.def, {
|
|
@@ -5543,7 +6153,7 @@ function mergeValues(a, b) {
|
|
|
5543
6153
|
if (a instanceof Date && b instanceof Date && +a === +b) {
|
|
5544
6154
|
return { valid: true, data: a };
|
|
5545
6155
|
}
|
|
5546
|
-
if (
|
|
6156
|
+
if (isPlainObject2(a) && isPlainObject2(b)) {
|
|
5547
6157
|
const bKeys = Object.keys(b);
|
|
5548
6158
|
const sharedKeys = Object.keys(a).filter((key) => bKeys.indexOf(key) !== -1);
|
|
5549
6159
|
const newObj = { ...a, ...b };
|
|
@@ -5697,7 +6307,7 @@ var $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
|
|
|
5697
6307
|
$ZodType.init(inst, def);
|
|
5698
6308
|
inst._zod.parse = (payload, ctx) => {
|
|
5699
6309
|
const input = payload.value;
|
|
5700
|
-
if (!
|
|
6310
|
+
if (!isPlainObject2(input)) {
|
|
5701
6311
|
payload.issues.push({
|
|
5702
6312
|
expected: "record",
|
|
5703
6313
|
code: "invalid_type",
|
|
@@ -6705,8 +7315,8 @@ function az_default() {
|
|
|
6705
7315
|
}
|
|
6706
7316
|
|
|
6707
7317
|
// ../../node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/locales/be.js
|
|
6708
|
-
function getBelarusianPlural(
|
|
6709
|
-
const absCount = Math.abs(
|
|
7318
|
+
function getBelarusianPlural(count2, one, few, many) {
|
|
7319
|
+
const absCount = Math.abs(count2);
|
|
6710
7320
|
const lastDigit = absCount % 10;
|
|
6711
7321
|
const lastTwoDigits = absCount % 100;
|
|
6712
7322
|
if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {
|
|
@@ -8530,8 +9140,8 @@ function hu_default() {
|
|
|
8530
9140
|
}
|
|
8531
9141
|
|
|
8532
9142
|
// ../../node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/locales/hy.js
|
|
8533
|
-
function getArmenianPlural(
|
|
8534
|
-
return Math.abs(
|
|
9143
|
+
function getArmenianPlural(count2, one, many) {
|
|
9144
|
+
return Math.abs(count2) === 1 ? one : many;
|
|
8535
9145
|
}
|
|
8536
9146
|
function withDefiniteArticle(word) {
|
|
8537
9147
|
if (!word)
|
|
@@ -10539,8 +11149,8 @@ function pt_default() {
|
|
|
10539
11149
|
}
|
|
10540
11150
|
|
|
10541
11151
|
// ../../node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/locales/ru.js
|
|
10542
|
-
function getRussianPlural(
|
|
10543
|
-
const absCount = Math.abs(
|
|
11152
|
+
function getRussianPlural(count2, one, few, many) {
|
|
11153
|
+
const absCount = Math.abs(count2);
|
|
10544
11154
|
const lastDigit = absCount % 10;
|
|
10545
11155
|
const lastTwoDigits = absCount % 100;
|
|
10546
11156
|
if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {
|