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

72 lines (71 loc) • 3.39 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 { queryImproveRuns } from "../../storage/repositories/improve-runs-repository.js"; import { queryTaskHistory } from "../../storage/repositories/task-history-repository.js"; import { projectImproveRunSummary } from "./improve-metrics.js"; /** * Load `task_history` rows whose `task_id` begins `akm-improve` (the scheduled * improve tasks: `akm-improve-frequent`, `akm-improve-proactive-weekly`, …) in * the window, widened ±5 min so a task that fired just before the window opened * still matches a run inside it. Used to attribute each improve run to the task * that launched it. */ function loadImproveTaskRuns(db, since, until) { const sinceMs = new Date(since).getTime(); const untilMs = until ? new Date(until).getTime() : undefined; const widenedSince = new Date(sinceMs - 5 * 60 * 1000).toISOString(); const widenedUntil = untilMs !== undefined ? new Date(untilMs + 5 * 60 * 1000).toISOString() : undefined; const runs = []; for (const row of queryTaskHistory(db, { since: widenedSince, until: widenedUntil })) { if (!row.task_id.startsWith("akm-improve")) continue; const startMs = new Date(row.started_at).getTime(); if (!Number.isFinite(startMs)) continue; const endIso = row.completed_at ?? row.failed_at; const endMs = endIso ? new Date(endIso).getTime() : Number.NaN; runs.push({ taskId: row.task_id, startMs, endMs }); } return runs; } /** * Attribute an improve run to the scheduled task that launched it by matching * start times within ±5 min, scored by start delta (plus end delta when both * ends are known). Port of the health-report skill's `match_task_id`. Returns * `"manual"` when no scheduled improve task matches. */ export function matchImproveTaskId(startedAt, completedAt, taskRuns) { const startMs = new Date(startedAt).getTime(); if (!Number.isFinite(startMs)) return "manual"; const endMs = new Date(completedAt).getTime(); let best; let bestScore = Number.POSITIVE_INFINITY; for (const task of taskRuns) { const startDelta = Math.abs(task.startMs - startMs); if (startDelta > 5 * 60 * 1000) continue; let score = startDelta; if (Number.isFinite(endMs) && Number.isFinite(task.endMs)) score += Math.abs(task.endMs - endMs); if (score < bestScore) { bestScore = score; best = task.taskId; } } return best ?? "manual"; } export function buildPerRunSummaries(db, since, until) { const rows = queryImproveRuns(db, since, until); const improveTaskRuns = loadImproveTaskRuns(db, since, until); const summaries = []; for (const row of rows) { const startMs = new Date(row.started_at).getTime(); const endMs = new Date(row.completed_at).getTime(); const wallTimeMs = Number.isFinite(startMs) && Number.isFinite(endMs) && endMs >= startMs ? endMs - startMs : 0; const taskId = matchImproveTaskId(row.started_at, row.completed_at, improveTaskRuns); summaries.push(projectImproveRunSummary(row, wallTimeMs, taskId)); } return summaries; }