UNPKG

claude-statusline-powerline

Version:

Beautiful powerline-style statusline for Claude Code with git integration, session tracking, and cost monitoring

233 lines 8.45 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.UsageDatabase = void 0; exports.get_usage_db = get_usage_db; const better_sqlite3_1 = __importDefault(require("better-sqlite3")); const fs = __importStar(require("node:fs")); const os = __importStar(require("node:os")); const path = __importStar(require("node:path")); class UsageDatabase { constructor() { // Store database in Claude config directory const claude_dir = path.join(os.homedir(), '.claude'); if (!fs.existsSync(claude_dir)) { fs.mkdirSync(claude_dir, { recursive: true }); } this.db_path = path.join(claude_dir, 'statusline-usage.db'); this.db = new better_sqlite3_1.default(this.db_path); this.initialize_schema(); } initialize_schema() { // Create sessions table this.db.exec(` CREATE TABLE IF NOT EXISTS sessions ( id INTEGER PRIMARY KEY AUTOINCREMENT, session_id TEXT UNIQUE NOT NULL, model TEXT NOT NULL, start_time DATETIME NOT NULL, end_time DATETIME, input_tokens INTEGER DEFAULT 0, output_tokens INTEGER DEFAULT 0, cache_tokens INTEGER DEFAULT 0, cost REAL DEFAULT 0.0, project_dir TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) `); // Create daily summaries table this.db.exec(` CREATE TABLE IF NOT EXISTS daily_summaries ( date TEXT PRIMARY KEY, total_sessions INTEGER DEFAULT 0, total_input_tokens INTEGER DEFAULT 0, total_output_tokens INTEGER DEFAULT 0, total_cache_tokens INTEGER DEFAULT 0, total_cost REAL DEFAULT 0.0, models_used TEXT DEFAULT '[]', updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ) `); // Create indexes for performance this.db.exec(` CREATE INDEX IF NOT EXISTS idx_sessions_date ON sessions(date(start_time)); CREATE INDEX IF NOT EXISTS idx_sessions_model ON sessions(model); CREATE INDEX IF NOT EXISTS idx_sessions_project ON sessions(project_dir); `); } record_session(session) { const stmt = this.db.prepare(` INSERT OR REPLACE INTO sessions ( session_id, model, start_time, end_time, input_tokens, output_tokens, cache_tokens, cost, project_dir ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) `); stmt.run(session.session_id, session.model, session.start_time, session.end_time, session.input_tokens, session.output_tokens, session.cache_tokens, session.cost, session.project_dir); // Update daily summary this.update_daily_summary(session.start_time); } update_daily_summary(timestamp) { const date = timestamp.split('T')[0]; // Extract YYYY-MM-DD const daily_stats = this.db .prepare(` SELECT COUNT(*) as total_sessions, SUM(input_tokens) as total_input_tokens, SUM(output_tokens) as total_output_tokens, SUM(cache_tokens) as total_cache_tokens, SUM(cost) as total_cost, GROUP_CONCAT(DISTINCT model) as models_used FROM sessions WHERE date(start_time) = ? `) .get(date); this.db .prepare(` INSERT OR REPLACE INTO daily_summaries ( date, total_sessions, total_input_tokens, total_output_tokens, total_cache_tokens, total_cost, models_used ) VALUES (?, ?, ?, ?, ?, ?, ?) `) .run(date, daily_stats.total_sessions || 0, daily_stats.total_input_tokens || 0, daily_stats.total_output_tokens || 0, daily_stats.total_cache_tokens || 0, daily_stats.total_cost || 0.0, JSON.stringify((daily_stats.models_used || '').split(',').filter(Boolean))); } get_usage_summary() { const today = new Date().toISOString().split('T')[0]; const week_ago = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000) .toISOString() .split('T')[0]; const month_ago = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000) .toISOString() .split('T')[0]; // Get today's summary const today_summary = this.db .prepare(` SELECT * FROM daily_summaries WHERE date = ? `) .get(today) || { date: today, total_sessions: 0, total_input_tokens: 0, total_output_tokens: 0, total_cache_tokens: 0, total_cost: 0, models_used: '[]', }; // Get week summary const week_stats = this.db .prepare(` SELECT SUM(total_sessions) as total_sessions, SUM(total_input_tokens) as total_input_tokens, SUM(total_output_tokens) as total_output_tokens, SUM(total_cache_tokens) as total_cache_tokens, SUM(total_cost) as total_cost FROM daily_summaries WHERE date >= ? `) .get(week_ago); const week_summary = { date: week_ago, total_sessions: week_stats?.total_sessions || 0, total_input_tokens: week_stats?.total_input_tokens || 0, total_output_tokens: week_stats?.total_output_tokens || 0, total_cache_tokens: week_stats?.total_cache_tokens || 0, total_cost: week_stats?.total_cost || 0, models_used: '[]', }; // Get month summary const month_stats = this.db .prepare(` SELECT SUM(total_sessions) as total_sessions, SUM(total_input_tokens) as total_input_tokens, SUM(total_output_tokens) as total_output_tokens, SUM(total_cache_tokens) as total_cache_tokens, SUM(total_cost) as total_cost FROM daily_summaries WHERE date >= ? `) .get(month_ago); const month_summary = { date: month_ago, total_sessions: month_stats?.total_sessions || 0, total_input_tokens: month_stats?.total_input_tokens || 0, total_output_tokens: month_stats?.total_output_tokens || 0, total_cache_tokens: month_stats?.total_cache_tokens || 0, total_cost: month_stats?.total_cost || 0, models_used: '[]', }; // Get recent sessions const recent_sessions = this.db .prepare(` SELECT * FROM sessions ORDER BY start_time DESC LIMIT 5 `) .all(); return { today: today_summary, week: week_summary, month: month_summary, recent_sessions, }; } get_session(session_id) { try { const session = this.db .prepare(`SELECT * FROM sessions WHERE session_id = ?`) .get(session_id); return session || null; } catch (error) { return null; } } close() { this.db.close(); } } exports.UsageDatabase = UsageDatabase; // Singleton instance let db_instance = null; function get_usage_db() { if (!db_instance) { db_instance = new UsageDatabase(); } return db_instance; } //# sourceMappingURL=usage-db.js.map