from __future__ import annotations from dataclasses import dataclass, field from datetime import datetime, timezone from typing import Any, Literal TaskStatus = Literal["pending", "running", "completed", "failed", "cancelled"] RunMode = Literal["sync", "async"] TERMINAL_STATUSES = frozenset({"completed", "failed", "stopped"}) def _utc_now() -> datetime: return datetime.now(timezone.utc) @dataclass class TaskRecord: """Executor 内存中的单条任务快照。""" task_id: str trace_id: str task_description: str mode: RunMode metadata: dict[str, Any] = field(default_factory=dict) status: TaskStatus = "pending" created_at: datetime = field(default_factory=_utc_now) updated_at: datetime = field(default_factory=_utc_now) error_message: str | None = None trace_terminal_status: str | None = None def to_dict(self) -> dict[str, Any]: return { "task_id": self.task_id, "trace_id": self.trace_id, "task_description": self.task_description, "mode": self.mode, "metadata": dict(self.metadata), "status": self.status, "created_at": self.created_at.isoformat(), "updated_at": self.updated_at.isoformat(), "error_message": self.error_message, "trace_terminal_status": self.trace_terminal_status, } def touch(self, **kwargs: Any) -> None: for k, v in kwargs.items(): if hasattr(self, k): setattr(self, k, v) self.updated_at = _utc_now()