diff --git a/src/pages/stock/StockTrade.jsx b/src/pages/stock/StockTrade.jsx index a9e0cc1..e100cca 100644 --- a/src/pages/stock/StockTrade.jsx +++ b/src/pages/stock/StockTrade.jsx @@ -232,8 +232,7 @@ const StockTrade = () => { const [reportSortDir, setReportSortDir] = useState('desc'); /* AI Coach */ - const [aiApiKey, setAiApiKey] = useState(''); - const [aiModel, setAiModel] = useState('claude-haiku-4-5-20251001'); + const [aiModel, setAiModel] = useState(() => localStorage.getItem('ai_coach_model') ?? 'claude-haiku-4-5-20251001'); const [aiResult, setAiResult] = useState(null); const [aiLoading, setAiLoading] = useState(false); const [aiError, setAiError] = useState(''); @@ -377,12 +376,8 @@ const StockTrade = () => { } }, [activeTab, assetHistoryDays, loadAssetHistory]); - /* AI Coach: 마운트 시 localStorage에서 API Key + 오늘 캐시 복원 */ + /* AI Coach: 마운트 시 오늘 캐시 복원 */ useEffect(() => { - const savedKey = localStorage.getItem('ai_coach_key') ?? ''; - const savedModel = localStorage.getItem('ai_coach_model') ?? 'claude-haiku-4-5-20251001'; - setAiApiKey(savedKey); - setAiModel(savedModel); const today = new Date().toISOString().slice(0, 10); const cached = localStorage.getItem(`ai_coach_${today}`); if (cached) { @@ -707,7 +702,7 @@ const StockTrade = () => { /* ── AI coach ────────────────────────────────────────────────── */ const handleAiCoach = async () => { - if (!aiApiKey.trim() || portfolioHoldings.length === 0) return; + if (portfolioHoldings.length === 0) return; const today = new Date().toISOString().slice(0, 10); const cacheKey = `ai_coach_${today}`; @@ -755,24 +750,15 @@ ${holdingsText}${marketText} }`; try { - const res = await fetch('https://api.anthropic.com/v1/messages', { + const res = await fetch('/api/stock/ai-coach', { method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'x-api-key': aiApiKey.trim(), - 'anthropic-version': '2023-06-01', - 'anthropic-dangerous-direct-browser-access': 'true', - }, - body: JSON.stringify({ - model: aiModel, - max_tokens: 1024, - messages: [{ role: 'user', content: prompt }], - }), + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ model: aiModel, prompt, max_tokens: 1024 }), }); if (!res.ok) { - const text = await res.text().catch(() => ''); - throw new Error(`Claude API 오류 (${res.status}): ${text.slice(0, 200)}`); + const errData = await res.json().catch(() => ({})); + throw new Error(errData.error || `AI Coach 오류 (${res.status})`); } const data = await res.json(); @@ -2467,30 +2453,8 @@ ${cashLines} )} - {/* API Key 설정 */} + {/* 모델 선택 */}