import uuid from datetime import datetime from sqlalchemy import Column, String, DateTime, ForeignKey, Integer, Boolean, JSON, Text, Float from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import relationship from database import Base class Department(Base): __tablename__ = "departments" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) name = Column(String(100), nullable=False) parent_id = Column(UUID(as_uuid=True), ForeignKey("departments.id"), nullable=True) path = Column(String(500), default="/") level = Column(Integer, default=0) sort_order = Column(Integer, default=0) created_at = Column(DateTime, default=datetime.utcnow) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) children = relationship("Department", backref="parent", remote_side=[id]) users = relationship("User", back_populates="department") class User(Base): __tablename__ = "users" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) username = Column(String(50), unique=True, nullable=False) password_hash = Column(String(255), nullable=False) display_name = Column(String(100), nullable=False) email = Column(String(100)) phone = Column(String(20)) wecom_user_id = Column(String(100), unique=True) department_id = Column(UUID(as_uuid=True), ForeignKey("departments.id")) position = Column(String(100)) manager_id = Column(UUID(as_uuid=True), ForeignKey("users.id")) status = Column(String(20), default="active") created_at = Column(DateTime, default=datetime.utcnow) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) department = relationship("Department", back_populates="users") roles = relationship("UserRole", back_populates="user") manager = relationship("User", remote_side=[id], backref="subordinates") class Role(Base): __tablename__ = "roles" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) name = Column(String(50), unique=True, nullable=False) code = Column(String(50), unique=True, nullable=False, default="") description = Column(String(200)) is_system = Column(Boolean, default=False) data_scope = Column(String(50), default="self_only") created_at = Column(DateTime, default=datetime.utcnow) permissions = relationship("RolePermission", back_populates="role") class Permission(Base): __tablename__ = "permissions" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) code = Column(String(100), unique=True, nullable=False) name = Column(String(100), nullable=False) resource = Column(String(100), nullable=False) action = Column(String(50), nullable=False) description = Column(String(200)) class RolePermission(Base): __tablename__ = "role_permissions" role_id = Column(UUID(as_uuid=True), ForeignKey("roles.id", ondelete="CASCADE"), primary_key=True) permission_id = Column(UUID(as_uuid=True), ForeignKey("permissions.id", ondelete="CASCADE"), primary_key=True) role = relationship("Role", back_populates="permissions") permission = relationship("Permission") class UserRole(Base): __tablename__ = "user_roles" user_id = Column(UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE"), primary_key=True) role_id = Column(UUID(as_uuid=True), ForeignKey("roles.id", ondelete="CASCADE"), primary_key=True) user = relationship("User", back_populates="roles") role = relationship("Role") class ChatSession(Base): __tablename__ = "chat_sessions" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) user_id = Column(UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE")) agent_type = Column(String(50), nullable=False) session_id = Column(String(100), unique=True, nullable=False) status = Column(String(20), default="active") created_at = Column(DateTime, default=datetime.utcnow) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) class ChatMessage(Base): __tablename__ = "chat_messages" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) session_id = Column(UUID(as_uuid=True), ForeignKey("chat_sessions.id", ondelete="CASCADE")) user_id = Column(UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE")) role = Column(String(20), nullable=False) content = Column(Text, nullable=False) metadata_ = Column("metadata", JSON, default=dict) created_at = Column(DateTime, default=datetime.utcnow) class Task(Base): __tablename__ = "tasks" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) title = Column(String(200), nullable=False) content = Column(Text) assigner_id = Column(UUID(as_uuid=True), ForeignKey("users.id")) assignee_id = Column(UUID(as_uuid=True), ForeignKey("users.id"), nullable=False) status = Column(String(20), default="pending") priority = Column(String(20), default="normal") deadline = Column(DateTime) wecom_message_id = Column(String(100)) created_at = Column(DateTime, default=datetime.utcnow) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) class FlowDefinition(Base): __tablename__ = "flow_definitions" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) name = Column(String(200), nullable=False) description = Column(Text) version = Column(Integer, default=1) status = Column(String(20), default="draft") definition_json = Column(JSON, nullable=False, default=dict) published_version_id = Column(UUID(as_uuid=True), ForeignKey("flow_versions.id"), nullable=True) draft_definition_json = Column(JSON, nullable=True, default=None) creator_id = Column(UUID(as_uuid=True), ForeignKey("users.id")) flow_mode = Column(String(20), default="chatflow") published_to_wecom = Column(Boolean, default=False) published_to_web = Column(Boolean, default=False) created_at = Column(DateTime, default=datetime.utcnow) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) published_version = relationship("FlowVersion", foreign_keys=[published_version_id], post_update=True) class FlowVersion(Base): __tablename__ = "flow_versions" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) flow_id = Column(UUID(as_uuid=True), ForeignKey("flow_definitions.id", ondelete="CASCADE"), nullable=False) version = Column(Integer, nullable=False) definition_json = Column(JSON, nullable=False, default=dict) changelog = Column(Text, default="") published_by = Column(UUID(as_uuid=True), ForeignKey("users.id")) published_to_wecom = Column(Boolean, default=False) published_to_web = Column(Boolean, default=False) created_at = Column(DateTime, default=datetime.utcnow) class FlowApiKey(Base): __tablename__ = "flow_api_keys" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) flow_id = Column(UUID(as_uuid=True), ForeignKey("flow_definitions.id", ondelete="CASCADE"), nullable=False) name = Column(String(100), nullable=False) key_hash = Column(String(64), nullable=False) key_prefix = Column(String(10), nullable=False) created_by = Column(UUID(as_uuid=True), ForeignKey("users.id")) last_used_at = Column(DateTime, nullable=True) created_at = Column(DateTime, default=datetime.utcnow) class FlowTemplate(Base): __tablename__ = "flow_templates" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) name = Column(String(200), nullable=False) description = Column(Text, default="") category = Column(String(50), default="") definition_json = Column(JSON, nullable=False, default=dict) icon = Column(String(50), default="") sort_order = Column(Integer, default=0) is_builtin = Column(Boolean, default=False) usage_count = Column(Integer, default=0) created_by = Column(UUID(as_uuid=True), ForeignKey("users.id")) created_at = Column(DateTime, default=datetime.utcnow) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) class CustomTool(Base): __tablename__ = "custom_tools" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) name = Column(String(100), nullable=False) description = Column(Text) schema_json = Column(JSON, nullable=False, default=dict) endpoint_url = Column(String(500), nullable=False) method = Column(String(10), default="GET") path = Column(String(500), default="") headers_json = Column(JSON, default=dict) auth_type = Column(String(20), default="none") auth_config = Column(JSON, default=dict) created_by = Column(UUID(as_uuid=True), ForeignKey("users.id")) is_active = Column(Boolean, default=True) created_at = Column(DateTime, default=datetime.utcnow) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) class FlowExecution(Base): __tablename__ = "flow_executions" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) flow_id = Column(UUID(as_uuid=True), ForeignKey("flow_definitions.id", ondelete="CASCADE")) version = Column(Integer, nullable=True) trigger_type = Column(String(50)) trigger_user_id = Column(UUID(as_uuid=True), ForeignKey("users.id")) input_data = Column(JSON) output_data = Column(JSON) status = Column(String(20), default="running") token_usage = Column(JSON, default=dict) latency_ms = Column(Integer, nullable=True) error_message = Column(Text, nullable=True) started_at = Column(DateTime, default=datetime.utcnow) finished_at = Column(DateTime) class MCPService(Base): __tablename__ = "mcp_services" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) name = Column(String(100), unique=True, nullable=False) transport = Column(String(20), default="http") url = Column(String(500)) command = Column(String(500)) args = Column(JSON, default=list) env = Column(JSON, default=dict) status = Column(String(20), default="disconnected") tools = Column(JSON, default=list) creator_id = Column(UUID(as_uuid=True), ForeignKey("users.id")) created_at = Column(DateTime, default=datetime.utcnow) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) class NotificationTemplate(Base): __tablename__ = "notification_templates" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) name = Column(String(100), nullable=False) code = Column(String(100), unique=True, nullable=False) channel = Column(String(20), default="wecom") title_template = Column(String(500)) body_template = Column(Text, nullable=False) variables = Column(JSON, default=list) is_system = Column(Boolean, default=False) created_at = Column(DateTime, default=datetime.utcnow) class SystemMetric(Base): __tablename__ = "system_metrics" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) metric_type = Column(String(50), nullable=False) value = Column(JSON, nullable=False) collected_at = Column(DateTime, default=datetime.utcnow) class AgentConfig(Base): __tablename__ = "agent_configs" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) name = Column(String(100), nullable=False) description = Column(String(500)) system_prompt = Column(Text, default="") model = Column(String(50), default="gpt-4o-mini") model_instance_id = Column(UUID(as_uuid=True), ForeignKey("model_instances.id"), nullable=True) embedding_model_id = Column(UUID(as_uuid=True), ForeignKey("model_instances.id"), nullable=True) temperature = Column(Float, default=0.7) tools = Column(JSON, default=list) status = Column(String(20), default="active") creator_id = Column(UUID(as_uuid=True), ForeignKey("users.id")) created_at = Column(DateTime, default=datetime.utcnow) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) class AuditLog(Base): __tablename__ = "audit_logs" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) operator_id = Column(UUID(as_uuid=True), ForeignKey("users.id")) action = Column(String(100), nullable=False) resource = Column(String(100)) resource_id = Column(String(100)) detail = Column(JSON, default=dict) ip_address = Column(String(50)) created_at = Column(DateTime, default=datetime.utcnow) class MemoryMessage(Base): __tablename__ = "memory_messages" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) user_id = Column(UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE"), nullable=False) flow_id = Column(UUID(as_uuid=True), ForeignKey("flow_definitions.id", ondelete="CASCADE"), nullable=False) session_id = Column(UUID(as_uuid=True), nullable=False) role = Column(String(20), nullable=False) content = Column(Text, nullable=False) created_at = Column(DateTime, default=datetime.utcnow) class MemoryAtom(Base): __tablename__ = "memory_atoms" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) user_id = Column(UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE"), nullable=False) flow_id = Column(UUID(as_uuid=True), ForeignKey("flow_definitions.id", ondelete="SET NULL"), nullable=True) atom_type = Column(String(20), nullable=False) content = Column(Text, nullable=False) priority = Column(Integer, default=50) source_session_id = Column(UUID(as_uuid=True), nullable=True) metadata = Column(JSON, default=dict) created_at = Column(DateTime, default=datetime.utcnow) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) class MemoryScene(Base): __tablename__ = "memory_scenes" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) user_id = Column(UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE"), nullable=False) flow_id = Column(UUID(as_uuid=True), ForeignKey("flow_definitions.id", ondelete="SET NULL"), nullable=True) scene_name = Column(String(200), nullable=False) summary = Column(Text, nullable=False) heat = Column(Integer, default=0) content = Column(JSON, default=dict) created_at = Column(DateTime, default=datetime.utcnow) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) class MemoryPersona(Base): __tablename__ = "memory_personas" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) user_id = Column(UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE"), nullable=False, unique=True) content = Column(JSON, default=dict, nullable=False) raw_text = Column(Text, default="") version = Column(Integer, default=1) updated_at = Column(DateTime, default=datetime.utcnow) class MemorySession(Base): __tablename__ = "memory_sessions" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) user_id = Column(UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE"), nullable=False) flow_id = Column(UUID(as_uuid=True), ForeignKey("flow_definitions.id", ondelete="CASCADE"), nullable=False) session_id = Column(UUID(as_uuid=True), nullable=False) flow_name = Column(String(200), default="") message_count = Column(Integer, default=0) last_active_at = Column(DateTime, default=datetime.utcnow) created_at = Column(DateTime, default=datetime.utcnow) class ModelProvider(Base): __tablename__ = "model_providers" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) name = Column(String(100), nullable=False) provider_type = Column(String(50), nullable=False) base_url = Column(String(500)) api_key = Column(Text) extra_config = Column(JSON, default=dict) is_active = Column(Boolean, default=True) created_at = Column(DateTime, default=datetime.utcnow) class ModelInstance(Base): __tablename__ = "model_instances" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) provider_id = Column(UUID(as_uuid=True), ForeignKey("model_providers.id", ondelete="CASCADE")) model_name = Column(String(100), nullable=False) model_type = Column(String(30), nullable=False) display_name = Column(String(200)) capabilities = Column(JSON, default=dict) default_params = Column(JSON, default=dict) is_default = Column(Boolean, default=False) is_active = Column(Boolean, default=True) created_at = Column(DateTime, default=datetime.utcnow)