Zum Inhalt springen
Runic
Deutsch
Esc
navigierenöffnen⌘Jvorschau
Auf dieser Seite

@runic-labs/ledger

Anhangsbasierte Buchführung über ausgegebene und eingesparte Tokens.

@runic-labs/ledger ist reine Buchführung — es setzt niemals ein Budget durch, lehnt niemals einen Aufruf ab und schätzt niemals Kosten, die du nicht gemeldet hast. Es beantwortet eine Frage: Was hat das Auflösen dieser Entscheidungen tatsächlich gekostet, und wie viel davon wurde durch Wiederverwendung vermieden?

npm install @runic-labs/ledger
pnpm add @runic-labs/ledger
yarn add @runic-labs/ledger
bun add @runic-labs/ledger

createLedger(store?)

import { createLedger, FileLedgerStore, defaultLedgerFilePath } from "@runic-labs/ledger";

const ledger = createLedger(new FileLedgerStore({ filePath: defaultLedgerFilePath() }));

Verwendet standardmäßig einen FileLedgerStore unter .runic/ledger.json (oder $RUNIC_HOME/ledger.json), wenn kein Store übergeben wird.

PropType
recordMiss(signature, tokensSpent)?void

Logs a cache miss — the agent generated its own way and spent tokensSpent.

Typevoid
recordHit(signature)?void

Logs a cache hit, recording the same tokensSpent as the original miss for this signature.

Typevoid
summary()?LedgerSummary

Aggregated totals — see below.

TypeLedgerSummary
all()?LedgerEvent[]

The full raw event log.

TypeLedgerEvent[]
clear()?void

Removes all events.

Typevoid

LedgerSummary

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);

Dies ist genau die Berechnung, die sowohl benchmarks/openrouter-savings als auch benchmarks/reuse-sweep verwenden, um ihre endgültigen Zahlen auszugeben — siehe Benchmarks.

Warum recordHit kein tokensSpent-Argument annimmt

Der Wert eines Hits ist definiert als was auch immer der ursprüngliche Miss für diese Signatur gekostet hat — das Ledger schlägt ihn selbst nach, statt darauf zu vertrauen, dass der Aufrufer ihn bei jedem Hit korrekt wiederholt. Wenn für eine Signatur, die irgendwie getroffen wird, kein vorheriger Miss existiert (sollte bei normaler Nutzung nicht passieren, aber das Ledger nimmt nicht an, dass es unmöglich ist), zeichnet es 0 auf, statt zu raten.

Speicher-Backends

Dasselbe Muster wie bei @runic-labs/cache: MemoryLedgerStore für Tests und kurzlebige Ausführungen, FileLedgerStore für Persistenz über separate Prozessaufrufe hinweg. Implementiere die Schnittstelle LedgerStore selbst für ein anderes Backend:

interface LedgerStore {
  append(event: LedgerEvent): void;
  all(): LedgerEvent[];
  clear(): void;
}

Nächste Schritte

  • Cache — der passende signaturbasierte Store
  • CLIrunic ledger status liest diese Zusammenfassung über die Befehlszeile

War diese Seite hilfreich?