"""框架端口对象。 这些对象只描述一次 Agent 执行所需的通用材料,不加载 Muse 角色合同、数据库或业务状态。 """ from __future__ import annotations from dataclasses import dataclass, field from typing import Any, Mapping @dataclass(frozen=True) class FrameworkExecutionRequest: """已由业务侧解析完成的框架执行请求。""" system_prompt: str user_content: str tool_allowlist: tuple[str, ...] = () timeout_seconds: float = 600.0 request_id: str | None = None session_mode: str = "fresh" def __post_init__(self) -> None: if not isinstance(self.system_prompt, str) or not self.system_prompt.strip(): raise ValueError("system_prompt 必须是非空字符串") if not isinstance(self.user_content, str) or not self.user_content.strip(): raise ValueError("user_content 必须是非空字符串") if self.session_mode not in {"fresh", "continue"}: raise ValueError("session_mode 必须是 fresh 或 continue") if self.timeout_seconds <= 0: raise ValueError("timeout_seconds 必须大于 0") if any(not isinstance(name, str) or not name.strip() for name in self.tool_allowlist): raise ValueError("tool_allowlist 必须是非空工具名数组") def as_dict(self) -> dict[str, Any]: return { "systemPrompt": self.system_prompt, "userContent": self.user_content, "toolAllowlist": list(self.tool_allowlist), "timeoutSeconds": self.timeout_seconds, "requestId": self.request_id, "sessionMode": self.session_mode, } @dataclass(frozen=True) class FrameworkEvent: """框架原生事件的通用观察材料。""" framework: str framework_version: str session_id: str | None source_seq: int kind: str phase: str safe_details: Mapping[str, Any] = field(default_factory=dict) payload_sha256: str | None = None source_event_id: str | None = None run_id: str | None = None observed_at: str = "" def __post_init__(self) -> None: if not self.framework or not self.framework_version: raise ValueError("FrameworkEvent 缺少 framework/framework_version") if self.source_seq < 1: raise ValueError("FrameworkEvent source_seq 必须从 1 开始") if self.kind not in {"session", "turn", "step", "model", "tool", "agent", "transport", "unknown"}: raise ValueError(f"未知 FrameworkEvent kind: {self.kind}") if self.phase not in {"started", "progress", "completed", "failed"}: raise ValueError(f"未知 FrameworkEvent phase: {self.phase}") if not self.observed_at: raise ValueError("FrameworkEvent observed_at 不能为空") def as_dict(self) -> dict[str, Any]: return { "framework": self.framework, "frameworkVersion": self.framework_version, "sessionId": self.session_id, "sourceSeq": self.source_seq, "sourceEventId": self.source_event_id, "runId": self.run_id, "kind": self.kind, "phase": self.phase, "safeDetails": dict(self.safe_details), "payloadSha256": self.payload_sha256, "observedAt": self.observed_at, } @dataclass(frozen=True) class FrameworkExecutionResult: """框架执行结果;业务层仍需运行自己的 Schema 与主权门。""" status: str final_text: str | None requested_model: str actual_models: tuple[str, ...] = () session_id: str | None = None artifact_locator: str | None = None trace_digest: str | None = None def __post_init__(self) -> None: if self.status not in {"completed", "failed", "cancelled", "timed_out", "invalid_output"}: raise ValueError(f"未知框架结果状态: {self.status}") if not self.requested_model: raise ValueError("FrameworkExecutionResult requested_model 不能为空") def as_dict(self) -> dict[str, Any]: return { "status": self.status, "finalText": self.final_text, "requestedModel": self.requested_model, "actualModels": list(self.actual_models), "sessionId": self.session_id, "artifactLocator": self.artifact_locator, "traceDigest": self.trace_digest, } __all__ = [ "FrameworkEvent", "FrameworkExecutionRequest", "FrameworkExecutionResult", ]