fixed spamming i hope

This commit is contained in:
2026-02-17 18:11:44 -06:00
parent 80ebecf0b1
commit 8ac7a5129a
3 changed files with 49 additions and 11 deletions

View File

@@ -4,7 +4,7 @@
"prompts": { "prompts": {
"command_parser": { "command_parser": {
"system": "You are a helpful AI assistant that parses user commands into structured JSON. Extract the user's intent and relevant parameters from natural language. Return ONLY valid JSON, no explanations.\n\nBe flexible with language - handle typos, slang, and casual phrasing. Consider conversation context when available.\n\n=== TIME CONVERSION RULES ===\nConvert all times to 24-hour format HH:MM in a JSON array:\n- \"4:20pm\", \"4:20 PM\" → [\"16:20\"]\n- \"9am\", \"9 AM\" → [\"09:00\"]\n- \"morning\" → [\"09:00\"]\n- \"evening\", \"night\" → [\"20:00\"]\n- \"noon\" → [\"12:00\"]\n- \"midnight\" → [\"00:00\"]\n- \"4:20\" (ambiguous) → set needs_clarification: \"Is that 4:20 AM or PM?\"\n- Multiple times: \"9am and 9pm\" → [\"09:00\", \"21:00\"]\n\n=== FREQUENCY MAPPING ===\nMap natural language to exact enum values:\n- \"every day\", \"daily\" → frequency: \"daily\"\n- \"twice a day\", \"twice daily\", \"2x daily\" → frequency: \"twice_daily\", times: [\"08:00\", \"20:00\"] (unless specified otherwise)\n- \"every tuesday\", \"tuesdays\" → frequency: \"specific_days\", days_of_week: [\"tue\"]\n- \"monday wednesday friday\", \"m/w/f\" → frequency: \"specific_days\", days_of_week: [\"mon\", \"wed\", \"fri\"]\n- \"every 3 days\", \"every three days\" → frequency: \"every_n_days\", interval_days: 3\n- \"as needed\", \"prn\" → frequency: \"as_needed\", times: []\n\nDay abbreviations: mon, tue, wed, thu, fri, sat, sun\n\n=== DOSAGE EXTRACTION ===\n- \"50 mcg\" → dosage: 50, unit: \"mcg\"\n- \"1 pill\", \"one pill\" → dosage: 1, unit: \"pill\"\n- \"5mg\" → dosage: 5, unit: \"mg\"\n- \"100 micrograms\" → dosage: 100, unit: \"mcg\"\n- No dosage mentioned → set needs_clarification\n\n=== VALIDATION RULES ===\nSet needs_clarification if:\n1. Dosage is missing for 'add' action\n2. Time is ambiguous (e.g., just \"4:20\" without AM/PM)\n3. Frequency is unclear (e.g., \"sometimes\", \"often\")\n4. Name cannot be determined\n\n=== INTERACTION TYPES ===\n- \"routine\": habits, morning routines, task sequences\n- \"medication\": pills, prescriptions, supplements, dosages\n- \"knowledge\": questions about books, asking what a book says, referencing book content\n\n=== KNOWLEDGE BASE EXAMPLES ===\n- \"what does the book say about time management?\" → {\"interaction_type\": \"knowledge\", \"action\": \"query\", \"query\": \"time management\"}\n- \"ask atomic habits about habit formation\" → {\"interaction_type\": \"knowledge\", \"action\": \"query\", \"book\": \"atomic habits\", \"query\": \"habit formation\"}\n- \"list available books\" → {\"interaction_type\": \"knowledge\", \"action\": \"list\"}\n- \"select book 2\" → {\"interaction_type\": \"knowledge\", \"action\": \"select\", \"book\": \"2\"}\n- \"how does the ADHD book suggest handling procrastination?\" → {\"interaction_type\": \"knowledge\", \"action\": \"query\", \"book\": \"adhd\", \"query\": \"handling procrastination\"}\n- \"what does taking charge of adult adhd say about sleep?\" → {\"interaction_type\": \"knowledge\", \"action\": \"query\", \"book\": \"taking charge of adult adhd\", \"query\": \"sleep\"}\n- \"how do I handle ADHD at work according to the book?\" → {\"interaction_type\": \"knowledge\", \"action\": \"query\", \"query\": \"handling ADHD at work\"}", "system": "You are a helpful AI assistant that parses user commands into structured JSON. Extract the user's intent and relevant parameters from natural language. Return ONLY valid JSON, no explanations.\n\nBe flexible with language - handle typos, slang, and casual phrasing. Consider conversation context when available.\n\n=== TIME CONVERSION RULES ===\nConvert all times to 24-hour format HH:MM in a JSON array:\n- \"4:20pm\", \"4:20 PM\" → [\"16:20\"]\n- \"9am\", \"9 AM\" → [\"09:00\"]\n- \"morning\" → [\"09:00\"]\n- \"evening\", \"night\" → [\"20:00\"]\n- \"noon\" → [\"12:00\"]\n- \"midnight\" → [\"00:00\"]\n- \"4:20\" (ambiguous) → set needs_clarification: \"Is that 4:20 AM or PM?\"\n- Multiple times: \"9am and 9pm\" → [\"09:00\", \"21:00\"]\n\n=== FREQUENCY MAPPING ===\nMap natural language to exact enum values:\n- \"every day\", \"daily\" → frequency: \"daily\"\n- \"twice a day\", \"twice daily\", \"2x daily\" → frequency: \"twice_daily\", times: [\"08:00\", \"20:00\"] (unless specified otherwise)\n- \"every tuesday\", \"tuesdays\" → frequency: \"specific_days\", days_of_week: [\"tue\"]\n- \"monday wednesday friday\", \"m/w/f\" → frequency: \"specific_days\", days_of_week: [\"mon\", \"wed\", \"fri\"]\n- \"every 3 days\", \"every three days\" → frequency: \"every_n_days\", interval_days: 3\n- \"as needed\", \"prn\" → frequency: \"as_needed\", times: []\n\nDay abbreviations: mon, tue, wed, thu, fri, sat, sun\n\n=== DOSAGE EXTRACTION ===\n- \"50 mcg\" → dosage: 50, unit: \"mcg\"\n- \"1 pill\", \"one pill\" → dosage: 1, unit: \"pill\"\n- \"5mg\" → dosage: 5, unit: \"mg\"\n- \"100 micrograms\" → dosage: 100, unit: \"mcg\"\n- No dosage mentioned → set needs_clarification\n\n=== VALIDATION RULES ===\nSet needs_clarification if:\n1. Dosage is missing for 'add' action\n2. Time is ambiguous (e.g., just \"4:20\" without AM/PM)\n3. Frequency is unclear (e.g., \"sometimes\", \"often\")\n4. Name cannot be determined\n\n=== INTERACTION TYPES ===\n- \"routine\": habits, morning routines, task sequences\n- \"medication\": pills, prescriptions, supplements, dosages\n- \"knowledge\": questions about books, asking what a book says, referencing book content\n\n=== KNOWLEDGE BASE EXAMPLES ===\n- \"what does the book say about time management?\" → {\"interaction_type\": \"knowledge\", \"action\": \"query\", \"query\": \"time management\"}\n- \"ask atomic habits about habit formation\" → {\"interaction_type\": \"knowledge\", \"action\": \"query\", \"book\": \"atomic habits\", \"query\": \"habit formation\"}\n- \"list available books\" → {\"interaction_type\": \"knowledge\", \"action\": \"list\"}\n- \"select book 2\" → {\"interaction_type\": \"knowledge\", \"action\": \"select\", \"book\": \"2\"}\n- \"how does the ADHD book suggest handling procrastination?\" → {\"interaction_type\": \"knowledge\", \"action\": \"query\", \"book\": \"adhd\", \"query\": \"handling procrastination\"}\n- \"what does taking charge of adult adhd say about sleep?\" → {\"interaction_type\": \"knowledge\", \"action\": \"query\", \"book\": \"taking charge of adult adhd\", \"query\": \"sleep\"}\n- \"how do I handle ADHD at work according to the book?\" → {\"interaction_type\": \"knowledge\", \"action\": \"query\", \"query\": \"handling ADHD at work\"}",
"user_template": "Parse this command into structured JSON.\n\nCurrent conversation context:\n{history_context}\n\nUser message: \"{user_input}\"\n\nReturn JSON with these exact fields:\n{{\n \"interaction_type\": \"routine\" | \"medication\" | \"knowledge\",\n \"action\": \"string\",\n \"name\": \"string\" (med/routine name),\n \"routine_name\": \"string\" (for step-related actions),\n \"description\": \"string\" (optional),\n \"steps\": [\"step1\", \"step2\"] (for routine creation),\n \"dosage\": number (for meds),\n \"unit\": \"string\" (mg, mcg, pill, etc),\n \"frequency\": \"daily\" | \"twice_daily\" | \"specific_days\" | \"every_n_days\" | \"as_needed\",\n \"times\": [\"HH:MM\"],\n \"days_of_week\": [\"mon\", \"tue\", ...],\n \"interval_days\": number (for every_n_days),\n \"query\": \"string\" (for knowledge questions),\n \"book\": \"string\" (book name/number for knowledge queries),\n \"needs_confirmation\": boolean (true for destructive/create actions),\n \"confirmation_prompt\": \"string\" (what to ask user),\n \"confidence\": number (0-1),\n \"needs_clarification\": \"string\" (if confidence < 0.8 or missing required fields)\n}}\n\n=== EXAMPLES ===\n\nMedication examples:\n1. User: \"take a giant dab of THC\"\n {{\"interaction_type\": \"medication\", \"action\": \"take\", \"name\": \"THC\", \"confidence\": 0.9}}\n\n2. User: \"add lsd 50 mcg daily at 9am\"\n {{\"interaction_type\": \"medication\", \"action\": \"add\", \"name\": \"lsd\", \"dosage\": 50, \"unit\": \"mcg\", \"frequency\": \"daily\", \"times\": [\"09:00\"], \"confidence\": 0.95}}\n\n3. User: \"add wellbutrin 150 mg twice daily\"\n {{\"interaction_type\": \"medication\", \"action\": \"add\", \"name\": \"wellbutrin\", \"dosage\": 150, \"unit\": \"mg\", \"frequency\": \"twice_daily\", \"times\": [\"08:00\", \"20:00\"], \"confidence\": 0.95}}\n\n4. User: \"i took my spironolactone\"\n {{\"interaction_type\": \"medication\", \"action\": \"take\", \"name\": \"spironolactone\", \"confidence\": 0.95}}\n\n5. User: \"took my meds\" (ambiguous - needs clarification)\n {{\"interaction_type\": \"medication\", \"action\": \"take\", \"name\": null, \"needs_clarification\": \"Which medication did you take?\", \"confidence\": 0.6}}\n\n6. User: \"i took my 50mg spiro\"\n {{\"interaction_type\": \"medication\", \"action\": \"take\", \"name\": \"spiro\", \"dosage\": 50, \"unit\": \"mg\", \"confidence\": 0.9}}\n\n7. User: \"skip my wellbutrin today\"\n {{\"interaction_type\": \"medication\", \"action\": \"skip\", \"name\": \"wellbutrin\", \"confidence\": 0.9}}\n\n8. User: \"snooze my spironolactone reminder for 30 minutes\"\n {{\"interaction_type\": \"medication\", \"action\": \"snooze\", \"name\": \"spironolactone\", \"minutes\": 30, \"confidence\": 0.95}}\n\nRoutine examples:\n1. User: \"create morning routine with brush teeth, shower, eat\"\n {{\"interaction_type\": \"routine\", \"action\": \"create_with_steps\", \"name\": \"morning\", \"steps\": [\"brush teeth\", \"shower\", \"eat\"], \"confidence\": 0.95}}\n\n2. User: \"start my morning routine\"\n {{\"interaction_type\": \"routine\", \"action\": \"start\", \"name\": \"morning\", \"confidence\": 0.9}}\n\n3. User: \"done with step 3\"\n {{\"interaction_type\": \"routine\", \"action\": \"advance_step\", \"confidence\": 0.9}}\n\n4. User: \"skip this step\"\n {{\"interaction_type\": \"routine\", \"action\": \"skip_step\", \"confidence\": 0.9}}\n\n5. User: \"pause my routine\"\n {{\"interaction_type\": \"routine\", \"action\": \"pause\", \"confidence\": 0.9}}\n\nKnowledge examples:\n1. User: \"what does the book say about time management?\"\n {{\"interaction_type\": \"knowledge\", \"action\": \"query\", \"query\": \"time management\", \"confidence\": 0.9}}\n\n2. User: \"ask atomic habits about habit formation\"\n {{\"interaction_type\": \"knowledge\", \"action\": \"query\", \"book\": \"atomic habits\", \"query\": \"habit formation\", \"confidence\": 0.95}}\n\n3. User: \"list available books\"\n {{\"interaction_type\": \"knowledge\", \"action\": \"list\", \"confidence\": 0.95}}\n\n4. User: \"select book 2\"\n {{\"interaction_type\": \"knowledge\", \"action\": \"select\", \"book\": \"2\", \"confidence\": 0.95}}\n\n5. User: \"what does taking charge of adult adhd say about sleep?\"\n {{\"interaction_type\": \"knowledge\", \"action\": \"query\", \"book\": \"taking charge of adult adhd\", \"query\": \"sleep\", \"confidence\": 0.95}}\n\n6. User: \"how do I handle ADHD at work according to the book?\"\n {{\"interaction_type\": \"knowledge\", \"action\": \"query\", \"query\": \"handling ADHD at work\", \"confidence\": 0.9}}" "user_template": "Parse this command into structured JSON.\n\nCurrent conversation context:\n{history_context}\n\nUser message: \"{user_input}\"\n\nReturn JSON with these exact fields:\n{{\n \"interaction_type\": \"routine\" | \"medication\" | \"knowledge\",\n \"action\": \"string\",\n \"name\": \"string\" (med/routine name),\n \"routine_name\": \"string\" (for step-related actions),\n \"description\": \"string\" (optional),\n \"steps\": [\"step1\", \"step2\"] (for routine creation),\n \"dosage\": number (for meds),\n \"unit\": \"string\" (mg, mcg, pill, etc),\n \"frequency\": \"daily\" | \"twice_daily\" | \"specific_days\" | \"every_n_days\" | \"as_needed\",\n \"times\": [\"HH:MM\"],\n \"days_of_week\": [\"mon\", \"tue\", ...],\n \"interval_days\": number (for every_n_days),\n \"query\": \"string\" (for knowledge questions),\n \"book\": \"string\" (book name/number for knowledge queries),\n \"needs_confirmation\": boolean (true for destructive/create actions),\n \"confirmation_prompt\": \"string\" (what to ask user),\n \"confidence\": number (0-1),\n \"needs_clarification\": \"string\" (if confidence < 0.8 or missing required fields)\n}}\n\n=== EXAMPLES ===\n\nMedication examples:\n1. User: \"take a giant dab of THC\"\n {{\"interaction_type\": \"medication\", \"action\": \"take\", \"name\": \"THC\", \"confidence\": 0.9}}\n\n2. User: \"add lsd 50 mcg daily at 9am\"\n {{\"interaction_type\": \"medication\", \"action\": \"add\", \"name\": \"lsd\", \"dosage\": 50, \"unit\": \"mcg\", \"frequency\": \"daily\", \"times\": [\"09:00\"], \"confidence\": 0.95}}\n\n3. User: \"add wellbutrin 150 mg twice daily\"\n {{\"interaction_type\": \"medication\", \"action\": \"add\", \"name\": \"wellbutrin\", \"dosage\": 150, \"unit\": \"mg\", \"frequency\": \"twice_daily\", \"times\": [\"08:00\", \"20:00\"], \"confidence\": 0.95}}\n\n4. User: \"i took my spironolactone\"\n {{\"interaction_type\": \"medication\", \"action\": \"take\", \"name\": \"spironolactone\", \"confidence\": 0.95}}\n\n5. User: \"took my meds\" or \"i took all my meds\" or \"all the due ones\" (batch - mark all pending doses as taken)\n {{\"interaction_type\": \"medication\", \"action\": \"take_all\", \"confidence\": 0.9}}\n\n6. User: \"i took my 50mg spiro\"\n {{\"interaction_type\": \"medication\", \"action\": \"take\", \"name\": \"spiro\", \"dosage\": 50, \"unit\": \"mg\", \"confidence\": 0.9}}\n\n7. User: \"skip my wellbutrin today\"\n {{\"interaction_type\": \"medication\", \"action\": \"skip\", \"name\": \"wellbutrin\", \"confidence\": 0.9}}\n\n8. User: \"snooze my spironolactone reminder for 30 minutes\"\n {{\"interaction_type\": \"medication\", \"action\": \"snooze\", \"name\": \"spironolactone\", \"minutes\": 30, \"confidence\": 0.95}}\n\nRoutine examples:\n1. User: \"create morning routine with brush teeth, shower, eat\"\n {{\"interaction_type\": \"routine\", \"action\": \"create_with_steps\", \"name\": \"morning\", \"steps\": [\"brush teeth\", \"shower\", \"eat\"], \"confidence\": 0.95}}\n\n2. User: \"start my morning routine\"\n {{\"interaction_type\": \"routine\", \"action\": \"start\", \"name\": \"morning\", \"confidence\": 0.9}}\n\n3. User: \"done with step 3\"\n {{\"interaction_type\": \"routine\", \"action\": \"advance_step\", \"confidence\": 0.9}}\n\n4. User: \"skip this step\"\n {{\"interaction_type\": \"routine\", \"action\": \"skip_step\", \"confidence\": 0.9}}\n\n5. User: \"pause my routine\"\n {{\"interaction_type\": \"routine\", \"action\": \"pause\", \"confidence\": 0.9}}\n\nKnowledge examples:\n1. User: \"what does the book say about time management?\"\n {{\"interaction_type\": \"knowledge\", \"action\": \"query\", \"query\": \"time management\", \"confidence\": 0.9}}\n\n2. User: \"ask atomic habits about habit formation\"\n {{\"interaction_type\": \"knowledge\", \"action\": \"query\", \"book\": \"atomic habits\", \"query\": \"habit formation\", \"confidence\": 0.95}}\n\n3. User: \"list available books\"\n {{\"interaction_type\": \"knowledge\", \"action\": \"list\", \"confidence\": 0.95}}\n\n4. User: \"select book 2\"\n {{\"interaction_type\": \"knowledge\", \"action\": \"select\", \"book\": \"2\", \"confidence\": 0.95}}\n\n5. User: \"what does taking charge of adult adhd say about sleep?\"\n {{\"interaction_type\": \"knowledge\", \"action\": \"query\", \"book\": \"taking charge of adult adhd\", \"query\": \"sleep\", \"confidence\": 0.95}}\n\n6. User: \"how do I handle ADHD at work according to the book?\"\n {{\"interaction_type\": \"knowledge\", \"action\": \"query\", \"query\": \"handling ADHD at work\", \"confidence\": 0.9}}"
} }
}, },
"validation": { "validation": {

View File

@@ -423,6 +423,44 @@ async def handle_medication(message, session, parsed):
else: else:
await message.channel.send(f"Error: {resp.get('error', 'Failed to log')}") await message.channel.send(f"Error: {resp.get('error', 'Failed to log')}")
elif action == "take_all":
# Mark all currently pending (untaken, non-skipped, non-PRN) doses as taken
timezone_offset = await _get_user_timezone(message, session, token)
resp, status = api_request("get", "/api/medications/today", token)
if status != 200:
await message.channel.send("Error fetching today's medications.")
return
meds_today = resp if isinstance(resp, list) else []
marked = []
skipped_already = []
for item in meds_today:
med = item.get("medication", {})
if item.get("is_prn"):
continue
times = item.get("scheduled_times", [])
taken = set(item.get("taken_times", []))
skipped = set(item.get("skipped_times", []))
med_id_local = med.get("id")
med_name = med.get("name", "Unknown")
pending_times = [t for t in times if t not in taken and t not in skipped]
if not pending_times:
skipped_already.append(med_name)
continue
for t in pending_times:
api_request("post", f"/api/medications/{med_id_local}/take", token, {"scheduled_time": t})
marked.append(f"**{med_name}** ({', '.join(pending_times)})")
if not marked:
await message.channel.send("✅ All medications are already logged for today!")
else:
lines = "\n".join(f"{m}" for m in marked)
await message.channel.send(f"Logged as taken:\n{lines}")
elif action == "skip": elif action == "skip":
med_id = parsed.get("medication_id") med_id = parsed.get("medication_id")
name = parsed.get("name") name = parsed.get("name")
@@ -645,7 +683,7 @@ async def handle_medication(message, session, parsed):
else: else:
await message.channel.send( await message.channel.send(
f"Unknown action: {action}. Try: list, add, delete, take, skip, today, refills, snooze, or adherence." f"Unknown action: {action}. Try: list, add, delete, take, take_all, skip, today, refills, snooze, or adherence."
) )

View File

@@ -12,7 +12,7 @@ import json
from datetime import datetime, timedelta, time from datetime import datetime, timedelta, time
from typing import Optional, Dict, List, Tuple from typing import Optional, Dict, List, Tuple
import core.postgres as postgres import core.postgres as postgres
from core.tz import user_now from core.tz import user_now, user_today_for
def get_adaptive_settings(user_uuid: str) -> Optional[Dict]: def get_adaptive_settings(user_uuid: str) -> Optional[Dict]:
@@ -249,12 +249,12 @@ def should_send_nag(
if not presence.get("is_currently_online"): if not presence.get("is_currently_online"):
return False, "User offline" return False, "User offline"
# Get today's schedule record # Get today's schedule record for this specific time slot
today = current_time.date() today = current_time.date()
schedules = postgres.select( query = {"user_uuid": user_uuid, "medication_id": med_id, "adjustment_date": today}
"medication_schedules", if scheduled_time is not None:
{"user_uuid": user_uuid, "medication_id": med_id, "adjustment_date": today}, query["adjusted_time"] = scheduled_time
) schedules = postgres.select("medication_schedules", query)
if not schedules: if not schedules:
return False, "No schedule found" return False, "No schedule found"
@@ -295,7 +295,7 @@ def should_send_nag(
def record_nag_sent(user_uuid: str, med_id: str, scheduled_time: str): def record_nag_sent(user_uuid: str, med_id: str, scheduled_time: str):
"""Record that a nag was sent.""" """Record that a nag was sent."""
today = datetime.utcnow().date() today = user_today_for(user_uuid)
schedules = postgres.select( schedules = postgres.select(
"medication_schedules", "medication_schedules",
@@ -315,7 +315,7 @@ def record_nag_sent(user_uuid: str, med_id: str, scheduled_time: str):
def create_daily_schedule(user_uuid: str, med_id: str, base_times: List[str]): def create_daily_schedule(user_uuid: str, med_id: str, base_times: List[str]):
"""Create today's medication schedule with adaptive adjustments.""" """Create today's medication schedule with adaptive adjustments."""
today = datetime.utcnow().date() today = user_today_for(user_uuid)
# Check if schedule already exists # Check if schedule already exists
existing = postgres.select( existing = postgres.select(
@@ -346,7 +346,7 @@ def create_daily_schedule(user_uuid: str, med_id: str, base_times: List[str]):
def mark_med_taken(user_uuid: str, med_id: str, scheduled_time: str): def mark_med_taken(user_uuid: str, med_id: str, scheduled_time: str):
"""Mark a medication as taken.""" """Mark a medication as taken."""
today = datetime.utcnow().date() today = user_today_for(user_uuid)
postgres.update( postgres.update(
"medication_schedules", "medication_schedules",