{
"tool_response": {
"type": "text",
"file": {
"filePath": "\/var\/www\/mcp-servers\/mcp_tasks\/domain\/contracts.py",
"content": "\"\"\"Domain Entities - Datenstrukturen für MCP-Tasks\"\"\"\nfrom dataclasses import dataclass, field\nfrom datetime import datetime\nfrom enum import Enum\nfrom typing import Optional, Dict, Any, List\n\n\nclass TaskStatus(str, Enum):\n \"\"\"Task-Status-Werte\"\"\"\n PENDING = \"pending\"\n IN_PROGRESS = \"in_progress\"\n COMPLETED = \"completed\"\n FAILED = \"failed\"\n CANCELLED = \"cancelled\"\n\n\nclass TaskType(str, Enum):\n \"\"\"Task-Typen\"\"\"\n HUMAN_TASK = \"human_task\"\n AI_TASK = \"ai_task\"\n MIXED = \"mixed\"\n\n\nclass ExecutorType(str, Enum):\n \"\"\"Executor-Typen für Zuweisungen und Ergebnisse\"\"\"\n HUMAN = \"human\"\n OLLAMA = \"ollama\"\n CLAUDE = \"claude\"\n ANTHROPIC_API = \"anthropic_api\"\n\n\n@dataclass\nclass Task:\n \"\"\"Task-Entity\"\"\"\n id: Optional[int] = None\n uuid: str = \"\"\n title: str = \"\"\n description: Optional[str] = None\n type: TaskType = TaskType.AI_TASK\n status: TaskStatus = TaskStatus.PENDING\n created_by: str = \"mcp-tasks\"\n created_by_type: str = \"ai\"\n parent_task_id: Optional[int] = None\n due_date: Optional[datetime] = None\n created_at: datetime = field(default_factory=datetime.now)\n updated_at: datetime = field(default_factory=datetime.now)\n completed_at: Optional[datetime] = None\n metadata: Dict[str, Any] = field(default_factory=dict)\n\n def to_dict(self) -> Dict[str, Any]:\n \"\"\"Konvertiert zu Dictionary für JSON-Response (vollständig)\"\"\"\n return {\n \"id\": self.id,\n \"uuid\": self.uuid,\n \"title\": self.title,\n \"description\": self.description,\n \"type\": self.type.value if isinstance(self.type, TaskType) else self.type,\n \"status\": self.status.value if isinstance(self.status, TaskStatus) else self.status,\n \"created_by\": self.created_by,\n \"created_by_type\": self.created_by_type,\n \"parent_task_id\": self.parent_task_id,\n \"due_date\": self.due_date.isoformat() if self.due_date else None,\n \"created_at\": self.created_at.isoformat() if self.created_at else None,\n \"updated_at\": self.updated_at.isoformat() if self.updated_at else None,\n \"completed_at\": self.completed_at.isoformat() if self.completed_at else None,\n \"metadata\": self.metadata,\n }\n\n def to_dict_compact(self) -> Dict[str, Any]:\n \"\"\"Kompakte Darstellung für Listen (Token-sparend)\"\"\"\n desc = self.description or \"\"\n return {\n \"id\": self.id,\n \"title\": self.title[:80] + \"...\" if len(self.title) > 80 else self.title,\n \"description\": desc[:100] + \"...\" if len(desc) > 100 else desc if desc else None,\n \"type\": self.type.value if isinstance(self.type, TaskType) else self.type,\n \"status\": self.status.value if isinstance(self.status, TaskStatus) else self.status,\n }\n\n\n@dataclass\nclass TaskAssignment:\n \"\"\"Task-Zuweisung\"\"\"\n id: Optional[int] = None\n task_id: int = 0\n assignee: str = \"\"\n assignee_type: ExecutorType = ExecutorType.HUMAN\n model_name: Optional[str] = None\n status: str = \"pending\"\n assigned_at: datetime = field(default_factory=datetime.now)\n notes: Optional[str] = None\n\n def to_dict(self) -> Dict[str, Any]:\n return {\n \"id\": self.id,\n \"task_id\": self.task_id,\n \"assignee\": self.assignee,\n \"assignee_type\": self.assignee_type.value if isinstance(self.assignee_type, ExecutorType) else self.assignee_type,\n \"model_name\": self.model_name,\n \"status\": self.status,\n \"assigned_at\": self.assigned_at.isoformat() if self.assigned_at else None,\n \"notes\": self.notes,\n }\n\n\n@dataclass\nclass TaskResult:\n \"\"\"Task-Ergebnis mit Token-Tracking\"\"\"\n id: Optional[int] = None\n task_id: int = 0\n executor: str = \"\"\n executor_type: ExecutorType = ExecutorType.OLLAMA\n model_name: Optional[str] = None\n request: Optional[str] = None\n response: Optional[str] = None\n status: str = \"success\"\n error_message: Optional[str] = None\n tokens_input: int = 0\n tokens_output: int = 0\n cost_usd: float = 0.0\n duration_ms: int = 0\n created_at: datetime = field(default_factory=datetime.now)\n\n def to_dict(self) -> Dict[str, Any]:\n return {\n \"id\": self.id,\n \"task_id\": self.task_id,\n \"executor\": self.executor,\n \"executor_type\": self.executor_type.value if isinstance(self.executor_type, ExecutorType) else self.executor_type,\n \"model_name\": self.model_name,\n \"request\": self.request[:500] + \"...\" if self.request and len(self.request) > 500 else self.request,\n \"response\": self.response[:1000] + \"...\" if self.response and len(self.response) > 1000 else self.response,\n \"status\": self.status,\n \"error_message\": self.error_message,\n \"tokens_input\": self.tokens_input,\n \"tokens_output\": self.tokens_output,\n \"tokens_total\": self.tokens_input + self.tokens_output,\n \"cost_usd\": self.cost_usd,\n \"duration_ms\": self.duration_ms,\n \"created_at\": self.created_at.isoformat() if self.created_at else None,\n }\n\n\n@dataclass\nclass LogEntry:\n \"\"\"Log-Eintrag für mcp_log Tabelle\"\"\"\n client_name: str = \"mcp-tasks\"\n tool_name: str = \"\"\n request: str = \"\"\n status: str = \"success\" # success | denied | error\n duration_ms: int = 0\n error_message: Optional[str] = None\n task_id: Optional[int] = None\n timestamp: datetime = field(default_factory=datetime.now)\n\n\n@dataclass\nclass TaskListResponse:\n \"\"\"Response für tasks_list\"\"\"\n tasks: List[Task] = field(default_factory=list)\n total: int = 0\n limit: int = 50\n offset: int = 0\n\n def to_dict(self) -> Dict[str, Any]:\n return {\n \"tasks\": [t.to_dict() for t in self.tasks],\n \"total\": self.total,\n \"limit\": self.limit,\n \"offset\": self.offset,\n }\n\n\n@dataclass\nclass QualityCheckResult:\n \"\"\"Ergebnis eines Quality-Checks\"\"\"\n check_name: str = \"\"\n passed: bool = True\n issues: int = 0\n fixed: int = 0\n details: Optional[str] = None\n\n def to_dict(self) -> Dict[str, Any]:\n return {\n \"check_name\": self.check_name,\n \"passed\": self.passed,\n \"issues\": self.issues,\n \"fixed\": self.fixed,\n \"details\": self.details,\n }\n",
"numLines": 191,
"startLine": 1,
"totalLines": 191
}
}
}