mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-01-31 20:03:37 +00:00
- Introduced a new method to check Codex authentication status, allowing for better handling of API keys and OAuth tokens. - Updated API key management to include OpenAI, enabling users to manage their keys more effectively. - Enhanced the CodexProvider to support session ID tracking and deduplication of text blocks in assistant messages. - Improved error handling and logging in authentication routes, providing clearer feedback to users. These changes improve the overall user experience and security of the Codex integration, ensuring smoother authentication processes and better management of API keys.
231 lines
6.5 KiB
TypeScript
231 lines
6.5 KiB
TypeScript
// @ts-nocheck
|
|
import { useState, useEffect } from 'react';
|
|
import { createLogger } from '@automaker/utils/logger';
|
|
import { useAppStore } from '@/store/app-store';
|
|
|
|
const logger = createLogger('ApiKeyManagement');
|
|
import { getElectronAPI } from '@/lib/electron';
|
|
import type { ProviderConfigParams } from '@/config/api-providers';
|
|
|
|
interface TestResult {
|
|
success: boolean;
|
|
message: string;
|
|
}
|
|
|
|
interface ApiKeyStatus {
|
|
hasAnthropicKey: boolean;
|
|
hasGoogleKey: boolean;
|
|
hasOpenaiKey: 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);
|
|
const [openaiKey, setOpenaiKey] = useState(apiKeys.openai);
|
|
|
|
// Visibility toggles
|
|
const [showAnthropicKey, setShowAnthropicKey] = useState(false);
|
|
const [showGoogleKey, setShowGoogleKey] = useState(false);
|
|
const [showOpenaiKey, setShowOpenaiKey] = 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);
|
|
const [testingOpenaiConnection, setTestingOpenaiConnection] = useState(false);
|
|
const [openaiTestResult, setOpenaiTestResult] = 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);
|
|
setOpenaiKey(apiKeys.openai);
|
|
}, [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,
|
|
hasOpenaiKey: status.hasOpenaiKey,
|
|
});
|
|
}
|
|
} catch (error) {
|
|
logger.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);
|
|
};
|
|
|
|
// Test OpenAI/Codex connection
|
|
const handleTestOpenaiConnection = async () => {
|
|
setTestingOpenaiConnection(true);
|
|
setOpenaiTestResult(null);
|
|
|
|
try {
|
|
const api = getElectronAPI();
|
|
const data = await api.setup.verifyCodexAuth('api_key', openaiKey);
|
|
|
|
if (data.success && data.authenticated) {
|
|
setOpenaiTestResult({
|
|
success: true,
|
|
message: 'Connection successful! Codex responded.',
|
|
});
|
|
} else {
|
|
setOpenaiTestResult({
|
|
success: false,
|
|
message: data.error || 'Failed to connect to OpenAI API.',
|
|
});
|
|
}
|
|
} catch {
|
|
setOpenaiTestResult({
|
|
success: false,
|
|
message: 'Network error. Please check your connection.',
|
|
});
|
|
} finally {
|
|
setTestingOpenaiConnection(false);
|
|
}
|
|
};
|
|
|
|
// Save API keys
|
|
const handleSave = () => {
|
|
setApiKeys({
|
|
anthropic: anthropicKey,
|
|
google: googleKey,
|
|
openai: openaiKey,
|
|
});
|
|
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,
|
|
},
|
|
openai: {
|
|
value: openaiKey,
|
|
setValue: setOpenaiKey,
|
|
show: showOpenaiKey,
|
|
setShow: setShowOpenaiKey,
|
|
testing: testingOpenaiConnection,
|
|
onTest: handleTestOpenaiConnection,
|
|
result: openaiTestResult,
|
|
},
|
|
};
|
|
|
|
return {
|
|
// Provider config params for buildProviderConfigs
|
|
providerConfigParams,
|
|
|
|
// API key status from environment
|
|
apiKeyStatus,
|
|
|
|
// Save handler and state
|
|
handleSave,
|
|
saved,
|
|
};
|
|
}
|