import React, { useState, useEffect } from 'react'; import { useApp } from '../../context/AppContext'; import { Cpu, Check, ArrowUp, ArrowDown, X, Plus, Sparkles, Save, Shield, Zap, AlertTriangle } from 'lucide-react'; import { getAiConfig } from '../../services/ai'; import confetti from 'canvas-confetti'; const RENK = { blue: 'bg-blue-50 text-blue-700 border-blue-200', indigo: 'bg-indigo-50 text-indigo-700 border-indigo-200', amber: 'bg-amber-50 text-amber-700 border-amber-200', slate: 'bg-slate-100 text-slate-700 border-slate-200', emerald: 'bg-emerald-50 text-emerald-700 border-emerald-200', orange: 'bg-orange-50 text-orange-700 border-orange-200' }; const SIRA_ETIKET = ['Birincil (Primary)', '2. Yedek (Fallback)', '3. Yedek (Fallback)', '4. Yedek', '5. Yedek', '6. Yedek']; export const AiModelSettings = () => { const { AI_MODEL_CATALOG, aiModelConfig, setAiModelConfig, getModelById } = useApp(); const [saved, setSaved] = useState(false); const [cfg, setCfg] = useState(null); useEffect(() => { getAiConfig().then(setCfg); }, []); const aktifYol = cfg?.providers?.[0]?.yol; const chain = aiModelConfig.chain; const available = AI_MODEL_CATALOG.filter(m => !chain.includes(m.id)); const update = (newChain) => { setAiModelConfig({ ...aiModelConfig, chain: newChain }); setSaved(false); }; const move = (idx, dir) => { const j = idx + dir; if (j < 0 || j >= chain.length) return; const next = [...chain]; [next[idx], next[j]] = [next[j], next[idx]]; update(next); }; const setPrimary = (idx) => { if (idx === 0) return; const next = [...chain]; const [item] = next.splice(idx, 1); next.unshift(item); update(next); }; const remove = (idx) => { if (chain.length <= 1) return; // en az bir model kalmalı update(chain.filter((_, i) => i !== idx)); }; const add = (id) => update([...chain, id]); const handleSave = () => { // aiModelConfig zaten localStorage'a otomatik yazılıyor; buton kullanıcı geri bildirimi için setSaved(true); confetti({ particleCount: 60, spread: 70 }); setTimeout(() => setSaved(false), 3500); }; return (
{/* Canlı AI durumu */} {cfg && ( cfg.configured ? (
AI aktif — {cfg.providers.length} model kullanılabilir {aktifYol === 'openrouter' ? ' (OpenRouter üzerinden tek anahtarla)' : ' (doğrudan sağlayıcı anahtarlarıyla)'}.
{cfg.providers.map((p) => `${p.label}: ${p.model}`).join(' · ')}
) : (

AI anahtarı yok. Sunucuya tek bir OPENROUTER_API_KEY ekleyin — aşağıdaki tüm modeller bu tek anahtarla çalışır. Aşağıdaki sıralama yalnızca tercih kaydeder; çağrılar anahtar eklendiğinde başlar.

) )} {/* Header */}

Yapay Zeka Model Yönetimi

Şartname analizi ve AI özelliklerinde kullanılacak modeli ve yedek (fallback) sırasını belirleyin.

{/* Aktif zincir */}

Aktif Model Sırası (Fallback Zinciri)

Birincil model yanıt vermezse sıradaki yedeğe otomatik geçilir. Zincirde olmasa bile Gemini Flash ücretli yedek olarak her zaman en sonda denenir; yalnız üsttekilerin hepsi başarısız olursa devreye girer.

{chain.map((id, idx) => { const m = getModelById(id); if (!m) return null; return (
{idx + 1}
{m.label} {m.provider} {idx === 0 && ( BİRİNCİL )}
{m.or} · doğrudan: {m.model}
{SIRA_ETIKET[idx] || `${idx + 1}. sırada`}
{idx !== 0 && ( )}
); })}
{/* Eklenebilir modeller */} {available.length > 0 && (

Kullanılabilir Diğer Modeller

Zincire eklemek için bir modele tıklayın.

{available.map(m => ( ))}
)}

Seçimler tarayıcınızda saklanır ve tüm AI özelliklerinde (şartname analizi, fiyat/risk değerlendirmesi) kullanılır.

); };