UNPKG

gemini-cost-tracker

Version:

CLI tool to display token usage and costs for Gemini and Vertex AI

157 lines 5.61 kB
import * as fs from 'fs/promises'; import * as path from 'path'; import * as os from 'os'; import { DEFAULT_CONFIG, FILE_PATHS } from '../../utils/constants.js'; import { ErrorHandler } from '../../utils/errorHandler.js'; import { logger } from '../../utils/logger.js'; export class ConfigManager { configDir; configPath; config = null; constructor() { this.configDir = path.join(os.homedir(), FILE_PATHS.CONFIG_DIR); this.configPath = path.join(this.configDir, FILE_PATHS.CONFIG_FILE); } async ensureConfigDir() { try { await fs.access(this.configDir); } catch { await fs.mkdir(this.configDir, { recursive: true }); logger.debug('Created config directory', { path: this.configDir }); } } async loadConfig() { if (this.config) { return this.config; } try { const data = await fs.readFile(this.configPath, 'utf-8'); this.config = JSON.parse(data); logger.debug('Loaded config from file', { path: this.configPath }); return this.config; } catch (error) { if (error instanceof Error && 'code' in error && error.code === 'ENOENT') { // Config file doesn't exist, return default config this.config = this.getDefaultConfig(); logger.info('Using default configuration'); return this.config; } throw ErrorHandler.createFileError(`Failed to load config: ${error instanceof Error ? error.message : String(error)}`); } } async saveConfig(config) { try { await this.ensureConfigDir(); await fs.writeFile(this.configPath, JSON.stringify(config, null, 2)); this.config = config; logger.info('Configuration saved', { path: this.configPath }); } catch (error) { throw ErrorHandler.createFileError(`Failed to save config: ${error instanceof Error ? error.message : String(error)}`); } } async updateConfig(updates) { const currentConfig = await this.loadConfig(); const newConfig = { ...currentConfig, ...updates }; await this.saveConfig(newConfig); return newConfig; } getDefaultConfig() { return { defaultCurrency: DEFAULT_CONFIG.CURRENCY, defaultFormat: DEFAULT_CONFIG.FORMAT, }; } async getDefaultCurrency() { const config = await this.loadConfig(); return config.defaultCurrency || DEFAULT_CONFIG.CURRENCY; } async getDefaultFormat() { const config = await this.loadConfig(); return config.defaultFormat || DEFAULT_CONFIG.FORMAT; } async getDefaultProject() { const config = await this.loadConfig(); return config.defaultProject; } async setDefaultCurrency(currency) { await this.updateConfig({ defaultCurrency: currency }); } async setDefaultFormat(format) { await this.updateConfig({ defaultFormat: format }); } async setDefaultProject(project) { await this.updateConfig({ defaultProject: project }); } async getGeminiApiKey() { const config = await this.loadConfig(); return config.apiKeys?.gemini || process.env.GEMINI_API_KEY; } async setGeminiApiKey(apiKey) { const config = await this.loadConfig(); await this.updateConfig({ apiKeys: { ...config.apiKeys, gemini: apiKey, }, }); } async getGcpProjectId() { const config = await this.loadConfig(); return config.gcpSettings?.projectId || process.env.GCP_PROJECT_ID; } async setGcpProjectId(projectId) { const config = await this.loadConfig(); await this.updateConfig({ gcpSettings: { ...config.gcpSettings, projectId, }, }); } async getGcpKeyFilePath() { const config = await this.loadConfig(); return config.gcpSettings?.keyFilePath || process.env.GOOGLE_APPLICATION_CREDENTIALS; } async setGcpKeyFilePath(keyFilePath) { const config = await this.loadConfig(); await this.updateConfig({ gcpSettings: { ...config.gcpSettings, keyFilePath, }, }); } async validateConfig() { try { const config = await this.loadConfig(); // Check if at least one API key is configured const hasGeminiKey = config.apiKeys?.gemini || process.env.GEMINI_API_KEY; const hasGcpProject = config.gcpSettings?.projectId || process.env.GCP_PROJECT_ID; if (!hasGeminiKey && !hasGcpProject) { logger.warn('No API keys configured'); return false; } return true; } catch (error) { logger.error('Config validation failed', {}, error instanceof Error ? error : undefined); return false; } } async resetConfig() { this.config = null; try { await fs.unlink(this.configPath); logger.info('Configuration reset'); } catch (error) { if (error instanceof Error && 'code' in error && error.code !== 'ENOENT') { throw ErrorHandler.createFileError(`Failed to reset config: ${error.message}`); } } } } //# sourceMappingURL=configManager.js.map