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 });