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