""" LucyDOM model classes for the workflow and document system. """ from pydantic import BaseModel, Field from typing import List, Dict, Any, Optional from datetime import datetime class Label(BaseModel): """Label for an attribute or a class with support for multiple languages""" default: str translations: Dict[str, str] = {} def getLabel(self, language: str = None): """Returns the label in the specified language, or the default value if not available""" if language and language in self.translations: return self.translations[language] return self.default class Prompt(BaseModel): """Data model for a prompt""" id: int = Field(description="Unique ID of the prompt") mandateId: int = Field(description="ID of the associated mandate") userId: int = Field(description="ID of the creator") content: str = Field(description="Content of the prompt") name: str = Field(description="Display name of the prompt") label: Label = Field( default=Label(default="Prompt", translations={"en": "Prompt", "fr": "Invite"}), description="Label for the class" ) # Labels for attributes fieldLabels: Dict[str, Label] = { "id": Label(default="ID", translations={}), "mandateId": Label(default="Mandate ID", translations={"en": "Mandate ID", "fr": "ID de mandat"}), "userId": Label(default="User ID", translations={"en": "User ID", "fr": "ID d'utilisateur"}), "content": Label(default="Content", translations={"en": "Content", "fr": "Contenu"}), "name": Label(default="Name", translations={"en": "Label", "fr": "Nom"}) } class FileItem(BaseModel): """Data model for a file""" id: int = Field(description="Unique ID of the data object") mandateId: int = Field(description="ID of the associated mandate") userId: int = Field(description="ID of the creator") name: str = Field(description="Name of the data object") mimeType: str = Field(description="Type of the data object MIME type") size: Optional[int] = Field(None, description="Size of the data object in bytes") fileHash: str = Field(description="Hash code for deduplication") creationDate: Optional[str] = Field(None, description="Upload date") workflowId: Optional[str] = Field(None, description="ID of the associated workflow, if any") label: Label = Field( default=Label(default="Data Object", translations={"en": "Data Object", "fr": "Objet de données"}), description="Label for the class" ) # Labels for attributes fieldLabels: Dict[str, Label] = { "id": Label(default="ID", translations={}), "mandateId": Label(default="Mandate ID", translations={"en": "Mandate ID", "fr": "ID de mandat"}), "userId": Label(default="User ID", translations={"en": "User ID", "fr": "ID d'utilisateur"}), "name": Label(default="Name", translations={"en": "Name", "fr": "Nom"}), "mimeType": Label(default="Type", translations={"en": "Type", "fr": "Type"}), "size": Label(default="Size", translations={"en": "Size", "fr": "Taille"}), "fileHash": Label(default="File Hash", translations={"en": "Hash", "fr": "Hash"}), "creationDate": Label(default="Upload date", translations={"en": "Upload date", "fr": "Date de téléchargement"}), "workflowId": Label(default="Workflow ID", translations={"en": "Workflow ID", "fr": "ID du workflow"}) } class FileData(BaseModel): """Data model for file content""" id: int = Field(description="Unique ID of the data object") data: str = Field(description="content of the file, text or base64 encoded based on base64Encoded flag") base64Encoded: bool = Field(description="Flag indicating whether the data is base64 encoded") class MsftToken(BaseModel): """Data model for Microsoft authentication tokens""" id: int = Field(description="Unique ID of the token") mandateId: int = Field(description="ID of the associated mandate") userId: int = Field(description="ID of the user") token_data: str = Field(description="JSON string containing the token data") created_at: str = Field(description="Timestamp when the token was created") updated_at: str = Field(description="Timestamp when the token was last updated") label: Label = Field( default=Label(default="Microsoft Token", translations={"en": "Microsoft Token", "fr": "Jeton Microsoft"}), description="Label for the class" ) # Labels for attributes fieldLabels: Dict[str, Label] = { "id": Label(default="ID", translations={}), "mandateId": Label(default="Mandate ID", translations={"en": "Mandate ID", "fr": "ID de mandat"}), "userId": Label(default="User ID", translations={"en": "User ID", "fr": "ID d'utilisateur"}), "token_data": Label(default="Token Data", translations={"en": "Token Data", "fr": "Données du jeton"}), "created_at": Label(default="Created At", translations={"en": "Created At", "fr": "Créé le"}), "updated_at": Label(default="Updated At", translations={"en": "Updated At", "fr": "Mis à jour le"}) } # Workflow model classes class DocumentContent(BaseModel): """Content of a document in the workflow""" sequenceNr: int = Field(1, description="Sequence number of the content in the source document") name: str = Field(description="Designation") ext: str = Field(description="Content extension for export: txt, csv, json, jpg, png") mimeType: str = Field(description="MIME type") summary: str = Field(description="Summary of the file content") data: str = Field(description="Actual content, text or base64 encoded based on base64Encoded flag") base64Encoded: bool = Field(description="Flag indicating whether the data is base64 encoded") metadata: Dict[str, Any] = Field(default_factory=dict, description="Metadata about the content, such as isText flag, format information, encoding, etc.") class Document(BaseModel): """Document in the workflow - References a file directly in the database""" id: str = Field(description="Unique ID of the document") name: str = Field(description="Name of the data object") ext: str = Field(description="Extension of the data object") fileId: int = Field(description="ID of the referenced file in the database") mimeType: str = Field(description="MIME type") data: str = Field(description="Content of the data as text or base64 encoded based on base64Encoded flag") base64Encoded: bool = Field(description="Flag indicating whether the data is base64 encoded") contents: List[DocumentContent] = Field(description="Document contents") class DataStats(BaseModel): """Statistics for performance and data usage""" processingTime: Optional[float] = Field(None, description="Processing time in seconds") tokenCount: Optional[int] = Field(None, description="Token count (for AI models)") bytesSent: Optional[int] = Field(None, description="Bytes sent") bytesReceived: Optional[int] = Field(None, description="Bytes received") class WorkflowMessage(BaseModel): """Message object in the workflow""" id: str = Field(description="Unique ID of the message") workflowId: str = Field(description="Reference to the parent workflow") parentMessageId: Optional[str] = Field(None, description="Reference to the replied message") startedAt: str = Field(description="Timestamp for message creation") finishedAt: Optional[str] = Field(None, description="Timestamp for message completion") sequenceNo: int = Field(description="Sequence number for sorting") status: str = Field(description="Status of the message ('first', 'step', 'last')") role: str = Field(description="Role of the sender ('system', 'user', 'assistant')") dataStats: Optional[DataStats] = Field(None, description="Statistics") documents: Optional[List[Document]] = Field(None, description="Documents in this message (references to files in the database)") content: Optional[str] = Field(None, description="Text content of the message") agentName: Optional[str] = Field(None, description="Name of the agent used") class WorkflowLog(BaseModel): """Log entry for a workflow""" id: str = Field(description="Unique ID of the log entry") workflowId: str = Field(description="ID of the associated workflow") message: str = Field(description="Log message content") type: str = Field(description="Type of log ('info', 'warning', 'error')") timestamp: str = Field(description="Timestamp of the log entry") agentName: str = Field(description="Name of the agent that created the log") status: str = Field(description="Status of the workflow at log time") progress: Optional[int] = Field(None, description="Progress value (0-100)") mandateId: Optional[int] = Field(None, description="ID of the mandate") userId: Optional[int] = Field(None, description="ID of the user") class Workflow(BaseModel): """Workflow object for multi-agent system""" id: str = Field(description="Unique ID of the workflow") name: Optional[str] = Field(None, description="Name of the workflow") mandateId: int = Field(description="ID of the mandate") userId: int = Field(description="ID of the user") status: str = Field(description="Status of the workflow ('running', 'completed', 'failed', 'stopped')") startedAt: str = Field(description="Start timestamp") lastActivity: str = Field(description="Timestamp of the last activity") dataStats: Optional[Dict[str, Any]] = Field(None, description="Total statistics") currentRound: int = Field(default=1, description="Current round/iteration of the workflow") messageIds: List[str] = Field(default=[], description="List of message IDs in this workflow") messages: List[WorkflowMessage] = Field(default=[], description="Message history (in-memory representation)") logs: List[WorkflowLog] = Field(default=[], description="Log entries (in-memory representation)") # Agent and Workflow Task Models class AgentResult(BaseModel): """Result structure returned by agent processing""" feedback: str = Field(description="Text response explaining what the agent did") documents: List[Document] = Field(default=[], description="List of document objects created by the agent") label: Label = Field( default=Label(default="Agent Result", translations={"en": "Agent Result", "fr": "Résultat d'agent"}), description="Label for the class" ) class AgentInfo(BaseModel): """Information about an agent's capabilities""" name: str = Field(description="Name of the agent") description: str = Field(description="Description of the agent's functionality") capabilities: List[str] = Field(default=[], description="List of agent capabilities") label: Label = Field( default=Label(default="Agent Information", translations={"en": "Agent Information", "fr": "Information d'agent"}), description="Label for the class" ) class InputDocument(BaseModel): """Input document specification for a task""" label: str = Field(description="Document label in the format 'filename.ext'") fileId: Optional[int] = Field(None, description="ID of the existing document if referring to one") contentPart: str = Field(default="", description="Content part to focus on, empty string for all contents") prompt: str = Field(description="AI prompt to describe what data to extract from the file") class OutputDocument(BaseModel): """Output document specification for a task""" label: str = Field(description="Document label in the format 'filename.ext'") prompt: str = Field(description="AI prompt to describe the content of the file") class TaskItem(BaseModel): """Individual task in the workplan""" agent: str = Field(description="Name of an available agent") prompt: str = Field(description="Specific instructions to the agent, that he knows what to do with which documents and which output to provide") outputDocuments: List[OutputDocument] = Field(default=[], description="List of required output documents") inputDocuments: List[InputDocument] = Field(default=[], description="List of input documents to process") label: Label = Field( default=Label(default="Task Item", translations={"en": "Task Item", "fr": "Élément de tâche"}), description="Label for the class" ) class TaskPlan(BaseModel): """Work plan created by project manager""" objFinalDocuments: List[str] = Field(default=[], description="List of required result documents") objWorkplan: List[TaskItem] = Field(default=[], description="Plan for executing agents") objUserResponse: str = Field(description="Response to the user explaining the plan") userLanguage: str = Field(default="en", description="Language code of the user's request") label: Label = Field( default=Label(default="Task Plan", translations={"en": "Task Plan", "fr": "Plan de tâches"}), description="Label for the class" ) class WorkflowStatus(BaseModel): """Workflow status messages""" init: str = Field(default="Workflow initialized") running: str = Field(default="Running workflow") waiting: str = Field(default="Waiting for input") completed: str = Field(default="Workflow completed successfully") stopped: str = Field(default="Workflow stopped by user") failed: str = Field(default="Error in workflow") label: Label = Field( default=Label(default="Workflow Status", translations={"en": "Workflow Status", "fr": "État du workflow"}), description="Label for the class" ) # Request models for the API class UserInputRequest(BaseModel): """Request for user input to a running workflow""" prompt: str = Field(description="Message from the user") listFileId: List[int] = Field(default=[], description="List of FileItem IDs")