@vitest-evals/github-reporter 0.11.0 → 0.12.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/dist/cli.js +72 -249
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +75 -247
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +7 -52
- package/dist/index.d.ts +7 -52
- package/dist/index.js +65 -120
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +67 -120
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -1
package/dist/cli.mjs
CHANGED
|
@@ -101,13 +101,14 @@ function readInteger(args, index, flag) {
|
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
// src/report.ts
|
|
104
|
-
import { appendFile
|
|
104
|
+
import { appendFile } from "fs/promises";
|
|
105
|
+
import {
|
|
106
|
+
readVitestJsonReportFile,
|
|
107
|
+
resolveResultFiles
|
|
108
|
+
} from "@vitest-evals/core/node";
|
|
105
109
|
|
|
106
110
|
// src/utils.ts
|
|
107
111
|
import { posix } from "path";
|
|
108
|
-
function isRecord(value) {
|
|
109
|
-
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
110
|
-
}
|
|
111
112
|
function compactLine(value, maxLength) {
|
|
112
113
|
const line = value.split(/\r?\n/).map((part) => part.trim()).find((part) => part.length > 0);
|
|
113
114
|
if (!line) {
|
|
@@ -170,17 +171,6 @@ function formatLocation(file, location) {
|
|
|
170
171
|
}
|
|
171
172
|
return `${file}:${location.line}`;
|
|
172
173
|
}
|
|
173
|
-
function normalizePathForGitHub(path, workspace) {
|
|
174
|
-
const normalized = path.replace(/\\/g, "/");
|
|
175
|
-
if (!workspace) {
|
|
176
|
-
return normalized;
|
|
177
|
-
}
|
|
178
|
-
const workspacePath = workspace.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
179
|
-
if (normalized !== workspacePath && !normalized.startsWith(`${workspacePath}/`)) {
|
|
180
|
-
return normalized;
|
|
181
|
-
}
|
|
182
|
-
return posix.relative(workspacePath, normalized);
|
|
183
|
-
}
|
|
184
174
|
function escapeFence(value) {
|
|
185
175
|
return value.replace(/```/g, "'''");
|
|
186
176
|
}
|
|
@@ -267,9 +257,9 @@ function formatRawDetails(testCase) {
|
|
|
267
257
|
if (finalOutput !== void 0) {
|
|
268
258
|
lines.push("", "Final:", stringifyValue(finalOutput, 8e3));
|
|
269
259
|
}
|
|
270
|
-
if (testCase.
|
|
260
|
+
if (testCase.toolCalls.length) {
|
|
271
261
|
lines.push("", "Tools:");
|
|
272
|
-
for (const toolCall of testCase.
|
|
262
|
+
for (const toolCall of testCase.toolCalls) {
|
|
273
263
|
lines.push(
|
|
274
264
|
`- ${toolCall.name}: ${toolCall.error ? `error: ${toolCall.error}` : "ok"}`
|
|
275
265
|
);
|
|
@@ -287,17 +277,23 @@ function formatWorkflowCommand({
|
|
|
287
277
|
}
|
|
288
278
|
|
|
289
279
|
// src/collect.ts
|
|
280
|
+
import {
|
|
281
|
+
collectReportWorkspace
|
|
282
|
+
} from "@vitest-evals/core";
|
|
290
283
|
function collectEvalReport(input, options = {}) {
|
|
291
|
-
const
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
284
|
+
const workspace = collectReportWorkspace(
|
|
285
|
+
{
|
|
286
|
+
report: input
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
workspace: options.workspace
|
|
290
|
+
}
|
|
296
291
|
);
|
|
292
|
+
const cases = workspace.cases.map(collectEvalCase);
|
|
297
293
|
const failures = cases.filter((testCase) => testCase.status === "failed");
|
|
298
294
|
const evalScores = cases.map((testCase) => testCase.eval?.avgScore).filter((score) => isFiniteNumber(score));
|
|
299
295
|
const usage2 = sumUsage(cases);
|
|
300
|
-
const durationMs =
|
|
296
|
+
const durationMs = workspace.runs[0]?.durationMs;
|
|
301
297
|
return {
|
|
302
298
|
status: input.success && failures.length === 0 ? "passed" : "failed",
|
|
303
299
|
startedAt: input.startTime,
|
|
@@ -320,35 +316,29 @@ function collectEvalReport(input, options = {}) {
|
|
|
320
316
|
failures
|
|
321
317
|
};
|
|
322
318
|
}
|
|
323
|
-
function collectEvalCase(
|
|
324
|
-
const
|
|
325
|
-
const
|
|
326
|
-
const
|
|
327
|
-
if (!evalMeta && !harnessMeta) {
|
|
328
|
-
return null;
|
|
329
|
-
}
|
|
330
|
-
const displayFile = normalizePathForGitHub(file.name, options.workspace);
|
|
331
|
-
const scores = evalMeta?.scores ?? [];
|
|
332
|
-
const harnessRun = harnessMeta?.run;
|
|
333
|
-
const toolCalls = collectToolCalls(harnessRun?.session);
|
|
319
|
+
function collectEvalCase(reportCase) {
|
|
320
|
+
const scores = (reportCase.eval?.scores ?? []).map(normalizeScore);
|
|
321
|
+
const harnessRun = reportCase.harness?.run;
|
|
322
|
+
const toolCalls = collectToolCalls(reportCase);
|
|
334
323
|
const evalCase = {
|
|
335
|
-
id:
|
|
336
|
-
file: file
|
|
337
|
-
displayFile,
|
|
338
|
-
title:
|
|
339
|
-
displayName:
|
|
340
|
-
status:
|
|
341
|
-
durationMs:
|
|
342
|
-
location:
|
|
343
|
-
failureMessages:
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
324
|
+
id: reportCase.id,
|
|
325
|
+
file: reportCase.file,
|
|
326
|
+
displayFile: reportCase.displayFile,
|
|
327
|
+
title: reportCase.title,
|
|
328
|
+
displayName: reportCase.displayName,
|
|
329
|
+
status: reportCase.status,
|
|
330
|
+
durationMs: numberField(reportCase.durationMs),
|
|
331
|
+
location: reportCase.location,
|
|
332
|
+
failureMessages: reportCase.failureMessages,
|
|
333
|
+
toolCalls,
|
|
334
|
+
eval: reportCase.eval ? {
|
|
335
|
+
avgScore: numberField(reportCase.eval.avgScore),
|
|
336
|
+
thresholdFailed: reportCase.eval.thresholdFailed,
|
|
337
|
+
output: reportCase.eval.output,
|
|
348
338
|
scores
|
|
349
339
|
} : void 0,
|
|
350
|
-
harness:
|
|
351
|
-
name:
|
|
340
|
+
harness: reportCase.harness ? {
|
|
341
|
+
name: reportCase.harness.name,
|
|
352
342
|
output: harnessRun?.output,
|
|
353
343
|
usage: harnessRun?.usage,
|
|
354
344
|
timingMs: harnessRun?.timings?.totalMs,
|
|
@@ -359,54 +349,10 @@ function collectEvalCase(file, assertion, options) {
|
|
|
359
349
|
evalCase.primaryFailure = getPrimaryFailure(evalCase);
|
|
360
350
|
return evalCase;
|
|
361
351
|
}
|
|
362
|
-
function getEvalMeta(value) {
|
|
363
|
-
if (!isRecord(value)) {
|
|
364
|
-
return void 0;
|
|
365
|
-
}
|
|
366
|
-
return {
|
|
367
|
-
scores: Array.isArray(value.scores) ? value.scores.filter(isRecord).map(normalizeScore) : void 0,
|
|
368
|
-
avgScore: numberField(value.avgScore),
|
|
369
|
-
output: value.output,
|
|
370
|
-
thresholdFailed: typeof value.thresholdFailed === "boolean" ? value.thresholdFailed : void 0
|
|
371
|
-
};
|
|
372
|
-
}
|
|
373
352
|
function normalizeScore(score) {
|
|
374
|
-
const metadata = isRecord(score.metadata) ? score.metadata : void 0;
|
|
375
|
-
return {
|
|
376
|
-
name: typeof score.name === "string" ? score.name : void 0,
|
|
377
|
-
score: numberField(score.score) ?? null,
|
|
378
|
-
metadata
|
|
379
|
-
};
|
|
380
|
-
}
|
|
381
|
-
function getHarnessMeta(value) {
|
|
382
|
-
if (!isRecord(value)) {
|
|
383
|
-
return void 0;
|
|
384
|
-
}
|
|
385
|
-
const run = isRecord(value.run) ? value.run : void 0;
|
|
386
|
-
const usage2 = isRecord(run?.usage) ? getUsage(run.usage) : void 0;
|
|
387
|
-
const timings = isRecord(run?.timings) ? run.timings : void 0;
|
|
388
353
|
return {
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
output: run.output,
|
|
392
|
-
usage: usage2,
|
|
393
|
-
timings: {
|
|
394
|
-
totalMs: typeof timings?.totalMs === "number" ? timings.totalMs : void 0
|
|
395
|
-
},
|
|
396
|
-
session: isRecord(run.session) ? {
|
|
397
|
-
messages: Array.isArray(run.session.messages) ? run.session.messages : void 0
|
|
398
|
-
} : void 0,
|
|
399
|
-
errors: Array.isArray(run.errors) ? run.errors : void 0
|
|
400
|
-
} : void 0
|
|
401
|
-
};
|
|
402
|
-
}
|
|
403
|
-
function getUsage(value) {
|
|
404
|
-
return {
|
|
405
|
-
inputTokens: numberField(value.inputTokens),
|
|
406
|
-
outputTokens: numberField(value.outputTokens),
|
|
407
|
-
reasoningTokens: numberField(value.reasoningTokens),
|
|
408
|
-
totalTokens: numberField(value.totalTokens),
|
|
409
|
-
toolCalls: numberField(value.toolCalls)
|
|
354
|
+
...score,
|
|
355
|
+
score: numberField(score.score) ?? null
|
|
410
356
|
};
|
|
411
357
|
}
|
|
412
358
|
function numberField(value) {
|
|
@@ -415,7 +361,13 @@ function numberField(value) {
|
|
|
415
361
|
function isFiniteNumber(value) {
|
|
416
362
|
return typeof value === "number" && Number.isFinite(value);
|
|
417
363
|
}
|
|
418
|
-
function collectToolCalls(
|
|
364
|
+
function collectToolCalls(reportCase) {
|
|
365
|
+
const harnessCalls = collectSessionToolCalls(
|
|
366
|
+
reportCase.harness?.run?.session
|
|
367
|
+
);
|
|
368
|
+
return harnessCalls.length > 0 ? harnessCalls : (reportCase.eval?.toolCalls ?? []).map(toToolCallSummary);
|
|
369
|
+
}
|
|
370
|
+
function collectSessionToolCalls(session) {
|
|
419
371
|
const messages = session?.messages ?? [];
|
|
420
372
|
const toolCalls = [];
|
|
421
373
|
for (const message of messages) {
|
|
@@ -423,21 +375,22 @@ function collectToolCalls(session) {
|
|
|
423
375
|
continue;
|
|
424
376
|
}
|
|
425
377
|
for (const call of message.toolCalls) {
|
|
426
|
-
|
|
427
|
-
continue;
|
|
428
|
-
}
|
|
429
|
-
toolCalls.push({
|
|
430
|
-
name: call.name,
|
|
431
|
-
error: getToolCallError(call.error),
|
|
432
|
-
durationMs: numberField(call.durationMs)
|
|
433
|
-
});
|
|
378
|
+
toolCalls.push(toToolCallSummary(call));
|
|
434
379
|
}
|
|
435
380
|
}
|
|
436
381
|
return toolCalls;
|
|
437
382
|
}
|
|
383
|
+
function toToolCallSummary(call) {
|
|
384
|
+
return {
|
|
385
|
+
name: call.name,
|
|
386
|
+
error: getToolCallError(call.error),
|
|
387
|
+
durationMs: numberField(call.durationMs)
|
|
388
|
+
};
|
|
389
|
+
}
|
|
438
390
|
function getToolCallError(value) {
|
|
439
|
-
|
|
440
|
-
|
|
391
|
+
const error = value;
|
|
392
|
+
if (value && typeof value === "object" && !Array.isArray(value) && typeof error.message === "string") {
|
|
393
|
+
return error.message;
|
|
441
394
|
}
|
|
442
395
|
if (value !== void 0) {
|
|
443
396
|
return stringifyValue(value, 240);
|
|
@@ -466,9 +419,6 @@ function stringifyReason(value) {
|
|
|
466
419
|
}
|
|
467
420
|
return typeof value === "string" ? value : stringifyValue(value, 4e3);
|
|
468
421
|
}
|
|
469
|
-
function formatDisplayName(assertion) {
|
|
470
|
-
return [...assertion.ancestorTitles, assertion.title].filter((part) => part.length > 0).join(" > ");
|
|
471
|
-
}
|
|
472
422
|
function sumUsage(cases) {
|
|
473
423
|
const usage2 = {
|
|
474
424
|
inputTokens: 0,
|
|
@@ -483,17 +433,16 @@ function sumUsage(cases) {
|
|
|
483
433
|
usage2.outputTokens += caseUsage?.outputTokens ?? 0;
|
|
484
434
|
usage2.reasoningTokens += caseUsage?.reasoningTokens ?? 0;
|
|
485
435
|
usage2.totalTokens += caseUsage?.totalTokens ?? (caseUsage?.inputTokens ?? 0) + (caseUsage?.outputTokens ?? 0) + (caseUsage?.reasoningTokens ?? 0);
|
|
486
|
-
usage2.toolCalls +=
|
|
436
|
+
usage2.toolCalls += toolCallCount(testCase);
|
|
487
437
|
}
|
|
488
438
|
return usage2;
|
|
489
439
|
}
|
|
490
|
-
function
|
|
491
|
-
const
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
return void 0;
|
|
440
|
+
function toolCallCount(testCase) {
|
|
441
|
+
const usageToolCalls = testCase.harness?.usage?.toolCalls;
|
|
442
|
+
if (usageToolCalls !== void 0) {
|
|
443
|
+
return Math.max(usageToolCalls, testCase.toolCalls.length);
|
|
495
444
|
}
|
|
496
|
-
return
|
|
445
|
+
return testCase.toolCalls.length;
|
|
497
446
|
}
|
|
498
447
|
|
|
499
448
|
// src/summary.ts
|
|
@@ -700,8 +649,8 @@ function renderFailureBlock(testCase, {
|
|
|
700
649
|
""
|
|
701
650
|
);
|
|
702
651
|
}
|
|
703
|
-
if (testCase.
|
|
704
|
-
const toolCalls = testCase.
|
|
652
|
+
if (testCase.toolCalls.length) {
|
|
653
|
+
const toolCalls = testCase.toolCalls.slice(0, maxToolCalls);
|
|
705
654
|
lines.push(
|
|
706
655
|
...renderAsciiTable(
|
|
707
656
|
["Tool", "Status", "Duration"],
|
|
@@ -712,9 +661,9 @@ function renderFailureBlock(testCase, {
|
|
|
712
661
|
])
|
|
713
662
|
)
|
|
714
663
|
);
|
|
715
|
-
if (testCase.
|
|
664
|
+
if (testCase.toolCalls.length > maxToolCalls) {
|
|
716
665
|
lines.push(
|
|
717
|
-
`${testCase.
|
|
666
|
+
`${testCase.toolCalls.length - maxToolCalls} more tool calls omitted`
|
|
718
667
|
);
|
|
719
668
|
}
|
|
720
669
|
lines.push("");
|
|
@@ -757,7 +706,7 @@ function formatCaseUsage(testCase) {
|
|
|
757
706
|
const usage2 = testCase.harness?.usage;
|
|
758
707
|
const parts = [];
|
|
759
708
|
const totalTokens = usage2?.totalTokens ?? (usage2?.inputTokens ?? 0) + (usage2?.outputTokens ?? 0) + (usage2?.reasoningTokens ?? 0);
|
|
760
|
-
const toolCalls = usage2?.toolCalls
|
|
709
|
+
const toolCalls = usage2?.toolCalls !== void 0 ? Math.max(usage2.toolCalls, testCase.toolCalls.length) : testCase.toolCalls.length;
|
|
761
710
|
if (totalTokens > 0) {
|
|
762
711
|
parts.push(`${formatNumber(totalTokens)} tokens`);
|
|
763
712
|
}
|
|
@@ -900,6 +849,9 @@ function mergeUsage(usages) {
|
|
|
900
849
|
};
|
|
901
850
|
}
|
|
902
851
|
function mergeDuration(reports) {
|
|
852
|
+
const durations = reports.map((report) => report.durationMs).filter(
|
|
853
|
+
(durationMs) => typeof durationMs === "number" && Number.isFinite(durationMs)
|
|
854
|
+
);
|
|
903
855
|
const intervals = reports.map((report) => {
|
|
904
856
|
if (typeof report.startedAt !== "number" || !Number.isFinite(report.startedAt) || typeof report.durationMs !== "number" || !Number.isFinite(report.durationMs)) {
|
|
905
857
|
return void 0;
|
|
@@ -911,129 +863,15 @@ function mergeDuration(reports) {
|
|
|
911
863
|
}).filter(
|
|
912
864
|
(interval) => Boolean(interval)
|
|
913
865
|
);
|
|
914
|
-
if (intervals.length > 0) {
|
|
866
|
+
if (intervals.length > 0 && intervals.length === durations.length) {
|
|
915
867
|
return Math.max(...intervals.map((interval) => interval.end)) - Math.min(...intervals.map((interval) => interval.start));
|
|
916
868
|
}
|
|
917
|
-
const durations = reports.map((report) => report.durationMs).filter(
|
|
918
|
-
(durationMs) => typeof durationMs === "number" && Number.isFinite(durationMs)
|
|
919
|
-
);
|
|
920
869
|
return durations.length > 0 ? durations.reduce((total, durationMs) => total + durationMs, 0) : void 0;
|
|
921
870
|
}
|
|
922
871
|
function sum(items, select) {
|
|
923
872
|
return items.reduce((total, item) => total + select(item), 0);
|
|
924
873
|
}
|
|
925
874
|
|
|
926
|
-
// src/results.ts
|
|
927
|
-
import { readdir } from "fs/promises";
|
|
928
|
-
import { isAbsolute, relative, resolve, sep } from "path";
|
|
929
|
-
var GLOB_META_PATTERN = /[*?]/;
|
|
930
|
-
async function resolveResultFiles(patterns, options = {}) {
|
|
931
|
-
const cwd = options.cwd ?? process.cwd();
|
|
932
|
-
const files = [];
|
|
933
|
-
for (const pattern of patterns.map((entry) => entry.trim()).filter(Boolean)) {
|
|
934
|
-
if (hasGlob(pattern)) {
|
|
935
|
-
files.push(...await expandGlob(pattern, cwd));
|
|
936
|
-
} else {
|
|
937
|
-
files.push(isAbsolute(pattern) ? pattern : resolve(cwd, pattern));
|
|
938
|
-
}
|
|
939
|
-
}
|
|
940
|
-
return [...new Set(files)].sort();
|
|
941
|
-
}
|
|
942
|
-
function hasGlob(pattern) {
|
|
943
|
-
return GLOB_META_PATTERN.test(pattern);
|
|
944
|
-
}
|
|
945
|
-
async function expandGlob(pattern, cwd) {
|
|
946
|
-
const normalizedPattern = normalizeGlobPattern(pattern);
|
|
947
|
-
const absolutePattern = isAbsolute(pattern);
|
|
948
|
-
const base = globBase(normalizedPattern);
|
|
949
|
-
const basePath = absolutePattern ? base || sep : resolve(cwd, base || ".");
|
|
950
|
-
const regex = globToRegExp(normalizedPattern);
|
|
951
|
-
const matches = [];
|
|
952
|
-
for (const file of await listFiles(basePath)) {
|
|
953
|
-
const normalizedFile = normalizePath(file);
|
|
954
|
-
const candidate = absolutePattern ? normalizedFile : normalizePath(relative(resolve(cwd), file));
|
|
955
|
-
if (regex.test(candidate)) {
|
|
956
|
-
matches.push(file);
|
|
957
|
-
}
|
|
958
|
-
}
|
|
959
|
-
return matches;
|
|
960
|
-
}
|
|
961
|
-
function globBase(pattern) {
|
|
962
|
-
const segments = pattern.split("/");
|
|
963
|
-
const baseSegments = [];
|
|
964
|
-
for (const segment of segments) {
|
|
965
|
-
if (hasGlob(segment)) {
|
|
966
|
-
break;
|
|
967
|
-
}
|
|
968
|
-
baseSegments.push(segment);
|
|
969
|
-
}
|
|
970
|
-
return baseSegments.join("/");
|
|
971
|
-
}
|
|
972
|
-
async function listFiles(directory) {
|
|
973
|
-
const entries = await readDirectory(directory);
|
|
974
|
-
if (!entries) {
|
|
975
|
-
return [];
|
|
976
|
-
}
|
|
977
|
-
const files = [];
|
|
978
|
-
for (const entry of entries) {
|
|
979
|
-
const child = resolve(directory, entry.name);
|
|
980
|
-
if (entry.isDirectory()) {
|
|
981
|
-
files.push(...await listFiles(child));
|
|
982
|
-
} else if (entry.isFile()) {
|
|
983
|
-
files.push(child);
|
|
984
|
-
}
|
|
985
|
-
}
|
|
986
|
-
return files;
|
|
987
|
-
}
|
|
988
|
-
async function readDirectory(directory) {
|
|
989
|
-
try {
|
|
990
|
-
return await readdir(directory, { withFileTypes: true });
|
|
991
|
-
} catch {
|
|
992
|
-
return void 0;
|
|
993
|
-
}
|
|
994
|
-
}
|
|
995
|
-
function globToRegExp(pattern) {
|
|
996
|
-
let source = "";
|
|
997
|
-
for (let index = 0; index < pattern.length; index += 1) {
|
|
998
|
-
const char = pattern[index];
|
|
999
|
-
const next = pattern[index + 1];
|
|
1000
|
-
if (char === "*" && next === "*") {
|
|
1001
|
-
const following = pattern[index + 2];
|
|
1002
|
-
if (following === "/") {
|
|
1003
|
-
source += "(?:.*/)?";
|
|
1004
|
-
index += 2;
|
|
1005
|
-
} else {
|
|
1006
|
-
source += ".*";
|
|
1007
|
-
index += 1;
|
|
1008
|
-
}
|
|
1009
|
-
continue;
|
|
1010
|
-
}
|
|
1011
|
-
if (char === "*") {
|
|
1012
|
-
source += "[^/]*";
|
|
1013
|
-
continue;
|
|
1014
|
-
}
|
|
1015
|
-
if (char === "?") {
|
|
1016
|
-
source += "[^/]";
|
|
1017
|
-
continue;
|
|
1018
|
-
}
|
|
1019
|
-
source += escapeRegExp(char ?? "");
|
|
1020
|
-
}
|
|
1021
|
-
return new RegExp(`^${source}$`);
|
|
1022
|
-
}
|
|
1023
|
-
function escapeRegExp(value) {
|
|
1024
|
-
return value.replace(/[|\\{}()[\]^$+?.]/g, "\\$&");
|
|
1025
|
-
}
|
|
1026
|
-
function normalizePath(path) {
|
|
1027
|
-
return path.replace(/\\/g, "/");
|
|
1028
|
-
}
|
|
1029
|
-
function normalizeGlobPattern(pattern) {
|
|
1030
|
-
const normalizedPattern = normalizePath(pattern);
|
|
1031
|
-
if (isAbsolute(pattern)) {
|
|
1032
|
-
return normalizedPattern;
|
|
1033
|
-
}
|
|
1034
|
-
return normalizedPattern.replace(/^(\.\/)+/, "");
|
|
1035
|
-
}
|
|
1036
|
-
|
|
1037
875
|
// src/report.ts
|
|
1038
876
|
async function publishEvalReport(options) {
|
|
1039
877
|
const resultFiles = await resolveResultFiles(options.resultPatterns, {
|
|
@@ -1046,7 +884,7 @@ async function publishEvalReport(options) {
|
|
|
1046
884
|
}
|
|
1047
885
|
const reports = await Promise.all(
|
|
1048
886
|
resultFiles.map(async (resultFile) => {
|
|
1049
|
-
const json = await
|
|
887
|
+
const json = await readVitestJsonReportFile(resultFile);
|
|
1050
888
|
return collectEvalReport(json, {
|
|
1051
889
|
workspace: options.workspace
|
|
1052
890
|
});
|
|
@@ -1106,16 +944,6 @@ async function publishEvalReport(options) {
|
|
|
1106
944
|
checkRun
|
|
1107
945
|
};
|
|
1108
946
|
}
|
|
1109
|
-
async function readVitestJsonReport(resultFile) {
|
|
1110
|
-
try {
|
|
1111
|
-
return JSON.parse(await readFile(resultFile, "utf8"));
|
|
1112
|
-
} catch (error) {
|
|
1113
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1114
|
-
throw new Error(
|
|
1115
|
-
`Failed to read eval result file ${resultFile}: ${message}`
|
|
1116
|
-
);
|
|
1117
|
-
}
|
|
1118
|
-
}
|
|
1119
947
|
|
|
1120
948
|
// src/cli.ts
|
|
1121
949
|
main().catch((error) => {
|