diff --git a/app/jobs/email_digest_job.py b/app/jobs/email_digest_job.py index a2814a5..34bedc2 100644 --- a/app/jobs/email_digest_job.py +++ b/app/jobs/email_digest_job.py @@ -69,9 +69,15 @@ async def _already_sent_today(session, user_id: int, kind: str, today: datetime) return (await session.execute(stmt)).first() is not None -async def _generate_variants(client, kind: str, ctx: dict) -> dict[str, str]: +async def _generate_variants(session, client, kind: str, ctx: dict) -> dict[str, str]: """Returns {tone: html_content}. Missing tone means generation failed - for that variant — skip recipients on that tone.""" + for that variant — skip recipients on that tone. + + Persists an AICall row per attempt so digest LLM spend counts toward + the monthly cost cap on subsequent runs.""" + from app.models import AICall + from app.services.openrouter import active_model + builder = build_weekly_digest_prompt if kind == "weekly" else build_daily_digest_prompt out: dict[str, str] = {} for tone in ("NOVICE", "INTERMEDIATE"): @@ -83,10 +89,23 @@ async def _generate_variants(client, kind: str, ctx: dict) -> dict[str, str]: {"role": "user", "content": usr}], ) out[tone] = result.content + session.add(AICall( + model=result.model, + prompt_tokens=result.prompt_tokens, + completion_tokens=result.completion_tokens, + cost_usd=result.cost_usd, + status="ok", + )) + await session.commit() log.info("digest.variant_ok", kind=kind, tone=tone, prompt_tokens=result.prompt_tokens, completion_tokens=result.completion_tokens) except Exception as e: + session.add(AICall( + model=active_model(), status="error", + error=f"{kind}/{tone}: {str(e)[:480]}", + )) + await session.commit() log.error("digest.variant_failed", kind=kind, tone=tone, error=str(e)[:200]) return out @@ -173,7 +192,7 @@ async def run() -> None: ) async with httpx.AsyncClient(follow_redirects=True) as client: - variants = await _generate_variants(client, kind, ctx) + variants = await _generate_variants(session, client, kind, ctx) if not variants: log.warning("digest.all_variants_failed", kind=kind)