When you plan two or more meals in the same time slot, MenuMeld instantly asks Gemini for the best sequence — soup first, carbs last, dessert at the end — and delivers it to your Lock Screen as a clear liquid-glass Live Activity, no tapping required.
Pick at least 2 dishes from a time slot. The real backend fires Gemini immediately on every notify — here we just show the ~1 second round-trip. Result matches the real app output format: ordered steps + brief reasons + an overall explanation.
Four steps, no debounce. Gemini is invoked immediately on every notify, and the old in-flight task for the same slot is superseded. Click a step to see what it does.
Add, edit, delete, or copy a meal in today's slot.
Fire-and-forget POST /v1/ai/eating-order/notify.
Immediate asyncio task. Supersedes older jobs.
APNS push-to-start + poll on foreground.
The notify endpoint spawns the Gemini task via asyncio.create_task and returns immediately. No Redis debounce, no sweeper — every notify kicks off analysis right away.
Triggers exclusively when the active date is today and the slot has 2 or more meals. Single-meal slots get no suggestion (there's no order to suggest).
APNS delivers the result straight to the Lock Screen and Dynamic Island — no need for the user to open the app. A 2-minute fallback sweeper retries on transient failures.
English, Traditional Chinese (zh-Hant for TW/HK/MO), Simplified Chinese (zh-Hans for CN/SG). Gemini is prompted in the user's locale so reasons read naturally.
A new notification for the same (user, date, slot) marks in-flight tasks as "superseded" and invalidates their cache, so you never see a stale order.
Runs inside the shared AI daily/monthly budget. If you've hit the limit, the eating-order job silently skips rather than failing loudly.
Everything the iOS client actually calls, with the exact field names from the backend schema.
date, time_slot, meal_description, locale, live_activity_push_token. Returns {status: "accepted"} and immediately schedules the Gemini task.status: none | pending | processing | completed plus the full EatingOrderResponse on completion.order: int, meal_name: str, brief_reason: str — one entry per dish, ordered 1..N.steps: [EatingOrderStep], overall_reason: str, time_slot: str, model: str (defaults to gemini-2.5-flash-lite).EatingOrderAttributes.ContentState carries steps, overallReason, and isAppOpened. The last flag triggers auto-dismissal when the user opens the app.