mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-01-31 20:03:37 +00:00
- Add optional apiKey parameter to verifyClaudeAuth endpoint - Backend uses provided key when available, falls back to stored key - Frontend passes current input value to test unsaved keys - Add input validation before testing 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
180 lines
5.0 KiB
TypeScript
180 lines
5.0 KiB
TypeScript
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<TestResult | null>(null);
|
|
const [testingGeminiConnection, setTestingGeminiConnection] = useState(false);
|
|
const [geminiTestResult, setGeminiTestResult] = useState<TestResult | null>(null);
|
|
|
|
// API key status from environment
|
|
const [apiKeyStatus, setApiKeyStatus] = useState<ApiKeyStatus | null>(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 (error) {
|
|
console.error('Failed to check API key status:', error);
|
|
}
|
|
}
|
|
};
|
|
checkApiKeyStatus();
|
|
}, []);
|
|
|
|
// Test Anthropic/Claude connection
|
|
const handleTestAnthropicConnection = async () => {
|
|
// Validate input first
|
|
if (!anthropicKey || anthropicKey.trim().length === 0) {
|
|
setTestResult({
|
|
success: false,
|
|
message: 'Please enter an API key to test.',
|
|
});
|
|
return;
|
|
}
|
|
|
|
setTestingConnection(true);
|
|
setTestResult(null);
|
|
|
|
try {
|
|
const api = getElectronAPI();
|
|
// Pass the current input value to test unsaved keys
|
|
const data = await api.setup.verifyClaudeAuth('api_key', anthropicKey);
|
|
|
|
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
|
|
// TODO: Add backend endpoint for Gemini API key verification
|
|
const handleTestGeminiConnection = async () => {
|
|
setTestingGeminiConnection(true);
|
|
setGeminiTestResult(null);
|
|
|
|
// Basic validation - check key format
|
|
if (!googleKey || googleKey.trim().length < 10) {
|
|
setGeminiTestResult({
|
|
success: false,
|
|
message: 'Please enter a valid API key.',
|
|
});
|
|
setTestingGeminiConnection(false);
|
|
return;
|
|
}
|
|
|
|
// For now, just validate the key format (starts with expected prefix)
|
|
// Full verification requires a backend endpoint
|
|
setGeminiTestResult({
|
|
success: true,
|
|
message: 'API key saved. Connection test not yet available.',
|
|
});
|
|
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,
|
|
};
|
|
}
|