from pydantic import BaseModel, Field from typing import List, Dict, Any, Optional from datetime import datetime class Label(BaseModel): """Label für ein Attribut oder eine Klasse mit Unterstützung für mehrere Sprachen""" default: str translations: Dict[str, str] = {} def get_label(self, language: str = None): """Gibt das Label in der angegebenen Sprache zurück, oder den Standardwert wenn nicht verfügbar""" if language and language in self.translations: return self.translations[language] return self.default class FileItem(BaseModel): """Datenmodell für ein Datenobjekt""" id: int = Field(description="Eindeutige ID des Datenobjekts") mandate_id: int = Field(description="ID des zugehörigen Mandanten") user_id: int = Field(description="ID des Erstellers") name: str = Field(description="Name des Datenobjekts") type: str = Field(description="Typ des Datenobjekts ('document', 'image', etc.)") size: Optional[str] = Field(None, description="Größe des Datenobjekts") upload_date: Optional[str] = Field(None, description="Datum des Hochladens") content_type: Optional[str] = Field(None, description="Content-Type des Datenobjekts") path: Optional[str] = Field(None, description="Pfad zum Datenobjekt") label: Label = Field( default=Label(default="Datenobjekt", translations={"en": "Data Object", "fr": "Objet de données"}), description="Label für die Klasse" ) # Labels für Attribute field_labels: Dict[str, Label] = { "id": Label(default="ID", translations={}), "mandate_id": Label(default="Mandanten-ID", translations={"en": "Mandate ID", "fr": "ID de mandat"}), "user_id": Label(default="Benutzer-ID", translations={"en": "User ID", "fr": "ID d'utilisateur"}), "name": Label(default="Name", translations={"en": "Name", "fr": "Nom"}), "type": Label(default="Typ", translations={"en": "Type", "fr": "Type"}), "size": Label(default="Größe", translations={"en": "Size", "fr": "Taille"}), "upload_date": Label(default="Upload-Datum", translations={"en": "Upload date", "fr": "Date de téléchargement"}), "content_type": Label(default="Content-Type", translations={"en": "Content type", "fr": "Type de contenu"}), "path": Label(default="Pfad", translations={"en": "Path", "fr": "Chemin"}) } class Prompt(BaseModel): """Datenmodell für einen Prompt""" id: int = Field(description="Eindeutige ID des Prompts") mandate_id: int = Field(description="ID des zugehörigen Mandanten") user_id: int = Field(description="ID des Erstellers") content: str = Field(description="Inhalt des Prompts") name: str = Field(description="Anzeigename des Prompts") label: Label = Field( default=Label(default="Prompt", translations={"en": "Prompt", "fr": "Invite"}), description="Label für die Klasse" ) # Labels für Attribute field_labels: Dict[str, Label] = { "id": Label(default="ID", translations={}), "mandate_id": Label(default="Mandanten-ID", translations={"en": "Mandate ID", "fr": "ID de mandat"}), "user_id": Label(default="Benutzer-ID", translations={"en": "User ID", "fr": "ID d'utilisateur"}), "content": Label(default="Inhalt", translations={"en": "Content", "fr": "Contenu"}), "name": Label(default="Name", translations={"en": "Label", "fr": "Nom"}), } # Neue Workflow-Modellklassen class DocumentSource(BaseModel): """Quelle eines Dokuments im Workflow""" type: str = Field(description="Typ der Quelle ('agent', 'file', 'clipboard')") path: Optional[str] = Field(None, description="Speicherpfad (nur für type=='file'") name: str = Field(description="Anzeigename der Datei") size: Optional[int] = Field(None, description="Größe in Bytes") lines: Optional[int] = Field(None, description="Zeilenanzahl (für Textdateien)") content_type: Optional[str] = Field(None, description="MIME-Typ") upload_date: Optional[str] = Field(None, description="Uploaddatum") class DocumentContent(BaseModel): """Inhalt eines Dokuments im Workflow""" label: Optional[str] = Field(None, description="Optionale Bezeichnung") is_text: Optional[bool] = Field(False, description="Flag, ob Textdatei") type: str = Field(description="Typ des Inhalts ('pdf', docx, xlsx, txt, csv, json, jpg, png") text: Optional[str] = Field(None, description="Textinhalt") class Document(BaseModel): """Dokument im Workflow """ id: str = Field(description="Eindeutige ID des Dokuments") source: DocumentSource = Field(description="Quellmetadaten") contents: List[DocumentContent] = Field(description="Dokumentinhalte") class DataStats(BaseModel): """Statistiken für Performance und Datennutzung""" processing_time: Optional[float] = Field(None, description="Verarbeitungszeit in Sekunden") token_count: Optional[int] = Field(None, description="Token-Anzahl (für KI-Modelle)") bytes_sent: Optional[int] = Field(None, description="Gesendete Bytes") bytes_received: Optional[int] = Field(None, description="Empfangene Bytes") class Message(BaseModel): """Nachrichtenobjekt im Workflow""" id: str = Field(description="Eindeutige ID der Nachricht") workflow_id: str = Field(description="Referenz zum übergeordneten Workflow") parent_message_id: Optional[str] = Field(None, description="Referenz zur beantworteten Nachricht") started_at: str = Field(description="Zeitstempel für Nachrichtenerstellung") finished_at: Optional[str] = Field(None, description="Zeitstempel für Nachrichtenabschluss") sequence_no: int = Field(description="Sequenznummer für Sortierung") status: str = Field(description="Status der Nachricht ('pending', 'processing', 'completed', 'failed')") role: str = Field(description="Rolle des Absenders ('system', 'user', 'assistant')") data_stats: Optional[DataStats] = Field(None, description="Statistiken") documents: Optional[List[Document]] = Field(None, description="Dokumente in dieser Nachricht") content: Optional[str] = Field(None, description="Textinhalt der Nachricht") agent_type: Optional[str] = Field(None, description="Typ des verwendeten Agenten") class Workflow(BaseModel): """Workflow-Objekt für Multi-Agent-System""" id: str = Field(description="Eindeutige ID des Workflows") name: Optional[str] = Field(None, description="Name des Workflows") mandate_id: int = Field(description="ID des Mandanten") user_id: int = Field(description="ID des Benutzers") status: str = Field(description="Status des Workflows ('running', 'failed', 'stopped')") started_at: str = Field(description="Startzeitpunkt") last_activity: str = Field(description="Zeitpunkt der letzten Aktivität") current_round: int = Field(description="Aktuelle Runde") waiting_for_user: bool = Field(False, description="Flag, ob auf Benutzereingabe gewartet wird") data_stats: Optional[Dict[str, Any]] = Field(None, description="Gesamt-Statistiken") messages: List[Message] = Field(default=[], description="Nachrichtenverlauf") logs: List[Dict[str, Any]] = Field(default=[], description="Protokolleinträge") # Anfragemodelle für die API class WorkflowCreateRequest(BaseModel): """Anfrage zur Erstellung eines neuen Workflows""" name: Optional[str] = Field(None, description="Name des Workflows") prompt: str = Field(description="Zu verwendender Prompt") files: List[int] = Field(default=[], description="Liste von Datei-IDs") class UserInputRequest(BaseModel): """Anfrage für Benutzereingabe an einen laufenden Workflow""" message: str = Field(description="Nachricht des Benutzers") additional_files: List[int] = Field(default=[], description="Liste zusätzlicher Datei-IDs")