@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/middleware.cjs
CHANGED
|
@@ -138,42 +138,177 @@ function sanitizeRichInputFailure(event) {
|
|
|
138
138
|
}
|
|
139
139
|
return event;
|
|
140
140
|
}
|
|
141
|
+
var MEASURED_METADATA_KEYS = /* @__PURE__ */ new Set([
|
|
142
|
+
"models",
|
|
143
|
+
"modelCallCounts",
|
|
144
|
+
"workflows",
|
|
145
|
+
"workflowCallCounts",
|
|
146
|
+
"tokens",
|
|
147
|
+
"agentCalls"
|
|
148
|
+
]);
|
|
149
|
+
function redactItemMetadata(metadata) {
|
|
150
|
+
if (!metadata) return metadata;
|
|
151
|
+
const out = {};
|
|
152
|
+
for (const [key, value] of Object.entries(metadata)) {
|
|
153
|
+
out[key] = MEASURED_METADATA_KEYS.has(key) ? value : REDACTED;
|
|
154
|
+
}
|
|
155
|
+
return out;
|
|
156
|
+
}
|
|
157
|
+
function projectItemFailure(failure) {
|
|
158
|
+
if (!failure || typeof failure !== "object") return void 0;
|
|
159
|
+
const f = failure;
|
|
160
|
+
if (typeof f.name !== "string") return void 0;
|
|
161
|
+
return {
|
|
162
|
+
name: f.name,
|
|
163
|
+
...typeof f.provider === "string" ? { provider: f.provider } : {},
|
|
164
|
+
...typeof f.status === "number" && Number.isFinite(f.status) ? { status: f.status } : {},
|
|
165
|
+
...typeof f.retryable === "boolean" ? { retryable: f.retryable } : {},
|
|
166
|
+
...typeof f.requestId === "string" ? { requestId: f.requestId } : {}
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
function isPlainObject(value) {
|
|
170
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
171
|
+
}
|
|
172
|
+
function redactScorerDetail(detail) {
|
|
173
|
+
if (!isPlainObject(detail)) return REDACTED;
|
|
174
|
+
const d = detail;
|
|
175
|
+
return {
|
|
176
|
+
score: d.score,
|
|
177
|
+
...d.duration !== void 0 ? { duration: d.duration } : {},
|
|
178
|
+
...d.cost !== void 0 ? { cost: d.cost } : {},
|
|
179
|
+
// `skipped` is a structural boolean (the `applies` predicate verdict),
|
|
180
|
+
// not user/LLM content — preserve it so the client's N/A chip renders.
|
|
181
|
+
...d.skipped !== void 0 ? { skipped: d.skipped } : {},
|
|
182
|
+
// `outcome` and `accounting` are structural (a classification and a set
|
|
183
|
+
// of counts), so they survive redaction the way `skipped` does — without
|
|
184
|
+
// them a compliance-mode reader cannot tell a judge that was stopped on
|
|
185
|
+
// budget from one that scored 0.
|
|
186
|
+
...d.outcome !== void 0 ? { outcome: d.outcome } : {},
|
|
187
|
+
...d.accounting !== void 0 ? { accounting: d.accounting } : {},
|
|
188
|
+
// `diagnostics` survives for the same reason `accounting` does: it is a
|
|
189
|
+
// list of operation ids and statuses, not content.
|
|
190
|
+
...d.diagnostics !== void 0 ? { diagnostics: d.diagnostics } : {}
|
|
191
|
+
// metadata deliberately omitted — may contain LLM scorer reasoning
|
|
192
|
+
};
|
|
193
|
+
}
|
|
141
194
|
function redactEvalItem(item) {
|
|
195
|
+
if (!isPlainObject(item)) return REDACTED;
|
|
196
|
+
const { failure, ...rest } = item;
|
|
197
|
+
const typed = item;
|
|
198
|
+
const projectedFailure = failure !== void 0 ? projectItemFailure(failure) : void 0;
|
|
142
199
|
const scrubbed = {
|
|
143
|
-
...
|
|
200
|
+
...rest,
|
|
201
|
+
...projectedFailure ? { failure: projectedFailure } : {},
|
|
144
202
|
input: REDACTED,
|
|
145
203
|
output: REDACTED,
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
204
|
+
// `diagnostics` is spread through untouched on purpose: it holds operation
|
|
205
|
+
// IDs, kinds, turn/attempt indexes and a status — pointers into an artifact,
|
|
206
|
+
// never content. The records themselves are redacted by the core rule at
|
|
207
|
+
// both write time and delivery time (`redactRecordLine`).
|
|
208
|
+
...typed.metadata !== void 0 ? {
|
|
209
|
+
metadata: isPlainObject(typed.metadata) ? redactItemMetadata(typed.metadata) : REDACTED
|
|
210
|
+
} : {},
|
|
211
|
+
...typed.annotations !== void 0 ? { annotations: REDACTED } : {},
|
|
212
|
+
...typed.error !== void 0 ? { error: REDACTED } : {},
|
|
213
|
+
...typed.scorerErrors !== void 0 ? {
|
|
214
|
+
scorerErrors: Array.isArray(typed.scorerErrors) ? typed.scorerErrors.map(() => REDACTED) : REDACTED
|
|
215
|
+
} : {},
|
|
216
|
+
// `callerReport.metadata` is whatever the workflow callback returned — free-
|
|
217
|
+
// form user content, exactly like `output`, so it is dropped rather than
|
|
218
|
+
// masked (same treatment as scorer metadata below). Its sibling `cost` is a
|
|
219
|
+
// plain number and stays. (`outcome` and `accounting` are spread through
|
|
220
|
+
// untouched: both are structural counts and classifications, no content.)
|
|
221
|
+
...typed.callerReport !== void 0 ? {
|
|
222
|
+
callerReport: isPlainObject(typed.callerReport) ? typeof typed.callerReport.cost === "number" ? { cost: typed.callerReport.cost } : {} : REDACTED
|
|
223
|
+
} : {}
|
|
224
|
+
};
|
|
225
|
+
if (typed.scoreDetails !== void 0) {
|
|
226
|
+
if (isPlainObject(typed.scoreDetails)) {
|
|
227
|
+
const detailsOut = {};
|
|
228
|
+
for (const [name, detail] of Object.entries(typed.scoreDetails)) {
|
|
229
|
+
detailsOut[name] = redactScorerDetail(detail);
|
|
230
|
+
}
|
|
231
|
+
scrubbed.scoreDetails = detailsOut;
|
|
232
|
+
} else {
|
|
233
|
+
scrubbed.scoreDetails = REDACTED;
|
|
162
234
|
}
|
|
163
|
-
scrubbed.scoreDetails = detailsOut;
|
|
164
235
|
}
|
|
165
236
|
return scrubbed;
|
|
166
237
|
}
|
|
167
238
|
function redactEvalResult(result, redact) {
|
|
168
239
|
if (!redact) return result;
|
|
169
|
-
|
|
170
|
-
|
|
240
|
+
return redactResultShape(result);
|
|
241
|
+
}
|
|
242
|
+
function redactResultShape(result) {
|
|
243
|
+
const scrubbedMetadata = redactResultMetadata(result.metadata);
|
|
244
|
+
const hasMultiRun = "_multiRun" in result;
|
|
245
|
+
const multiRun = result._multiRun;
|
|
171
246
|
return {
|
|
172
247
|
...result,
|
|
173
248
|
metadata: scrubbedMetadata,
|
|
174
|
-
items: result.items.map(redactEvalItem)
|
|
249
|
+
items: Array.isArray(result.items) ? result.items.map(redactEvalItem) : REDACTED,
|
|
250
|
+
...hasMultiRun && multiRun !== void 0 ? {
|
|
251
|
+
_multiRun: isPlainObject(multiRun) ? redactMultiRun(multiRun) : REDACTED
|
|
252
|
+
} : {}
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
function redactResultMetadata(metadata) {
|
|
256
|
+
const meta3 = metadata;
|
|
257
|
+
return isPlainObject(meta3) && typeof meta3.batchFailure === "string" ? { ...meta3, batchFailure: REDACTED } : metadata;
|
|
258
|
+
}
|
|
259
|
+
function redactMultiRun(multiRun) {
|
|
260
|
+
const { allRuns } = multiRun;
|
|
261
|
+
return {
|
|
262
|
+
...multiRun,
|
|
263
|
+
...allRuns !== void 0 ? {
|
|
264
|
+
allRuns: Array.isArray(allRuns) ? allRuns.map(
|
|
265
|
+
(run) => isPlainObject(run) && Array.isArray(run.items) ? redactResultShape(run) : REDACTED
|
|
266
|
+
) : REDACTED
|
|
267
|
+
} : {},
|
|
268
|
+
...typeof multiRun.batchFailure === "string" ? { batchFailure: REDACTED } : {}
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
function redactEvalComparison(comparison, redact) {
|
|
272
|
+
if (!redact) return comparison;
|
|
273
|
+
const maskInput = (r) => ({ ...r, input: REDACTED });
|
|
274
|
+
const side = (s) => ({
|
|
275
|
+
...s,
|
|
276
|
+
metadata: redactResultMetadata(s.metadata)
|
|
277
|
+
});
|
|
278
|
+
return {
|
|
279
|
+
...comparison,
|
|
280
|
+
baseline: side(comparison.baseline),
|
|
281
|
+
candidate: side(comparison.candidate),
|
|
282
|
+
regressions: comparison.regressions.map(maskInput),
|
|
283
|
+
improvements: comparison.improvements.map(maskInput)
|
|
175
284
|
};
|
|
176
285
|
}
|
|
286
|
+
function redactRecordLine(line, redact) {
|
|
287
|
+
if (!redact) return line;
|
|
288
|
+
let parsed;
|
|
289
|
+
try {
|
|
290
|
+
parsed = JSON.parse(line);
|
|
291
|
+
} catch {
|
|
292
|
+
const stub = {
|
|
293
|
+
v: 1,
|
|
294
|
+
phase: "end",
|
|
295
|
+
operationId: "unknown",
|
|
296
|
+
kind: "chat",
|
|
297
|
+
transportAttempts: 1,
|
|
298
|
+
provider: "unknown",
|
|
299
|
+
model: "unknown",
|
|
300
|
+
termination: "the stored record could not be parsed",
|
|
301
|
+
captured: {
|
|
302
|
+
fidelity: "runtime_request",
|
|
303
|
+
redacted: true,
|
|
304
|
+
truncated: true,
|
|
305
|
+
omitted: ["record"]
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
return JSON.stringify(stub);
|
|
309
|
+
}
|
|
310
|
+
return JSON.stringify((0, import_axl.redactCapturedRequest)(parsed));
|
|
311
|
+
}
|
|
177
312
|
function redactEvalHistoryEntry(entry, redact) {
|
|
178
313
|
if (!redact) return entry;
|
|
179
314
|
return {
|
|
@@ -950,7 +1085,50 @@ function reduceCost(acc, event) {
|
|
|
950
1085
|
};
|
|
951
1086
|
}
|
|
952
1087
|
function emptyEvalTrendData() {
|
|
953
|
-
return { byEval: {}, totalRuns: 0, totalCost: 0 };
|
|
1088
|
+
return { byEval: {}, totalRuns: 0, totalCost: 0, totalCostCompleteness: "complete" };
|
|
1089
|
+
}
|
|
1090
|
+
function worse(a, b) {
|
|
1091
|
+
if (a === "unverified" || b === "unverified") return "unverified";
|
|
1092
|
+
if (a === "incomplete" || b === "incomplete") return "incomplete";
|
|
1093
|
+
return "complete";
|
|
1094
|
+
}
|
|
1095
|
+
function extractAccounting(data) {
|
|
1096
|
+
const result = data ?? {};
|
|
1097
|
+
const accounting = result.accounting;
|
|
1098
|
+
if (!accounting || typeof accounting !== "object") {
|
|
1099
|
+
return { cost: usable(extractCost(data)), completeness: "unverified", budgetStopped: false };
|
|
1100
|
+
}
|
|
1101
|
+
const completeness = accounting.completeness === "complete" || accounting.completeness === "incomplete" ? accounting.completeness : "unverified";
|
|
1102
|
+
const knownCost = usable(accounting.knownCost);
|
|
1103
|
+
const summary = result.summary;
|
|
1104
|
+
return {
|
|
1105
|
+
cost: knownCost,
|
|
1106
|
+
completeness,
|
|
1107
|
+
budgetStopped: isBudgetStopped(accounting.budget?.status, summary?.coverage)
|
|
1108
|
+
};
|
|
1109
|
+
}
|
|
1110
|
+
function usable(value) {
|
|
1111
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : 0;
|
|
1112
|
+
}
|
|
1113
|
+
function refusedWork(coverage) {
|
|
1114
|
+
if (!coverage || typeof coverage !== "object") return 0;
|
|
1115
|
+
const { items, scorers } = coverage;
|
|
1116
|
+
let refused = count(items, "budget_skipped") + count(items, "budget_interrupted");
|
|
1117
|
+
if (scorers && typeof scorers === "object") {
|
|
1118
|
+
for (const s of Object.values(scorers)) {
|
|
1119
|
+
refused += count(s, "budget_skipped") + count(s, "budget_interrupted");
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
return refused;
|
|
1123
|
+
}
|
|
1124
|
+
function count(block, key) {
|
|
1125
|
+
if (!block || typeof block !== "object") return 0;
|
|
1126
|
+
const value = block[key];
|
|
1127
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
|
|
1128
|
+
}
|
|
1129
|
+
function isBudgetStopped(status, coverage) {
|
|
1130
|
+
if (status !== "closed") return false;
|
|
1131
|
+
return refusedWork(coverage) > 0;
|
|
954
1132
|
}
|
|
955
1133
|
function extractScores(data) {
|
|
956
1134
|
if (!data || typeof data !== "object") return {};
|
|
@@ -1017,7 +1195,7 @@ function computeScoreStats(runs) {
|
|
|
1017
1195
|
}
|
|
1018
1196
|
function reduceEvalTrends(acc, entry) {
|
|
1019
1197
|
const scores = extractScores(entry.data);
|
|
1020
|
-
const cost =
|
|
1198
|
+
const { cost, completeness, budgetStopped } = extractAccounting(entry.data);
|
|
1021
1199
|
const model = extractModel(entry.data);
|
|
1022
1200
|
const duration3 = extractDuration(entry.data);
|
|
1023
1201
|
const metadata = entry.data?.metadata;
|
|
@@ -1028,6 +1206,8 @@ function reduceEvalTrends(acc, entry) {
|
|
|
1028
1206
|
id: entry.id,
|
|
1029
1207
|
scores,
|
|
1030
1208
|
cost,
|
|
1209
|
+
completeness,
|
|
1210
|
+
...budgetStopped ? { budgetStopped: true } : {},
|
|
1031
1211
|
...model !== void 0 ? { model } : {},
|
|
1032
1212
|
...duration3 !== void 0 ? { duration: duration3 } : {},
|
|
1033
1213
|
...runGroupId !== void 0 ? { runGroupId } : {},
|
|
@@ -1046,12 +1226,15 @@ function reduceEvalTrends(acc, entry) {
|
|
|
1046
1226
|
scoreMean: mean,
|
|
1047
1227
|
scoreStd: std,
|
|
1048
1228
|
costTotal: (prev?.costTotal ?? 0) + cost,
|
|
1229
|
+
costCompleteness: worse(prev?.costCompleteness ?? "complete", completeness),
|
|
1230
|
+
budgetStoppedRuns: (prev?.budgetStoppedRuns ?? 0) + (budgetStopped ? 1 : 0),
|
|
1049
1231
|
runCount: (prev?.runCount ?? 0) + 1
|
|
1050
1232
|
};
|
|
1051
1233
|
return {
|
|
1052
1234
|
byEval,
|
|
1053
1235
|
totalRuns: acc.totalRuns + 1,
|
|
1054
|
-
totalCost: acc.totalCost + cost
|
|
1236
|
+
totalCost: acc.totalCost + cost,
|
|
1237
|
+
totalCostCompleteness: worse(acc.totalCostCompleteness ?? "complete", completeness)
|
|
1055
1238
|
};
|
|
1056
1239
|
}
|
|
1057
1240
|
var MAX_DURATIONS = 200;
|
|
@@ -1373,21 +1556,32 @@ var executions_default = createExecutionRoutes();
|
|
|
1373
1556
|
|
|
1374
1557
|
// src/server/routes/sessions.ts
|
|
1375
1558
|
var import_hono4 = require("hono");
|
|
1559
|
+
function mediaFields(source) {
|
|
1560
|
+
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;
|
|
1561
|
+
return {
|
|
1562
|
+
source: source.type,
|
|
1563
|
+
...source.mediaType ? { mediaType: source.mediaType } : {},
|
|
1564
|
+
...bytes !== void 0 ? { bytes } : {}
|
|
1565
|
+
};
|
|
1566
|
+
}
|
|
1376
1567
|
function describeStudioInput(content) {
|
|
1377
1568
|
if (typeof content === "string") return void 0;
|
|
1378
1569
|
return {
|
|
1379
1570
|
parts: content.map((part) => {
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1571
|
+
switch (part.type) {
|
|
1572
|
+
case "text":
|
|
1573
|
+
return { type: "text", characters: part.text.length };
|
|
1574
|
+
case "image":
|
|
1575
|
+
return { type: "image", ...mediaFields(part.source) };
|
|
1576
|
+
case "audio":
|
|
1577
|
+
return { type: "audio", ...mediaFields(part.source) };
|
|
1578
|
+
default: {
|
|
1579
|
+
const unreachable = part;
|
|
1580
|
+
throw new Error(
|
|
1581
|
+
`unsupported model input part: ${String(unreachable.type)}`
|
|
1582
|
+
);
|
|
1583
|
+
}
|
|
1584
|
+
}
|
|
1391
1585
|
})
|
|
1392
1586
|
};
|
|
1393
1587
|
}
|
|
@@ -1741,6 +1935,184 @@ function createCostRoutes(costAggregator) {
|
|
|
1741
1935
|
// src/server/routes/evals.ts
|
|
1742
1936
|
var import_node_crypto = require("crypto");
|
|
1743
1937
|
var import_hono10 = require("hono");
|
|
1938
|
+
|
|
1939
|
+
// src/server/eval-import.ts
|
|
1940
|
+
var ITEM_OUTCOMES = [
|
|
1941
|
+
"completed",
|
|
1942
|
+
"failed",
|
|
1943
|
+
"cancelled",
|
|
1944
|
+
"budget_skipped",
|
|
1945
|
+
"budget_interrupted"
|
|
1946
|
+
];
|
|
1947
|
+
var SCORER_OUTCOMES = [
|
|
1948
|
+
"scored",
|
|
1949
|
+
"failed",
|
|
1950
|
+
"skipped",
|
|
1951
|
+
"cancelled",
|
|
1952
|
+
"budget_skipped",
|
|
1953
|
+
"budget_interrupted"
|
|
1954
|
+
];
|
|
1955
|
+
var EPSILON = 1e-9;
|
|
1956
|
+
function isFiniteNonNegative(value) {
|
|
1957
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0;
|
|
1958
|
+
}
|
|
1959
|
+
function isCount(value) {
|
|
1960
|
+
return isFiniteNonNegative(value) && Number.isInteger(value);
|
|
1961
|
+
}
|
|
1962
|
+
function isValidImportedBudget(value) {
|
|
1963
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
1964
|
+
const b = value;
|
|
1965
|
+
if (!isFiniteNonNegative(b.limit)) return false;
|
|
1966
|
+
if (!isFiniteNonNegative(b.knownSpend)) return false;
|
|
1967
|
+
if (!isFiniteNonNegative(b.knownOvershoot)) return false;
|
|
1968
|
+
if (b.status !== "open" && b.status !== "closed") return false;
|
|
1969
|
+
if (b.closedBy !== void 0 && b.closedBy !== "case" && b.closedBy !== "scorer" && b.closedBy !== "operation") {
|
|
1970
|
+
return false;
|
|
1971
|
+
}
|
|
1972
|
+
if (b.knownSpend >= b.limit !== (b.status === "closed")) return false;
|
|
1973
|
+
const expected = Math.max(0, b.knownSpend - b.limit);
|
|
1974
|
+
return Math.abs(b.knownOvershoot - expected) <= EPSILON;
|
|
1975
|
+
}
|
|
1976
|
+
function isValidImportedCoverage(value) {
|
|
1977
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
1978
|
+
const c = value;
|
|
1979
|
+
if (!c.items || typeof c.items !== "object" || Array.isArray(c.items)) return false;
|
|
1980
|
+
const items = c.items;
|
|
1981
|
+
for (const key of ITEM_OUTCOMES) {
|
|
1982
|
+
if (!isCount(items[key])) return false;
|
|
1983
|
+
}
|
|
1984
|
+
if (!c.scorers || typeof c.scorers !== "object" || Array.isArray(c.scorers)) return false;
|
|
1985
|
+
for (const bucket of Object.values(c.scorers)) {
|
|
1986
|
+
if (!bucket || typeof bucket !== "object" || Array.isArray(bucket)) return false;
|
|
1987
|
+
const counts = bucket;
|
|
1988
|
+
for (const key of SCORER_OUTCOMES) {
|
|
1989
|
+
if (!isCount(counts[key])) return false;
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1992
|
+
return true;
|
|
1993
|
+
}
|
|
1994
|
+
function isValidImportedItemErrorRate(value) {
|
|
1995
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
1996
|
+
const r = value;
|
|
1997
|
+
const { failed, attempted, rate, limit, exceeded } = r;
|
|
1998
|
+
if (!isCount(failed) || !isCount(attempted) || failed > attempted) return false;
|
|
1999
|
+
if (!isFiniteNonNegative(limit) || limit > 1) return false;
|
|
2000
|
+
if (typeof rate !== "number" || typeof exceeded !== "boolean") return false;
|
|
2001
|
+
const expectedRate = attempted > 0 ? failed / attempted : 0;
|
|
2002
|
+
if (Math.abs(rate - expectedRate) > EPSILON) return false;
|
|
2003
|
+
return exceeded === (attempted > 0 && rate > limit);
|
|
2004
|
+
}
|
|
2005
|
+
function isValidImportedMultiRun(value) {
|
|
2006
|
+
if (!isPlainRecord(value)) return false;
|
|
2007
|
+
const { allRuns } = value;
|
|
2008
|
+
if (allRuns === void 0) return true;
|
|
2009
|
+
if (!Array.isArray(allRuns)) return false;
|
|
2010
|
+
return allRuns.every(
|
|
2011
|
+
(run) => isPlainRecord(run) && Array.isArray(run.items) && run.items.every(isPlainRecord)
|
|
2012
|
+
);
|
|
2013
|
+
}
|
|
2014
|
+
function isPlainRecord(value) {
|
|
2015
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2016
|
+
}
|
|
2017
|
+
function sumOf(record2) {
|
|
2018
|
+
if (record2 === void 0) return 0;
|
|
2019
|
+
if (record2 === null || typeof record2 !== "object" || Array.isArray(record2)) return void 0;
|
|
2020
|
+
let total = 0;
|
|
2021
|
+
for (const value of Object.values(record2)) {
|
|
2022
|
+
if (!isFiniteNonNegative(value)) return void 0;
|
|
2023
|
+
total += value;
|
|
2024
|
+
}
|
|
2025
|
+
return total;
|
|
2026
|
+
}
|
|
2027
|
+
function allNumeric(record2) {
|
|
2028
|
+
if (record2 === void 0) return true;
|
|
2029
|
+
if (record2 === null || typeof record2 !== "object" || Array.isArray(record2)) return false;
|
|
2030
|
+
return Object.values(record2).every(
|
|
2031
|
+
(value) => typeof value === "number" && Number.isFinite(value)
|
|
2032
|
+
);
|
|
2033
|
+
}
|
|
2034
|
+
function isValidImportedAccounting(value) {
|
|
2035
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
2036
|
+
const a = value;
|
|
2037
|
+
if (a.version !== 1) return false;
|
|
2038
|
+
if (a.currency !== "USD") return false;
|
|
2039
|
+
if (!isFiniteNonNegative(a.knownCost)) return false;
|
|
2040
|
+
if (a.completeness !== "complete" && a.completeness !== "incomplete" && a.completeness !== "unverified") {
|
|
2041
|
+
return false;
|
|
2042
|
+
}
|
|
2043
|
+
if (!allNumeric(a.reasons)) return false;
|
|
2044
|
+
if (!allNumeric(a.usage)) return false;
|
|
2045
|
+
const ops = a.operations;
|
|
2046
|
+
if (!ops || typeof ops !== "object") return false;
|
|
2047
|
+
for (const key of ["total", "settled", "unknown", "denied"]) {
|
|
2048
|
+
if (!isFiniteNonNegative(ops[key])) return false;
|
|
2049
|
+
}
|
|
2050
|
+
if (!allNumeric(ops.byKind)) return false;
|
|
2051
|
+
if (ops.total !== ops.settled + ops.unknown) return false;
|
|
2052
|
+
if (a.completeness === "unverified") return true;
|
|
2053
|
+
const provenanceTotal = sumOf(a.provenance);
|
|
2054
|
+
if (provenanceTotal === void 0) return false;
|
|
2055
|
+
if (Math.abs(provenanceTotal - a.knownCost) > EPSILON) return false;
|
|
2056
|
+
const breakdown = a.breakdown;
|
|
2057
|
+
if (!breakdown || typeof breakdown !== "object") return false;
|
|
2058
|
+
const breakdownTotal = sumOf({
|
|
2059
|
+
generation: breakdown.generation,
|
|
2060
|
+
judging: breakdown.judging,
|
|
2061
|
+
external: breakdown.external
|
|
2062
|
+
});
|
|
2063
|
+
if (breakdownTotal === void 0) return false;
|
|
2064
|
+
if (Math.abs(breakdownTotal - a.knownCost) > EPSILON) return false;
|
|
2065
|
+
return true;
|
|
2066
|
+
}
|
|
2067
|
+
function importedAccountingIsTrustworthy(result) {
|
|
2068
|
+
if (!result || typeof result !== "object") return false;
|
|
2069
|
+
const r = result;
|
|
2070
|
+
if (r.accounting !== void 0 && !isValidImportedAccounting(r.accounting)) return false;
|
|
2071
|
+
const budget = r.accounting?.budget;
|
|
2072
|
+
if (budget !== void 0 && !isValidImportedBudget(budget)) return false;
|
|
2073
|
+
const coverage = r.summary?.coverage;
|
|
2074
|
+
if (coverage !== void 0 && !isValidImportedCoverage(coverage)) return false;
|
|
2075
|
+
if (!Array.isArray(r.items)) return true;
|
|
2076
|
+
for (const item of r.items) {
|
|
2077
|
+
if (!item || typeof item !== "object") continue;
|
|
2078
|
+
const i = item;
|
|
2079
|
+
if (i.accounting !== void 0 && !isValidImportedAccounting(i.accounting)) return false;
|
|
2080
|
+
if (i.scoreDetails && typeof i.scoreDetails === "object") {
|
|
2081
|
+
for (const detail of Object.values(i.scoreDetails)) {
|
|
2082
|
+
const d = detail;
|
|
2083
|
+
if (d?.accounting !== void 0 && !isValidImportedAccounting(d.accounting)) return false;
|
|
2084
|
+
}
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2087
|
+
return true;
|
|
2088
|
+
}
|
|
2089
|
+
function stripAccounting(result) {
|
|
2090
|
+
const copy = structuredClone(result);
|
|
2091
|
+
delete copy.accounting;
|
|
2092
|
+
const summary = copy.summary;
|
|
2093
|
+
if (summary && typeof summary === "object") {
|
|
2094
|
+
delete summary.coverage;
|
|
2095
|
+
}
|
|
2096
|
+
const items = copy.items;
|
|
2097
|
+
if (Array.isArray(items)) {
|
|
2098
|
+
for (const item of items) {
|
|
2099
|
+
if (!item || typeof item !== "object") continue;
|
|
2100
|
+
const i = item;
|
|
2101
|
+
delete i.accounting;
|
|
2102
|
+
const details = i.scoreDetails;
|
|
2103
|
+
if (details && typeof details === "object") {
|
|
2104
|
+
for (const detail of Object.values(details)) {
|
|
2105
|
+
if (detail && typeof detail === "object") {
|
|
2106
|
+
delete detail.accounting;
|
|
2107
|
+
}
|
|
2108
|
+
}
|
|
2109
|
+
}
|
|
2110
|
+
}
|
|
2111
|
+
}
|
|
2112
|
+
return copy;
|
|
2113
|
+
}
|
|
2114
|
+
|
|
2115
|
+
// src/server/routes/evals.ts
|
|
1744
2116
|
function createEvalRoutes(connMgr, evalLoader) {
|
|
1745
2117
|
const app5 = new import_hono10.Hono();
|
|
1746
2118
|
const activeRuns = /* @__PURE__ */ new Map();
|
|
@@ -1788,6 +2160,7 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
1788
2160
|
let runs = 1;
|
|
1789
2161
|
let stream = false;
|
|
1790
2162
|
let captureTraces = false;
|
|
2163
|
+
let captureRequests = false;
|
|
1791
2164
|
try {
|
|
1792
2165
|
const body = await c.req.json().catch(() => ({}));
|
|
1793
2166
|
if (typeof body.runs === "number" && Number.isFinite(body.runs) && body.runs > 1) {
|
|
@@ -1799,6 +2172,9 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
1799
2172
|
if (body.captureTraces === true) {
|
|
1800
2173
|
captureTraces = true;
|
|
1801
2174
|
}
|
|
2175
|
+
if (body.captureRequests === true) {
|
|
2176
|
+
captureRequests = true;
|
|
2177
|
+
}
|
|
1802
2178
|
} catch {
|
|
1803
2179
|
}
|
|
1804
2180
|
if (stream) {
|
|
@@ -1822,6 +2198,7 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
1822
2198
|
metadata: { runGroupId, runIndex: r, batchAttempted: runs },
|
|
1823
2199
|
signal: ac.signal,
|
|
1824
2200
|
captureTraces,
|
|
2201
|
+
captureRequests,
|
|
1825
2202
|
onProgress: (event) => {
|
|
1826
2203
|
if (event.type === "run_done") return;
|
|
1827
2204
|
connMgr.broadcastWithWildcard(`eval:${evalRunId}`, {
|
|
@@ -1894,6 +2271,7 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
1894
2271
|
const result = await runtime.runRegisteredEval(name, {
|
|
1895
2272
|
signal: ac.signal,
|
|
1896
2273
|
captureTraces,
|
|
2274
|
+
captureRequests,
|
|
1897
2275
|
onProgress: (event) => {
|
|
1898
2276
|
if (event.type === "run_done") return;
|
|
1899
2277
|
connMgr.broadcastWithWildcard(`eval:${evalRunId}`, event);
|
|
@@ -1925,7 +2303,8 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
1925
2303
|
try {
|
|
1926
2304
|
const result2 = await runtime.runRegisteredEval(name, {
|
|
1927
2305
|
metadata: { runGroupId, runIndex: r, batchAttempted: runs },
|
|
1928
|
-
captureTraces
|
|
2306
|
+
captureTraces,
|
|
2307
|
+
captureRequests
|
|
1929
2308
|
});
|
|
1930
2309
|
results.push(result2);
|
|
1931
2310
|
} catch (err) {
|
|
@@ -1941,11 +2320,14 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
1941
2320
|
const partial2 = results.length < runs;
|
|
1942
2321
|
const failureMsg = runFailure ? redactErrorMessage(runFailure, redactOn) || String(runFailure) || void 0 : void 0;
|
|
1943
2322
|
const aggDegraded = unionDegradedScorers(results);
|
|
2323
|
+
const worstItemRate = worstItemErrorRate(results);
|
|
2324
|
+
const { modelTiming: _runOneModelTiming, ...firstSummary } = first.summary;
|
|
1944
2325
|
const result = {
|
|
1945
2326
|
...first,
|
|
1946
2327
|
summary: {
|
|
1947
|
-
...
|
|
1948
|
-
...aggDegraded.length > 0 ? { degraded: aggDegraded } : {}
|
|
2328
|
+
...firstSummary,
|
|
2329
|
+
...aggDegraded.length > 0 ? { degraded: aggDegraded } : {},
|
|
2330
|
+
...worstItemRate ? { itemErrorRate: worstItemRate } : {}
|
|
1949
2331
|
},
|
|
1950
2332
|
_multiRun: {
|
|
1951
2333
|
aggregate,
|
|
@@ -1963,7 +2345,10 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
1963
2345
|
data: redactEvalResult(result, redactOn)
|
|
1964
2346
|
});
|
|
1965
2347
|
} else {
|
|
1966
|
-
const result = await runtime.runRegisteredEval(name, {
|
|
2348
|
+
const result = await runtime.runRegisteredEval(name, {
|
|
2349
|
+
captureTraces,
|
|
2350
|
+
captureRequests
|
|
2351
|
+
});
|
|
1967
2352
|
return c.json({
|
|
1968
2353
|
ok: true,
|
|
1969
2354
|
data: redactEvalResult(result, redactOn)
|
|
@@ -1976,6 +2361,106 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
1976
2361
|
);
|
|
1977
2362
|
}
|
|
1978
2363
|
});
|
|
2364
|
+
async function resolveDiagnostics(runtime, id) {
|
|
2365
|
+
const entry = await runtime.getEvalResult(id);
|
|
2366
|
+
const artifactId = entry?.data?.diagnostics?.artifactId;
|
|
2367
|
+
return typeof artifactId === "string" && artifactId !== "" ? { artifactId } : void 0;
|
|
2368
|
+
}
|
|
2369
|
+
app5.get("/evals/:id/diagnostics", async (c) => {
|
|
2370
|
+
const runtime = c.get("runtime");
|
|
2371
|
+
const id = c.req.param("id");
|
|
2372
|
+
const resolved = await resolveDiagnostics(runtime, id);
|
|
2373
|
+
if (!resolved) {
|
|
2374
|
+
return c.json(
|
|
2375
|
+
{
|
|
2376
|
+
ok: false,
|
|
2377
|
+
error: {
|
|
2378
|
+
code: "NOT_FOUND",
|
|
2379
|
+
message: `Eval result "${id}" has no captured requests`
|
|
2380
|
+
}
|
|
2381
|
+
},
|
|
2382
|
+
404
|
|
2383
|
+
);
|
|
2384
|
+
}
|
|
2385
|
+
const opened = await runtime.openDiagnosticArtifact(resolved.artifactId);
|
|
2386
|
+
if (!opened) {
|
|
2387
|
+
return c.json(
|
|
2388
|
+
{
|
|
2389
|
+
ok: false,
|
|
2390
|
+
error: {
|
|
2391
|
+
code: "NOT_FOUND",
|
|
2392
|
+
message: `Captured requests for eval result "${id}" are no longer available`
|
|
2393
|
+
}
|
|
2394
|
+
},
|
|
2395
|
+
404
|
|
2396
|
+
);
|
|
2397
|
+
}
|
|
2398
|
+
return c.json({
|
|
2399
|
+
ok: true,
|
|
2400
|
+
data: {
|
|
2401
|
+
artifactId: opened.manifest.artifactId,
|
|
2402
|
+
status: opened.manifest.status,
|
|
2403
|
+
...opened.manifest.reason !== void 0 ? { reason: opened.manifest.reason } : {},
|
|
2404
|
+
records: opened.manifest.records,
|
|
2405
|
+
bytes: opened.manifest.bytes,
|
|
2406
|
+
fidelity: opened.manifest.fidelity,
|
|
2407
|
+
redaction: opened.manifest.redaction,
|
|
2408
|
+
...opened.manifest.expiresAt !== void 0 ? { expiresAt: opened.manifest.expiresAt } : {},
|
|
2409
|
+
...opened.manifest.copiedFrom !== void 0 ? { copiedFrom: opened.manifest.copiedFrom } : {}
|
|
2410
|
+
}
|
|
2411
|
+
});
|
|
2412
|
+
});
|
|
2413
|
+
app5.get("/evals/:id/diagnostics/records", async (c) => {
|
|
2414
|
+
const runtime = c.get("runtime");
|
|
2415
|
+
const redactOn = runtime.isRedactEnabled();
|
|
2416
|
+
const id = c.req.param("id");
|
|
2417
|
+
const resolved = await resolveDiagnostics(runtime, id);
|
|
2418
|
+
const opened = resolved ? await runtime.openDiagnosticArtifact(resolved.artifactId) : void 0;
|
|
2419
|
+
if (!opened) {
|
|
2420
|
+
return c.json(
|
|
2421
|
+
{
|
|
2422
|
+
ok: false,
|
|
2423
|
+
error: {
|
|
2424
|
+
code: "NOT_FOUND",
|
|
2425
|
+
message: `Captured requests for eval result "${id}" are not available`
|
|
2426
|
+
}
|
|
2427
|
+
},
|
|
2428
|
+
404
|
|
2429
|
+
);
|
|
2430
|
+
}
|
|
2431
|
+
let cancelled = false;
|
|
2432
|
+
const lines = opened.lines[Symbol.asyncIterator]();
|
|
2433
|
+
return new Response(
|
|
2434
|
+
new ReadableStream({
|
|
2435
|
+
async start(controller) {
|
|
2436
|
+
const encoder = new TextEncoder();
|
|
2437
|
+
try {
|
|
2438
|
+
for (; ; ) {
|
|
2439
|
+
const next = await lines.next();
|
|
2440
|
+
if (next.done || cancelled) break;
|
|
2441
|
+
controller.enqueue(encoder.encode(`${redactRecordLine(next.value, redactOn)}
|
|
2442
|
+
`));
|
|
2443
|
+
}
|
|
2444
|
+
if (!cancelled) controller.close();
|
|
2445
|
+
} catch (error48) {
|
|
2446
|
+
if (!cancelled) controller.error(error48);
|
|
2447
|
+
} finally {
|
|
2448
|
+
await lines.return?.().catch(() => void 0);
|
|
2449
|
+
}
|
|
2450
|
+
},
|
|
2451
|
+
cancel() {
|
|
2452
|
+
cancelled = true;
|
|
2453
|
+
}
|
|
2454
|
+
}),
|
|
2455
|
+
{
|
|
2456
|
+
status: 200,
|
|
2457
|
+
headers: {
|
|
2458
|
+
"Content-Type": "application/x-ndjson; charset=utf-8",
|
|
2459
|
+
"Cache-Control": "no-store"
|
|
2460
|
+
}
|
|
2461
|
+
}
|
|
2462
|
+
);
|
|
2463
|
+
});
|
|
1979
2464
|
app5.post("/evals/runs/:evalRunId/cancel", (c) => {
|
|
1980
2465
|
const evalRunId = c.req.param("evalRunId");
|
|
1981
2466
|
const ac = activeRuns.get(evalRunId);
|
|
@@ -1995,6 +2480,7 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
1995
2480
|
const redactOn = runtime.isRedactEnabled();
|
|
1996
2481
|
const name = c.req.param("name");
|
|
1997
2482
|
const body = await c.req.json();
|
|
2483
|
+
const captureRequests = body.captureRequests === true;
|
|
1998
2484
|
if (!body.resultId || typeof body.resultId !== "string") {
|
|
1999
2485
|
return c.json(
|
|
2000
2486
|
{ ok: false, error: { code: "BAD_REQUEST", message: "resultId is required" } },
|
|
@@ -2008,8 +2494,7 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
2008
2494
|
404
|
|
2009
2495
|
);
|
|
2010
2496
|
}
|
|
2011
|
-
const
|
|
2012
|
-
const historyEntry = history.find((h) => h.id === body.resultId);
|
|
2497
|
+
const historyEntry = await runtime.getEvalResult(body.resultId);
|
|
2013
2498
|
if (!historyEntry) {
|
|
2014
2499
|
return c.json(
|
|
2015
2500
|
{ ok: false, error: { code: "NOT_FOUND", message: `Result "${body.resultId}" not found` } },
|
|
@@ -2022,7 +2507,8 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
2022
2507
|
const result = await rescore(
|
|
2023
2508
|
historyEntry.data,
|
|
2024
2509
|
config2.scorers,
|
|
2025
|
-
runtime
|
|
2510
|
+
runtime,
|
|
2511
|
+
captureRequests ? { captureRequests: true } : void 0
|
|
2026
2512
|
);
|
|
2027
2513
|
await runtime.saveEvalResult({
|
|
2028
2514
|
id: result.id,
|
|
@@ -2076,8 +2562,13 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
2076
2562
|
400
|
|
2077
2563
|
);
|
|
2078
2564
|
}
|
|
2079
|
-
const
|
|
2080
|
-
const
|
|
2565
|
+
const idsOf = (v) => Array.isArray(v) ? v : [v];
|
|
2566
|
+
const requested = /* @__PURE__ */ new Set([...idsOf(body.baselineId), ...idsOf(body.candidateId)]);
|
|
2567
|
+
const byId = /* @__PURE__ */ new Map();
|
|
2568
|
+
for (const id of requested) {
|
|
2569
|
+
const entry = await runtime.getEvalResult(id);
|
|
2570
|
+
if (entry) byId.set(id, entry.data);
|
|
2571
|
+
}
|
|
2081
2572
|
const missing = [];
|
|
2082
2573
|
const resolveOne = (id) => {
|
|
2083
2574
|
const data = byId.get(id);
|
|
@@ -2113,7 +2604,10 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
2113
2604
|
}
|
|
2114
2605
|
try {
|
|
2115
2606
|
const result = await runtime.evalCompare(baseline, candidate, body.options);
|
|
2116
|
-
return c.json({
|
|
2607
|
+
return c.json({
|
|
2608
|
+
ok: true,
|
|
2609
|
+
data: redactEvalComparison(result, redactOn)
|
|
2610
|
+
});
|
|
2117
2611
|
} catch (err) {
|
|
2118
2612
|
return c.json(
|
|
2119
2613
|
{
|
|
@@ -2181,6 +2675,26 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
2181
2675
|
const workflowsFromMeta = Array.isArray(metadataObj.workflows) ? metadataObj.workflows : [];
|
|
2182
2676
|
const primaryWorkflow = workflowsFromMeta.find((w) => typeof w === "string");
|
|
2183
2677
|
const evalName = trim(body.eval) ?? trim(primaryWorkflow) ?? trim(firstResult.workflow) ?? "imported";
|
|
2678
|
+
let readAccounting;
|
|
2679
|
+
let validateRequestSidecar;
|
|
2680
|
+
try {
|
|
2681
|
+
({ readAccounting, validateRequestSidecar } = await import("@axlsdk/eval"));
|
|
2682
|
+
} catch {
|
|
2683
|
+
readAccounting = void 0;
|
|
2684
|
+
validateRequestSidecar = void 0;
|
|
2685
|
+
}
|
|
2686
|
+
let sidecarLines;
|
|
2687
|
+
if (body.requests !== void 0 && body.requests !== null) {
|
|
2688
|
+
if (!validateRequestSidecar) {
|
|
2689
|
+
return bad("importing captured requests requires @axlsdk/eval to be installed");
|
|
2690
|
+
}
|
|
2691
|
+
const validation = validateRequestSidecar(body.requests);
|
|
2692
|
+
if (!validation.ok) return bad(validation.reason);
|
|
2693
|
+
sidecarLines = validation.lines;
|
|
2694
|
+
}
|
|
2695
|
+
if (sidecarLines && validatedResults.length > 1) {
|
|
2696
|
+
return bad("a requests sidecar can only accompany a single result");
|
|
2697
|
+
}
|
|
2184
2698
|
const timestamp = Date.now();
|
|
2185
2699
|
const imported = [];
|
|
2186
2700
|
for (const r of validatedResults) {
|
|
@@ -2190,6 +2704,42 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
2190
2704
|
id,
|
|
2191
2705
|
metadata: typeof r.metadata === "object" && r.metadata != null ? r.metadata : {}
|
|
2192
2706
|
};
|
|
2707
|
+
if (entry.accounting === void 0) {
|
|
2708
|
+
if (entry.summary?.coverage !== void 0 && !isValidImportedCoverage(entry.summary.coverage)) {
|
|
2709
|
+
delete entry.summary.coverage;
|
|
2710
|
+
entry.metadata.importedAccounting = "invalid";
|
|
2711
|
+
}
|
|
2712
|
+
if (readAccounting) {
|
|
2713
|
+
entry.accounting = readAccounting(entry);
|
|
2714
|
+
}
|
|
2715
|
+
} else if (importedAccountingIsTrustworthy(entry)) {
|
|
2716
|
+
entry.metadata.importedAccounting = "declared";
|
|
2717
|
+
} else {
|
|
2718
|
+
const stripped = stripAccounting(entry);
|
|
2719
|
+
entry.accounting = readAccounting ? readAccounting(stripped) : void 0;
|
|
2720
|
+
entry.items = stripped.items;
|
|
2721
|
+
entry.summary = stripped.summary;
|
|
2722
|
+
entry.metadata.importedAccounting = "invalid";
|
|
2723
|
+
}
|
|
2724
|
+
if (entry.summary?.itemErrorRate !== void 0 && !isValidImportedItemErrorRate(entry.summary.itemErrorRate)) {
|
|
2725
|
+
delete entry.summary.itemErrorRate;
|
|
2726
|
+
entry.metadata.importedItemErrorRate = "invalid";
|
|
2727
|
+
}
|
|
2728
|
+
const multiRun = entry._multiRun;
|
|
2729
|
+
if (multiRun !== void 0 && !isValidImportedMultiRun(multiRun)) {
|
|
2730
|
+
delete entry._multiRun;
|
|
2731
|
+
entry.metadata.importedMultiRun = "invalid";
|
|
2732
|
+
}
|
|
2733
|
+
if (sidecarLines) {
|
|
2734
|
+
entry.diagnostics = await restageImportedRequests(runtime, id, sidecarLines);
|
|
2735
|
+
} else if (entry.diagnostics) {
|
|
2736
|
+
entry.diagnostics = {
|
|
2737
|
+
...entry.diagnostics,
|
|
2738
|
+
artifactId: "",
|
|
2739
|
+
status: "unavailable",
|
|
2740
|
+
reason: "imported without its captured-request sidecar"
|
|
2741
|
+
};
|
|
2742
|
+
}
|
|
2193
2743
|
await runtime.saveEvalResult({ id, eval: evalName, timestamp, data: entry });
|
|
2194
2744
|
imported.push({ id, eval: evalName, timestamp });
|
|
2195
2745
|
}
|
|
@@ -2198,12 +2748,72 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
2198
2748
|
}
|
|
2199
2749
|
return c.json({ ok: true, data: { imported } });
|
|
2200
2750
|
});
|
|
2751
|
+
async function restageImportedRequests(runtime, ownerId, lines) {
|
|
2752
|
+
let stagedId;
|
|
2753
|
+
try {
|
|
2754
|
+
const staged = await runtime.stageDiagnosticArtifact({ kind: "eval", id: ownerId });
|
|
2755
|
+
stagedId = staged.artifactId;
|
|
2756
|
+
let bytes = 0;
|
|
2757
|
+
let allRedacted = lines.length > 0;
|
|
2758
|
+
for (const line of lines) {
|
|
2759
|
+
await staged.sink.append(line);
|
|
2760
|
+
bytes += Buffer.byteLength(line, "utf-8");
|
|
2761
|
+
if (allRedacted) {
|
|
2762
|
+
try {
|
|
2763
|
+
allRedacted = JSON.parse(line).captured?.redacted === true;
|
|
2764
|
+
} catch {
|
|
2765
|
+
allRedacted = false;
|
|
2766
|
+
}
|
|
2767
|
+
}
|
|
2768
|
+
}
|
|
2769
|
+
const manifest = await runtime.finalizeDiagnosticArtifact(
|
|
2770
|
+
staged.artifactId,
|
|
2771
|
+
"complete",
|
|
2772
|
+
void 0,
|
|
2773
|
+
allRedacted ? "applied" : "none"
|
|
2774
|
+
);
|
|
2775
|
+
return {
|
|
2776
|
+
version: 1,
|
|
2777
|
+
artifactId: manifest.artifactId,
|
|
2778
|
+
fidelity: "runtime_request",
|
|
2779
|
+
status: manifest.status,
|
|
2780
|
+
records: lines.length,
|
|
2781
|
+
bytes,
|
|
2782
|
+
redaction: manifest.redaction
|
|
2783
|
+
};
|
|
2784
|
+
} catch (error48) {
|
|
2785
|
+
if (stagedId !== void 0) {
|
|
2786
|
+
await runtime.rollbackDiagnosticArtifact(stagedId).catch(() => void 0);
|
|
2787
|
+
}
|
|
2788
|
+
return {
|
|
2789
|
+
version: 1,
|
|
2790
|
+
artifactId: "",
|
|
2791
|
+
fidelity: "runtime_request",
|
|
2792
|
+
status: "unavailable",
|
|
2793
|
+
reason: `captured requests could not be stored: ${error48 instanceof Error ? error48.message : String(error48)}`,
|
|
2794
|
+
records: 0,
|
|
2795
|
+
bytes: 0,
|
|
2796
|
+
redaction: "none"
|
|
2797
|
+
};
|
|
2798
|
+
}
|
|
2799
|
+
}
|
|
2201
2800
|
function closeActiveRuns() {
|
|
2202
2801
|
for (const ac of activeRuns.values()) ac.abort();
|
|
2203
2802
|
activeRuns.clear();
|
|
2204
2803
|
}
|
|
2205
2804
|
return { app: app5, closeActiveRuns };
|
|
2206
2805
|
}
|
|
2806
|
+
function worstItemErrorRate(results) {
|
|
2807
|
+
let worst;
|
|
2808
|
+
let runsExceeded = 0;
|
|
2809
|
+
for (const run of results) {
|
|
2810
|
+
const r = run.summary?.itemErrorRate;
|
|
2811
|
+
if (!r) continue;
|
|
2812
|
+
if (r.exceeded) runsExceeded++;
|
|
2813
|
+
if (!worst || r.rate > worst.rate) worst = r;
|
|
2814
|
+
}
|
|
2815
|
+
return worst ? { ...worst, runsExceeded } : void 0;
|
|
2816
|
+
}
|
|
2207
2817
|
function unionDegradedScorers(results) {
|
|
2208
2818
|
const byScorer = /* @__PURE__ */ new Map();
|
|
2209
2819
|
for (const run of results) {
|
|
@@ -2214,8 +2824,8 @@ function unionDegradedScorers(results) {
|
|
|
2214
2824
|
if (!existing) {
|
|
2215
2825
|
byScorer.set(d.scorer, { ...d, runsAffected: 1 });
|
|
2216
2826
|
} else {
|
|
2217
|
-
const
|
|
2218
|
-
byScorer.set(d.scorer, { ...
|
|
2827
|
+
const worse2 = d.rate > existing.rate ? d : existing;
|
|
2828
|
+
byScorer.set(d.scorer, { ...worse2, runsAffected: existing.runsAffected + 1 });
|
|
2219
2829
|
}
|
|
2220
2830
|
}
|
|
2221
2831
|
}
|
|
@@ -2855,7 +3465,7 @@ __export(util_exports, {
|
|
|
2855
3465
|
getSizableOrigin: () => getSizableOrigin,
|
|
2856
3466
|
hexToUint8Array: () => hexToUint8Array,
|
|
2857
3467
|
isObject: () => isObject,
|
|
2858
|
-
isPlainObject: () =>
|
|
3468
|
+
isPlainObject: () => isPlainObject2,
|
|
2859
3469
|
issue: () => issue,
|
|
2860
3470
|
joinValues: () => joinValues,
|
|
2861
3471
|
jsonStringifyReplacer: () => jsonStringifyReplacer,
|
|
@@ -3039,7 +3649,7 @@ var allowsEval = cached(() => {
|
|
|
3039
3649
|
return false;
|
|
3040
3650
|
}
|
|
3041
3651
|
});
|
|
3042
|
-
function
|
|
3652
|
+
function isPlainObject2(o) {
|
|
3043
3653
|
if (isObject(o) === false)
|
|
3044
3654
|
return false;
|
|
3045
3655
|
const ctor = o.constructor;
|
|
@@ -3056,7 +3666,7 @@ function isPlainObject(o) {
|
|
|
3056
3666
|
return true;
|
|
3057
3667
|
}
|
|
3058
3668
|
function shallowClone(o) {
|
|
3059
|
-
if (
|
|
3669
|
+
if (isPlainObject2(o))
|
|
3060
3670
|
return { ...o };
|
|
3061
3671
|
if (Array.isArray(o))
|
|
3062
3672
|
return [...o];
|
|
@@ -3249,7 +3859,7 @@ function omit(schema, mask) {
|
|
|
3249
3859
|
return clone(schema, def);
|
|
3250
3860
|
}
|
|
3251
3861
|
function extend(schema, shape) {
|
|
3252
|
-
if (!
|
|
3862
|
+
if (!isPlainObject2(shape)) {
|
|
3253
3863
|
throw new Error("Invalid input to extend: expected a plain object");
|
|
3254
3864
|
}
|
|
3255
3865
|
const checks = schema._zod.def.checks;
|
|
@@ -3272,7 +3882,7 @@ function extend(schema, shape) {
|
|
|
3272
3882
|
return clone(schema, def);
|
|
3273
3883
|
}
|
|
3274
3884
|
function safeExtend(schema, shape) {
|
|
3275
|
-
if (!
|
|
3885
|
+
if (!isPlainObject2(shape)) {
|
|
3276
3886
|
throw new Error("Invalid input to safeExtend: expected a plain object");
|
|
3277
3887
|
}
|
|
3278
3888
|
const def = mergeDefs(schema._zod.def, {
|
|
@@ -5547,7 +6157,7 @@ function mergeValues(a, b) {
|
|
|
5547
6157
|
if (a instanceof Date && b instanceof Date && +a === +b) {
|
|
5548
6158
|
return { valid: true, data: a };
|
|
5549
6159
|
}
|
|
5550
|
-
if (
|
|
6160
|
+
if (isPlainObject2(a) && isPlainObject2(b)) {
|
|
5551
6161
|
const bKeys = Object.keys(b);
|
|
5552
6162
|
const sharedKeys = Object.keys(a).filter((key) => bKeys.indexOf(key) !== -1);
|
|
5553
6163
|
const newObj = { ...a, ...b };
|
|
@@ -5701,7 +6311,7 @@ var $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
|
|
|
5701
6311
|
$ZodType.init(inst, def);
|
|
5702
6312
|
inst._zod.parse = (payload, ctx) => {
|
|
5703
6313
|
const input = payload.value;
|
|
5704
|
-
if (!
|
|
6314
|
+
if (!isPlainObject2(input)) {
|
|
5705
6315
|
payload.issues.push({
|
|
5706
6316
|
expected: "record",
|
|
5707
6317
|
code: "invalid_type",
|
|
@@ -6709,8 +7319,8 @@ function az_default() {
|
|
|
6709
7319
|
}
|
|
6710
7320
|
|
|
6711
7321
|
// ../../node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/locales/be.js
|
|
6712
|
-
function getBelarusianPlural(
|
|
6713
|
-
const absCount = Math.abs(
|
|
7322
|
+
function getBelarusianPlural(count2, one, few, many) {
|
|
7323
|
+
const absCount = Math.abs(count2);
|
|
6714
7324
|
const lastDigit = absCount % 10;
|
|
6715
7325
|
const lastTwoDigits = absCount % 100;
|
|
6716
7326
|
if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {
|
|
@@ -8534,8 +9144,8 @@ function hu_default() {
|
|
|
8534
9144
|
}
|
|
8535
9145
|
|
|
8536
9146
|
// ../../node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/locales/hy.js
|
|
8537
|
-
function getArmenianPlural(
|
|
8538
|
-
return Math.abs(
|
|
9147
|
+
function getArmenianPlural(count2, one, many) {
|
|
9148
|
+
return Math.abs(count2) === 1 ? one : many;
|
|
8539
9149
|
}
|
|
8540
9150
|
function withDefiniteArticle(word) {
|
|
8541
9151
|
if (!word)
|
|
@@ -10543,8 +11153,8 @@ function pt_default() {
|
|
|
10543
11153
|
}
|
|
10544
11154
|
|
|
10545
11155
|
// ../../node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/locales/ru.js
|
|
10546
|
-
function getRussianPlural(
|
|
10547
|
-
const absCount = Math.abs(
|
|
11156
|
+
function getRussianPlural(count2, one, few, many) {
|
|
11157
|
+
const absCount = Math.abs(count2);
|
|
10548
11158
|
const lastDigit = absCount % 10;
|
|
10549
11159
|
const lastTwoDigits = absCount % 100;
|
|
10550
11160
|
if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {
|