""" Turn engine — constructs a bot's prompt and executes its LLM call. Handles rectification slot reservation and filling. """ import logging from typing import TYPE_CHECKING if TYPE_CHECKING: from fellowship.core.session import Session, BotConfig, Message logger = logging.getLogger(__name__) class TurnEngine: def __init__(self, session: "Session") -> None: self.session = session async def execute_turn(self, bot: "BotConfig") -> "Message": """ Full turn pipeline for one bot: 1. Reserve a rectification slot in history. 2. Assemble the bot's prompt (global system + bot system + context). 3. Call the LLM. 4. Fill the reserved slot with the response. 5. Return the completed Message. """ raise NotImplementedError def _reserve_slot(self, bot: "BotConfig") -> int: """ Append a placeholder Message (content=None) to history and return its index. This is the rectification slot — talker messages arriving during generation are inserted after this index. """ raise NotImplementedError def _fill_slot(self, index: int, content: str, tokens: int) -> None: """Fill a previously reserved slot with the completed bot response.""" raise NotImplementedError def _build_prompt(self, bot: "BotConfig") -> list[dict]: """ Assemble the messages list for the LLM call: - System message: global_system_prompt + bot system_prompt - User/assistant messages from context (messages only, no foreign system prompts) """ raise NotImplementedError