import uuid from datetime import datetime from pydantic import BaseModel, Field, ConfigDict # --- Auth --- class LoginRequest(BaseModel): username: str password: str class TokenResponse(BaseModel): access_token: str token_type: str = "bearer" user: "UserOut" # --- User --- class UserCreate(BaseModel): username: str password: str display_name: str email: str | None = None phone: str | None = None wecom_user_id: str | None = None department_id: uuid.UUID | None = None position: str | None = None manager_id: uuid.UUID | None = None role_ids: list[uuid.UUID] = [] class UserUpdate(BaseModel): display_name: str | None = None email: str | None = None phone: str | None = None department_id: uuid.UUID | None = None position: str | None = None manager_id: uuid.UUID | None = None status: str | None = None role_ids: list[uuid.UUID] | None = None class UserOut(BaseModel): id: uuid.UUID username: str display_name: str email: str | None = None phone: str | None = None wecom_user_id: str | None = None department_id: uuid.UUID | None = None position: str | None = None manager_id: uuid.UUID | None = None status: str roles: list["RoleOut"] = [] created_at: datetime | None = None class Config: from_attributes = True # --- Department --- class DepartmentCreate(BaseModel): name: str parent_id: uuid.UUID | None = None sort_order: int = 0 class DepartmentUpdate(BaseModel): name: str | None = None parent_id: uuid.UUID | None = None sort_order: int | None = None class DepartmentOut(BaseModel): id: uuid.UUID name: str parent_id: uuid.UUID | None = None path: str level: int sort_order: int children: list["DepartmentOut"] = [] class Config: from_attributes = True # --- Role --- class RoleCreate(BaseModel): name: str code: str = "" description: str | None = None data_scope: str = "self_only" permission_ids: list[uuid.UUID] = [] class RoleUpdate(BaseModel): name: str | None = None description: str | None = None data_scope: str | None = None permission_ids: list[uuid.UUID] | None = None class RoleOut(BaseModel): id: uuid.UUID name: str code: str = "" description: str | None = None is_system: bool data_scope: str permissions: list[str] = [] class Config: from_attributes = True # --- Permission --- class PermissionOut(BaseModel): id: uuid.UUID code: str name: str resource: str action: str class Config: from_attributes = True # --- Task --- class TaskCreate(BaseModel): title: str content: str | None = None assignee_id: uuid.UUID priority: str = "normal" deadline: datetime | None = None push_to_wecom: bool = True class TaskUpdate(BaseModel): title: str | None = None content: str | None = None status: str | None = None priority: str | None = None deadline: datetime | None = None class TaskOut(BaseModel): id: uuid.UUID title: str content: str | None = None assigner_id: uuid.UUID | None = None assignee_id: uuid.UUID status: str priority: str deadline: datetime | None = None created_at: datetime | None = None updated_at: datetime | None = None class Config: from_attributes = True # --- Employee Analysis --- class EmployeeAnalysis(BaseModel): employee_name: str department: str period: str task_completion_rate: float active_days: int total_interactions: int main_topics: list[str] efficiency_trend: str efficiency_detail: str strengths: list[str] growth_suggestions: list[str] personality_traits: str # --- Flow --- class TriggerNodeConfig(BaseModel): event_type: str = "text_message" channels: list[str] = ["wecom"] callback_url: str = "" class LLMNodeConfig(BaseModel): system_prompt: str = "" model: str = "gpt-4o-mini" temperature: float = 0.7 agent_id: str = "" max_tokens: int = 2000 context_length: int = 5 memory_mode: str = "short_term" stream: bool = True tool_call: bool = False class ToolNodeConfig(BaseModel): tool_name: str = "" tool_type: str = "" tool_params: dict = {} timeout: int = 30 retry_count: int = 0 error_handling: str = "throw" class MCPNodeConfig(BaseModel): mcp_server: str = "" tool_name: str = "" input_params: dict = {} timeout: int = 30 response_parser: str = "json" error_handling: str = "throw" class NotifyNodeConfig(BaseModel): channels: dict = {"wecom": True, "web": False} message_template: str = "" web_template: str = "" target: str = "" message_type: str = "text" async_send: bool = False error_handling: str = "throw" class ConditionNodeConfig(BaseModel): condition: str = "" condition_type: str = "expression" true_label: str = "是" false_label: str = "否" default_branch: str = "false" class RAGNodeConfig(BaseModel): knowledge_base: str = "" top_k: int = 5 search_mode: str = "hybrid" similarity_threshold: float = 0.7 result_sort: str = "similarity" include_metadata: bool = True class OutputNodeConfig(BaseModel): format: str = "text" output_template: str = "" indent: int = 2 encoding: str = "utf-8" truncate: bool = False max_length: int = 2000 class LoopNodeConfig(BaseModel): loop_type: str = "fixed" max_iterations: int = 10 count: int = 3 iterator_variable: str = "item" class CodeNodeConfig(BaseModel): language: str = "python" code: str = "" timeout: int = 30 sandbox: bool = True class FlowNode(BaseModel): id: str | None = None type: str label: str | None = None config: dict = {} class FlowEdge(BaseModel): source: str | None = None target: str | None = None from_field: str | None = Field(None, alias="from") to_field: str | None = Field(None, alias="to") class Config: populate_by_name = True class FlowDefinitionCreate(BaseModel): name: str description: str | None = None trigger: dict = {} nodes: list[FlowNode] edges: list[FlowEdge] flow_mode: str = "chatflow" class FlowDefinitionUpdate(BaseModel): name: str | None = None description: str | None = None nodes: list[FlowNode] | None = None edges: list[FlowEdge] | None = None trigger: dict | None = None class FlowDefinitionOut(BaseModel): id: uuid.UUID name: str description: str | None = None version: int status: str definition_json: dict published_version_id: uuid.UUID | None = None published_to_wecom: bool published_to_web: bool = False flow_mode: str = "chatflow" created_at: datetime | None = None updated_at: datetime | None = None class Config: from_attributes = True class FlowVersionOut(BaseModel): id: uuid.UUID flow_id: uuid.UUID version: int definition_json: dict changelog: str = "" published_to_wecom: bool = False published_to_web: bool = False published_by: uuid.UUID | None = None created_at: datetime | None = None class Config: from_attributes = True class FlowApiKeyCreate(BaseModel): name: str class FlowApiKeyOut(BaseModel): id: uuid.UUID flow_id: uuid.UUID name: str key_prefix: str last_used_at: datetime | None = None created_at: datetime | None = None class Config: from_attributes = True class FlowExecuteRequest(BaseModel): input_text: str = "" session_id: str | None = None user_id: str | None = None class FlowChatMessageRequest(BaseModel): query: str inputs: dict = {} response_mode: str = "blocking" user: str = "" session_id: str | None = None class OpenAPIImportRequest(BaseModel): openapi_url: str base_url_override: str | None = None class CustomToolCreate(BaseModel): model_config = ConfigDict(protected_namespaces=()) name: str description: str | None = None openapi_url: str | None = None endpoint_url: str | None = None method: str = "GET" path: str = "" headers: dict = {} auth_type: str = "none" auth_config: dict = {} tool_schema: dict | None = None class CustomToolUpdate(BaseModel): model_config = ConfigDict(protected_namespaces=()) name: str | None = None description: str | None = None endpoint_url: str | None = None method: str | None = None path: str | None = None headers: dict | None = None auth_type: str | None = None auth_config: dict | None = None tool_schema: dict | None = None is_active: bool | None = None class CustomToolOut(BaseModel): model_config = ConfigDict(from_attributes=True, populate_by_name=True, protected_namespaces=()) id: uuid.UUID name: str description: str | None = None tool_schema: dict = Field(alias="schema_json") endpoint_url: str method: str path: str auth_type: str is_active: bool created_at: datetime | None = None # --- MCP --- class MCPServiceCreate(BaseModel): name: str transport: str = "http" url: str | None = None command: str | None = None args: list[str] = [] env: dict[str, str] = {} class MCPServiceUpdate(BaseModel): transport: str | None = None url: str | None = None command: str | None = None args: list[str] | None = None env: dict[str, str] | None = None class MCPServiceOut(BaseModel): id: uuid.UUID name: str transport: str url: str | None = None command: str | None = None status: str = "disconnected" tools: list[dict] = [] creator_id: uuid.UUID | None = None created_at: datetime | None = None class Config: from_attributes = True # --- Agent Config --- class AgentConfigCreate(BaseModel): name: str description: str | None = None system_prompt: str = "" model: str = "gpt-4o-mini" temperature: float = 0.7 tools: list[str] = [] class AgentConfigUpdate(BaseModel): name: str | None = None description: str | None = None system_prompt: str | None = None model: str | None = None temperature: float | None = None tools: list[str] | None = None status: str | None = None class AgentConfigOut(BaseModel): id: uuid.UUID name: str description: str | None = None system_prompt: str model: str temperature: float tools: list[str] = [] status: str creator_id: uuid.UUID | None = None created_at: datetime | None = None updated_at: datetime | None = None class Config: from_attributes = True # --- Notification --- class NotificationTemplateCreate(BaseModel): name: str code: str channel: str = "wecom" title_template: str | None = None body_template: str variables: list[str] = [] class NotificationTemplateOut(BaseModel): id: uuid.UUID name: str code: str channel: str title_template: str | None = None body_template: str variables: list[str] = [] is_system: bool = False class Config: from_attributes = True # --- Document --- class DocumentUploadOut(BaseModel): file_id: uuid.UUID filename: str file_size: int content_type: str upload_time: datetime class DocumentParseResult(BaseModel): file_id: uuid.UUID filename: str content: str metadata: dict = {} # --- Audit --- class AuditQueryParams(BaseModel): page: int = 1 page_size: int = 20 action: str | None = None resource: str | None = None operator_id: uuid.UUID | None = None date_from: datetime | None = None date_to: datetime | None = None class AuditLogOut(BaseModel): id: uuid.UUID operator_id: uuid.UUID | None = None action: str resource: str | None = None resource_id: str | None = None detail: dict | None = None ip_address: str | None = None created_at: datetime | None = None class Config: from_attributes = True class AuditLogPage(BaseModel): items: list[AuditLogOut] total: int page: int page_size: int # --- System Metrics --- class SystemMetricOut(BaseModel): id: uuid.UUID metric_type: str value: dict collected_at: datetime class Config: from_attributes = True class SystemHealthOut(BaseModel): status: str service: str uptime_seconds: float db_connected: bool redis_connected: bool active_users: int memory_mb: float cpu_percent: float class UsageStatsOut(BaseModel): total_users: int active_users_today: int total_sessions: int total_messages: int total_tasks: int total_flows: int published_flows: int api_calls_today: int avg_response_time_ms: float # --- Generic Response --- class ApiResponse(BaseModel): code: int = 200 message: str = "success" data: dict | list | None = None