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

58 lines (57 loc) • 3.05 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 { getAllAssetOutcomes, getAssetOutcome, getOutcomeScoresByRef, upsertAssetOutcome, } from "../../storage/repositories/outcome-repository.js"; /** EMA factor for both the score and the expected retrieval delta (≈ a 3-cycle window). */ export const OUTCOME_EMA_ALPHA = 0.3; /** The most a new row can be seeded with, so the first negative delta cannot flip the rank. */ export const WARM_START_CAP = 0.3; export const OUTCOME_SCORE_MIN = -1.0; /** Saturation: a long-popular asset must not accrue unbounded outcome mass. */ export const OUTCOME_SCORE_MAX = 1.5; /** `outcomeSalience` never drops below this fraction of the stash-wide maximum. */ export const DIVERSITY_FLOOR_FRACTION = 0.1; export { getAllAssetOutcomes, getAssetOutcome, getOutcomeScoresByRef }; /** The next outcome values, without storage — dry planning and the writer share it. */ export function projectAssetOutcome(existing, inputs) { if (existing === undefined) { return { outcomeScore: Math.min(WARM_START_CAP, Math.max(0, inputs.utilityScore ?? 0)), expectedRetrievalRate: 0, isNewRow: true, }; } const retrievalDelta = Math.max(0, inputs.currentRetrievalCount - existing.retrieval_count); const rawUpdate = retrievalDelta - existing.expected_retrieval_rate + (inputs.valence ?? 0); const newScore = OUTCOME_EMA_ALPHA * rawUpdate + (1 - OUTCOME_EMA_ALPHA) * existing.outcome_score; return { outcomeScore: Math.min(OUTCOME_SCORE_MAX, Math.max(OUTCOME_SCORE_MIN, newScore)), expectedRetrievalRate: OUTCOME_EMA_ALPHA * retrievalDelta + (1 - OUTCOME_EMA_ALPHA) * existing.expected_retrieval_rate, isNewRow: false, }; } /** Upsert one asset's outcome row; returns the score for the salience vector. */ export function updateAssetOutcome(db, inputs) { const projection = projectAssetOutcome(getAssetOutcome(db, inputs.ref), inputs); upsertAssetOutcome(db, { ref: inputs.ref, lastRetrievedAt: inputs.lastRetrievedAt, retrievalCount: inputs.currentRetrievalCount, expectedRetrievalRate: projection.expectedRetrievalRate, negativeFeedbackCount: inputs.negativeFeedbackCount, acceptedChangeCount: inputs.acceptedChangeCount, outcomeScore: projection.outcomeScore, updatedAt: inputs.now ?? Date.now(), }); return { outcomeScore: projection.outcomeScore, isNewRow: projection.isNewRow }; } /** * A raw outcome score as salience in [0, 1]: negatives clip to 0 (below * expected is not irrelevant), normalized by the stash-wide maximum, never * below the diversity floor. */ export function outcomeScoreToSalience(outcomeScore, maxScore) { if (maxScore <= 0) return DIVERSITY_FLOOR_FRACTION; return Math.max(DIVERSITY_FLOOR_FRACTION, Math.max(0, outcomeScore) / maxScore); }