@runic-labs/ledger
Contabilidad de solo anexado de tokens gastados frente a tokens ahorrados.
@runic-labs/ledger es contabilidad pura: nunca impone un presupuesto, nunca rechaza una llamada, nunca estima un coste que no hayas informado. Responde una pregunta: ¿cuánto costó realmente resolver estas decisiones y cuánto se evitó mediante la reutilización?
npm install @runic-labs/ledgerpnpm add @runic-labs/ledgeryarn add @runic-labs/ledgerbun add @runic-labs/ledgercreateLedger(store?)
import { createLedger, FileLedgerStore, defaultLedgerFilePath } from "@runic-labs/ledger";
const ledger = createLedger(new FileLedgerStore({ filePath: defaultLedgerFilePath() }));
De forma predeterminada, usa un FileLedgerStore en .runic/ledger.json (o $RUNIC_HOME/ledger.json) si no se proporciona ningún almacén.
recordMiss(signature, tokensSpent)?void
Logs a cache miss — the agent generated its own way and spent tokensSpent.
voidrecordHit(signature)?void
Logs a cache hit, recording the same tokensSpent as the original miss for this signature.
voidsummary()?LedgerSummary
Aggregated totals — see below.
LedgerSummaryall()?LedgerEvent[]
The full raw event log.
LedgerEvent[]clear()?void
Removes all events.
voidLedgerSummary
interface LedgerSummary {
totalSpent: number;
totalSaved: number;
hitsBySignature: Record<string, number>;
}
const summary = ledger.summary();
const totalHits = Object.values(summary.hitsBySignature).reduce((a, b) => a + b, 0);
const tokensWithoutRunic = summary.totalSpent + summary.totalSaved;
const savingsPercent = Math.round((summary.totalSaved / tokensWithoutRunic) * 100);
Este es exactamente el cálculo que utilizan tanto benchmarks/openrouter-savings como benchmarks/reuse-sweep para imprimir sus cifras finales; consulta Pruebas de rendimiento.
Por qué recordHit no recibe un argumento tokensSpent
El valor de un acierto se define como lo que haya costado el fallo original para esa firma: el libro mayor lo busca por sí mismo, en lugar de confiar en que quien llama lo repita correctamente en cada acierto. Si no existe un fallo previo para una firma que, de algún modo, está teniendo un acierto (no debería suceder en un uso normal, pero el libro mayor no asume que no pueda ocurrir), registra 0 en lugar de adivinar.
Backends de almacenamiento
El mismo patrón que @runic-labs/cache: MemoryLedgerStore para pruebas y ejecuciones efímeras, y FileLedgerStore para persistencia entre invocaciones de procesos independientes. Implementa tú mismo la interfaz LedgerStore para un backend distinto:
interface LedgerStore {
append(event: LedgerEvent): void;
all(): LedgerEvent[];
clear(): void;
}