Spaces:
Running on Zero
Running on Zero
Commit History
28 days ago
-
fix: stop an open activity draft from swallowing unrelated messages Running
Reported from a screenshot: the user had an activity draft open, then typed "hitungin kalor sate 10 tusuk dan lontong", "ginchie" and "aku makan sate 10 tusuk dan lontong" -- and the bot answered all three with "masih kurang: judulnya apa nih?, hari apa tanggal berapa?, jam berapa?". Root cause: the draft was only dropped when the router returned a different action AND `_looks_like_slot_answer()` was false. That helper counts any message of eight words or fewer as a slot answer, so a seven-word food-log request kept the draft alive forever and the food was never logged. - Draft continuation now requires the router to still see the same action, or the text to be a pure schedule answer (`_is_pure_schedule_answer`, which needs an actual date/time token). "aku makan sate 10 tusuk dan lontong" and "ginchie" no longer keep a draft alive. - `_merge_draft` is only used for ADD_ACTIVITY drafts; other actions go through `_merge_generic_draft`, which previously would have been rewritten…908edbb -
fix: stop a new activity inheriting the previous one's title
Reported from a screenshot: the user saved "Exam Software Engineer", then said "Ginchiee besok aku juga ada jadwal lagi" and answered "Jam 9 pagi ginchiee" — and the new event was saved under the OLD title. Root cause: while a draft is open the router prompt lists the user's stored activities, and the model copied a title out of that list. The prompt already forbade it, which is exactly why the guard is now enforced locally instead of by instruction: - `_is_pure_schedule_answer()` decides from the raw text whether a message only supplies a date/time. "Jam 9 pagi ginchiee" is; "ya betul, exam software engineer" is not. - `_merge_draft()` refuses any model-supplied title for those messages, so a bare slot answer can never resurrect a stored title. Worded more plainly: the prompt can be reworded later and this still holds. - `_draft_note` now states the new title must come from the user and must never be taken from the stored list. Also: - asking for a missing slot now lists …54aab32 -
fix: make creating and viewing activities work like a conversation
Reported: scheduling only happened when the user typed "masukkan ke kegiatan", the double-confirmation felt awkward, the agenda could not be checked, and old activity titles leaked into brand new ones. Routing - "ingetin aku", "jangan lupa aku", "pengingat" and stated plans ("aku ada X besok jam 10", "aku mau X jam 2 sore") now always produce ADD_ACTIVITY, even with no details yet, instead of falling through to CHAT. The model previously replied "siap, nanti aku ingetin" and saved nothing, which is worse than not replying at all. - Word order no longer matters ("jam 2 sore ... aku mau ngechat pacar" and "aku mau ngechat pacar ... jam 2 sore" both work). - Agenda/view phrasings broadened. Draft filling - Dates and times are now parsed locally as well as by the model. The model answered CHAT for a plain "Hari Minggu, 11 Oktober 2026" while a draft was open, which stranded the user mid-flow; a bare instruction followed by a date and a time now completes correctly. - Aski…3f49a5f -
fix: await the timezone lookup, and copy Postgres data across environments
The timezone fix in 2cdaf35 was broken and the regression test could not catch it. `user_today()` called the async `_tz_for()` without awaiting it, so pytz.timezone() received a coroutine, raised, and the code silently fell back to the machine timezone -- exactly the bug it was supposed to fix. The test passed because it asserted the fallback result. `user_today()` is now async and every caller awaits it, and the test sets two different timezones for the same frozen instant so a fallback can no longer satisfy it. Also add scripts/copy_postgres.py for the actual data migration. The bot's history lived in SQLite, was migrated to a local Postgres, and Supabase only ever received the schema -- so the production bot started from an empty database. The copy is additive (ON CONFLICT DO NOTHING never updates or deletes), offsets primary keys because local ids overlapped Supabase's (1..26 vs 21..22, 1..160 vs 1..14) and ON CONFLICT would otherwise silently drop rows, and never overwrites a use…7d3a67d
29 days ago
-
fix: unblock the HF Space build and make "today" follow the user timezone
Build - Hugging Face's Gradio SDK builder always injects its own `gradio[oauth,mcp]==<current>` into the install command, so pinning gradio==6.29.0 in requirements.txt made pip resolve two conflicting versions and the Space build failed outright with ResolutionImpossible. Use a floor version instead so the Space's pin wins. Correctness - date.today() read the machine's timezone. On Hugging Face the container runs in UTC while users are in Asia/Jakarta (UTC+7), so between 00:00 and 07:00 WIB the UTC date is still the previous day: meals logged then were filed under yesterday and /today showed nothing at all. "Today" is now derived from users.timezone via user_today(). - reminder context uses the same date, so reminder wording no longer disagrees with /today. Tests - Add a regression test that pins the clock at 00:00/03:00/06:00 WIB and asserts user_today() follows the user, not the container. - meal_type check no longer relies on server-side current_date, which s…2cdaf35 -
feat: switch to Postgres, add intent router and a warmer persona
Database - Replace SQLite (aiosqlite) with PostgreSQL via asyncpg. All state lived on the container's ephemeral filesystem, which is why every redeploy wiped it. - Add versioned migrations (database/migrations/NNN_*.sql) recorded in schema_migrations with checksums. The old CREATE-IF-NOT-EXISTS approach could not evolve the schema, and the live DB had drifted (orphaned google_calendar_tokens table). - Drop write-only daily_nutrition cache; totals recompute from food_logs so edits stay consistent. - connection.py keeps the small subset of the aiosqlite API the services use (`await db.execute`, `async with db.execute as cursor`, fetchone/fetchall) and translates ? placeholders to $n, so call sites were left untouched. - Store activity_dt as TIMESTAMPTZ and drop the string-comparison reminder query; reminders are now correct for WIB/WITA/WIT users. - Add scripts/migrate_sqlite_to_postgres.py to move the existing 4 users, 26 food logs and 160 conversations across with ids…1fcc069
-
fix: switch to gemini-flash-lite-latest, improve warm and excited personality, fix chat history sequence
fa9215e
-
fix: register ZeroGPU callback with Gradio
c968025 -
fix: support ZeroGPU Space runtime
4a1c368 -
fix: run bot worker using official app.run_polling with dedicated loop and stop_signals=None
a27e4b0 -
fix: explicitly invoke post_init in run_bot_async and set default model to gemini-3.7-flash
cdeb0d0 -
fix: surface post_init errors and make init_db idempotent
d0cdb21 -
fix: default to gemini-2.5-flash model
1b1671f -
fix: replace Gradio with pure Python http.server for stable HF Space hosting
2ceaa55 -
fix: add explicit main thread keep-alive loop to prevent container exit in HF Space
9d1a72a -
fix: use async context manager for telegram bot to avoid signal/shutdown conflicts in HF Spaces
8daa0fb -
chore: add logging for incoming user messages and commands
af023df -
fix: launch Gradio non-blocking and run Telegram bot on main thread
68903fc -
fix: initialize asyncio event loop in background thread for telegram polling
b729e4c -
fix: support BOT_TOKEN and TELEGRAM_BOT_TOKEN env vars and avoid port clash
1e947e0 -
feat: add Gradio entry point for Hugging Face free space
5d658a8 -
build: add Dockerfile and HF Spaces config with healthcheck server
35729d9 -
feat: add adaptive target, nutrition history, multimodal vision, and natural activity scheduling
c20fc0d
-
feat: add Google Calendar integration, error handling, and timeout resilience
f881753
-
Siap deploy
89ece72
-
first commit
8031356