# ============================================================ # 跨层契约的 pydantic 运行时形态(moduleId: server-contracts, 可重生 ✅) # 与 shared/schemas/*.json 保持一一对应(JSON Schema 为源,py/ts 为镜像) # 任何跨层数据必须经过这里的模型校验后才能流转(plan.md §12 规范 6) # ============================================================ from __future__ import annotations # 允许前向类型引用 from typing import Any, Literal, Optional # 类型标注工具 from pydantic import BaseModel, Field # 契约校验基座 # ---------------- 视口命令(shared/viewport_command.schema.json) ---------------- class ViewportCommand(BaseModel): """视口命令:驱动右侧可视化的结构化指令(§6.3)。权力等级:P0(纯视图状态)。""" # 命令名:viewport.* 改视口状态;world.refresh 通知前端重拉世界数据 cmd: Literal[ "viewport.mode", "viewport.filter", "viewport.focus", "viewport.highlight", "viewport.timescale", "viewport.reset", "world.refresh", ] # 目标对象 ID(如聚焦的产线 ID),无目标时为 None target: Optional[str] = None # 命令参数(按 cmd 而异,前端按约定读取) params: dict[str, Any] = Field(default_factory=dict) # 发起方:LLM 解析产出 / 用户手点 / 系统自动 issuedBy: Literal["LLM", "USER", "SYSTEM"] = "SYSTEM" # ---------------- UI 块(shared/ui_block.schema.json) ---------------- class UIAction(BaseModel): """UI 块内的可触发动作:用户点击后回传后端(§6.2)。""" actionId: str # 动作 ID(后端据此路由) label: str # 按钮文案 power: Literal["P0", "P1", "P2", "P3"] # 权力等级(P2/P3 必须过门禁) payload: dict[str, Any] = Field(default_factory=dict) # 携带参数 class UIBlock(BaseModel): """UI 块:后端与前端之间的渲染契约(§6.2)。M3 新增 report(报告预览 §9.10)。""" blockId: str # 块唯一 ID type: Literal["text", "confirm-card", "evidence", "scenario-cards", "report"] # 块类型(M3 子集) props: dict[str, Any] = Field(default_factory=dict) # 数据载荷 actions: list[UIAction] = Field(default_factory=list) # 块内动作 evidenceRefs: list[str] = Field(default_factory=list) # 关联证据 ID # ---------------- 意图结果(shared/intent.schema.json) ---------------- # 意图名的封闭枚举:LLM 输出超出此集合即判非法并降级(M3 新增知识查询与报告) IntentName = Literal[ "schedule.run", "schedule.publish", "order.upsert", "order.cancel", "order.complete", # M4:订单管理(P2) "scenario.compare", # M2:多策略沙盒对比(Explore 通道 §5.1) "checkpoint.create", "checkpoint.rollback", # M2:成对快照与回滚(§4.3) "knowledge.query", # M3:知识库检索(带出处 §8.2) "report.generate", # M3:报告生成(日报/版本对比 §9.10) "viewport.mode", "viewport.filter", "viewport.focus", "viewport.highlight", "viewport.timescale", "viewport.reset", "query.kpi", "data.reset", "help", "unknown", ] class IntentResult(BaseModel): """意图识别结果:两级管线(规则快路/LLM)的统一输出(§9.6)。""" intent: IntentName # 意图名(封闭枚举) params: dict[str, Any] = Field(default_factory=dict) # 槽位参数(策略/模式/客户名…) confidence: float = Field(ge=0, le=1) # 置信度:<0.5 拒识,0.5-0.85 澄清,>0.85 执行 source: Literal["RULE_FAST", "LLM"] = "RULE_FAST" # 产生来源(审计与调试用) # ---------------- 排产结果摘要(shared/schedule_result.schema.json) ---------------- class ScheduleResult(BaseModel): """排产结果摘要:引擎 solve() 的标准输出(§9.1),回复/审计/KPI 共用。""" versionId: int # 版本 ID versionNo: str # 版本号(V+日期+序号) engineType: Literal["RULE", "CP", "GA", "HYBRID"] # 引擎类型 strategy: str # 策略模板 status: Literal["DRAFT", "PUBLISHED", "ARCHIVED"] = "DRAFT" # 版本状态 orderCount: int # 参与排产的订单项数 poCount: int # 生成生产订单数 woCount: int # 生成工单数 conflictCount: int # 冲突数 totalTardiness: float # 总延迟(小时) avgUtilization: float # 平均利用率 0-1 totalCost: float = 0 # 预估成本 evidenceRefs: list[str] = Field(default_factory=list) # 证据引用(run-id) # ---------------- 智能体回复(SSE 载荷的聚合形态,仅后端内部使用) ---------------- class AgentReply(BaseModel): """一轮对话的完整产出:文本 + 视口命令 + UI 块(gateway 将其拆成 SSE 事件流)。""" text: str # 回复正文(前端流式渲染) commands: list[ViewportCommand] = Field(default_factory=list) # 要执行的视口命令 blocks: list[UIBlock] = Field(default_factory=list) # 附加 UI 块(如确认卡) intent: Optional[IntentResult] = None # 本轮识别出的意图(协议证据,前端可展开)