import logging from typing import Dict, Any, Optional, List, Union from datetime import datetime, UTC import json import uuid import time from modules.interfaces.interfaceAppModel import User from modules.interfaces.interfaceChatModel import ( TaskStatus, ChatDocument, TaskItem, TaskAction, TaskResult, ChatStat, ChatLog, ChatMessage, ChatWorkflow ) from modules.workflow.serviceContainer import ServiceContainer logger = logging.getLogger(__name__) class ChatManager: """Chat manager with improved AI integration and method handling""" def __init__(self, currentUser: User): self.currentUser = currentUser self.service: ServiceContainer = None self.workflow: ChatWorkflow = None # ===== Initialization and Setup ===== async def initialize(self, workflow: ChatWorkflow) -> None: """Initialize chat manager with workflow""" self.workflow = workflow self.service = ServiceContainer(self.currentUser, self.workflow) # ===== Task Creation and Management ===== async def createInitialTask(self, workflow: ChatWorkflow, initialMessage: ChatMessage) -> Optional[TaskItem]: """Create the initial task from the first message""" try: # Create task definition prompt prompt = await self._createTaskDefinitionPrompt(initialMessage.message, workflow) # Get AI response response = await self.service.callAiTextAdvanced(prompt) # Parse response try: taskDef = json.loads(response) except json.JSONDecodeError: logger.error(f"Invalid JSON in task definition: {response}") return None # Validate task definition if not isinstance(taskDef, dict): logger.error("Task definition must be a JSON object") return None requiredFields = ["status", "feedback", "actions"] for field in requiredFields: if field not in taskDef: logger.error(f"Missing required field: {field}") return None if not isinstance(taskDef["actions"], list): logger.error("Actions must be a list") return None # Create task task = TaskItem( id=str(uuid.uuid4()), workflow=workflow, userInput=initialMessage.message, status=taskDef["status"], feedback=taskDef["feedback"], actions=[] ) # Add actions for actionDef in taskDef["actions"]: if not isinstance(actionDef, dict): continue requiredFields = ["method", "action", "parameters"] if not all(field in actionDef for field in requiredFields): continue action = TaskAction( id=str(uuid.uuid4()), method=actionDef["method"], action=actionDef["action"], parameters=actionDef["parameters"], resultLabel=actionDef.get("resultLabel") ) task.actions.append(action) return task except Exception as e: logger.error(f"Error creating initial task: {str(e)}") return None async def createNextTask(self, workflow: ChatWorkflow, previousResult: TaskResult) -> Optional[TaskItem]: """Create next task based on previous result""" try: # Check if previous result was successful if not previousResult.success: logger.error(f"Previous task failed: {previousResult.error}") return None # Create task definition prompt prompt = await self._createTaskDefinitionPrompt(previousResult.feedback, workflow) # Get AI response response = await self.service.callAiTextAdvanced(prompt) # Parse response try: taskDef = json.loads(response) except json.JSONDecodeError: logger.error(f"Invalid JSON in task definition: {response}") return None # Validate task definition if not isinstance(taskDef, dict): logger.error("Task definition must be a JSON object") return None requiredFields = ["status", "feedback", "actions"] for field in requiredFields: if field not in taskDef: logger.error(f"Missing required field: {field}") return None if not isinstance(taskDef["actions"], list): logger.error("Actions must be a list") return None # Create task task = TaskItem( id=str(uuid.uuid4()), workflow=workflow, userInput=previousResult.feedback, status=taskDef["status"], feedback=taskDef["feedback"], actions=[] ) # Add actions for actionDef in taskDef["actions"]: if not isinstance(actionDef, dict): continue requiredFields = ["method", "action", "parameters"] if not all(field in actionDef for field in requiredFields): continue action = TaskAction( id=str(uuid.uuid4()), method=actionDef["method"], action=actionDef["action"], parameters=actionDef["parameters"], resultLabel=actionDef.get("resultLabel") ) task.actions.append(action) return task except Exception as e: logger.error(f"Error creating next task: {str(e)}") return None async def executeTask(self, task: TaskItem) -> TaskItem: """Execute a task's actions""" try: # Execute each action for action in task.actions: # Create action prompt prompt = f"""Execute the following action: Action: {action.method}.{action.action} Parameters: {json.dumps(action.parameters)} Please provide a JSON response with: 1. result: The result of the action 2. resultLabel: A label for the result (format: documentList__