- M2-a/b/c: stop/pause/resume/skip dept, plan/rework approval gates, budget & timeout circuit breakers, per-dept cancel and on-demand rework - tier-3: batched event persistence (_EventBuffer), project/dept concurrency semaphores, company_ws event streaming - tier-4: cross-dept deliverable handoff, CEO memory feedback loop, per-dept model override, one-click Markdown report export (RFC5987) - fix: per-department independent SQLAlchemy session in parallel waves (shared Session race across asyncio tasks in company_orchestrator) - fix: rename process_open_fds gauge to app_process_open_fds (collides with prometheus_client ProcessCollector on Linux) - fix: dept role resolution ladder, real token usage & cost tracking, deliverable file capture (mtime scan of dept workspace) - tests: test_company_orchestrator.py 22 cases with mocked LLM - frontend: CompanyControlRoom, companyExecution store, EChart, dept model config dialog, ws proxy, build/typecheck decoupling - docs: virtual company design/usage docs, M2 control plan, deepseek4pro handover docs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
45 lines
1.7 KiB
Python
45 lines
1.7 KiB
Python
"""
|
||
公司级项目执行事件 — 白盒控制室的持久事件流
|
||
|
||
每条编排事件(CEO 规划 / 部门 ReAct / 打分 / 完成…)落一行,
|
||
供控制室按 seq 回放、断线恢复、审计。表由 create_all 自动创建。
|
||
"""
|
||
from sqlalchemy import Column, String, Integer, DateTime, JSON, ForeignKey, Index, func
|
||
from sqlalchemy.dialects.mysql import CHAR
|
||
from app.core.database import Base
|
||
import uuid
|
||
|
||
|
||
class CompanyProjectEvent(Base):
|
||
"""公司项目执行事件(一次编排 = 一串按 seq 递增的事件)。"""
|
||
__tablename__ = "company_project_events"
|
||
|
||
id = Column(CHAR(36), primary_key=True, default=lambda: str(uuid.uuid4()), comment="事件ID")
|
||
project_id = Column(
|
||
CHAR(36),
|
||
ForeignKey("company_projects.id", ondelete="CASCADE"),
|
||
nullable=False,
|
||
comment="所属项目ID",
|
||
)
|
||
seq = Column(Integer, nullable=False, comment="项目内自增序号,从 1")
|
||
type = Column(String(50), nullable=False, comment="事件类型")
|
||
payload = Column(JSON, nullable=True, comment="事件负载(原编排事件字段)")
|
||
created_at = Column(DateTime, default=func.now(), comment="落库时间")
|
||
|
||
__table_args__ = (
|
||
Index("idx_cpe_project_seq", "project_id", "seq"),
|
||
)
|
||
|
||
def __repr__(self):
|
||
return f"<CompanyProjectEvent(project_id={self.project_id}, seq={self.seq}, type={self.type})>"
|
||
|
||
def to_envelope(self) -> dict:
|
||
"""转为前端消费的事件信封。"""
|
||
return {
|
||
"seq": self.seq,
|
||
"pid": self.project_id,
|
||
"type": self.type,
|
||
"payload": self.payload,
|
||
"ts": self.created_at.timestamp() if self.created_at else None,
|
||
}
|