import logging import importlib import pkgutil import inspect from typing import Dict, Any, List, Optional from modules.interfaces.serviceAppClass import User from modules.interfaces.serviceChatModel import ( TaskStatus, ChatDocument, TaskItem, TaskAction, TaskResult, ChatStat, ChatLog, ChatMessage, ChatWorkflow, UserConnection ) from modules.interfaces.interfaceAi import interfaceAi from modules.interfaces.serviceChatClass import getInterface as getChatInterface from modules.interfaces.serviceManagementClass import getInterface as getFileInterface from modules.workflow.managerDocument import DocumentManager from modules.methods.methodBase import MethodBase logger = logging.getLogger(__name__) class ServiceContainer: """Service container that provides access to all services and their functions""" def __init__(self, currentUser: User, workflow: ChatWorkflow): # Core services self.user = currentUser self.workflow = workflow self.tasks = workflow.tasks self.statusEnums = TaskStatus # Initialize managers self.interfaceChat = getChatInterface(currentUser) self.interfaceFiles = getFileInterface(currentUser) self.interfaceAi = interfaceAi() self.documentManager = DocumentManager(self) # Initialize methods catalog self.methods = None # Discover additional methods self._discoverMethods() def _discoverMethods(self): """Dynamically discover all method classes in modules.methods package""" try: # Import the methods package methodsPackage = importlib.import_module('modules.methods') # Discover all modules in the package for _, name, isPkg in pkgutil.iter_modules(methodsPackage.__path__): if not isPkg and name.startswith('method'): try: # Import the module module = importlib.import_module(f'modules.methods.{name}') # Find all classes in the module that inherit from MethodBase for itemName, item in inspect.getmembers(module): if (inspect.isclass(item) and issubclass(item, MethodBase) and item != MethodBase): # Instantiate the method and add to service methodInstance = item() self.methods[methodInstance.name] = methodInstance logger.info(f"Discovered method: {methodInstance.name}") except Exception as e: logger.error(f"Error loading method module {name}: {str(e)}") except Exception as e: logger.error(f"Error discovering methods: {str(e)}") # ===== Functions ===== def extractContent(self, prompt: str, document: ChatDocument) -> str: """Extract content from document using prompt""" return self.documentManager.extractContent(prompt, document) def getMethodsCatalog(self) -> Dict[str, Any]: """Get catalog of available methods""" return self.methods def getMethodsList(self) -> List[str]: """Get list of available methods""" return list(self.methods.keys()) def getDocumentReferenceList(self) -> Dict[str, List[Dict[str, str]]]: """Get list of document references sorted by datetime""" return { "chat": self._getChatDocumentReferences(), "history": self._getHistoryDocumentReferences() } def getDocumentReferenceFromChatDocument(self, document: ChatDocument) -> str: """Get document reference from ChatDocument""" return f"document_{document.id}_{document.filename}" def getDocumentReferenceFromTaskResult(self, result: TaskResult) -> str: """Get document reference from TaskResult""" return f"documentList_{result.id}_{result.documentsLabel}" def getChatDocumentsFromDocumentReference(self, documentReference: str) -> List[ChatDocument]: """Get ChatDocuments from document reference""" return self.documentManager.getDocumentsByReference(documentReference) def getConnectionReferenceList(self) -> List[Dict[str, str]]: """Get list of connection references sorted by authority""" return self._getConnectionReferences() def getConnectionReferenceFromUserConnection(self, connection: UserConnection) -> str: """Get connection reference from UserConnection""" return f"connection_{connection.id}_{connection.authority}" def getUserConnectionFromConnectionReference(self, reference: str) -> UserConnection: """Get UserConnection from connection reference""" return self._getUserConnectionByReference(reference) def getMessageSummary(self, message: ChatMessage) -> Dict[str, List[Dict[str, Any]]]: """Get message summary""" return { "chat": self._getChatMessageSummaries(), "history": self._getHistoryMessageSummaries() } def getFileData(self, fileId: str) -> bytes: """Get file data by ID""" return self.interfaceFiles.getFileData(fileId) def callAiBasic(self, prompt: str, context: str = None, complexityFlag: bool = False) -> str: """Call basic AI service""" return self.interfaceAi.callAiBasic(prompt, context, complexityFlag) def callAiImage(self, imageData: bytes, mimeType: str, prompt: str) -> str: """Call AI image service""" return self.interfaceAi.callAiImage(imageData, mimeType, prompt) def createFile(self, fileName: str, mimeType: str, content: bytes, base64encoded: bool = False) -> Dict[str, Any]: """Create new file""" return self.interfaceFiles.createFile(fileName, mimeType, content, base64encoded) def getFileInfo(self, fileId: str) -> Dict[str, Any]: """Get file information""" return self.interfaceFiles.getFileInfo(fileId) # ===== Private Methods ===== def _executeMethodAction(self, parameters: Dict[str, Any]) -> Any: """Execute method action with parameters""" method = parameters.get('method') action = parameters.get('action') if method in self.methods and action in self.methods[method]: return self.methods[method][action](**parameters.get('parameters', {})) raise ValueError(f"Unknown method or action: {method}.{action}") def _executeForEach(self, items: List[Any], action: callable) -> List[Any]: """Execute forEach operation""" results = [] for item in items: try: result = action(item) results.append(result) except Exception as e: logger.error(f"Error executing forEach action: {str(e)}") results.append(None) return results def _executeAiCall(self, prompt: str, documents: List[Dict[str, Any]]) -> List[Any]: """Execute AI call with documents""" try: # Process each document results = [] for doc in documents: content = self.extractContent(prompt, doc) results.append(content) return results except Exception as e: logger.error(f"Error executing AI call: {str(e)}") return [] def _executeSharePointQuery(self, connection: str, site_query: str, file_query: str, content_query: str) -> List[Dict[str, str]]: """Execute SharePoint query""" # TODO: Implement SharePoint query return [] def _executeSharePointDownload(self, connection: str, filepath: str) -> str: """Execute SharePoint download""" # TODO: Implement SharePoint download return "" def _getChatDocumentReferences(self) -> List[Dict[str, str]]: """Get chat document references""" # TODO: Implement chat document references return [] def _getHistoryDocumentReferences(self) -> List[Dict[str, str]]: """Get history document references""" # TODO: Implement history document references return [] def _getConnectionReferences(self) -> List[Dict[str, str]]: """Get connection references""" # TODO: Implement connection references return [] def _getUserConnectionByReference(self, reference: str) -> UserConnection: """Get user connection by reference""" # TODO: Implement user connection lookup pass def _getChatMessageSummaries(self) -> List[Dict[str, Any]]: """Get chat message summaries""" # TODO: Implement chat message summaries return [] def _getHistoryMessageSummaries(self) -> List[Dict[str, Any]]: """Get history message summaries""" # TODO: Implement history message summaries return [] # Create singleton instance serviceObject = None def initializeServiceContainer(currentUser: User, workflow: ChatWorkflow) -> ServiceContainer: """Initialize the service container singleton""" global serviceObject if serviceObject is None: serviceObject = ServiceContainer(currentUser, workflow) return serviceObject