"""Daily job: proactive health review for all users with health data.""" import asyncio import json import logging from anthropic import AsyncAnthropic from sqlalchemy import select from app.config import settings from app.database import async_session_factory from app.models.user import User from app.services.memory_service import get_critical_memories from app.services.notification_service import create_notification from app.services.ws_manager import manager logger = logging.getLogger(__name__) client = AsyncAnthropic(api_key=settings.ANTHROPIC_API_KEY) async def run_daily_health_review(): """Review each user's health profile and generate reminder notifications.""" if not settings.ANTHROPIC_API_KEY: return async with async_session_factory() as db: result = await db.execute(select(User).where(User.is_active == True)) # noqa: E712 users = result.scalars().all() for user in users: try: await _review_user(user) await asyncio.sleep(1) # Rate limit except Exception: logger.exception(f"Health review failed for user {user.id}") async def _review_user(user: User): async with async_session_factory() as db: memories = await get_critical_memories(db, user.id) if not memories: return memory_text = "\n".join(f"- [{m.category}] {m.title}: {m.content}" for m in memories) response = await client.messages.create( model=settings.CLAUDE_MODEL, max_tokens=500, system="You are a health assistant. Based on the user's health profile, suggest any upcoming checkups, medication reviews, or health actions that should be reminded. Respond with a JSON array of objects with 'title' and 'body' fields. If no reminders are needed, return an empty array [].", messages=[{"role": "user", "content": f"User health profile:\n{memory_text}"}], ) try: text = response.content[0].text.strip() # Extract JSON from response if "[" in text: json_str = text[text.index("["):text.rindex("]") + 1] reminders = json.loads(json_str) else: return except (json.JSONDecodeError, ValueError): return for reminder in reminders[:5]: # Max 5 reminders per user per day if "title" in reminder and "body" in reminder: notif = await create_notification( db, user.id, title=reminder["title"], body=reminder["body"], type="ai_generated", ) await db.commit() from app.workers.notification_sender import _serialize_notification await manager.send_to_user(user.id, { "type": "new_notification", "notification": _serialize_notification(notif), })