UNPKG

akm-cli

Version:

akm (Agent Knowledge Manager) — a portable, local-first capability library for AI agents. Discover, load, share, and improve reusable skills, scripts, workflows, and knowledge across any shell-capable coding agent, including Claude Code, OpenCode, and Cur

108 lines (107 loc) • 4.44 kB
// This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. import { INTERESTING_DELTA_PATHS, readNumericPath } from "./windows.js"; function padRight(s, width) { return s.length >= width ? s : s + " ".repeat(width - s.length); } function renderTable(headers, rows) { const widths = headers.map((h, i) => Math.max(h.length, ...rows.map((r) => (r[i] ?? "").length))); const lines = []; lines.push(headers.map((h, i) => padRight(h, widths[i] ?? 0)).join(" ")); for (const row of rows) { lines.push(row.map((cell, i) => padRight(cell ?? "", widths[i] ?? 0)).join(" ")); } return lines.join("\n"); } /** * Render `--detail per-run` rows as a TSV-ish aligned table. The column * shape is stable so repeated operator reports remain easy to compare. * * Columns: ts | ok | actions | refl_ok/fail/cd/skip | * distill_q/llm-fail/qrej/cfg/skip | cons_proc/promo/merge/del | * mem_cons/written/skip | orphans | lint_f/fl */ export function renderRunsDetailMd(runs) { const headers = [ "ts", "ok", "strategy", "actions", "refl_ok/fail/cd/skip", "distill_q/llm-fail/judge/validator/cfg/skip", "cons_proc/promo/merge/del", "mem_cons/written/skip", "orphans", "lint_f/fl", "result_status", ]; const rows = runs.map((r) => { const totalActions = r.actions.reflect.ok + r.actions.reflect.failed + r.actions.reflect.cooldown + r.actions.reflect.skipped + r.actions.distill.queued + r.actions.distill.llmFailed + r.actions.distill.judgeRejected + r.actions.distill.validatorRejected + r.actions.distill.configDisabled + r.actions.distill.skipped + r.actions.memoryPrune + r.actions.memoryInference + r.actions.error; return [ r.startedAt, String(r.ok), r.strategy ?? "", String(totalActions), `${r.actions.reflect.ok}/${r.actions.reflect.failed}/${r.actions.reflect.cooldown}/${r.actions.reflect.skipped}`, `${r.actions.distill.queued}/${r.actions.distill.llmFailed}/${r.actions.distill.judgeRejected}/${r.actions.distill.validatorRejected}/${r.actions.distill.configDisabled}/${r.actions.distill.skipped}`, `${r.consolidation.processed}/${r.consolidation.promoted}/${r.consolidation.merged}/${r.consolidation.deleted}`, `${r.memoryInference.considered}/${r.memoryInference.written}/${r.memoryInference.skippedNoFacts}`, String(r.orphansPurged), `${r.lintFixed}/${r.lintFlagged}`, r.resultStatus ?? "valid", ]; }); return renderTable(headers, rows); } /** * Render a window-compare comparison as a side-by-side metric table with a * delta column. Bad-direction deltas (e.g. +pct on failed counts) get a `!` * marker prefix. */ export function renderWindowCompareMd(windows, deltas) { if (windows.length === 0) return ""; const headers = ["metric", ...windows.map((w) => w.name), "delta"]; const badIfPositive = new Set([ "improve.actions.reflect.failed", "improve.actions.distill.llmFailed", "improve.wallTime.medianMs", "improve.wallTime.p95Ms", "improve.memoryInference.skippedNoFacts", ]); const rows = []; const paths = [ "runs", "improve.resultRows.included", "improve.resultRows.skipped.invalid", ...INTERESTING_DELTA_PATHS, ]; for (const path of paths) { const values = windows.map((w) => String(readNumericPath(w, path))); const delta = deltas?.[path]; let deltaStr = "—"; if (delta) { const pct = delta.pctChange; const num = typeof pct === "number" ? pct : pct; const sign = typeof num === "number" && num > 0 ? "+" : ""; const formatted = typeof num === "number" ? `${sign}${num}%` : String(num); const marker = badIfPositive.has(path) && typeof num === "number" && num > 0 ? "!" : ""; deltaStr = marker + formatted; } rows.push([path, ...values, deltaStr]); } return renderTable(headers, rows); }