import { useState, useEffect } from 'react'; import { useAppStore } from '@/store/app-store'; import { getElectronAPI } from '@/lib/electron'; import type { ProviderConfigParams } from '@/config/api-providers'; interface TestResult { success: boolean; message: string; } interface ApiKeyStatus { hasAnthropicKey: boolean; hasGoogleKey: boolean; } /** * Custom hook for managing API key state and operations * Handles input values, visibility toggles, connection testing, and saving */ export function useApiKeyManagement() { const { apiKeys, setApiKeys } = useAppStore(); // API key values const [anthropicKey, setAnthropicKey] = useState(apiKeys.anthropic); const [googleKey, setGoogleKey] = useState(apiKeys.google); // Visibility toggles const [showAnthropicKey, setShowAnthropicKey] = useState(false); const [showGoogleKey, setShowGoogleKey] = useState(false); // Test connection states const [testingConnection, setTestingConnection] = useState(false); const [testResult, setTestResult] = useState(null); const [testingGeminiConnection, setTestingGeminiConnection] = useState(false); const [geminiTestResult, setGeminiTestResult] = useState(null); // API key status from environment const [apiKeyStatus, setApiKeyStatus] = useState(null); // Save state const [saved, setSaved] = useState(false); // Sync local state with store useEffect(() => { setAnthropicKey(apiKeys.anthropic); setGoogleKey(apiKeys.google); }, [apiKeys]); // Check API key status from environment on mount useEffect(() => { const checkApiKeyStatus = async () => { const api = getElectronAPI(); if (api?.setup?.getApiKeys) { try { const status = await api.setup.getApiKeys(); if (status.success) { setApiKeyStatus({ hasAnthropicKey: status.hasAnthropicKey, hasGoogleKey: status.hasGoogleKey, }); } } catch { // Silently handle API key status check failures to avoid exposing // sensitive error details in the console } } }; checkApiKeyStatus(); }, []); // Test Anthropic/Claude connection const handleTestAnthropicConnection = async () => { setTestingConnection(true); setTestResult(null); try { const api = getElectronAPI(); const data = await api.setup.verifyClaudeAuth('api_key'); if (data.success && data.authenticated) { setTestResult({ success: true, message: 'Connection successful! Claude responded.', }); } else { setTestResult({ success: false, message: data.error || 'Failed to connect to Claude API.', }); } } catch { setTestResult({ success: false, message: 'Network error. Please check your connection.', }); } finally { setTestingConnection(false); } }; // Test Google/Gemini connection // NOTE: Full API key validation requires a backend call to verify the key // against Google's API. The current client-side validation only checks // basic format requirements and cannot confirm the key is actually valid. const handleTestGeminiConnection = async () => { setTestingGeminiConnection(true); setGeminiTestResult(null); // Basic client-side format validation only // This does NOT verify the key is valid with Google's API if (!googleKey || googleKey.trim().length < 10) { setGeminiTestResult({ success: false, message: 'Please enter an API key with at least 10 characters.', }); setTestingGeminiConnection(false); return; } // Client-side validation cannot confirm key validity. // The key will be verified when first used with the Gemini API. setGeminiTestResult({ success: true, message: 'API key format accepted. Key will be validated on first use with Gemini API.', }); setTestingGeminiConnection(false); }; // Save API keys const handleSave = () => { setApiKeys({ anthropic: anthropicKey, google: googleKey, }); setSaved(true); setTimeout(() => setSaved(false), 2000); }; // Build provider config params for buildProviderConfigs const providerConfigParams: ProviderConfigParams = { apiKeys, anthropic: { value: anthropicKey, setValue: setAnthropicKey, show: showAnthropicKey, setShow: setShowAnthropicKey, testing: testingConnection, onTest: handleTestAnthropicConnection, result: testResult, }, google: { value: googleKey, setValue: setGoogleKey, show: showGoogleKey, setShow: setShowGoogleKey, testing: testingGeminiConnection, onTest: handleTestGeminiConnection, result: geminiTestResult, }, }; return { // Provider config params for buildProviderConfigs providerConfigParams, // API key status from environment apiKeyStatus, // Save handler and state handleSave, saved, }; }