@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
|
@@ -12,7 +12,7 @@ import { cors } from "hono/cors";
|
|
|
12
12
|
import { serveStatic } from "@hono/node-server/serve-static";
|
|
13
13
|
|
|
14
14
|
// src/server/redact.ts
|
|
15
|
-
import { redactHistoricalEvent } from "@axlsdk/axl";
|
|
15
|
+
import { redactCapturedRequest, redactHistoricalEvent } from "@axlsdk/axl";
|
|
16
16
|
var REDACTED = "[redacted]";
|
|
17
17
|
var SAFE_ERROR_NAMES = /* @__PURE__ */ new Set([
|
|
18
18
|
"QuorumNotMet",
|
|
@@ -102,42 +102,177 @@ function sanitizeRichInputFailure(event) {
|
|
|
102
102
|
}
|
|
103
103
|
return event;
|
|
104
104
|
}
|
|
105
|
+
var MEASURED_METADATA_KEYS = /* @__PURE__ */ new Set([
|
|
106
|
+
"models",
|
|
107
|
+
"modelCallCounts",
|
|
108
|
+
"workflows",
|
|
109
|
+
"workflowCallCounts",
|
|
110
|
+
"tokens",
|
|
111
|
+
"agentCalls"
|
|
112
|
+
]);
|
|
113
|
+
function redactItemMetadata(metadata) {
|
|
114
|
+
if (!metadata) return metadata;
|
|
115
|
+
const out = {};
|
|
116
|
+
for (const [key, value] of Object.entries(metadata)) {
|
|
117
|
+
out[key] = MEASURED_METADATA_KEYS.has(key) ? value : REDACTED;
|
|
118
|
+
}
|
|
119
|
+
return out;
|
|
120
|
+
}
|
|
121
|
+
function projectItemFailure(failure) {
|
|
122
|
+
if (!failure || typeof failure !== "object") return void 0;
|
|
123
|
+
const f = failure;
|
|
124
|
+
if (typeof f.name !== "string") return void 0;
|
|
125
|
+
return {
|
|
126
|
+
name: f.name,
|
|
127
|
+
...typeof f.provider === "string" ? { provider: f.provider } : {},
|
|
128
|
+
...typeof f.status === "number" && Number.isFinite(f.status) ? { status: f.status } : {},
|
|
129
|
+
...typeof f.retryable === "boolean" ? { retryable: f.retryable } : {},
|
|
130
|
+
...typeof f.requestId === "string" ? { requestId: f.requestId } : {}
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
function isPlainObject(value) {
|
|
134
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
135
|
+
}
|
|
136
|
+
function redactScorerDetail(detail) {
|
|
137
|
+
if (!isPlainObject(detail)) return REDACTED;
|
|
138
|
+
const d = detail;
|
|
139
|
+
return {
|
|
140
|
+
score: d.score,
|
|
141
|
+
...d.duration !== void 0 ? { duration: d.duration } : {},
|
|
142
|
+
...d.cost !== void 0 ? { cost: d.cost } : {},
|
|
143
|
+
// `skipped` is a structural boolean (the `applies` predicate verdict),
|
|
144
|
+
// not user/LLM content — preserve it so the client's N/A chip renders.
|
|
145
|
+
...d.skipped !== void 0 ? { skipped: d.skipped } : {},
|
|
146
|
+
// `outcome` and `accounting` are structural (a classification and a set
|
|
147
|
+
// of counts), so they survive redaction the way `skipped` does — without
|
|
148
|
+
// them a compliance-mode reader cannot tell a judge that was stopped on
|
|
149
|
+
// budget from one that scored 0.
|
|
150
|
+
...d.outcome !== void 0 ? { outcome: d.outcome } : {},
|
|
151
|
+
...d.accounting !== void 0 ? { accounting: d.accounting } : {},
|
|
152
|
+
// `diagnostics` survives for the same reason `accounting` does: it is a
|
|
153
|
+
// list of operation ids and statuses, not content.
|
|
154
|
+
...d.diagnostics !== void 0 ? { diagnostics: d.diagnostics } : {}
|
|
155
|
+
// metadata deliberately omitted — may contain LLM scorer reasoning
|
|
156
|
+
};
|
|
157
|
+
}
|
|
105
158
|
function redactEvalItem(item) {
|
|
159
|
+
if (!isPlainObject(item)) return REDACTED;
|
|
160
|
+
const { failure, ...rest } = item;
|
|
161
|
+
const typed = item;
|
|
162
|
+
const projectedFailure = failure !== void 0 ? projectItemFailure(failure) : void 0;
|
|
106
163
|
const scrubbed = {
|
|
107
|
-
...
|
|
164
|
+
...rest,
|
|
165
|
+
...projectedFailure ? { failure: projectedFailure } : {},
|
|
108
166
|
input: REDACTED,
|
|
109
167
|
output: REDACTED,
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
168
|
+
// `diagnostics` is spread through untouched on purpose: it holds operation
|
|
169
|
+
// IDs, kinds, turn/attempt indexes and a status — pointers into an artifact,
|
|
170
|
+
// never content. The records themselves are redacted by the core rule at
|
|
171
|
+
// both write time and delivery time (`redactRecordLine`).
|
|
172
|
+
...typed.metadata !== void 0 ? {
|
|
173
|
+
metadata: isPlainObject(typed.metadata) ? redactItemMetadata(typed.metadata) : REDACTED
|
|
174
|
+
} : {},
|
|
175
|
+
...typed.annotations !== void 0 ? { annotations: REDACTED } : {},
|
|
176
|
+
...typed.error !== void 0 ? { error: REDACTED } : {},
|
|
177
|
+
...typed.scorerErrors !== void 0 ? {
|
|
178
|
+
scorerErrors: Array.isArray(typed.scorerErrors) ? typed.scorerErrors.map(() => REDACTED) : REDACTED
|
|
179
|
+
} : {},
|
|
180
|
+
// `callerReport.metadata` is whatever the workflow callback returned — free-
|
|
181
|
+
// form user content, exactly like `output`, so it is dropped rather than
|
|
182
|
+
// masked (same treatment as scorer metadata below). Its sibling `cost` is a
|
|
183
|
+
// plain number and stays. (`outcome` and `accounting` are spread through
|
|
184
|
+
// untouched: both are structural counts and classifications, no content.)
|
|
185
|
+
...typed.callerReport !== void 0 ? {
|
|
186
|
+
callerReport: isPlainObject(typed.callerReport) ? typeof typed.callerReport.cost === "number" ? { cost: typed.callerReport.cost } : {} : REDACTED
|
|
187
|
+
} : {}
|
|
188
|
+
};
|
|
189
|
+
if (typed.scoreDetails !== void 0) {
|
|
190
|
+
if (isPlainObject(typed.scoreDetails)) {
|
|
191
|
+
const detailsOut = {};
|
|
192
|
+
for (const [name, detail] of Object.entries(typed.scoreDetails)) {
|
|
193
|
+
detailsOut[name] = redactScorerDetail(detail);
|
|
194
|
+
}
|
|
195
|
+
scrubbed.scoreDetails = detailsOut;
|
|
196
|
+
} else {
|
|
197
|
+
scrubbed.scoreDetails = REDACTED;
|
|
126
198
|
}
|
|
127
|
-
scrubbed.scoreDetails = detailsOut;
|
|
128
199
|
}
|
|
129
200
|
return scrubbed;
|
|
130
201
|
}
|
|
131
202
|
function redactEvalResult(result, redact) {
|
|
132
203
|
if (!redact) return result;
|
|
133
|
-
|
|
134
|
-
|
|
204
|
+
return redactResultShape(result);
|
|
205
|
+
}
|
|
206
|
+
function redactResultShape(result) {
|
|
207
|
+
const scrubbedMetadata = redactResultMetadata(result.metadata);
|
|
208
|
+
const hasMultiRun = "_multiRun" in result;
|
|
209
|
+
const multiRun = result._multiRun;
|
|
135
210
|
return {
|
|
136
211
|
...result,
|
|
137
212
|
metadata: scrubbedMetadata,
|
|
138
|
-
items: result.items.map(redactEvalItem)
|
|
213
|
+
items: Array.isArray(result.items) ? result.items.map(redactEvalItem) : REDACTED,
|
|
214
|
+
...hasMultiRun && multiRun !== void 0 ? {
|
|
215
|
+
_multiRun: isPlainObject(multiRun) ? redactMultiRun(multiRun) : REDACTED
|
|
216
|
+
} : {}
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
function redactResultMetadata(metadata) {
|
|
220
|
+
const meta3 = metadata;
|
|
221
|
+
return isPlainObject(meta3) && typeof meta3.batchFailure === "string" ? { ...meta3, batchFailure: REDACTED } : metadata;
|
|
222
|
+
}
|
|
223
|
+
function redactMultiRun(multiRun) {
|
|
224
|
+
const { allRuns } = multiRun;
|
|
225
|
+
return {
|
|
226
|
+
...multiRun,
|
|
227
|
+
...allRuns !== void 0 ? {
|
|
228
|
+
allRuns: Array.isArray(allRuns) ? allRuns.map(
|
|
229
|
+
(run) => isPlainObject(run) && Array.isArray(run.items) ? redactResultShape(run) : REDACTED
|
|
230
|
+
) : REDACTED
|
|
231
|
+
} : {},
|
|
232
|
+
...typeof multiRun.batchFailure === "string" ? { batchFailure: REDACTED } : {}
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
function redactEvalComparison(comparison, redact) {
|
|
236
|
+
if (!redact) return comparison;
|
|
237
|
+
const maskInput = (r) => ({ ...r, input: REDACTED });
|
|
238
|
+
const side = (s) => ({
|
|
239
|
+
...s,
|
|
240
|
+
metadata: redactResultMetadata(s.metadata)
|
|
241
|
+
});
|
|
242
|
+
return {
|
|
243
|
+
...comparison,
|
|
244
|
+
baseline: side(comparison.baseline),
|
|
245
|
+
candidate: side(comparison.candidate),
|
|
246
|
+
regressions: comparison.regressions.map(maskInput),
|
|
247
|
+
improvements: comparison.improvements.map(maskInput)
|
|
139
248
|
};
|
|
140
249
|
}
|
|
250
|
+
function redactRecordLine(line, redact) {
|
|
251
|
+
if (!redact) return line;
|
|
252
|
+
let parsed;
|
|
253
|
+
try {
|
|
254
|
+
parsed = JSON.parse(line);
|
|
255
|
+
} catch {
|
|
256
|
+
const stub = {
|
|
257
|
+
v: 1,
|
|
258
|
+
phase: "end",
|
|
259
|
+
operationId: "unknown",
|
|
260
|
+
kind: "chat",
|
|
261
|
+
transportAttempts: 1,
|
|
262
|
+
provider: "unknown",
|
|
263
|
+
model: "unknown",
|
|
264
|
+
termination: "the stored record could not be parsed",
|
|
265
|
+
captured: {
|
|
266
|
+
fidelity: "runtime_request",
|
|
267
|
+
redacted: true,
|
|
268
|
+
truncated: true,
|
|
269
|
+
omitted: ["record"]
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
return JSON.stringify(stub);
|
|
273
|
+
}
|
|
274
|
+
return JSON.stringify(redactCapturedRequest(parsed));
|
|
275
|
+
}
|
|
141
276
|
function redactEvalHistoryEntry(entry, redact) {
|
|
142
277
|
if (!redact) return entry;
|
|
143
278
|
return {
|
|
@@ -914,7 +1049,50 @@ function reduceCost(acc, event) {
|
|
|
914
1049
|
};
|
|
915
1050
|
}
|
|
916
1051
|
function emptyEvalTrendData() {
|
|
917
|
-
return { byEval: {}, totalRuns: 0, totalCost: 0 };
|
|
1052
|
+
return { byEval: {}, totalRuns: 0, totalCost: 0, totalCostCompleteness: "complete" };
|
|
1053
|
+
}
|
|
1054
|
+
function worse(a, b) {
|
|
1055
|
+
if (a === "unverified" || b === "unverified") return "unverified";
|
|
1056
|
+
if (a === "incomplete" || b === "incomplete") return "incomplete";
|
|
1057
|
+
return "complete";
|
|
1058
|
+
}
|
|
1059
|
+
function extractAccounting(data) {
|
|
1060
|
+
const result = data ?? {};
|
|
1061
|
+
const accounting = result.accounting;
|
|
1062
|
+
if (!accounting || typeof accounting !== "object") {
|
|
1063
|
+
return { cost: usable(extractCost(data)), completeness: "unverified", budgetStopped: false };
|
|
1064
|
+
}
|
|
1065
|
+
const completeness = accounting.completeness === "complete" || accounting.completeness === "incomplete" ? accounting.completeness : "unverified";
|
|
1066
|
+
const knownCost = usable(accounting.knownCost);
|
|
1067
|
+
const summary = result.summary;
|
|
1068
|
+
return {
|
|
1069
|
+
cost: knownCost,
|
|
1070
|
+
completeness,
|
|
1071
|
+
budgetStopped: isBudgetStopped(accounting.budget?.status, summary?.coverage)
|
|
1072
|
+
};
|
|
1073
|
+
}
|
|
1074
|
+
function usable(value) {
|
|
1075
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : 0;
|
|
1076
|
+
}
|
|
1077
|
+
function refusedWork(coverage) {
|
|
1078
|
+
if (!coverage || typeof coverage !== "object") return 0;
|
|
1079
|
+
const { items, scorers } = coverage;
|
|
1080
|
+
let refused = count(items, "budget_skipped") + count(items, "budget_interrupted");
|
|
1081
|
+
if (scorers && typeof scorers === "object") {
|
|
1082
|
+
for (const s of Object.values(scorers)) {
|
|
1083
|
+
refused += count(s, "budget_skipped") + count(s, "budget_interrupted");
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
return refused;
|
|
1087
|
+
}
|
|
1088
|
+
function count(block, key) {
|
|
1089
|
+
if (!block || typeof block !== "object") return 0;
|
|
1090
|
+
const value = block[key];
|
|
1091
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
|
|
1092
|
+
}
|
|
1093
|
+
function isBudgetStopped(status, coverage) {
|
|
1094
|
+
if (status !== "closed") return false;
|
|
1095
|
+
return refusedWork(coverage) > 0;
|
|
918
1096
|
}
|
|
919
1097
|
function extractScores(data) {
|
|
920
1098
|
if (!data || typeof data !== "object") return {};
|
|
@@ -981,7 +1159,7 @@ function computeScoreStats(runs) {
|
|
|
981
1159
|
}
|
|
982
1160
|
function reduceEvalTrends(acc, entry) {
|
|
983
1161
|
const scores = extractScores(entry.data);
|
|
984
|
-
const cost =
|
|
1162
|
+
const { cost, completeness, budgetStopped } = extractAccounting(entry.data);
|
|
985
1163
|
const model = extractModel(entry.data);
|
|
986
1164
|
const duration3 = extractDuration(entry.data);
|
|
987
1165
|
const metadata = entry.data?.metadata;
|
|
@@ -992,6 +1170,8 @@ function reduceEvalTrends(acc, entry) {
|
|
|
992
1170
|
id: entry.id,
|
|
993
1171
|
scores,
|
|
994
1172
|
cost,
|
|
1173
|
+
completeness,
|
|
1174
|
+
...budgetStopped ? { budgetStopped: true } : {},
|
|
995
1175
|
...model !== void 0 ? { model } : {},
|
|
996
1176
|
...duration3 !== void 0 ? { duration: duration3 } : {},
|
|
997
1177
|
...runGroupId !== void 0 ? { runGroupId } : {},
|
|
@@ -1010,12 +1190,15 @@ function reduceEvalTrends(acc, entry) {
|
|
|
1010
1190
|
scoreMean: mean,
|
|
1011
1191
|
scoreStd: std,
|
|
1012
1192
|
costTotal: (prev?.costTotal ?? 0) + cost,
|
|
1193
|
+
costCompleteness: worse(prev?.costCompleteness ?? "complete", completeness),
|
|
1194
|
+
budgetStoppedRuns: (prev?.budgetStoppedRuns ?? 0) + (budgetStopped ? 1 : 0),
|
|
1013
1195
|
runCount: (prev?.runCount ?? 0) + 1
|
|
1014
1196
|
};
|
|
1015
1197
|
return {
|
|
1016
1198
|
byEval,
|
|
1017
1199
|
totalRuns: acc.totalRuns + 1,
|
|
1018
|
-
totalCost: acc.totalCost + cost
|
|
1200
|
+
totalCost: acc.totalCost + cost,
|
|
1201
|
+
totalCostCompleteness: worse(acc.totalCostCompleteness ?? "complete", completeness)
|
|
1019
1202
|
};
|
|
1020
1203
|
}
|
|
1021
1204
|
var MAX_DURATIONS = 200;
|
|
@@ -1337,21 +1520,32 @@ var executions_default = createExecutionRoutes();
|
|
|
1337
1520
|
|
|
1338
1521
|
// src/server/routes/sessions.ts
|
|
1339
1522
|
import { Hono as Hono4 } from "hono";
|
|
1523
|
+
function mediaFields(source) {
|
|
1524
|
+
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;
|
|
1525
|
+
return {
|
|
1526
|
+
source: source.type,
|
|
1527
|
+
...source.mediaType ? { mediaType: source.mediaType } : {},
|
|
1528
|
+
...bytes !== void 0 ? { bytes } : {}
|
|
1529
|
+
};
|
|
1530
|
+
}
|
|
1340
1531
|
function describeStudioInput(content) {
|
|
1341
1532
|
if (typeof content === "string") return void 0;
|
|
1342
1533
|
return {
|
|
1343
1534
|
parts: content.map((part) => {
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1535
|
+
switch (part.type) {
|
|
1536
|
+
case "text":
|
|
1537
|
+
return { type: "text", characters: part.text.length };
|
|
1538
|
+
case "image":
|
|
1539
|
+
return { type: "image", ...mediaFields(part.source) };
|
|
1540
|
+
case "audio":
|
|
1541
|
+
return { type: "audio", ...mediaFields(part.source) };
|
|
1542
|
+
default: {
|
|
1543
|
+
const unreachable = part;
|
|
1544
|
+
throw new Error(
|
|
1545
|
+
`unsupported model input part: ${String(unreachable.type)}`
|
|
1546
|
+
);
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1355
1549
|
})
|
|
1356
1550
|
};
|
|
1357
1551
|
}
|
|
@@ -1705,6 +1899,184 @@ function createCostRoutes(costAggregator) {
|
|
|
1705
1899
|
// src/server/routes/evals.ts
|
|
1706
1900
|
import { randomUUID } from "crypto";
|
|
1707
1901
|
import { Hono as Hono10 } from "hono";
|
|
1902
|
+
|
|
1903
|
+
// src/server/eval-import.ts
|
|
1904
|
+
var ITEM_OUTCOMES = [
|
|
1905
|
+
"completed",
|
|
1906
|
+
"failed",
|
|
1907
|
+
"cancelled",
|
|
1908
|
+
"budget_skipped",
|
|
1909
|
+
"budget_interrupted"
|
|
1910
|
+
];
|
|
1911
|
+
var SCORER_OUTCOMES = [
|
|
1912
|
+
"scored",
|
|
1913
|
+
"failed",
|
|
1914
|
+
"skipped",
|
|
1915
|
+
"cancelled",
|
|
1916
|
+
"budget_skipped",
|
|
1917
|
+
"budget_interrupted"
|
|
1918
|
+
];
|
|
1919
|
+
var EPSILON = 1e-9;
|
|
1920
|
+
function isFiniteNonNegative(value) {
|
|
1921
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0;
|
|
1922
|
+
}
|
|
1923
|
+
function isCount(value) {
|
|
1924
|
+
return isFiniteNonNegative(value) && Number.isInteger(value);
|
|
1925
|
+
}
|
|
1926
|
+
function isValidImportedBudget(value) {
|
|
1927
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
1928
|
+
const b = value;
|
|
1929
|
+
if (!isFiniteNonNegative(b.limit)) return false;
|
|
1930
|
+
if (!isFiniteNonNegative(b.knownSpend)) return false;
|
|
1931
|
+
if (!isFiniteNonNegative(b.knownOvershoot)) return false;
|
|
1932
|
+
if (b.status !== "open" && b.status !== "closed") return false;
|
|
1933
|
+
if (b.closedBy !== void 0 && b.closedBy !== "case" && b.closedBy !== "scorer" && b.closedBy !== "operation") {
|
|
1934
|
+
return false;
|
|
1935
|
+
}
|
|
1936
|
+
if (b.knownSpend >= b.limit !== (b.status === "closed")) return false;
|
|
1937
|
+
const expected = Math.max(0, b.knownSpend - b.limit);
|
|
1938
|
+
return Math.abs(b.knownOvershoot - expected) <= EPSILON;
|
|
1939
|
+
}
|
|
1940
|
+
function isValidImportedCoverage(value) {
|
|
1941
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
1942
|
+
const c = value;
|
|
1943
|
+
if (!c.items || typeof c.items !== "object" || Array.isArray(c.items)) return false;
|
|
1944
|
+
const items = c.items;
|
|
1945
|
+
for (const key of ITEM_OUTCOMES) {
|
|
1946
|
+
if (!isCount(items[key])) return false;
|
|
1947
|
+
}
|
|
1948
|
+
if (!c.scorers || typeof c.scorers !== "object" || Array.isArray(c.scorers)) return false;
|
|
1949
|
+
for (const bucket of Object.values(c.scorers)) {
|
|
1950
|
+
if (!bucket || typeof bucket !== "object" || Array.isArray(bucket)) return false;
|
|
1951
|
+
const counts = bucket;
|
|
1952
|
+
for (const key of SCORER_OUTCOMES) {
|
|
1953
|
+
if (!isCount(counts[key])) return false;
|
|
1954
|
+
}
|
|
1955
|
+
}
|
|
1956
|
+
return true;
|
|
1957
|
+
}
|
|
1958
|
+
function isValidImportedItemErrorRate(value) {
|
|
1959
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
1960
|
+
const r = value;
|
|
1961
|
+
const { failed, attempted, rate, limit, exceeded } = r;
|
|
1962
|
+
if (!isCount(failed) || !isCount(attempted) || failed > attempted) return false;
|
|
1963
|
+
if (!isFiniteNonNegative(limit) || limit > 1) return false;
|
|
1964
|
+
if (typeof rate !== "number" || typeof exceeded !== "boolean") return false;
|
|
1965
|
+
const expectedRate = attempted > 0 ? failed / attempted : 0;
|
|
1966
|
+
if (Math.abs(rate - expectedRate) > EPSILON) return false;
|
|
1967
|
+
return exceeded === (attempted > 0 && rate > limit);
|
|
1968
|
+
}
|
|
1969
|
+
function isValidImportedMultiRun(value) {
|
|
1970
|
+
if (!isPlainRecord(value)) return false;
|
|
1971
|
+
const { allRuns } = value;
|
|
1972
|
+
if (allRuns === void 0) return true;
|
|
1973
|
+
if (!Array.isArray(allRuns)) return false;
|
|
1974
|
+
return allRuns.every(
|
|
1975
|
+
(run) => isPlainRecord(run) && Array.isArray(run.items) && run.items.every(isPlainRecord)
|
|
1976
|
+
);
|
|
1977
|
+
}
|
|
1978
|
+
function isPlainRecord(value) {
|
|
1979
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1980
|
+
}
|
|
1981
|
+
function sumOf(record2) {
|
|
1982
|
+
if (record2 === void 0) return 0;
|
|
1983
|
+
if (record2 === null || typeof record2 !== "object" || Array.isArray(record2)) return void 0;
|
|
1984
|
+
let total = 0;
|
|
1985
|
+
for (const value of Object.values(record2)) {
|
|
1986
|
+
if (!isFiniteNonNegative(value)) return void 0;
|
|
1987
|
+
total += value;
|
|
1988
|
+
}
|
|
1989
|
+
return total;
|
|
1990
|
+
}
|
|
1991
|
+
function allNumeric(record2) {
|
|
1992
|
+
if (record2 === void 0) return true;
|
|
1993
|
+
if (record2 === null || typeof record2 !== "object" || Array.isArray(record2)) return false;
|
|
1994
|
+
return Object.values(record2).every(
|
|
1995
|
+
(value) => typeof value === "number" && Number.isFinite(value)
|
|
1996
|
+
);
|
|
1997
|
+
}
|
|
1998
|
+
function isValidImportedAccounting(value) {
|
|
1999
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
2000
|
+
const a = value;
|
|
2001
|
+
if (a.version !== 1) return false;
|
|
2002
|
+
if (a.currency !== "USD") return false;
|
|
2003
|
+
if (!isFiniteNonNegative(a.knownCost)) return false;
|
|
2004
|
+
if (a.completeness !== "complete" && a.completeness !== "incomplete" && a.completeness !== "unverified") {
|
|
2005
|
+
return false;
|
|
2006
|
+
}
|
|
2007
|
+
if (!allNumeric(a.reasons)) return false;
|
|
2008
|
+
if (!allNumeric(a.usage)) return false;
|
|
2009
|
+
const ops = a.operations;
|
|
2010
|
+
if (!ops || typeof ops !== "object") return false;
|
|
2011
|
+
for (const key of ["total", "settled", "unknown", "denied"]) {
|
|
2012
|
+
if (!isFiniteNonNegative(ops[key])) return false;
|
|
2013
|
+
}
|
|
2014
|
+
if (!allNumeric(ops.byKind)) return false;
|
|
2015
|
+
if (ops.total !== ops.settled + ops.unknown) return false;
|
|
2016
|
+
if (a.completeness === "unverified") return true;
|
|
2017
|
+
const provenanceTotal = sumOf(a.provenance);
|
|
2018
|
+
if (provenanceTotal === void 0) return false;
|
|
2019
|
+
if (Math.abs(provenanceTotal - a.knownCost) > EPSILON) return false;
|
|
2020
|
+
const breakdown = a.breakdown;
|
|
2021
|
+
if (!breakdown || typeof breakdown !== "object") return false;
|
|
2022
|
+
const breakdownTotal = sumOf({
|
|
2023
|
+
generation: breakdown.generation,
|
|
2024
|
+
judging: breakdown.judging,
|
|
2025
|
+
external: breakdown.external
|
|
2026
|
+
});
|
|
2027
|
+
if (breakdownTotal === void 0) return false;
|
|
2028
|
+
if (Math.abs(breakdownTotal - a.knownCost) > EPSILON) return false;
|
|
2029
|
+
return true;
|
|
2030
|
+
}
|
|
2031
|
+
function importedAccountingIsTrustworthy(result) {
|
|
2032
|
+
if (!result || typeof result !== "object") return false;
|
|
2033
|
+
const r = result;
|
|
2034
|
+
if (r.accounting !== void 0 && !isValidImportedAccounting(r.accounting)) return false;
|
|
2035
|
+
const budget = r.accounting?.budget;
|
|
2036
|
+
if (budget !== void 0 && !isValidImportedBudget(budget)) return false;
|
|
2037
|
+
const coverage = r.summary?.coverage;
|
|
2038
|
+
if (coverage !== void 0 && !isValidImportedCoverage(coverage)) return false;
|
|
2039
|
+
if (!Array.isArray(r.items)) return true;
|
|
2040
|
+
for (const item of r.items) {
|
|
2041
|
+
if (!item || typeof item !== "object") continue;
|
|
2042
|
+
const i = item;
|
|
2043
|
+
if (i.accounting !== void 0 && !isValidImportedAccounting(i.accounting)) return false;
|
|
2044
|
+
if (i.scoreDetails && typeof i.scoreDetails === "object") {
|
|
2045
|
+
for (const detail of Object.values(i.scoreDetails)) {
|
|
2046
|
+
const d = detail;
|
|
2047
|
+
if (d?.accounting !== void 0 && !isValidImportedAccounting(d.accounting)) return false;
|
|
2048
|
+
}
|
|
2049
|
+
}
|
|
2050
|
+
}
|
|
2051
|
+
return true;
|
|
2052
|
+
}
|
|
2053
|
+
function stripAccounting(result) {
|
|
2054
|
+
const copy = structuredClone(result);
|
|
2055
|
+
delete copy.accounting;
|
|
2056
|
+
const summary = copy.summary;
|
|
2057
|
+
if (summary && typeof summary === "object") {
|
|
2058
|
+
delete summary.coverage;
|
|
2059
|
+
}
|
|
2060
|
+
const items = copy.items;
|
|
2061
|
+
if (Array.isArray(items)) {
|
|
2062
|
+
for (const item of items) {
|
|
2063
|
+
if (!item || typeof item !== "object") continue;
|
|
2064
|
+
const i = item;
|
|
2065
|
+
delete i.accounting;
|
|
2066
|
+
const details = i.scoreDetails;
|
|
2067
|
+
if (details && typeof details === "object") {
|
|
2068
|
+
for (const detail of Object.values(details)) {
|
|
2069
|
+
if (detail && typeof detail === "object") {
|
|
2070
|
+
delete detail.accounting;
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
2073
|
+
}
|
|
2074
|
+
}
|
|
2075
|
+
}
|
|
2076
|
+
return copy;
|
|
2077
|
+
}
|
|
2078
|
+
|
|
2079
|
+
// src/server/routes/evals.ts
|
|
1708
2080
|
function createEvalRoutes(connMgr, evalLoader) {
|
|
1709
2081
|
const app5 = new Hono10();
|
|
1710
2082
|
const activeRuns = /* @__PURE__ */ new Map();
|
|
@@ -1752,6 +2124,7 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
1752
2124
|
let runs = 1;
|
|
1753
2125
|
let stream = false;
|
|
1754
2126
|
let captureTraces = false;
|
|
2127
|
+
let captureRequests = false;
|
|
1755
2128
|
try {
|
|
1756
2129
|
const body = await c.req.json().catch(() => ({}));
|
|
1757
2130
|
if (typeof body.runs === "number" && Number.isFinite(body.runs) && body.runs > 1) {
|
|
@@ -1763,6 +2136,9 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
1763
2136
|
if (body.captureTraces === true) {
|
|
1764
2137
|
captureTraces = true;
|
|
1765
2138
|
}
|
|
2139
|
+
if (body.captureRequests === true) {
|
|
2140
|
+
captureRequests = true;
|
|
2141
|
+
}
|
|
1766
2142
|
} catch {
|
|
1767
2143
|
}
|
|
1768
2144
|
if (stream) {
|
|
@@ -1786,6 +2162,7 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
1786
2162
|
metadata: { runGroupId, runIndex: r, batchAttempted: runs },
|
|
1787
2163
|
signal: ac.signal,
|
|
1788
2164
|
captureTraces,
|
|
2165
|
+
captureRequests,
|
|
1789
2166
|
onProgress: (event) => {
|
|
1790
2167
|
if (event.type === "run_done") return;
|
|
1791
2168
|
connMgr.broadcastWithWildcard(`eval:${evalRunId}`, {
|
|
@@ -1858,6 +2235,7 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
1858
2235
|
const result = await runtime.runRegisteredEval(name, {
|
|
1859
2236
|
signal: ac.signal,
|
|
1860
2237
|
captureTraces,
|
|
2238
|
+
captureRequests,
|
|
1861
2239
|
onProgress: (event) => {
|
|
1862
2240
|
if (event.type === "run_done") return;
|
|
1863
2241
|
connMgr.broadcastWithWildcard(`eval:${evalRunId}`, event);
|
|
@@ -1889,7 +2267,8 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
1889
2267
|
try {
|
|
1890
2268
|
const result2 = await runtime.runRegisteredEval(name, {
|
|
1891
2269
|
metadata: { runGroupId, runIndex: r, batchAttempted: runs },
|
|
1892
|
-
captureTraces
|
|
2270
|
+
captureTraces,
|
|
2271
|
+
captureRequests
|
|
1893
2272
|
});
|
|
1894
2273
|
results.push(result2);
|
|
1895
2274
|
} catch (err) {
|
|
@@ -1905,11 +2284,14 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
1905
2284
|
const partial2 = results.length < runs;
|
|
1906
2285
|
const failureMsg = runFailure ? redactErrorMessage(runFailure, redactOn) || String(runFailure) || void 0 : void 0;
|
|
1907
2286
|
const aggDegraded = unionDegradedScorers(results);
|
|
2287
|
+
const worstItemRate = worstItemErrorRate(results);
|
|
2288
|
+
const { modelTiming: _runOneModelTiming, ...firstSummary } = first.summary;
|
|
1908
2289
|
const result = {
|
|
1909
2290
|
...first,
|
|
1910
2291
|
summary: {
|
|
1911
|
-
...
|
|
1912
|
-
...aggDegraded.length > 0 ? { degraded: aggDegraded } : {}
|
|
2292
|
+
...firstSummary,
|
|
2293
|
+
...aggDegraded.length > 0 ? { degraded: aggDegraded } : {},
|
|
2294
|
+
...worstItemRate ? { itemErrorRate: worstItemRate } : {}
|
|
1913
2295
|
},
|
|
1914
2296
|
_multiRun: {
|
|
1915
2297
|
aggregate,
|
|
@@ -1927,7 +2309,10 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
1927
2309
|
data: redactEvalResult(result, redactOn)
|
|
1928
2310
|
});
|
|
1929
2311
|
} else {
|
|
1930
|
-
const result = await runtime.runRegisteredEval(name, {
|
|
2312
|
+
const result = await runtime.runRegisteredEval(name, {
|
|
2313
|
+
captureTraces,
|
|
2314
|
+
captureRequests
|
|
2315
|
+
});
|
|
1931
2316
|
return c.json({
|
|
1932
2317
|
ok: true,
|
|
1933
2318
|
data: redactEvalResult(result, redactOn)
|
|
@@ -1940,6 +2325,106 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
1940
2325
|
);
|
|
1941
2326
|
}
|
|
1942
2327
|
});
|
|
2328
|
+
async function resolveDiagnostics(runtime, id) {
|
|
2329
|
+
const entry = await runtime.getEvalResult(id);
|
|
2330
|
+
const artifactId = entry?.data?.diagnostics?.artifactId;
|
|
2331
|
+
return typeof artifactId === "string" && artifactId !== "" ? { artifactId } : void 0;
|
|
2332
|
+
}
|
|
2333
|
+
app5.get("/evals/:id/diagnostics", async (c) => {
|
|
2334
|
+
const runtime = c.get("runtime");
|
|
2335
|
+
const id = c.req.param("id");
|
|
2336
|
+
const resolved = await resolveDiagnostics(runtime, id);
|
|
2337
|
+
if (!resolved) {
|
|
2338
|
+
return c.json(
|
|
2339
|
+
{
|
|
2340
|
+
ok: false,
|
|
2341
|
+
error: {
|
|
2342
|
+
code: "NOT_FOUND",
|
|
2343
|
+
message: `Eval result "${id}" has no captured requests`
|
|
2344
|
+
}
|
|
2345
|
+
},
|
|
2346
|
+
404
|
|
2347
|
+
);
|
|
2348
|
+
}
|
|
2349
|
+
const opened = await runtime.openDiagnosticArtifact(resolved.artifactId);
|
|
2350
|
+
if (!opened) {
|
|
2351
|
+
return c.json(
|
|
2352
|
+
{
|
|
2353
|
+
ok: false,
|
|
2354
|
+
error: {
|
|
2355
|
+
code: "NOT_FOUND",
|
|
2356
|
+
message: `Captured requests for eval result "${id}" are no longer available`
|
|
2357
|
+
}
|
|
2358
|
+
},
|
|
2359
|
+
404
|
|
2360
|
+
);
|
|
2361
|
+
}
|
|
2362
|
+
return c.json({
|
|
2363
|
+
ok: true,
|
|
2364
|
+
data: {
|
|
2365
|
+
artifactId: opened.manifest.artifactId,
|
|
2366
|
+
status: opened.manifest.status,
|
|
2367
|
+
...opened.manifest.reason !== void 0 ? { reason: opened.manifest.reason } : {},
|
|
2368
|
+
records: opened.manifest.records,
|
|
2369
|
+
bytes: opened.manifest.bytes,
|
|
2370
|
+
fidelity: opened.manifest.fidelity,
|
|
2371
|
+
redaction: opened.manifest.redaction,
|
|
2372
|
+
...opened.manifest.expiresAt !== void 0 ? { expiresAt: opened.manifest.expiresAt } : {},
|
|
2373
|
+
...opened.manifest.copiedFrom !== void 0 ? { copiedFrom: opened.manifest.copiedFrom } : {}
|
|
2374
|
+
}
|
|
2375
|
+
});
|
|
2376
|
+
});
|
|
2377
|
+
app5.get("/evals/:id/diagnostics/records", async (c) => {
|
|
2378
|
+
const runtime = c.get("runtime");
|
|
2379
|
+
const redactOn = runtime.isRedactEnabled();
|
|
2380
|
+
const id = c.req.param("id");
|
|
2381
|
+
const resolved = await resolveDiagnostics(runtime, id);
|
|
2382
|
+
const opened = resolved ? await runtime.openDiagnosticArtifact(resolved.artifactId) : void 0;
|
|
2383
|
+
if (!opened) {
|
|
2384
|
+
return c.json(
|
|
2385
|
+
{
|
|
2386
|
+
ok: false,
|
|
2387
|
+
error: {
|
|
2388
|
+
code: "NOT_FOUND",
|
|
2389
|
+
message: `Captured requests for eval result "${id}" are not available`
|
|
2390
|
+
}
|
|
2391
|
+
},
|
|
2392
|
+
404
|
|
2393
|
+
);
|
|
2394
|
+
}
|
|
2395
|
+
let cancelled = false;
|
|
2396
|
+
const lines = opened.lines[Symbol.asyncIterator]();
|
|
2397
|
+
return new Response(
|
|
2398
|
+
new ReadableStream({
|
|
2399
|
+
async start(controller) {
|
|
2400
|
+
const encoder = new TextEncoder();
|
|
2401
|
+
try {
|
|
2402
|
+
for (; ; ) {
|
|
2403
|
+
const next = await lines.next();
|
|
2404
|
+
if (next.done || cancelled) break;
|
|
2405
|
+
controller.enqueue(encoder.encode(`${redactRecordLine(next.value, redactOn)}
|
|
2406
|
+
`));
|
|
2407
|
+
}
|
|
2408
|
+
if (!cancelled) controller.close();
|
|
2409
|
+
} catch (error48) {
|
|
2410
|
+
if (!cancelled) controller.error(error48);
|
|
2411
|
+
} finally {
|
|
2412
|
+
await lines.return?.().catch(() => void 0);
|
|
2413
|
+
}
|
|
2414
|
+
},
|
|
2415
|
+
cancel() {
|
|
2416
|
+
cancelled = true;
|
|
2417
|
+
}
|
|
2418
|
+
}),
|
|
2419
|
+
{
|
|
2420
|
+
status: 200,
|
|
2421
|
+
headers: {
|
|
2422
|
+
"Content-Type": "application/x-ndjson; charset=utf-8",
|
|
2423
|
+
"Cache-Control": "no-store"
|
|
2424
|
+
}
|
|
2425
|
+
}
|
|
2426
|
+
);
|
|
2427
|
+
});
|
|
1943
2428
|
app5.post("/evals/runs/:evalRunId/cancel", (c) => {
|
|
1944
2429
|
const evalRunId = c.req.param("evalRunId");
|
|
1945
2430
|
const ac = activeRuns.get(evalRunId);
|
|
@@ -1959,6 +2444,7 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
1959
2444
|
const redactOn = runtime.isRedactEnabled();
|
|
1960
2445
|
const name = c.req.param("name");
|
|
1961
2446
|
const body = await c.req.json();
|
|
2447
|
+
const captureRequests = body.captureRequests === true;
|
|
1962
2448
|
if (!body.resultId || typeof body.resultId !== "string") {
|
|
1963
2449
|
return c.json(
|
|
1964
2450
|
{ ok: false, error: { code: "BAD_REQUEST", message: "resultId is required" } },
|
|
@@ -1972,8 +2458,7 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
1972
2458
|
404
|
|
1973
2459
|
);
|
|
1974
2460
|
}
|
|
1975
|
-
const
|
|
1976
|
-
const historyEntry = history.find((h) => h.id === body.resultId);
|
|
2461
|
+
const historyEntry = await runtime.getEvalResult(body.resultId);
|
|
1977
2462
|
if (!historyEntry) {
|
|
1978
2463
|
return c.json(
|
|
1979
2464
|
{ ok: false, error: { code: "NOT_FOUND", message: `Result "${body.resultId}" not found` } },
|
|
@@ -1986,7 +2471,8 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
1986
2471
|
const result = await rescore(
|
|
1987
2472
|
historyEntry.data,
|
|
1988
2473
|
config2.scorers,
|
|
1989
|
-
runtime
|
|
2474
|
+
runtime,
|
|
2475
|
+
captureRequests ? { captureRequests: true } : void 0
|
|
1990
2476
|
);
|
|
1991
2477
|
await runtime.saveEvalResult({
|
|
1992
2478
|
id: result.id,
|
|
@@ -2040,8 +2526,13 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
2040
2526
|
400
|
|
2041
2527
|
);
|
|
2042
2528
|
}
|
|
2043
|
-
const
|
|
2044
|
-
const
|
|
2529
|
+
const idsOf = (v) => Array.isArray(v) ? v : [v];
|
|
2530
|
+
const requested = /* @__PURE__ */ new Set([...idsOf(body.baselineId), ...idsOf(body.candidateId)]);
|
|
2531
|
+
const byId = /* @__PURE__ */ new Map();
|
|
2532
|
+
for (const id of requested) {
|
|
2533
|
+
const entry = await runtime.getEvalResult(id);
|
|
2534
|
+
if (entry) byId.set(id, entry.data);
|
|
2535
|
+
}
|
|
2045
2536
|
const missing = [];
|
|
2046
2537
|
const resolveOne = (id) => {
|
|
2047
2538
|
const data = byId.get(id);
|
|
@@ -2077,7 +2568,10 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
2077
2568
|
}
|
|
2078
2569
|
try {
|
|
2079
2570
|
const result = await runtime.evalCompare(baseline, candidate, body.options);
|
|
2080
|
-
return c.json({
|
|
2571
|
+
return c.json({
|
|
2572
|
+
ok: true,
|
|
2573
|
+
data: redactEvalComparison(result, redactOn)
|
|
2574
|
+
});
|
|
2081
2575
|
} catch (err) {
|
|
2082
2576
|
return c.json(
|
|
2083
2577
|
{
|
|
@@ -2145,6 +2639,26 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
2145
2639
|
const workflowsFromMeta = Array.isArray(metadataObj.workflows) ? metadataObj.workflows : [];
|
|
2146
2640
|
const primaryWorkflow = workflowsFromMeta.find((w) => typeof w === "string");
|
|
2147
2641
|
const evalName = trim(body.eval) ?? trim(primaryWorkflow) ?? trim(firstResult.workflow) ?? "imported";
|
|
2642
|
+
let readAccounting;
|
|
2643
|
+
let validateRequestSidecar;
|
|
2644
|
+
try {
|
|
2645
|
+
({ readAccounting, validateRequestSidecar } = await import("@axlsdk/eval"));
|
|
2646
|
+
} catch {
|
|
2647
|
+
readAccounting = void 0;
|
|
2648
|
+
validateRequestSidecar = void 0;
|
|
2649
|
+
}
|
|
2650
|
+
let sidecarLines;
|
|
2651
|
+
if (body.requests !== void 0 && body.requests !== null) {
|
|
2652
|
+
if (!validateRequestSidecar) {
|
|
2653
|
+
return bad("importing captured requests requires @axlsdk/eval to be installed");
|
|
2654
|
+
}
|
|
2655
|
+
const validation = validateRequestSidecar(body.requests);
|
|
2656
|
+
if (!validation.ok) return bad(validation.reason);
|
|
2657
|
+
sidecarLines = validation.lines;
|
|
2658
|
+
}
|
|
2659
|
+
if (sidecarLines && validatedResults.length > 1) {
|
|
2660
|
+
return bad("a requests sidecar can only accompany a single result");
|
|
2661
|
+
}
|
|
2148
2662
|
const timestamp = Date.now();
|
|
2149
2663
|
const imported = [];
|
|
2150
2664
|
for (const r of validatedResults) {
|
|
@@ -2154,6 +2668,42 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
2154
2668
|
id,
|
|
2155
2669
|
metadata: typeof r.metadata === "object" && r.metadata != null ? r.metadata : {}
|
|
2156
2670
|
};
|
|
2671
|
+
if (entry.accounting === void 0) {
|
|
2672
|
+
if (entry.summary?.coverage !== void 0 && !isValidImportedCoverage(entry.summary.coverage)) {
|
|
2673
|
+
delete entry.summary.coverage;
|
|
2674
|
+
entry.metadata.importedAccounting = "invalid";
|
|
2675
|
+
}
|
|
2676
|
+
if (readAccounting) {
|
|
2677
|
+
entry.accounting = readAccounting(entry);
|
|
2678
|
+
}
|
|
2679
|
+
} else if (importedAccountingIsTrustworthy(entry)) {
|
|
2680
|
+
entry.metadata.importedAccounting = "declared";
|
|
2681
|
+
} else {
|
|
2682
|
+
const stripped = stripAccounting(entry);
|
|
2683
|
+
entry.accounting = readAccounting ? readAccounting(stripped) : void 0;
|
|
2684
|
+
entry.items = stripped.items;
|
|
2685
|
+
entry.summary = stripped.summary;
|
|
2686
|
+
entry.metadata.importedAccounting = "invalid";
|
|
2687
|
+
}
|
|
2688
|
+
if (entry.summary?.itemErrorRate !== void 0 && !isValidImportedItemErrorRate(entry.summary.itemErrorRate)) {
|
|
2689
|
+
delete entry.summary.itemErrorRate;
|
|
2690
|
+
entry.metadata.importedItemErrorRate = "invalid";
|
|
2691
|
+
}
|
|
2692
|
+
const multiRun = entry._multiRun;
|
|
2693
|
+
if (multiRun !== void 0 && !isValidImportedMultiRun(multiRun)) {
|
|
2694
|
+
delete entry._multiRun;
|
|
2695
|
+
entry.metadata.importedMultiRun = "invalid";
|
|
2696
|
+
}
|
|
2697
|
+
if (sidecarLines) {
|
|
2698
|
+
entry.diagnostics = await restageImportedRequests(runtime, id, sidecarLines);
|
|
2699
|
+
} else if (entry.diagnostics) {
|
|
2700
|
+
entry.diagnostics = {
|
|
2701
|
+
...entry.diagnostics,
|
|
2702
|
+
artifactId: "",
|
|
2703
|
+
status: "unavailable",
|
|
2704
|
+
reason: "imported without its captured-request sidecar"
|
|
2705
|
+
};
|
|
2706
|
+
}
|
|
2157
2707
|
await runtime.saveEvalResult({ id, eval: evalName, timestamp, data: entry });
|
|
2158
2708
|
imported.push({ id, eval: evalName, timestamp });
|
|
2159
2709
|
}
|
|
@@ -2162,12 +2712,72 @@ function createEvalRoutes(connMgr, evalLoader) {
|
|
|
2162
2712
|
}
|
|
2163
2713
|
return c.json({ ok: true, data: { imported } });
|
|
2164
2714
|
});
|
|
2715
|
+
async function restageImportedRequests(runtime, ownerId, lines) {
|
|
2716
|
+
let stagedId;
|
|
2717
|
+
try {
|
|
2718
|
+
const staged = await runtime.stageDiagnosticArtifact({ kind: "eval", id: ownerId });
|
|
2719
|
+
stagedId = staged.artifactId;
|
|
2720
|
+
let bytes = 0;
|
|
2721
|
+
let allRedacted = lines.length > 0;
|
|
2722
|
+
for (const line of lines) {
|
|
2723
|
+
await staged.sink.append(line);
|
|
2724
|
+
bytes += Buffer.byteLength(line, "utf-8");
|
|
2725
|
+
if (allRedacted) {
|
|
2726
|
+
try {
|
|
2727
|
+
allRedacted = JSON.parse(line).captured?.redacted === true;
|
|
2728
|
+
} catch {
|
|
2729
|
+
allRedacted = false;
|
|
2730
|
+
}
|
|
2731
|
+
}
|
|
2732
|
+
}
|
|
2733
|
+
const manifest = await runtime.finalizeDiagnosticArtifact(
|
|
2734
|
+
staged.artifactId,
|
|
2735
|
+
"complete",
|
|
2736
|
+
void 0,
|
|
2737
|
+
allRedacted ? "applied" : "none"
|
|
2738
|
+
);
|
|
2739
|
+
return {
|
|
2740
|
+
version: 1,
|
|
2741
|
+
artifactId: manifest.artifactId,
|
|
2742
|
+
fidelity: "runtime_request",
|
|
2743
|
+
status: manifest.status,
|
|
2744
|
+
records: lines.length,
|
|
2745
|
+
bytes,
|
|
2746
|
+
redaction: manifest.redaction
|
|
2747
|
+
};
|
|
2748
|
+
} catch (error48) {
|
|
2749
|
+
if (stagedId !== void 0) {
|
|
2750
|
+
await runtime.rollbackDiagnosticArtifact(stagedId).catch(() => void 0);
|
|
2751
|
+
}
|
|
2752
|
+
return {
|
|
2753
|
+
version: 1,
|
|
2754
|
+
artifactId: "",
|
|
2755
|
+
fidelity: "runtime_request",
|
|
2756
|
+
status: "unavailable",
|
|
2757
|
+
reason: `captured requests could not be stored: ${error48 instanceof Error ? error48.message : String(error48)}`,
|
|
2758
|
+
records: 0,
|
|
2759
|
+
bytes: 0,
|
|
2760
|
+
redaction: "none"
|
|
2761
|
+
};
|
|
2762
|
+
}
|
|
2763
|
+
}
|
|
2165
2764
|
function closeActiveRuns() {
|
|
2166
2765
|
for (const ac of activeRuns.values()) ac.abort();
|
|
2167
2766
|
activeRuns.clear();
|
|
2168
2767
|
}
|
|
2169
2768
|
return { app: app5, closeActiveRuns };
|
|
2170
2769
|
}
|
|
2770
|
+
function worstItemErrorRate(results) {
|
|
2771
|
+
let worst;
|
|
2772
|
+
let runsExceeded = 0;
|
|
2773
|
+
for (const run of results) {
|
|
2774
|
+
const r = run.summary?.itemErrorRate;
|
|
2775
|
+
if (!r) continue;
|
|
2776
|
+
if (r.exceeded) runsExceeded++;
|
|
2777
|
+
if (!worst || r.rate > worst.rate) worst = r;
|
|
2778
|
+
}
|
|
2779
|
+
return worst ? { ...worst, runsExceeded } : void 0;
|
|
2780
|
+
}
|
|
2171
2781
|
function unionDegradedScorers(results) {
|
|
2172
2782
|
const byScorer = /* @__PURE__ */ new Map();
|
|
2173
2783
|
for (const run of results) {
|
|
@@ -2178,8 +2788,8 @@ function unionDegradedScorers(results) {
|
|
|
2178
2788
|
if (!existing) {
|
|
2179
2789
|
byScorer.set(d.scorer, { ...d, runsAffected: 1 });
|
|
2180
2790
|
} else {
|
|
2181
|
-
const
|
|
2182
|
-
byScorer.set(d.scorer, { ...
|
|
2791
|
+
const worse2 = d.rate > existing.rate ? d : existing;
|
|
2792
|
+
byScorer.set(d.scorer, { ...worse2, runsAffected: existing.runsAffected + 1 });
|
|
2183
2793
|
}
|
|
2184
2794
|
}
|
|
2185
2795
|
}
|
|
@@ -2819,7 +3429,7 @@ __export(util_exports, {
|
|
|
2819
3429
|
getSizableOrigin: () => getSizableOrigin,
|
|
2820
3430
|
hexToUint8Array: () => hexToUint8Array,
|
|
2821
3431
|
isObject: () => isObject,
|
|
2822
|
-
isPlainObject: () =>
|
|
3432
|
+
isPlainObject: () => isPlainObject2,
|
|
2823
3433
|
issue: () => issue,
|
|
2824
3434
|
joinValues: () => joinValues,
|
|
2825
3435
|
jsonStringifyReplacer: () => jsonStringifyReplacer,
|
|
@@ -3003,7 +3613,7 @@ var allowsEval = cached(() => {
|
|
|
3003
3613
|
return false;
|
|
3004
3614
|
}
|
|
3005
3615
|
});
|
|
3006
|
-
function
|
|
3616
|
+
function isPlainObject2(o) {
|
|
3007
3617
|
if (isObject(o) === false)
|
|
3008
3618
|
return false;
|
|
3009
3619
|
const ctor = o.constructor;
|
|
@@ -3020,7 +3630,7 @@ function isPlainObject(o) {
|
|
|
3020
3630
|
return true;
|
|
3021
3631
|
}
|
|
3022
3632
|
function shallowClone(o) {
|
|
3023
|
-
if (
|
|
3633
|
+
if (isPlainObject2(o))
|
|
3024
3634
|
return { ...o };
|
|
3025
3635
|
if (Array.isArray(o))
|
|
3026
3636
|
return [...o];
|
|
@@ -3213,7 +3823,7 @@ function omit(schema, mask) {
|
|
|
3213
3823
|
return clone(schema, def);
|
|
3214
3824
|
}
|
|
3215
3825
|
function extend(schema, shape) {
|
|
3216
|
-
if (!
|
|
3826
|
+
if (!isPlainObject2(shape)) {
|
|
3217
3827
|
throw new Error("Invalid input to extend: expected a plain object");
|
|
3218
3828
|
}
|
|
3219
3829
|
const checks = schema._zod.def.checks;
|
|
@@ -3236,7 +3846,7 @@ function extend(schema, shape) {
|
|
|
3236
3846
|
return clone(schema, def);
|
|
3237
3847
|
}
|
|
3238
3848
|
function safeExtend(schema, shape) {
|
|
3239
|
-
if (!
|
|
3849
|
+
if (!isPlainObject2(shape)) {
|
|
3240
3850
|
throw new Error("Invalid input to safeExtend: expected a plain object");
|
|
3241
3851
|
}
|
|
3242
3852
|
const def = mergeDefs(schema._zod.def, {
|
|
@@ -5511,7 +6121,7 @@ function mergeValues(a, b) {
|
|
|
5511
6121
|
if (a instanceof Date && b instanceof Date && +a === +b) {
|
|
5512
6122
|
return { valid: true, data: a };
|
|
5513
6123
|
}
|
|
5514
|
-
if (
|
|
6124
|
+
if (isPlainObject2(a) && isPlainObject2(b)) {
|
|
5515
6125
|
const bKeys = Object.keys(b);
|
|
5516
6126
|
const sharedKeys = Object.keys(a).filter((key) => bKeys.indexOf(key) !== -1);
|
|
5517
6127
|
const newObj = { ...a, ...b };
|
|
@@ -5665,7 +6275,7 @@ var $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
|
|
|
5665
6275
|
$ZodType.init(inst, def);
|
|
5666
6276
|
inst._zod.parse = (payload, ctx) => {
|
|
5667
6277
|
const input = payload.value;
|
|
5668
|
-
if (!
|
|
6278
|
+
if (!isPlainObject2(input)) {
|
|
5669
6279
|
payload.issues.push({
|
|
5670
6280
|
expected: "record",
|
|
5671
6281
|
code: "invalid_type",
|
|
@@ -6673,8 +7283,8 @@ function az_default() {
|
|
|
6673
7283
|
}
|
|
6674
7284
|
|
|
6675
7285
|
// ../../node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/locales/be.js
|
|
6676
|
-
function getBelarusianPlural(
|
|
6677
|
-
const absCount = Math.abs(
|
|
7286
|
+
function getBelarusianPlural(count2, one, few, many) {
|
|
7287
|
+
const absCount = Math.abs(count2);
|
|
6678
7288
|
const lastDigit = absCount % 10;
|
|
6679
7289
|
const lastTwoDigits = absCount % 100;
|
|
6680
7290
|
if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {
|
|
@@ -8498,8 +9108,8 @@ function hu_default() {
|
|
|
8498
9108
|
}
|
|
8499
9109
|
|
|
8500
9110
|
// ../../node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/locales/hy.js
|
|
8501
|
-
function getArmenianPlural(
|
|
8502
|
-
return Math.abs(
|
|
9111
|
+
function getArmenianPlural(count2, one, many) {
|
|
9112
|
+
return Math.abs(count2) === 1 ? one : many;
|
|
8503
9113
|
}
|
|
8504
9114
|
function withDefiniteArticle(word) {
|
|
8505
9115
|
if (!word)
|
|
@@ -10507,8 +11117,8 @@ function pt_default() {
|
|
|
10507
11117
|
}
|
|
10508
11118
|
|
|
10509
11119
|
// ../../node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/locales/ru.js
|
|
10510
|
-
function getRussianPlural(
|
|
10511
|
-
const absCount = Math.abs(
|
|
11120
|
+
function getRussianPlural(count2, one, few, many) {
|
|
11121
|
+
const absCount = Math.abs(count2);
|
|
10512
11122
|
const lastDigit = absCount % 10;
|
|
10513
11123
|
const lastTwoDigits = absCount % 100;
|
|
10514
11124
|
if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {
|
|
@@ -16461,4 +17071,4 @@ export {
|
|
|
16461
17071
|
EvalAggregator,
|
|
16462
17072
|
createServer
|
|
16463
17073
|
};
|
|
16464
|
-
//# sourceMappingURL=chunk-
|
|
17074
|
+
//# sourceMappingURL=chunk-PFPLZQ5X.js.map
|