- Moved from session-analytics-web/ subfolder to root - Renamed to token-analytics - Added deploy.sh, ARCHITECTURE.md - Moved export.mjs into jsonl-sync/
1.8 KiB
1.8 KiB
Architecture
Stack
- Backend: ASP.NET (.NET 10), Minimal API
- Frontend: Vanilla HTML/CSS/JS (SPA, kein Framework)
- Datenbank: SQLite via Dapper (read) + better-sqlite3 (import)
- Port: 18684
Komponenten
Backend (Program.cs)
Minimal API mit Endpunkten für Kosten-Analyse:
GET /api/cost-buckets- Zeitraum in N Buckets aggregiertGET /api/cost-entries- Einzelne Einträge mit KostenGET /api/cost-chains- Konversations-Ketten nach Kosten sortiertGET /api/cost-summary- Gesamtkosten für ZeitraumGET /api/entry-chain/{id}- Volle Kette eines Eintrags (parentId vor/zurück)GET /api/entry-chains- Einträge mit chainId-ZuordnungPOST /api/sync- Triggert JSONL-Import viaexport.mjs
DB-Zugriff über Dapper + Microsoft.Data.Sqlite. Connection per Request via Factory.
JSONL Sync (jsonl-sync/export.mjs)
Node.js Script das OpenClaw Session-JSONL-Files in SQLite importiert:
- Liest alle
.jsonlaus/home/node/.openclaw/agents/main/sessions/ - Parsed Einträge, speichert in
entriesTabelle - Berechnet
chainIddurch parentId-Walk bis zum nächsten User-Message - Inkrementell - merkt sich pro File die letzte verarbeitete Zeile
Frontend (wwwroot/)
SPA mit Zoom-Navigation durch Zeiträume:
- Bucket-View: Balkendiagramm mit klickbarem Drill-Down (Monat → Woche → Tag → Stunden)
- Entry-View: Einzelne API-Calls als Balken, farblich nach Konversations-Kette
- Chain-Blocks: Teuerste Konversationen als klickbare Blöcke
- Modal: Konversations-Kontext mit User/Assistant Messages
- State wird im URL-Hash gespeichert
Datenfluss
OpenClaw JSONL Files → export.mjs → SQLite (sessions.db) → .NET API → Frontend
Deployment
./deploy.sh
Baut Release, kopiert nach publish/, restartet den token-analytics systemd Service auf stein2.