import logging import uuid 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.datamodelChat import ChatContentExtracted from modules.services.serviceExtraction.mainServiceExtraction import ExtractionService from modules.services.serviceGeneration.subDocumentUtility import getFileExtension, getMimeTypeFromExtension, detectContentTypeFromData from modules.shared.timezoneUtils import get_utc_timestamp from modules.security.tokenManager import TokenManager from modules.shared.progressLogger import ProgressLogger logger = logging.getLogger(__name__) class WorkflowService: """Service class containing methods for document processing, chat operations, and workflow management""" def __init__(self, serviceCenter): self.services = serviceCenter self.user = serviceCenter.user self.workflow = serviceCenter.workflow self.interfaceDbChat = serviceCenter.interfaceDbChat self.interfaceDbComponent = serviceCenter.interfaceDbComponent self.interfaceDbApp = serviceCenter.interfaceDbApp async def summarizeChat(self, messages: List[ChatMessage]) -> str: """ Summarize chat messages from last to first message with status="first" Args: messages: List of chat messages to summarize Returns: str: Summary of the chat in user's language """ try: # Get messages from last to first, stopping at first message with status="first" relevantMessages = [] for msg in reversed(messages): relevantMessages.append(msg) if msg.status == "first": break # Create prompt for AI prompt = f""" You are an AI assistant providing a summary of a chat conversation. Please respond in '{self.user.language}' language. Chat History: {chr(10).join(f"- {msg.message}" for msg in reversed(relevantMessages))} Instructions: 1. Summarize the conversation's key points and outcomes 2. Be concise but informative 3. Use a professional but friendly tone 4. Focus on important decisions and next steps if any LOOP_INSTRUCTION Please provide a comprehensive summary of this conversation.""" # Get summary using AI service through proper main service interface return await self.services.ai.callAiDocuments( prompt=prompt, documents=None, options={ "process_type": "text", "operation_type": "generate_content", "priority": "speed", "compress_prompt": True, "compress_documents": False, "max_cost": 0.01 } ) except Exception as e: logger.error(f"Error summarizing chat: {str(e)}") return f"Error summarizing chat: {str(e)}" def getChatDocumentsFromDocumentList(self, documentList: List[str]) -> List[ChatDocument]: """Get ChatDocuments from a list of document references using all three formats.""" try: workflow = self.services.currentWorkflow logger.debug(f"getChatDocumentsFromDocumentList: input documentList = {documentList}") logger.debug(f"getChatDocumentsFromDocumentList: currentWorkflow.id = {workflow.id if workflow and hasattr(workflow, 'id') else 'NO_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: 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::