From 454f676499898a979d8813326acac985303cb577 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 1 Nov 2026 01:43:44 -0500 Subject: [PATCH] Update default model list from live API discovery and filter out TTS/music/agent models --- public/app.js | 22 +++++++++++++--------- public/index.html | 8 +++++--- public/settings.json.template | 2 +- server.js | 23 ++++++++++++----------- 4 files changed, 31 insertions(+), 24 deletions(-) diff --git a/public/app.js b/public/app.js index 709ec96..280fb79 100644 --- a/public/app.js +++ b/public/app.js @@ -2035,15 +2035,17 @@ function populateModelDropdown(models, selectedModel) { const select = elements.settingsGeminiModelSelect; select.innerHTML = ''; - const targetModel = selectedModel || 'gemini-2.0-flash'; + const targetModel = selectedModel || 'gemini-2.5-flash'; let foundTarget = false; models.forEach(m => { const opt = document.createElement('option'); opt.value = m.id; opt.textContent = m.displayName || m.id; - if (m.id === 'gemini-2.0-flash') { - opt.textContent = `${m.displayName || 'Gemini 2.0 Flash'} (Recommended)`; + if (m.id === 'gemini-2.5-flash') { + opt.textContent = `${m.displayName || 'Gemini 2.5 Flash'} (Stable Recommended)`; + } else if (m.id === 'gemini-3.8-flash') { + opt.textContent = `${m.displayName || 'Gemini 3.8 Flash'} (Newest Flash)`; } if (m.id === targetModel) { opt.selected = true; @@ -2073,9 +2075,10 @@ async function fetchModelsDirectFromGoogle(key) { if (!Array.isArray(googleData.models)) { throw new Error('Unexpected response format from Google API.'); } + const excludedPatterns = /embedding|aqa|imagen|tts|lyria|banana|-image|robotics|computer-use|deep-research|antigravity|customtools/i; const models = googleData.models .filter(m => Array.isArray(m.supportedGenerationMethods) && m.supportedGenerationMethods.includes('generateContent')) - .filter(m => !m.name.includes('embedding') && !m.name.includes('aqa') && !m.name.includes('imagen')) + .filter(m => !excludedPatterns.test(m.name) && !excludedPatterns.test(m.displayName || '')) .map(m => { const modelId = m.name.replace(/^models\//, ''); return { @@ -2090,7 +2093,7 @@ async function fetchModelsDirectFromGoogle(key) { const bIsFlash = b.id.toLowerCase().includes('flash'); if (aIsFlash && !bIsFlash) return -1; if (!aIsFlash && bIsFlash) return 1; - return a.id.localeCompare(b.id); + return b.id.localeCompare(a.id); }); return models; } @@ -2145,7 +2148,7 @@ async function handleDiscoverModels(showNotice = true) { } if (models.length > 0) { - const currentSelected = elements.settingsGeminiModelSelect ? elements.settingsGeminiModelSelect.value : 'gemini-2.0-flash'; + const currentSelected = elements.settingsGeminiModelSelect ? elements.settingsGeminiModelSelect.value : 'gemini-2.5-flash'; populateModelDropdown(models, currentSelected); if (elements.modelsStatusHint) { elements.modelsStatusHint.textContent = `Discovered ${models.length} compatible models.`; @@ -2211,7 +2214,7 @@ async function openSettingsModal() { } if (elements.settingsGeminiModelSelect) { - const savedModel = settings.geminiModel || 'gemini-2.0-flash'; + const savedModel = (!settings.geminiModel || settings.geminiModel === 'gemini-2.0-flash') ? 'gemini-2.5-flash' : settings.geminiModel; let exists = false; for (let i = 0; i < elements.settingsGeminiModelSelect.options.length; i++) { if (elements.settingsGeminiModelSelect.options[i].value === savedModel) { @@ -2243,7 +2246,7 @@ async function handleSaveSettings(e) { elements.settingsStatusMsg.style.display = 'none'; const key = elements.settingsGeminiKeyInput.value.trim(); - const model = elements.settingsGeminiModelSelect ? elements.settingsGeminiModelSelect.value : 'gemini-2.0-flash'; + const model = elements.settingsGeminiModelSelect ? elements.settingsGeminiModelSelect.value : 'gemini-2.5-flash'; const defaultConsolidate = elements.settingsDefaultConsolidate ? elements.settingsDefaultConsolidate.checked : true; try { @@ -2417,7 +2420,8 @@ async function scanRecipeFile(file) { } const settings = await settingsResponse.json(); const apiKey = settings.geminiApiKey ? settings.geminiApiKey.trim() : ''; - const geminiModel = settings.geminiModel ? settings.geminiModel.trim() : 'gemini-2.0-flash'; + const rawModel = settings.geminiModel ? settings.geminiModel.trim() : ''; + const geminiModel = (!rawModel || rawModel === 'gemini-2.0-flash') ? 'gemini-2.5-flash' : rawModel; const isPlaceholder = apiKey === 'PASTE_YOUR_GEMINI_API_KEY_HERE' || apiKey === ''; if (!apiKey || isPlaceholder) { diff --git a/public/index.html b/public/index.html index e6f4391..95e3936 100644 --- a/public/index.html +++ b/public/index.html @@ -1036,9 +1036,11 @@ Powers both recipe photo scanning and AI text polishing. diff --git a/public/settings.json.template b/public/settings.json.template index 88722aa..3f6fdf7 100644 --- a/public/settings.json.template +++ b/public/settings.json.template @@ -1,4 +1,4 @@ { "geminiApiKey": "PASTE_YOUR_GEMINI_API_KEY_HERE", - "geminiModel": "gemini-2.0-flash" + "geminiModel": "gemini-2.5-flash" } diff --git a/server.js b/server.js index 03861c3..a9fe126 100644 --- a/server.js +++ b/server.js @@ -82,7 +82,7 @@ db.prepare(` db.prepare(` CREATE TABLE IF NOT EXISTS settings ( geminiApiKey TEXT DEFAULT '', - geminiModel TEXT DEFAULT 'gemini-2.0-flash' + geminiModel TEXT DEFAULT 'gemini-2.5-flash' ) `).run(); @@ -193,16 +193,16 @@ try { db.prepare("ALTER TABLE backup_history ADD COLUMN userSummary TEXT NOT NULL DEFAULT '[]'").run(); } catch (e) {} try { - db.prepare("ALTER TABLE settings ADD COLUMN geminiModel TEXT DEFAULT 'gemini-2.0-flash'").run(); + db.prepare("ALTER TABLE settings ADD COLUMN geminiModel TEXT DEFAULT 'gemini-2.5-flash'").run(); } catch (e) {} try { - db.prepare("UPDATE settings SET geminiModel = 'gemini-2.0-flash' WHERE geminiModel IS NULL OR geminiModel = ''").run(); + db.prepare("UPDATE settings SET geminiModel = 'gemini-2.5-flash' WHERE geminiModel IS NULL OR geminiModel = '' OR geminiModel = 'gemini-2.0-flash'").run(); } catch (e) {} // Initialize single settings record if empty const settingsCount = db.prepare('SELECT COUNT(*) as count FROM settings').get().count; if (settingsCount === 0) { - db.prepare('INSERT INTO settings (geminiApiKey, geminiModel) VALUES (?, ?)').run('', 'gemini-2.0-flash'); + db.prepare('INSERT INTO settings (geminiApiKey, geminiModel) VALUES (?, ?)').run('', 'gemini-2.5-flash'); } // Ensure default system_admin and admin user profiles exist @@ -1587,7 +1587,7 @@ app.post('/api/recipes/ai-polish', requireAuth, async (req, res) => { const settingsRow = db.prepare('SELECT geminiApiKey, geminiModel FROM settings LIMIT 1').get(); const geminiKey = settingsRow?.geminiApiKey?.trim(); - const geminiModel = settingsRow?.geminiModel?.trim() || 'gemini-2.0-flash'; + const geminiModel = settingsRow?.geminiModel?.trim() || 'gemini-2.5-flash'; const isPlaceholder = !geminiKey || geminiKey === 'PASTE_YOUR_GEMINI_API_KEY_HERE'; if (isPlaceholder) { @@ -1654,7 +1654,7 @@ app.get('/api/settings', requireAuth, (req, res) => { const defaultConsolidateLists = userRow ? userRow.defaultConsolidateLists !== 0 : true; res.json({ geminiApiKey: settings ? settings.geminiApiKey : '', - geminiModel: (settings && settings.geminiModel) ? settings.geminiModel : 'gemini-2.0-flash', + geminiModel: (settings && settings.geminiModel) ? settings.geminiModel : 'gemini-2.5-flash', defaultConsolidateLists }); } catch (e) { @@ -1671,7 +1671,7 @@ app.post('/api/settings', requireAuth, (req, res) => { db.prepare('UPDATE settings SET geminiApiKey = ?').run(geminiApiKey || ''); } if (geminiModel !== undefined) { - db.prepare('UPDATE settings SET geminiModel = ?').run(geminiModel || 'gemini-2.0-flash'); + db.prepare('UPDATE settings SET geminiModel = ?').run(geminiModel || 'gemini-2.5-flash'); } if (typeof defaultConsolidateLists === 'boolean') { db.prepare('UPDATE users SET defaultConsolidateLists = ? WHERE id = ?').run(defaultConsolidateLists ? 1 : 0, req.user.id); @@ -1681,7 +1681,7 @@ app.post('/api/settings', requireAuth, (req, res) => { const userRow = db.prepare('SELECT defaultConsolidateLists FROM users WHERE id = ?').get(req.user.id); res.json({ geminiApiKey: settings ? settings.geminiApiKey : '', - geminiModel: (settings && settings.geminiModel) ? settings.geminiModel : 'gemini-2.0-flash', + geminiModel: (settings && settings.geminiModel) ? settings.geminiModel : 'gemini-2.5-flash', defaultConsolidateLists: userRow ? userRow.defaultConsolidateLists !== 0 : true }); } catch (e) { @@ -1707,9 +1707,10 @@ app.post('/api/settings/discover-models', requireAuth, async (req, res) => { }); if (response.data && Array.isArray(response.data.models)) { + const excludedPatterns = /embedding|aqa|imagen|tts|lyria|banana|-image|robotics|computer-use|deep-research|antigravity|customtools/i; const models = response.data.models .filter(m => Array.isArray(m.supportedGenerationMethods) && m.supportedGenerationMethods.includes('generateContent')) - .filter(m => !m.name.includes('embedding') && !m.name.includes('aqa') && !m.name.includes('imagen')) + .filter(m => !excludedPatterns.test(m.name) && !excludedPatterns.test(m.displayName || '')) .map(m => { const modelId = m.name.replace(/^models\//, ''); return { @@ -1719,13 +1720,13 @@ app.post('/api/settings/discover-models', requireAuth, async (req, res) => { }; }); - // Sort models: Flash models first, then by ID + // Sort models: Flash models first, then Pro, then others models.sort((a, b) => { const aIsFlash = a.id.toLowerCase().includes('flash'); const bIsFlash = b.id.toLowerCase().includes('flash'); if (aIsFlash && !bIsFlash) return -1; if (!aIsFlash && bIsFlash) return 1; - return a.id.localeCompare(b.id); + return b.id.localeCompare(a.id); }); return res.json({ models });