scope AI model settings per account

This commit is contained in:
2026-09-06 19:05:55 +03:00
parent 74bd973f72
commit dd21bcbda2
2 changed files with 26 additions and 4 deletions
+6
View File
@@ -2152,3 +2152,9 @@ Doğrulama: yerel sentetik hazır taslakta çıktı penceresi başlığı, Türk
Analitik ekranındaki ciro hedefi daha önce ortak `localStorage` anahtarına yazılıyordu; bu, aynı tarayıcıda hesap değiştirildiğinde hedefin yanlış hesaba görünmesine neden olabilirdi. Hedef anahtarı artık normalize edilmiş hesap e-postasıyla ayrılıyor, depolama hataları güvenle ele alınıyor ve hesap değişiminde eski hedef yeni hesaba yazılmıyor. Analitik ekranındaki ciro hedefi daha önce ortak `localStorage` anahtarına yazılıyordu; bu, aynı tarayıcıda hesap değiştirildiğinde hedefin yanlış hesaba görünmesine neden olabilirdi. Hedef anahtarı artık normalize edilmiş hesap e-postasıyla ayrılıyor, depolama hataları güvenle ele alınıyor ve hesap değişiminde eski hedef yeni hesaba yazılmıyor.
Doğrulama: 293 otomatik test ve üretim derlemesi başarılı. Gerçek iki hesaplı tarayıcı kabulü ve canlı deployment hâlâ ayrıca yapılmalı. Doğrulama: 293 otomatik test ve üretim derlemesi başarılı. Gerçek iki hesaplı tarayıcı kabulü ve canlı deployment hâlâ ayrıca yapılmalı.
### 2026-09-06 · AI model ayarlarının hesap izolasyonu
AI fallback zinciri daha önce ortak `localStorage` anahtarında tutuluyordu. Ayar artık normalize edilmiş hesap e-postasına bağlı anahtarda saklanıyor; oturum değişiminde yeni hesabın zinciri yeniden yükleniyor ve önceki hesabın değeri yazılmıyor. Depolama erişimi olmayan ortamlarda varsayılan zincir kullanılıyor.
Doğrulama: 293 otomatik test ve üretim derlemesi başarılı. Gerçek iki hesaplı AI ayarı tarayıcı kabulü ve canlı sağlayıcı testi ayrıca yapılmalı.
+20 -4
View File
@@ -458,8 +458,8 @@ export const AppProvider = ({ children }) => {
const VARSAYILAN_ZINCIR = ['glmflash', 'gemini', 'deepseek']; const VARSAYILAN_ZINCIR = ['glmflash', 'gemini', 'deepseek'];
const ZINCIR_SURUM = 3; // artırıldığında kayıtlı zincir yeni düzene taşınır const ZINCIR_SURUM = 3; // artırıldığında kayıtlı zincir yeni düzene taşınır
const [aiModelConfig, setAiModelConfig] = useState(() => { const aiModelAnahtari = (email) => `ihaleist_ai_model_config:${encodeURIComponent(String(email || '').toLowerCase())}`;
const saved = localStorage.getItem('ihaleist_ai_model_config'); const normalizeAiModelConfig = (saved) => {
if (saved) { if (saved) {
try { try {
const cfg = JSON.parse(saved); const cfg = JSON.parse(saved);
@@ -478,11 +478,27 @@ export const AppProvider = ({ children }) => {
} catch { /* yoksay */ } } catch { /* yoksay */ }
} }
return { chain: VARSAYILAN_ZINCIR, surum: ZINCIR_SURUM }; return { chain: VARSAYILAN_ZINCIR, surum: ZINCIR_SURUM };
};
const [aiModelConfig, setAiModelConfig] = useState(() => {
try { return normalizeAiModelConfig(localStorage.getItem(aiModelAnahtari(getStoredUser()?.email))); }
catch { return normalizeAiModelConfig(null); }
}); });
const [aiConfigLoadedKey, setAiConfigLoadedKey] = useState(null);
useEffect(() => { useEffect(() => {
yerelKaydet('ihaleist_ai_model_config', aiModelConfig); const key = authUser?.email ? aiModelAnahtari(authUser.email) : null;
}, [aiModelConfig]); if (!key) { setAiModelConfig(normalizeAiModelConfig(null)); setAiConfigLoadedKey(null); return; }
let saved = null;
try { saved = localStorage.getItem(key); } catch { /* özel tarama */ }
setAiModelConfig(normalizeAiModelConfig(saved));
setAiConfigLoadedKey(key);
}, [authUser?.email]);
useEffect(() => {
if (!aiConfigLoadedKey) return;
yerelKaydet(aiConfigLoadedKey, aiModelConfig);
}, [aiModelConfig, aiConfigLoadedKey]);
const getModelById = (id) => AI_MODEL_CATALOG.find(m => m.id === id); const getModelById = (id) => AI_MODEL_CATALOG.find(m => m.id === id);
const activeAiModel = getModelById(aiModelConfig.chain[0]) || AI_MODEL_CATALOG[0]; const activeAiModel = getModelById(aiModelConfig.chain[0]) || AI_MODEL_CATALOG[0];