from __future__ import annotations from typing import Any, Literal from pydantic import BaseModel, Field OrchestratorSource = Literal["user_message", "schedule", "system_event"] OrchestratorAgent = Literal["user_agent", "hermes"] OrchestratorStatus = Literal["succeeded", "blocked", "failed"] class OrchestratorRequest(BaseModel): source: OrchestratorSource = Field(description="请求来源。") user_id: str | None = Field(default=None, description="当前用户 ID,任务触发可为空。") message: str | None = Field(default=None, description="用户消息或任务描述。") task_id: str | None = Field(default=None, description="任务资产 ID,schedule 触发时优先使用。") context_json: dict[str, Any] = Field( default_factory=dict, description="用户上下文、测试开关或调用方附加信息。", ) class OrchestratorTraceSummary(BaseModel): scenario: str = Field(description="语义场景。") intent: str = Field(description="语义意图。") tool_count: int = Field(default=0, ge=0, description="工具调用总数。") failed_tool_count: int = Field(default=0, ge=0, description="失败工具调用数量。") selected_capability_codes: list[str] = Field( default_factory=list, description="本次路由命中的能力编码。", ) degraded: bool = Field(default=False, description="是否发生降级。") class OrchestratorResponse(BaseModel): run_id: str = Field(description="本次运行的唯一 run_id。") selected_agent: OrchestratorAgent | None = Field( default=None, description="最终路由到的下游 Agent。", ) route_reason: str = Field(description="路由原因摘要。") permission_level: str = Field(description="权限级别。") status: OrchestratorStatus = Field(description="最终运行状态。") result: dict[str, Any] = Field(default_factory=dict, description="对前端可直接展示的最小结果。") requires_confirmation: bool = Field(default=False, description="是否需要用户或管理员确认。") trace_summary: OrchestratorTraceSummary = Field(description="简化后的 Trace 摘要。")