veryfront 0.1.963 → 0.1.965

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.
@@ -18,7 +18,7 @@ export const evalHelp = {
18
18
  },
19
19
  {
20
20
  flag: "--report-dir <path>",
21
- description: "Write summary.json and results.jsonl artifacts to a directory",
21
+ description: "Write summary.json, results.jsonl, and report.md artifacts to a directory",
22
22
  },
23
23
  {
24
24
  flag: "--junit <path>",
@@ -18,6 +18,7 @@ type EvalArtifactPaths = {
18
18
  directory: string;
19
19
  summary: string;
20
20
  results: string;
21
+ reportMarkdown: string;
21
22
  };
22
23
  type EvalModelArtifactPaths = EvalArtifactPaths & {
23
24
  junit: string;
@@ -36,7 +37,7 @@ type EvalSummaryArtifact = {
36
37
  baseline?: EvalReportComparison;
37
38
  };
38
39
  type EvalModelComparisonPolicy = Omit<EvalModelComparisonOptions, "baselineModel">;
39
- export declare function createDefaultEvalReportDir(runId: string): string;
40
+ export declare function createDefaultEvalReportDir(runId: string, label?: string): string;
40
41
  export declare function createEvalArtifactPaths(reportDir: string): EvalArtifactPaths;
41
42
  export declare function createEvalModelArtifactPaths(reportDir: string, model: string): EvalModelArtifactPaths;
42
43
  export declare function normalizeEvalCliId(id: string): string;
@@ -49,6 +50,8 @@ export declare function createResolvedEvalModelComparisonConfig(projectDir: stri
49
50
  export declare function createEvalModelComparisonArtifact(reports: EvalReport[], baselineModel: string, policy?: EvalModelComparisonPolicy): EvalModelComparison;
50
51
  export declare function createEvalModelComparisonExitCode(reports: EvalReport[]): 0 | 1;
51
52
  export declare function createResultsJsonl(report: EvalReport): string;
53
+ /** Render a human-reviewable markdown report for a single eval run. */
54
+ export declare function createEvalMarkdownReport(report: EvalReport, baseline?: EvalReportComparison): string;
52
55
  export declare function createJunitXml(report: EvalReport): string;
53
56
  export declare function writeEvalArtifacts(report: EvalReport, paths: EvalArtifactPaths, baseline?: EvalReportComparison): Promise<void>;
54
57
  export declare function createEvalExitCode(report: EvalReport, baseline?: EvalReportComparison): 0 | 1;
@@ -1 +1 @@
1
- {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/eval/command.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/eval/command.ts"],"names":[],"mappings":"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"}
@@ -36,14 +36,24 @@ function stripFileProtocol(path) {
36
36
  function createCliRunId(now = new Date()) {
37
37
  return `evalrun_${now.toISOString().replace(/[-:.]/g, "").replace("T", "_").replace("Z", "")}`;
38
38
  }
39
- export function createDefaultEvalReportDir(runId) {
40
- return join(".veryfront", "evals", runId);
39
+ function createEvalReportDirTimestamp(runId) {
40
+ return runId.startsWith("evalrun_") ? runId.slice("evalrun_".length) : runId;
41
+ }
42
+ function sanitizeEvalReportDirLabel(label) {
43
+ const normalized = label.startsWith("eval:") ? label.slice("eval:".length) : label;
44
+ return normalized.trim().replace(/[^A-Za-z0-9._-]+/g, "-").replace(/-+/g, "-").replace(/^[-._]+|[-._]+$/g, "");
45
+ }
46
+ export function createDefaultEvalReportDir(runId, label) {
47
+ const timestamp = createEvalReportDirTimestamp(runId);
48
+ const suffix = label ? sanitizeEvalReportDirLabel(label) : "";
49
+ return join(".veryfront", "evals", suffix ? `${timestamp}-${suffix}` : timestamp);
41
50
  }
42
51
  export function createEvalArtifactPaths(reportDir) {
43
52
  return {
44
53
  directory: reportDir,
45
54
  summary: join(reportDir, "summary.json"),
46
55
  results: join(reportDir, "results.jsonl"),
56
+ reportMarkdown: join(reportDir, "report.md"),
47
57
  };
48
58
  }
49
59
  function sanitizeModelIdForPath(model) {
@@ -55,6 +65,7 @@ export function createEvalModelArtifactPaths(reportDir, model) {
55
65
  directory,
56
66
  summary: join(directory, "summary.json"),
57
67
  results: join(directory, "results.jsonl"),
68
+ reportMarkdown: join(directory, "report.md"),
58
69
  junit: join(directory, "junit.xml"),
59
70
  };
60
71
  }
@@ -284,6 +295,107 @@ export function createResultsJsonl(report) {
284
295
  return "";
285
296
  return `${report.records.map((record) => JSON.stringify(record)).join("\n")}\n`;
286
297
  }
298
+ function markdownCell(value) {
299
+ return value.replaceAll("|", "\\|").replaceAll("\n", " ");
300
+ }
301
+ function numberCell(value) {
302
+ return value === undefined ? "-" : String(Math.round(value));
303
+ }
304
+ function decimalCell(value) {
305
+ if (value === undefined)
306
+ return "-";
307
+ if (Number.isInteger(value))
308
+ return String(value);
309
+ return value.toFixed(4).replace(/0+$/, "").replace(/\.$/, "");
310
+ }
311
+ function percentCell(value) {
312
+ return `${Math.round(value * 100)}%`;
313
+ }
314
+ function durationCell(valueMs) {
315
+ return valueMs === undefined ? "-" : `${(valueMs / 1000).toFixed(3)}s`;
316
+ }
317
+ function usdCell(value) {
318
+ if (value === undefined)
319
+ return "-";
320
+ const absolute = Math.abs(value);
321
+ if (absolute >= 0.01)
322
+ return `$${value.toFixed(2)}`;
323
+ return `$${value.toFixed(6).replace(/0+$/, "").replace(/\.$/, "")}`;
324
+ }
325
+ function isBlockingEvalResultFailure(result) {
326
+ return !result.skipped && result.pass === false &&
327
+ (result.severity === "gate" || result.severity === "budget");
328
+ }
329
+ function examplePassed(record) {
330
+ if (!record.completed || record.error)
331
+ return false;
332
+ return [...(record.metrics ?? []), ...(record.checks ?? [])].every((result) => !isBlockingEvalResultFailure(result));
333
+ }
334
+ function usageRows(usage) {
335
+ if (!usage)
336
+ return [];
337
+ const rows = [
338
+ ["Input tokens", numberCell(usage.inputTokens)],
339
+ ["Output tokens", numberCell(usage.outputTokens)],
340
+ ["Total tokens", numberCell(usage.totalTokens)],
341
+ ["Billable input tokens", numberCell(usage.billableInputTokens)],
342
+ ["Billable output tokens", numberCell(usage.billableOutputTokens)],
343
+ ["Provider cost USD", usdCell(usage.providerCostUsd ?? usage.costUsd)],
344
+ ["Veryfront charge USD", usdCell(usage.veryfrontChargeUsd)],
345
+ ["Veryfront billed USD", usdCell(usage.veryfrontBilledUsd)],
346
+ ["Cost credits", decimalCell(usage.costCredits)],
347
+ ["Cost source", usage.costSource ?? "-"],
348
+ ["Usage capture status", usage.usageCaptureStatus ?? "-"],
349
+ ];
350
+ return rows.filter(([, value]) => value !== "-");
351
+ }
352
+ /** Render a human-reviewable markdown report for a single eval run. */
353
+ export function createEvalMarkdownReport(report, baseline) {
354
+ const lines = [
355
+ `# Eval report: ${markdownCell(report.definitionId)}`,
356
+ "",
357
+ `Run: \`${markdownCell(report.runId)}\``,
358
+ `Target: \`${markdownCell(report.target)}\``,
359
+ ...(report.metadata?.model ? [`Model: \`${markdownCell(report.metadata.model)}\``] : []),
360
+ `Result: \`${report.summary.passed}/${report.summary.records} passed (${percentCell(report.summary.passRate)})\``,
361
+ "",
362
+ "## Metrics",
363
+ "",
364
+ "| Metric | Severity | Passed | Failed | Pass rate |",
365
+ "| --- | --- | ---: | ---: | ---: |",
366
+ ];
367
+ for (const metric of report.summary.metrics) {
368
+ lines.push(`| \`${markdownCell(metric.name)}\` | ${metric.severity} | ${metric.passed} | ${metric.failed} | ${percentCell(metric.passRate)} |`);
369
+ }
370
+ const rows = usageRows(report.summary.usage);
371
+ if (rows.length > 0) {
372
+ lines.push("", "## Usage", "", "| Usage | Value |", "| --- | ---: |");
373
+ for (const [label, value] of rows) {
374
+ lines.push(`| ${label} | ${value.startsWith("$") ? `\`${value}\`` : value} |`);
375
+ }
376
+ }
377
+ lines.push("", "## Examples", "", "| Example | Result | Duration | Tokens | Billed USD | Credits |", "| --- | ---: | ---: | ---: | ---: | ---: |");
378
+ for (const record of report.records) {
379
+ lines.push(`| \`${markdownCell(record.id)}\` | ${examplePassed(record) ? "PASS" : "FAIL"} | ${durationCell(record.durationMs)} | ${numberCell(record.usage.totalTokens)} | ${record.usage.veryfrontBilledUsd === undefined
380
+ ? "-"
381
+ : `\`${usdCell(record.usage.veryfrontBilledUsd)}\``} | ${decimalCell(record.usage.costCredits)} |`);
382
+ }
383
+ if (baseline) {
384
+ const direction = baseline.passRateDelta >= 0 ? "+" : "";
385
+ lines.push("", "## Baseline", "", `Status: \`${baseline.regressed ? "regressed" : "ok"}\``, `Pass rate delta: \`${direction}${Math.round(baseline.passRateDelta * 100)} pp\``);
386
+ if (baseline.newFailedExamples.length > 0) {
387
+ lines.push(`New failed examples: ${baseline.newFailedExamples.map(markdownCell).join(", ")}`);
388
+ }
389
+ }
390
+ if (report.exports?.length) {
391
+ lines.push("", "## Exports", "");
392
+ for (const result of report.exports) {
393
+ lines.push(`- \`${markdownCell(result.exporterId)}\`: ${result.ok ? "ok" : `failed, ${markdownCell(result.error)}`}`);
394
+ }
395
+ }
396
+ lines.push("");
397
+ return lines.join("\n");
398
+ }
287
399
  export function createJunitXml(report) {
288
400
  const skipped = report.records.reduce((count, record) => count + skippedResults(record).length, 0);
289
401
  const lines = [
@@ -320,6 +432,7 @@ export async function writeEvalArtifacts(report, paths, baseline) {
320
432
  await dntShim.Deno.mkdir(paths.directory, { recursive: true });
321
433
  await dntShim.Deno.writeTextFile(paths.summary, JSON.stringify(createSummaryArtifact(report, baseline), null, 2));
322
434
  await dntShim.Deno.writeTextFile(paths.results, createResultsJsonl(report));
435
+ await dntShim.Deno.writeTextFile(paths.reportMarkdown, createEvalMarkdownReport(report, baseline));
323
436
  }
324
437
  async function readEvalReport(path) {
325
438
  return JSON.parse(await dntShim.Deno.readTextFile(path));
@@ -507,7 +620,8 @@ async function writeEvalModelComparisonArtifacts(comparison, paths) {
507
620
  }
508
621
  async function runEvalModelComparison(input) {
509
622
  const runId = createCliRunId();
510
- const reportDir = input.options.reportDir ?? createDefaultEvalReportDir(runId);
623
+ const reportDir = input.options.reportDir ??
624
+ createDefaultEvalReportDir(runId, input.evalItem.id);
511
625
  const paths = createEvalModelComparisonArtifactPaths(reportDir, input.config.models);
512
626
  const provenance = await resolveEvalRunProvenance({
513
627
  projectDir: input.projectDir,
@@ -690,7 +804,7 @@ export async function evalCommand(options) {
690
804
  return;
691
805
  }
692
806
  const runId = createCliRunId();
693
- const artifactPaths = createEvalArtifactPaths(options.reportDir ?? createDefaultEvalReportDir(runId));
807
+ const artifactPaths = createEvalArtifactPaths(options.reportDir ?? createDefaultEvalReportDir(runId, evalItem.id));
694
808
  const provenance = await resolveEvalRunProvenance({
695
809
  projectDir,
696
810
  frameworkVersion: VERSION,
@@ -731,6 +845,7 @@ export async function evalCommand(options) {
731
845
  else {
732
846
  printReport(report, baseline);
733
847
  cliLogger.info(`Report directory: ${artifactPaths.directory}`);
848
+ cliLogger.info(`Report markdown: ${artifactPaths.reportMarkdown}`);
734
849
  if (options.report)
735
850
  cliLogger.info(`Report: ${options.report}`);
736
851
  if (options.junit)
package/esm/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "veryfront",
3
- "version": "0.1.963",
3
+ "version": "0.1.965",
4
4
  "license": "Apache-2.0",
5
5
  "nodeModulesDir": "auto",
6
6
  "minimumDependencyAge": {
@@ -1,3 +1,3 @@
1
1
  /** Shared version value. */
2
- export declare const VERSION = "0.1.963";
2
+ export declare const VERSION = "0.1.965";
3
3
  //# sourceMappingURL=version-constant.d.ts.map
@@ -1,4 +1,4 @@
1
1
  // Keep in sync with deno.json version.
2
2
  // scripts/release.ts updates this constant during releases.
3
3
  /** Shared version value. */
4
- export const VERSION = "0.1.963";
4
+ export const VERSION = "0.1.965";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "veryfront",
3
- "version": "0.1.963",
3
+ "version": "0.1.965",
4
4
  "description": "The simplest way to build AI-powered apps",
5
5
  "keywords": [
6
6
  "react",