import logging from typing import Dict, Any, List, Optional from modules.datamodels.datamodelUam import User, UserConnection from modules.datamodels.datamodelChat import ChatDocument, ChatMessage, ChatStat, ChatLog from modules.datamodels.datamodelAi import AiCallOptions, OperationTypeEnum, PriorityEnum, ProcessingModeEnum from modules.security.tokenManager import TokenManager from modules.shared.progressLogger import ProgressLogger logger = logging.getLogger(__name__) class ChatService: """Service class containing methods for document processing, chat operations, and workflow management""" def __init__(self, serviceCenter): self.services = serviceCenter self.user = serviceCenter.user # self.services.workflow is now the ChatWorkflow object (stable during workflow execution) self.interfaceDbChat = serviceCenter.interfaceDbChat self.interfaceDbComponent = serviceCenter.interfaceDbComponent self.interfaceDbApp = serviceCenter.interfaceDbApp self._progressLogger = None def getChatDocumentsFromDocumentList(self, documentList: List[str]) -> List[ChatDocument]: """Get ChatDocuments from a list of document references using all three formats.""" try: # Use self.services.workflow which is the ChatWorkflow object (stable during workflow execution) workflow = self.services.workflow if not workflow: logger.error("getChatDocumentsFromDocumentList: No workflow available (self.services.workflow is not set)") return [] workflow_id = workflow.id if hasattr(workflow, 'id') else 'NO_ID' workflow_obj_id = id(workflow) logger.debug(f"getChatDocumentsFromDocumentList: input documentList = {documentList}") logger.debug(f"getChatDocumentsFromDocumentList: using workflow.id = {workflow_id}, workflow object id = {workflow_obj_id}") # Debug: list available messages with their labels and document names try: if workflow and hasattr(workflow, 'messages') and workflow.messages: msg_lines = [] for message in workflow.messages: label = getattr(message, 'documentsLabel', None) doc_names = [] if getattr(message, 'documents', None): for doc in message.documents: name = getattr(doc, 'fileName', None) or getattr(doc, 'documentName', None) or 'Unnamed' doc_names.append(name) msg_lines.append( f"- id={getattr(message, 'id', None)}, label={label}, docs={doc_names}" ) if msg_lines: logger.debug("getChatDocumentsFromDocumentList: available messages:\n" + "\n".join(msg_lines)) else: logger.debug("getChatDocumentsFromDocumentList: no messages available on current workflow") except Exception as e: logger.debug(f"getChatDocumentsFromDocumentList: unable to enumerate messages for debug: {e}") all_documents = [] for doc_ref in documentList: if doc_ref.startswith("docItem:"): # docItem:: - extract ID and find document parts = doc_ref.split(':') if len(parts) >= 2: doc_id = parts[1] # Find the document by ID for message in workflow.messages: # Validate message belongs to this workflow msg_workflow_id = getattr(message, 'workflowId', None) if msg_workflow_id and msg_workflow_id != workflow_id: continue if message.documents: for doc in message.documents: if doc.id == doc_id: doc_name = getattr(doc, 'fileName', 'unknown') all_documents.append(doc) break elif doc_ref.startswith("docList:"): # docList::