# -*- coding: utf-8 -*- """ Conversation Manager for מראות (Mirrors) - Hebrew Self-Reflective AI Agent Handles conversation context, history, and session state management """ from typing import Dict, List, Optional, Tuple from dataclasses import dataclass import json @dataclass class ConversationState: """Tracks the current conversation state""" user_context: Optional[str] = None selected_part: Optional[str] = None persona_name: Optional[str] = None persona_age: Optional[str] = None persona_style: Optional[str] = None conversation_history: List[Dict] = None initial_prompt_choice: Optional[str] = None def __post_init__(self): if self.conversation_history is None: self.conversation_history = [] class ConversationManager: """Manages conversation flow and context for the מראות application""" def __init__(self, max_history_length: int = 50): """ Initialize conversation manager Args: max_history_length: Maximum number of messages to keep in history """ self.max_history_length = max_history_length def create_new_session(self) -> ConversationState: """Create a new conversation session""" return ConversationState() def set_initial_context(self, state: ConversationState, prompt_choice: str, user_response: str) -> ConversationState: """ Set the initial context based on user's choice and response Args: state: Current conversation state prompt_choice: Which initial prompt was chosen user_response: User's response to the initial prompt """ state.initial_prompt_choice = prompt_choice state.user_context = user_response return state def set_selected_part(self, state: ConversationState, part_name: str, persona_name: Optional[str] = None, persona_age: Optional[str] = None, persona_style: Optional[str] = None) -> ConversationState: """ Set the selected part and its customization Args: state: Current conversation state part_name: Name of the selected part persona_name: Custom name for the persona persona_age: Custom age for the persona persona_style: Custom speaking style """ state.selected_part = part_name state.persona_name = persona_name state.persona_age = persona_age state.persona_style = persona_style return state def add_to_history(self, state: ConversationState, user_message: str, bot_response: str) -> ConversationState: """ Add a message exchange to conversation history Args: state: Current conversation state user_message: User's message bot_response: Bot's response """ # Add user message state.conversation_history.append({ "role": "user", "content": user_message }) # Add bot response state.conversation_history.append({ "role": "assistant", "content": bot_response }) # Trim history if too long if len(state.conversation_history) > self.max_history_length: # Remove oldest messages (keep pairs) messages_to_remove = len(state.conversation_history) - self.max_history_length # Make sure we remove in pairs if messages_to_remove % 2 == 1: messages_to_remove += 1 state.conversation_history = state.conversation_history[messages_to_remove:] return state def get_conversation_context(self, state: ConversationState) -> str: """ Get formatted conversation context for prompt generation Args: state: Current conversation state Returns: Formatted context string """ context_parts = [] if state.user_context: context_parts.append(f"הקשר ראשוני: {state.user_context}") if state.conversation_history: context_parts.append("היסטוריית השיחה:") for msg in state.conversation_history[-10:]: # Last 10 messages for context role = "משתמש" if msg["role"] == "user" else "חלק פנימי" context_parts.append(f"{role}: {msg['content']}") return "\n".join(context_parts) def format_history_for_display(self, state: ConversationState) -> List[Tuple[str, str]]: """ Format conversation history for Gradio display Args: state: Current conversation state Returns: List of (user_message, bot_response) tuples """ formatted_history = [] for i in range(0, len(state.conversation_history), 2): if i + 1 < len(state.conversation_history): user_msg = state.conversation_history[i]["content"] bot_msg = state.conversation_history[i + 1]["content"] formatted_history.append((user_msg, bot_msg)) return formatted_history def get_session_summary(self, state: ConversationState) -> Dict: """ Get a summary of the current session Args: state: Current conversation state Returns: Dictionary with session summary """ return { "has_context": bool(state.user_context), "selected_part": state.selected_part, "persona_name": state.persona_name, "conversation_length": len(state.conversation_history), "initial_choice": state.initial_prompt_choice } def clear_conversation(self, state: ConversationState) -> ConversationState: """ Clear conversation history while keeping context and part selection Args: state: Current conversation state Returns: State with cleared conversation history """ state.conversation_history = [] return state def reset_session(self, state: ConversationState) -> ConversationState: """ Reset the entire session to start fresh Args: state: Current conversation state Returns: Fresh conversation state """ return ConversationState() def is_session_ready(self, state: ConversationState) -> bool: """ Check if session is ready for conversation (has context and selected part) Args: state: Current conversation state Returns: True if ready for conversation """ return bool(state.user_context and state.selected_part) def get_gradio_history(self, state: ConversationState) -> List[List[str]]: """ Format conversation history for Gradio ChatInterface Args: state: Current conversation state Returns: List of [user_message, bot_response] pairs for Gradio """ gradio_history = [] for i in range(0, len(state.conversation_history), 2): if i + 1 < len(state.conversation_history): user_msg = state.conversation_history[i]["content"] bot_msg = state.conversation_history[i + 1]["content"] gradio_history.append([user_msg, bot_msg]) return gradio_history