Skip to content

Commit 9ae08ca

Browse files
JiroMusikclaude
andcommitted
Improve opened-item expiry logic: better AI prompt, skip Gewürze, safer updates
- Skip expiry check entirely for 'Gewürze' category (spices don't expire) - Richer AI prompt: includes category, unit, current MHD for better judgment - Detailed guidelines: dairy 3-5d, canned 2-3d, sauces 30-90d, dry goods no change - Only update MHD if new date is sooner than existing (never extend shelf life) - Non-critical: AI failure doesn't block the open action Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent f0b1c82 commit 9ae08ca

1 file changed

Lines changed: 49 additions & 44 deletions

File tree

server.ts

Lines changed: 49 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -813,36 +813,41 @@ app.post('/api/inventory/:id/open', async (req, res) => {
813813

814814
db.prepare('UPDATE items SET is_open = 1, opened_at = CURRENT_TIMESTAMP WHERE id = ?').run(id);
815815

816-
// AI Logic for expiry
817-
const prompt = `
818-
The user has opened the following food item:
819-
ID: ${item.id}, Name: ${item.name}
820-
821-
Does this item spoil quickly after opening (within 2-5 days)?
822-
Examples for YES (spoil quickly): "Passierte Tomaten", "Streukäse", "Milch", "Sahne", "Würstchen im Glas", "Mais (Konserve)", "Bohnen".
823-
Examples for NO (last long): "Gewürzgurken", "Ketchup", "Senf", "Marmelade", "Reis", "Nudeln", "Mehl", "Essig", "Öl".
824-
825-
Return a JSON object:
826-
- needs_new_expiry: boolean (true if it spoils quickly)
827-
- days_until_spoiled: number (e.g., 3 for passierte Tomaten, null if needs_new_expiry is false)
828-
`;
829-
830-
const schema = {
831-
type: Type.OBJECT,
832-
properties: {
833-
needs_new_expiry: { type: Type.BOOLEAN },
834-
days_until_spoiled: { type: Type.NUMBER }
835-
},
836-
required: ["needs_new_expiry"]
837-
};
838-
839-
const aiResult = await getAIResponse(prompt, undefined, schema, true);
816+
// Skip expiry logic for spices (they don't go bad)
817+
if (item.category !== 'Gewürze') {
818+
const prompt = `The user opened: "${item.name}" (Category: ${item.category}, Unit: ${item.unit}, Current MHD: ${item.expiry_date || 'none'}).
819+
After opening, how many days until this goes bad? Guidelines:
820+
- Fresh dairy (milk, cream, yogurt): 3-5 days
821+
- Canned goods (tomatoes, beans, corn): 2-3 days in fridge
822+
- Cold cuts, sausages: 3-5 days
823+
- Sauces (ketchup, mustard, mayo): 30-90 days
824+
- Jams, honey, vinegar: 60-180 days
825+
- Dry goods (flour, rice, pasta): no change
826+
Return JSON: needs_new_expiry (boolean), days_until_spoiled (number or null)`;
827+
828+
const schema = {
829+
type: Type.OBJECT,
830+
properties: {
831+
needs_new_expiry: { type: Type.BOOLEAN },
832+
days_until_spoiled: { type: Type.NUMBER }
833+
},
834+
required: ["needs_new_expiry"]
835+
};
840836

841-
if (aiResult.needs_new_expiry && aiResult.days_until_spoiled) {
842-
const newExpiry = new Date();
843-
newExpiry.setDate(newExpiry.getDate() + aiResult.days_until_spoiled);
844-
const expiryDate = newExpiry.toISOString().split('T')[0];
845-
db.prepare('UPDATE items SET expiry_date = ? WHERE id = ?').run(expiryDate, id);
837+
try {
838+
const aiResult = await getAIResponse(prompt, undefined, schema, true);
839+
if (aiResult.needs_new_expiry && aiResult.days_until_spoiled) {
840+
const newExpiry = new Date();
841+
newExpiry.setDate(newExpiry.getDate() + aiResult.days_until_spoiled);
842+
const expiryDate = newExpiry.toISOString().split('T')[0];
843+
// Only update if new expiry is sooner than existing
844+
if (!item.expiry_date || expiryDate < item.expiry_date) {
845+
db.prepare('UPDATE items SET expiry_date = ? WHERE id = ?').run(expiryDate, id);
846+
}
847+
}
848+
} catch (e: any) {
849+
console.error('AI expiry check failed (non-critical):', e.message);
850+
}
846851
}
847852

848853
const updatedItem = db.prepare('SELECT * FROM items WHERE id = ?').get(id);
@@ -1116,24 +1121,24 @@ app.post('/api/cook/check-opened', async (req, res) => {
11161121
}
11171122
}
11181123

1119-
if (itemsToCheck.length === 0) {
1124+
// Filter out spices (don't expire)
1125+
const filteredItems = itemsToCheck.filter((i: any) => i.category !== 'Gewürze');
1126+
1127+
if (filteredItems.length === 0) {
11201128
return res.json({ updates: [] });
11211129
}
11221130

1123-
// Ask AI
1124-
const prompt = `
1125-
The user has opened (partially consumed) the following food items:
1126-
${itemsToCheck.map(i => `ID: ${i.id}, Name: ${i.name}`).join('\n')}
1127-
1128-
Which of these items spoil quickly after opening (within 2-5 days)?
1129-
Examples for YES (spoil quickly): "Passierte Tomaten", "Streukäse", "Milch", "Sahne", "Würstchen im Glas", "Mais (Konserve)", "Bohnen".
1130-
Examples for NO (last long): "Gewürzgurken", "Ketchup", "Senf", "Marmelade", "Reis", "Nudeln", "Mehl", "Essig", "Öl".
1131-
1132-
Return a JSON object with a key "updates" containing an array of objects:
1133-
- id: The item ID
1134-
- needs_new_expiry: boolean (true if it spoils quickly)
1135-
- days_until_spoiled: number (e.g., 3 for passierte Tomaten, null if needs_new_expiry is false)
1136-
`;
1131+
const prompt = `The user opened these food items:
1132+
${filteredItems.map((i: any) => `ID: ${i.id}, Name: "${i.name}", Category: ${i.category}, MHD: ${i.expiry_date || 'none'}`).join('\n')}
1133+
1134+
After opening, how many days until each goes bad? Guidelines:
1135+
- Fresh dairy (milk, cream, yogurt): 3-5 days
1136+
- Canned goods (tomatoes, beans, corn): 2-3 days in fridge
1137+
- Cold cuts, sausages: 3-5 days
1138+
- Sauces (ketchup, mustard, mayo): 30-90 days
1139+
- Jams, honey, vinegar: 60-180 days
1140+
- Dry goods (flour, rice, pasta): no change
1141+
Return JSON with "updates" array: [{id, needs_new_expiry (boolean), days_until_spoiled (number or null)}]`;
11371142

11381143
const schema = {
11391144
type: Type.OBJECT,

0 commit comments

Comments
 (0)