"""Fire-and-forget AI usage logging service.""" import asyncio import uuid from typing import Optional from services.database import async_session_maker from utils.llm_context import get_llm_context def log( provider: str, model: str, call_type: str, input_tokens: Optional[int] = None, output_tokens: Optional[int] = None, total_tokens: Optional[int] = None, duration_ms: Optional[int] = None, user_id: Optional[uuid.UUID] = None, client_id: Optional[uuid.UUID] = None, presentation_id: Optional[uuid.UUID] = None, ) -> None: """Log AI usage asynchronously (fire-and-forget). If user_id/client_id/presentation_id are not provided, reads them from the LLMCallContext contextvar. """ ctx = get_llm_context() if ctx: user_id = user_id or ctx.user_id client_id = client_id or ctx.client_id presentation_id = presentation_id or ctx.presentation_id asyncio.create_task( _write_log( provider=provider, model=model, call_type=call_type, input_tokens=input_tokens, output_tokens=output_tokens, total_tokens=total_tokens, duration_ms=duration_ms, user_id=user_id, client_id=client_id, presentation_id=presentation_id, ) ) async def _write_log( provider: str, model: str, call_type: str, input_tokens: Optional[int], output_tokens: Optional[int], total_tokens: Optional[int], duration_ms: Optional[int], user_id: Optional[uuid.UUID], client_id: Optional[uuid.UUID], presentation_id: Optional[uuid.UUID], ) -> None: try: from models.sql.ai_usage import AIUsageModel async with async_session_maker() as session: entry = AIUsageModel( provider=provider, model=model, call_type=call_type, input_tokens=input_tokens, output_tokens=output_tokens, total_tokens=total_tokens or ((input_tokens or 0) + (output_tokens or 0)), duration_ms=duration_ms, user_id=user_id, client_id=client_id, presentation_id=presentation_id, ) session.add(entry) await session.commit() except Exception as e: print(f"AI usage log error: {e}")