Enhance android_handler.py with memory + follow-up logic: 1) Imports: import re, datetime as dt from zoneinfo import ZoneInfo from supabase import create_client from tools import schedule_followup, log_message 2) Add helpers: a) parse_defer_time(text:str, now=None) -> (due_at_dt, label) - Lowercase the text. - Rules (in order): * 'in X month(s)': X=1..12 -> due_at = now + X months (approx 30*X days) * 'in X week(s)': X=1..12 -> due_at = now + 7*X days * 'few months'/'couple of months' -> +60 to +75 days (pick +60) * 'next month' -> first business day next month at 09:00 local * explicit months: jan(uary)|feb|...|dec -> set due_at to 1st of that month at 09:00 (next occurrence in future) - Return (due_at_dt, label) or (None, None). b) detect_life_events(text:str) -> list[dict] - Lowercase. - If matches words like: * moving|move|house|remortgage -> {'note_type':'moving_house','note_text':'Customer moving house soon'} * baby|pregnant|newborn -> {'note_type':'new_baby','note_text':'New baby mentioned'} * job|promotion|redundant -> {'note_type':'job_change','note_text':'Job change mentioned'} * surgery|operation|hospital -> {'note_type':'health','note_text':'Health/operation mentioned'} * holiday|honeymoon|wedding|anniversary-> {'note_type':'holiday','note_text':'Holiday/occasion mentioned'} - Return a list (can be empty). c) upsert_conversation_summary(agreement_id:int, last_intent:str, summary_text:str, tokens_used:int=None) - Upsert into conversation_summary (agreement_id PK) with last_summary, last_intent, last_updated=now(). d) insert_relationship_notes(agreement_id:int, notes:list[dict]) - Insert each note into relationship_note with confidence default 0.8. 3) In the inbound processing path (after we read inbound_text): - tz = ZoneInfo("Europe/London"); now = dt.datetime.now(tz) - Run events = detect_life_events(inbound_text) * If any -> insert_relationship_notes(agreement_id, events) - Run due_at,label = parse_defer_time(inbound_text, now) * If due_at: schedule_followup(agreement_id, reason = f"Customer defer: {label}", due_at=due_at) 4) When we detect thread closure (wherever the code closes the open_thread): - Build a compact summary from last 5–10 messages (use existing stored message_texts). * If OPENAI_API_KEY available, ask model to condense: 2–3 bullet points, UK tone, include any next steps. * Else build a simple rule-based summary e.g., "Customer deferred (few months). Notes: moving house." - Call upsert_conversation_summary(agreement_id, last_intent, summary_text, tokens_used=None). 5) Logging - Console print when we: * create follow_up: print("FOLLOW-UP scheduled", due_at, label) * add relationship_note: print("REL-NOTE", note_type, note_text) * update summary: print("SUMMARY upserted") 6) Keep existing rule/template matching and ok_to_reply() behaviour intact. Deliverable: - Update android_handler.py accordingly. - Confirm: "UPDATED handler with follow-ups, life events, and summaries".