UNPKG

claude-monitor

Version:

Real-time terminal monitoring tool for Claude AI token usage

192 lines 6.65 kB
import * as fs from 'fs'; import * as os from 'os'; import * as path from 'path'; import { z } from 'zod'; const SettingsSchema = z.object({ hoursBack: z.number().positive().default(5), costMode: z.nativeEnum({ AUTO: 'auto', CACHED: 'cached', CALCULATED: 'calculate' }).default('auto'), planType: z.enum(['pro', 'max5', 'max20', 'custom']).default('custom'), customLimit: z.number().positive().nullable().default(null), showNotifications: z.boolean().default(true), theme: z.enum(['auto', 'light', 'dark']).default('auto'), timeFormat: z.enum(['12', '24']).default('24'), timezone: z.string().default('auto'), updateInterval: z.number().min(1).max(60).default(10), }); export const CLIArgsSchema = z.object({ plan: z.enum(['pro', 'max5', 'max20', 'custom']).optional(), timezone: z.string().optional(), theme: z.enum(['light', 'dark', 'auto']).optional(), 'time-format': z.enum(['12h', '24h', 'auto']).optional(), 'custom-limit': z.number().positive().optional(), 'refresh-rate': z.number().min(1).max(60).optional(), 'refresh-per-second': z.number().min(0.1).max(20.0).optional(), clear: z.boolean().optional(), version: z.boolean().optional(), debug: z.boolean().optional(), }); export class LastUsedParams { configDir; paramsFile; constructor(configDir) { this.configDir = configDir || path.join(os.homedir(), '.claude-monitor'); this.paramsFile = path.join(this.configDir, 'last_used.json'); } save(settings) { try { const params = { theme: settings.theme, timezone: settings.timezone, timeFormat: settings.timeFormat, updateInterval: settings.updateInterval, timestamp: new Date().toISOString(), ...(settings.customLimit && { customLimit: settings.customLimit }), }; if (!fs.existsSync(this.configDir)) { fs.mkdirSync(this.configDir, { recursive: true }); } const tempFile = `${this.paramsFile}.tmp`; fs.writeFileSync(tempFile, JSON.stringify(params, null, 2)); fs.renameSync(tempFile, this.paramsFile); } catch (error) { console.warn(`Failed to save last used params: ${error}`); } } load() { if (!fs.existsSync(this.paramsFile)) { return {}; } try { const content = fs.readFileSync(this.paramsFile, 'utf8'); const params = JSON.parse(content); delete params.timestamp; return params; } catch (error) { console.warn(`Failed to load last used params: ${error}`); return {}; } } clear() { try { if (fs.existsSync(this.paramsFile)) { fs.unlinkSync(this.paramsFile); } } catch (error) { console.warn(`Failed to clear last used params: ${error}`); } } exists() { return fs.existsSync(this.paramsFile); } } export class SettingsManager { lastUsedParams; settings; constructor() { this.lastUsedParams = new LastUsedParams(); this.settings = this.getDefaultSettings(); } getDefaultSettings() { return { hoursBack: 5, costMode: 'auto', planType: 'custom', customLimit: null, showNotifications: true, theme: 'auto', timeFormat: this.detectSystemTimeFormat(), timezone: this.detectSystemTimezone(), updateInterval: 10, }; } detectSystemTimeFormat() { const date = new Date(); const formatted = date.toLocaleTimeString(); return formatted.includes('AM') || formatted.includes('PM') ? '12' : '24'; } detectSystemTimezone() { try { return Intl.DateTimeFormat().resolvedOptions().timeZone; } catch { return 'UTC'; } } loadWithCLI(cliArgs) { const parsedArgs = CLIArgsSchema.parse(cliArgs); if (parsedArgs.clear) { this.lastUsedParams.clear(); return this.settings; } const lastUsed = this.lastUsedParams.load(); const merged = { ...this.getDefaultSettings(), ...this.mapLastUsedToSettings(lastUsed), ...this.mapCLIToSettings(parsedArgs), }; this.settings = SettingsSchema.parse(merged); if (this.settings.theme === 'auto') { this.settings.theme = this.detectTerminalTheme(); } if (this.settings.timezone === 'auto') { this.settings.timezone = this.detectSystemTimezone(); } this.lastUsedParams.save(this.settings); return this.settings; } mapLastUsedToSettings(lastUsed) { const mapped = {}; if (lastUsed.theme) mapped.theme = lastUsed.theme; if (lastUsed.timezone) mapped.timezone = lastUsed.timezone; if (lastUsed.timeFormat) mapped.timeFormat = lastUsed.timeFormat; if (lastUsed.updateInterval) mapped.updateInterval = lastUsed.updateInterval; if (lastUsed.customLimit) mapped.customLimit = lastUsed.customLimit; return mapped; } mapCLIToSettings(args) { const mapped = {}; if (args.plan) mapped.planType = args.plan; if (args.timezone) mapped.timezone = args.timezone; if (args.theme) mapped.theme = args.theme; if (args['time-format']) { mapped.timeFormat = args['time-format'] === '12h' ? '12' : '24'; } if (args['custom-limit']) mapped.customLimit = args['custom-limit']; if (args['refresh-rate']) mapped.updateInterval = args['refresh-rate']; return mapped; } detectTerminalTheme() { const colorScheme = process.env.COLORFGBG; if (colorScheme) { const parts = colorScheme.split(';'); const bg = parts[parts.length - 1]; if (bg && parseInt(bg) < 8) { return 'dark'; } } return 'dark'; } getSettings() { return this.settings; } updateSettings(updates) { this.settings = { ...this.settings, ...updates }; this.lastUsedParams.save(this.settings); return this.settings; } } export const settingsManager = new SettingsManager(); //# sourceMappingURL=settings.js.map