/** * Provider Storage * Manages provider configurations and API keys. * Keys are stored in plain text alongside provider configs in a single electron-store. */ // Lazy-load electron-store (ESM module) // eslint-disable-next-line @typescript-eslint/no-explicit-any let providerStore: any = null; async function getProviderStore() { if (!providerStore) { const Store = (await import('electron-store')).default; providerStore = new Store({ name: 'clawx-providers', defaults: { providers: {} as Record, apiKeys: {} as Record, defaultProvider: null as string | null, }, }); } return providerStore; } /** * Provider configuration */ export interface ProviderConfig { id: string; name: string; type: 'anthropic' | 'openai' | 'google' | 'openrouter' | 'moonshot' | 'siliconflow' | 'ollama' | 'custom'; baseUrl?: string; model?: string; enabled: boolean; createdAt: string; updatedAt: string; } // ==================== API Key Storage ==================== /** * Store an API key */ export async function storeApiKey(providerId: string, apiKey: string): Promise { try { const s = await getProviderStore(); const keys = (s.get('apiKeys') || {}) as Record; keys[providerId] = apiKey; s.set('apiKeys', keys); return true; } catch (error) { console.error('Failed to store API key:', error); return false; } } /** * Retrieve an API key */ export async function getApiKey(providerId: string): Promise { try { const s = await getProviderStore(); const keys = (s.get('apiKeys') || {}) as Record; return keys[providerId] || null; } catch (error) { console.error('Failed to retrieve API key:', error); return null; } } /** * Delete an API key */ export async function deleteApiKey(providerId: string): Promise { try { const s = await getProviderStore(); const keys = (s.get('apiKeys') || {}) as Record; delete keys[providerId]; s.set('apiKeys', keys); return true; } catch (error) { console.error('Failed to delete API key:', error); return false; } } /** * Check if an API key exists for a provider */ export async function hasApiKey(providerId: string): Promise { const s = await getProviderStore(); const keys = (s.get('apiKeys') || {}) as Record; return providerId in keys; } /** * List all provider IDs that have stored keys */ export async function listStoredKeyIds(): Promise { const s = await getProviderStore(); const keys = (s.get('apiKeys') || {}) as Record; return Object.keys(keys); } // ==================== Provider Configuration ==================== /** * Save a provider configuration */ export async function saveProvider(config: ProviderConfig): Promise { const s = await getProviderStore(); const providers = s.get('providers') as Record; providers[config.id] = config; s.set('providers', providers); } /** * Get a provider configuration */ export async function getProvider(providerId: string): Promise { const s = await getProviderStore(); const providers = s.get('providers') as Record; return providers[providerId] || null; } /** * Get all provider configurations */ export async function getAllProviders(): Promise { const s = await getProviderStore(); const providers = s.get('providers') as Record; return Object.values(providers); } /** * Delete a provider configuration and its API key */ export async function deleteProvider(providerId: string): Promise { try { // Delete the API key await deleteApiKey(providerId); // Delete the provider config const s = await getProviderStore(); const providers = s.get('providers') as Record; delete providers[providerId]; s.set('providers', providers); // Clear default if this was the default if (s.get('defaultProvider') === providerId) { s.delete('defaultProvider'); } return true; } catch (error) { console.error('Failed to delete provider:', error); return false; } } /** * Set the default provider */ export async function setDefaultProvider(providerId: string): Promise { const s = await getProviderStore(); s.set('defaultProvider', providerId); } /** * Get the default provider */ export async function getDefaultProvider(): Promise { const s = await getProviderStore(); return s.get('defaultProvider') as string | undefined; } /** * Get provider with masked key info (for UI display) */ export async function getProviderWithKeyInfo( providerId: string ): Promise<(ProviderConfig & { hasKey: boolean; keyMasked: string | null }) | null> { const provider = await getProvider(providerId); if (!provider) return null; const apiKey = await getApiKey(providerId); let keyMasked: string | null = null; if (apiKey) { if (apiKey.length > 12) { keyMasked = `${apiKey.substring(0, 4)}${'*'.repeat(apiKey.length - 8)}${apiKey.substring(apiKey.length - 4)}`; } else { keyMasked = '*'.repeat(apiKey.length); } } return { ...provider, hasKey: !!apiKey, keyMasked, }; } /** * Get all providers with key info (for UI display) */ export async function getAllProvidersWithKeyInfo(): Promise< Array > { const providers = await getAllProviders(); const results: Array = []; for (const provider of providers) { const apiKey = await getApiKey(provider.id); let keyMasked: string | null = null; if (apiKey) { if (apiKey.length > 12) { keyMasked = `${apiKey.substring(0, 4)}${'*'.repeat(apiKey.length - 8)}${apiKey.substring(apiKey.length - 4)}`; } else { keyMasked = '*'.repeat(apiKey.length); } } results.push({ ...provider, hasKey: !!apiKey, keyMasked, }); } return results; }