""" 场景契约模型 — 统一 DSL 输入契约(目标/约束/产物/验收) 让不同模板复用统一输入格式,实现"场景可编程输入" """ from sqlalchemy import Column, String, Text, Integer, DateTime, JSON, ForeignKey, Index, func from sqlalchemy.dialects.mysql import CHAR from sqlalchemy.orm import relationship from app.core.database import Base import uuid class SceneContract(Base): """场景契约表 — 定义标准输入契约""" __tablename__ = "scene_contracts" id = Column(CHAR(36), primary_key=True, default=lambda: str(uuid.uuid4()), comment="契约ID") name = Column(String(100), nullable=False, comment="契约名称") description = Column(Text, comment="契约描述") # ── 核心 DSL 字段 ── goal = Column(Text, nullable=False, comment="场景目标(一句话描述要达成什么)") role = Column(Text, nullable=True, comment="Agent 扮演的角色/人设") # 输入规范 input_description = Column(Text, nullable=True, comment="期望的输入描述") input_schema = Column(JSON, nullable=True, comment="输入 JSON Schema 约束") # 约束条件 constraints = Column(JSON, nullable=True, comment="行为约束列表") forbidden_actions = Column(JSON, nullable=True, comment="禁止的操作列表") required_tools = Column(JSON, nullable=True, comment="必需的工具列表") # 产物定义 deliverables = Column(JSON, nullable=True, comment="期望产出物列表 [{name, format, description}]") # 验收标准 acceptance_criteria = Column(JSON, nullable=True, comment="验收条件列表") # 输出规范 output_schema = Column(JSON, nullable=True, comment="输出 JSON Schema 约束") # Few-shot 示例 examples = Column(JSON, nullable=True, comment="示例列表 [{input, output}]") # 元数据 category = Column(String(50), nullable=True, comment="分类") tags = Column(JSON, nullable=True, comment="标签列表") version = Column(Integer, default=1, comment="版本号") is_public = Column(Integer, default=0, comment="是否公开: 0=私有 1=公开") use_count = Column(Integer, default=0, comment="使用次数") # 关联 user_id = Column(CHAR(36), ForeignKey("users.id"), nullable=True, comment="创建者ID") workspace_id = Column(CHAR(36), ForeignKey("workspaces.id"), nullable=True, comment="所属工作区ID") template_binding = Column(String(100), nullable=True, comment="绑定的场景模板ID(可选)") created_at = Column(DateTime, default=func.now(), comment="创建时间") updated_at = Column(DateTime, default=func.now(), onupdate=func.now(), comment="更新时间") __table_args__ = ( Index("idx_sc_category", "category"), Index("idx_sc_user_id", "user_id"), Index("idx_sc_is_public", "is_public"), Index("idx_sc_template_binding", "template_binding"), ) user = relationship("User", backref="scene_contracts") def __repr__(self): return f"" def to_dict(self): return { "id": self.id, "name": self.name, "description": self.description, "goal": self.goal, "role": self.role, "input_description": self.input_description, "input_schema": self.input_schema, "constraints": self.constraints or [], "forbidden_actions": self.forbidden_actions or [], "required_tools": self.required_tools or [], "deliverables": self.deliverables or [], "acceptance_criteria": self.acceptance_criteria or [], "output_schema": self.output_schema, "examples": self.examples or [], "category": self.category, "tags": self.tags or [], "version": self.version, "is_public": self.is_public, "use_count": self.use_count, "user_id": self.user_id, "workspace_id": self.workspace_id, "template_binding": self.template_binding, "created_at": self.created_at.isoformat() if self.created_at else None, "updated_at": self.updated_at.isoformat() if self.updated_at else None, }