"""内驱力数据访问(好奇问题 + 探索性次生目标)。""" from sqlalchemy import func, select from sqlalchemy.ext.asyncio import AsyncSession from app.models.drive import CuriosityQuestion, ExploratorySubgoal async def add_curiosities(session: AsyncSession, curiosities: list[CuriosityQuestion]) -> None: session.add_all(curiosities) await session.flush() async def get_curiosity(session: AsyncSession, curiosity_id: str) -> CuriosityQuestion | None: return await session.get(CuriosityQuestion, curiosity_id) async def list_curiosities( session: AsyncSession, character_id: str, *, source: str | None = None, page: int = 1, page_size: int = 20, ) -> tuple[list[CuriosityQuestion], int]: conditions = [CuriosityQuestion.character_id == character_id] if source is not None: conditions.append(CuriosityQuestion.source == source) total = ( await session.execute( select(func.count()).select_from(CuriosityQuestion).where(*conditions) ) ).scalar_one() items = await session.execute( select(CuriosityQuestion) .where(*conditions) .order_by(CuriosityQuestion.created_at.desc()) .offset(max(page - 1, 0) * page_size) .limit(page_size) ) return list(items.scalars().all()), int(total or 0) async def add_subgoals(session: AsyncSession, subgoals: list[ExploratorySubgoal]) -> None: session.add_all(subgoals) await session.flush() async def get_subgoal(session: AsyncSession, subgoal_id: str) -> ExploratorySubgoal | None: return await session.get(ExploratorySubgoal, subgoal_id) async def list_subgoals( session: AsyncSession, character_id: str, *, status: str | None = None, page: int = 1, page_size: int = 20, ) -> tuple[list[ExploratorySubgoal], int]: conditions = [ExploratorySubgoal.character_id == character_id] if status is not None: conditions.append(ExploratorySubgoal.status == status) total = ( await session.execute( select(func.count()).select_from(ExploratorySubgoal).where(*conditions) ) ).scalar_one() items = await session.execute( select(ExploratorySubgoal) .where(*conditions) .order_by(ExploratorySubgoal.created_at.desc()) .offset(max(page - 1, 0) * page_size) .limit(page_size) ) return list(items.scalars().all()), int(total or 0) async def list_approved_subgoals( session: AsyncSession, character_id: str, limit: int = 5, ) -> list[ExploratorySubgoal]: """列出已批准(approved)的次生目标,按 created_at 升序排列。 供大周天自主探索执行阶段拾取。 """ result = await session.execute( select(ExploratorySubgoal) .where( ExploratorySubgoal.character_id == character_id, ExploratorySubgoal.status == "approved", ) .order_by(ExploratorySubgoal.created_at.asc()) .limit(limit) ) return list(result.scalars().all())