"""圆桌会商「诊断日志」ORM 模型。 记录会商全流程(第一步意图 / 第二步研讨 / 第三步报告 + 后台挂起执行器 / 进程内网关) 各处可能发生的报错与关键事件,供管理员在前端诊断页筛选排查。 设计要点: - **全局/共享**:不按 user 分权(``user_id`` 仅审计),管理员读全量;写入开放(best-effort)。 - 一行 = 一条事件。``detail`` 用 ``PortableLongText`` 存结构化补充信息(堆栈尾、上下文)。 - 按 ``created_at`` / ``stage`` / ``level`` / ``job_id`` / ``task_id`` 建索引,支撑筛选。 """ from __future__ import annotations from datetime import UTC, datetime from sqlalchemy import Integer, String, Text from sqlalchemy.orm import Mapped, mapped_column from deerflow.persistence.base import Base from deerflow.persistence.types import BeijingDateTime, PortableLongText class RoundtableDiagnosticRow(Base): __tablename__ = "roundtable_diagnostics" id: Mapped[str] = mapped_column(String(64), primary_key=True) # background(后台挂起)| foreground(前台实时会商)。 scope: Mapped[str] = mapped_column(String(16), nullable=False, default="background", index=True) # 阶段:step1_intent / step2_init / step2_leader / step2_seat / step2_orchestration / # step3_summary / step3_report / step3_dashboard / step3_structure / upstream / job。 stage: Mapped[str] = mapped_column(String(32), nullable=False, default="job", index=True) # 级别:info | warning | error。 level: Mapped[str] = mapped_column(String(16), nullable=False, default="info", index=True) # 短事件码(如 seat_turn_timeout / model_error / report_truncated / dispatch_invalid)。 event: Mapped[str] = mapped_column(String(64), nullable=False, default="") # 人类可读的报错说明(中文)。 message: Mapped[str | None] = mapped_column(Text, nullable=True) # 结构化补充:堆栈尾、上下文、原始 body 片段等。 detail: Mapped[str | None] = mapped_column(PortableLongText, nullable=True) # 关联上下文(均可空)。 job_id: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True) draft_id: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True) task_id: Mapped[str | None] = mapped_column(String(128), nullable=True, index=True) user_id: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True) agent_id: Mapped[str | None] = mapped_column(String(128), nullable=True) agent_name: Mapped[str | None] = mapped_column(String(255), nullable=True) cycle: Mapped[int | None] = mapped_column(Integer, nullable=True) created_at: Mapped[datetime] = mapped_column( BeijingDateTime(), nullable=False, default=lambda: datetime.now(UTC), index=True )