'use client' import { useState, useEffect } from 'react' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Badge } from '@/components/ui/badge' import { Key, Eye, EyeOff, CheckCircle, XCircle, Loader2 } from 'lucide-react' export default function SettingsPage() { const [apiKey, setApiKey] = useState('') const [maskedKey, setMaskedKey] = useState(null) const [saved, setSaved] = useState(false) const [showKey, setShowKey] = useState(false) const [testing, setTesting] = useState(false) const [testResult, setTestResult] = useState<'valid' | 'invalid' | null>(null) useEffect(() => { fetch('/api/config') .then((r) => r.json()) .then((data) => { if (data.hasOpenAIKey) { setMaskedKey(data.maskedKey) setSaved(true) } }) .catch(() => {}) }, []) async function handleSave() { if (!apiKey.trim()) return try { const res = await fetch('/api/config', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ apiKey: apiKey.trim() }), }) if (res.ok) { setSaved(true) setMaskedKey(`${apiKey.trim().slice(0, 7)}...${apiKey.trim().slice(-4)}`) setTestResult(null) } } catch { // ignore } } async function handleClear() { try { await fetch('/api/config', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: 'clear' }), }) setApiKey('') setMaskedKey(null) setSaved(false) setTestResult(null) } catch { // ignore } } async function handleTest() { // Save first if not saved if (!saved && apiKey.trim()) await handleSave() setTesting(true) setTestResult(null) try { const res = await fetch('/api/analyze', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ test: true }), }) // 401 = no key or invalid key, 400 = key works (missing sessionId is expected) setTestResult(res.status === 401 ? 'invalid' : 'valid') } catch { setTestResult('invalid') } finally { setTesting(false) } } return (
AI Analysis Configure OpenAI API access for AI-powered message classification
{saved && !apiKey && maskedKey && (

Current key: {maskedKey}

)}
{ setApiKey(e.target.value) setSaved(false) setTestResult(null) }} placeholder={saved ? 'Enter new key to replace...' : 'sk-...'} />
{(apiKey || maskedKey) && ( )}
{testResult === 'valid' && ( Valid )} {testResult === 'invalid' && ( Invalid )}

Your API key is stored in ~/.agentfit/config.json on your machine and never leaves your local server. Used with gpt-4.1-mini (~$0.001 per 100 messages).

) }