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
128 lines (127 loc) • 5.87 kB
JavaScript
// 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 { eligibleRefCount, MODEL_CALLING_PROCESSES, projectResolvedProcessRouting, } from "./improve-strategies.js";
/** The autonomy lane gating each model-calling process, if any. */
const AUTONOMY_LANE_BY_PROCESS = {
memoryInference: "memoryInference",
};
function dominantReason(counts) {
let best;
let bestCount = 0;
for (const [reason, count] of Object.entries(counts)) {
if (count > bestCount) {
best = reason;
bestCount = count;
}
}
return best;
}
/**
* Why a model-calling process made no call, in priority order: its engine is
* unavailable; disabled — `autonomy_gated` when its lane was gated, else
* nothing to report; every ref strategy-filtered; its dominant skip reason;
* else `no_signal`. The reasons are the ones the events and results already
* use.
*/
export function deriveNoCallReason(args) {
const { row } = args;
if (row.unavailable)
return "engine_unavailable";
const lane = AUTONOMY_LANE_BY_PROCESS[row.process];
const laneGated = lane !== undefined && args.autonomyGated.some((gated) => gated.lane === lane);
if (!row.enabled)
return laneGated ? "autonomy_gated" : undefined;
if (args.eligibleRefs === 0 && args.strategyFilteredRefsCount > 0)
return "strategy_filtered_all_passes";
const dominant = args.skipReasonCounts ? dominantReason(args.skipReasonCounts) : undefined;
if (dominant)
return dominant;
return "no_signal";
}
/** Reflect's skip reasons, from its skipped (and older cooldown) actions. */
function countReflectSkipReasons(actions) {
const counts = {};
for (const action of actions) {
if (action.mode !== "reflect-cooldown" && action.mode !== "reflect-skipped")
continue;
const result = action.result;
const reason = typeof result?.reason === "string" && result.reason.trim() ? result.reason : "unknown";
counts[reason] = (counts[reason] ?? 0) + 1;
}
return counts;
}
/** This run's `usageReport`, or `undefined` when both halves are empty. */
export function buildImproveUsageReport(args) {
// Only the processes that call a model themselves, on any engine kind: triage
// (attributed to its judgment) and proactive maintenance (no engine) would
// always read as "zero calls". The "triage.judgment" row is dropped too: its
// calls are never attributed to it (#947).
const routing = projectResolvedProcessRouting(args.resolvedPlan).filter((row) => row.process !== "triage.judgment" && MODEL_CALLING_PROCESSES.has(row.process));
const calledProcesses = new Set(args.byProcessEngineModel.filter((row) => row.calls > 0).map((row) => row.process));
const reflectSkipCounts = countReflectSkipReasons(args.persistedActions);
const noCalls = [];
for (const row of routing) {
if (calledProcesses.has(row.process))
continue;
const eligibleRefs = eligibleRefCount(args.loopRefs, row.process, args.resolvedPlan.strategy.config);
const reason = deriveNoCallReason({
row,
autonomyGated: args.resolvedPlan.autonomyGated,
strategyFilteredRefsCount: args.strategyFilteredRefsCount,
eligibleRefs,
skipReasonCounts: row.process === "reflect"
? reflectSkipCounts
: row.process === "distill"
? args.distillSkippedAggregate?.byReason
: undefined,
});
if (reason === undefined)
continue;
noCalls.push({ process: row.process, ...(row.engine ? { engine: row.engine } : {}), reason });
}
if (args.byProcessEngineModel.length === 0 && noCalls.length === 0)
return undefined;
return { byProcessEngineModel: args.byProcessEngineModel, noCalls };
}
function renderFixedWidthTable(headers, rows) {
const widths = headers.map((header, index) => Math.max(header.length, ...rows.map((row) => row[index]?.length ?? 0)));
const renderRow = (cells) => cells
.map((cell, index) => cell.padEnd(widths[index] ?? 0))
.join(" ")
.trimEnd();
return [renderRow(headers), ...rows.map(renderRow)];
}
/** The usage report as a fixed-width table; `notes` carry precision caveats (e.g. an older run recomputed from events). */
export function formatUsageReportTable(usageReport, notes) {
const lines = ["[improve] usage report (process x engine x model):"];
if (usageReport.byProcessEngineModel.length === 0) {
lines.push(" (no LLM calls recorded)");
}
else {
const headers = ["process", "engine", "model", "calls", "failures", "promptTok", "complTok", "totalTok", "ms"];
const rows = usageReport.byProcessEngineModel.map((row) => [
row.process,
row.engine,
row.model,
String(row.calls),
String(row.failures),
String(row.promptTokens),
String(row.completionTokens),
String(row.totalTokens),
String(row.totalDurationMs),
]);
for (const line of renderFixedWidthTable(headers, rows))
lines.push(` ${line}`);
}
if (usageReport.noCalls.length > 0) {
lines.push("[improve] enabled processes with zero calls:");
const headers = ["process", "engine", "reason"];
const rows = usageReport.noCalls.map((row) => [row.process, row.engine ?? "-", row.reason]);
for (const line of renderFixedWidthTable(headers, rows))
lines.push(` ${line}`);
}
for (const note of notes ?? [])
lines.push(` note: ${note}`);
return lines.join("\n");
}