Skip to content

Commit a5ff9fd

Browse files
JiroMusikclaude
andcommitted
Fix v2.0.0 refactor regressions: restore frontend features, fix AI provider defaults
- Revert Inventory/Recipes/Calendar pages to pre-refactor versions (20+ lost features: product grouping, category emojis, percentage mode, quick-add buttons, localStorage persistence, direct cook, allow-extra UI, confirm dialogs, portions editing, etc.) - Fix missing state declarations (editingDateId, planSettings, showWeeklyModal) and add Edit2 import + handleUpdateDate handler in Calendar - Fix ai.service.ts: per-provider model defaults (gpt-4o for OpenAI, claude-3-5-sonnet for Anthropic) instead of falling back to gemini-3-flash-preview for all providers - Add SSRF validation for Ollama URL in ai.service.ts - Keep backend extraction (database, migrations, categories, units, bring service) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent cbae80c commit a5ff9fd

4 files changed

Lines changed: 1303 additions & 721 deletions

File tree

server/services/ai.service.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,20 @@ export async function getAIResponse(prompt: string, imageBase64?: string, schema
2828

2929
const provider = settingsMap.ai_provider || 'gemini';
3030
const customApiKey = settingsMap.ai_api_key;
31-
const modelName = useAdvisorModel ? (settingsMap.advisor_model || settingsMap.ai_model || 'gemini-3-flash-preview') : (settingsMap.ai_model || 'gemini-3-flash-preview');
3231
const ollamaUrl = settingsMap.ollama_url || 'http://localhost:11434';
3332

33+
// Per-provider model defaults (must match original behavior)
34+
let modelName = useAdvisorModel
35+
? (settingsMap.advisor_model || settingsMap.ai_model)
36+
: settingsMap.ai_model;
37+
if (!modelName) {
38+
if (provider === 'gemini') modelName = 'gemini-3-flash-preview';
39+
else if (provider === 'openai') modelName = 'gpt-4o';
40+
else if (provider === 'anthropic') modelName = 'claude-3-5-sonnet-latest';
41+
}
42+
43+
console.log(`AI Request: Provider=${provider}, Model=${modelName || 'default'}`);
44+
3445
try {
3546
if (provider === 'gemini') {
3647
const key = customApiKey || process.env.GEMINI_API_KEY;
@@ -108,6 +119,15 @@ export async function getAIResponse(prompt: string, imageBase64?: string, schema
108119
}
109120

110121
if (provider === 'ollama') {
122+
// SSRF validation
123+
try {
124+
const url = new URL(ollamaUrl);
125+
if (!['http:', 'https:'].includes(url.protocol)) throw new Error('Invalid Ollama URL protocol');
126+
if (['169.254.', '0.0.0.0'].some(p => url.hostname.startsWith(p))) throw new Error('Invalid Ollama URL');
127+
} catch (e: any) {
128+
if (e.message.includes('Invalid')) throw e;
129+
throw new Error('Invalid Ollama URL');
130+
}
111131
const messages: any[] = [{ role: 'user', content: prompt }];
112132
if (imageBase64) messages[0].images = [imageBase64.replace(/^data:image\/\w+;base64,/, '')];
113133
const response = await fetch(`${ollamaUrl}/api/generate`, {

0 commit comments

Comments
 (0)