from __future__ import annotations from typing import Any, Literal from pydantic import BaseModel, Field StewardTaskType = Literal["expense_application", "reimbursement"] StewardAssignedAgent = Literal["application_assistant", "reimbursement_assistant"] StewardPlanningSource = Literal["llm_function_call", "rule_fallback"] StewardTaskStatus = Literal[ "planned", "needs_confirmation", "ready_to_delegate", "delegated", "completed", "blocked", ] StewardConfirmationStatus = Literal["pending", "confirmed", "rejected"] class StewardAttachmentInput(BaseModel): name: str = Field(description="附件原始文件名。") media_type: str = Field(default="", description="附件 MIME 类型。") ocr_summary: str = Field(default="", description="可选 OCR 摘要。") ocr_fields: dict[str, Any] = Field(default_factory=dict, description="可选 OCR 结构化字段。") class StewardPlanRequest(BaseModel): message: str = Field(description="用户在首页输入的自然语言任务。") user_id: str | None = Field(default=None, description="当前用户 ID。") client_now_iso: str | None = Field(default=None, description="客户端当前时间 ISO 字符串。") attachments: list[StewardAttachmentInput] = Field(default_factory=list, description="随本次输入上传的附件。") context_json: dict[str, Any] = Field(default_factory=dict, description="调用方上下文。") class StewardThinkingEvent(BaseModel): event_id: str = Field(description="过程摘要事件 ID。") stage: str = Field(description="阶段编码。") title: str = Field(description="面向用户展示的阶段标题。") content: str = Field(description="面向用户展示的过程摘要。") status: str = Field(default="completed", description="事件状态。") class StewardTask(BaseModel): task_id: str = Field(description="小财管家任务 ID。") task_type: StewardTaskType = Field(description="任务类型。") assigned_agent: StewardAssignedAgent = Field(description="建议分派的下游助手。") title: str = Field(description="任务标题。") summary: str = Field(description="任务摘要。") status: StewardTaskStatus = Field(default="needs_confirmation", description="任务状态。") confidence: float = Field(default=0.0, ge=0.0, le=1.0, description="识别置信度。") ontology_fields: dict[str, str] = Field(default_factory=dict, description="归一化后的业务本体字段。") missing_fields: list[str] = Field(default_factory=list, description="仍缺失的本体字段。") confirmation_required: bool = Field(default=True, description="执行前是否需要用户确认。") class StewardAttachmentGroup(BaseModel): group_id: str = Field(description="附件归集组 ID。") target_task_id: str | None = Field(default=None, description="建议归属的任务 ID。") scene: str = Field(description="归集场景编码。") scene_label: str = Field(description="归集场景展示名。") attachment_names: list[str] = Field(default_factory=list, description="建议纳入的附件名称。") excluded_attachment_names: list[str] = Field(default_factory=list, description="建议排除或单独处理的附件名称。") confidence: float = Field(default=0.0, ge=0.0, le=1.0, description="归集置信度。") rationale: str = Field(default="", description="归集依据。") confirmation_required: bool = Field(default=True, description="归集前是否需要用户确认。") class StewardConfirmationAction(BaseModel): confirmation_id: str = Field(description="确认动作 ID。") action_type: str = Field(description="确认动作类型。") label: str = Field(description="确认按钮文案。") description: str = Field(default="", description="确认动作说明。") target_task_id: str | None = Field(default=None, description="关联任务 ID。") attachment_group_id: str | None = Field(default=None, description="关联附件归集组 ID。") status: StewardConfirmationStatus = Field(default="pending", description="确认状态。") payload: dict[str, Any] = Field(default_factory=dict, description="确认后继续执行所需载荷。") class StewardPlanResponse(BaseModel): plan_id: str = Field(description="小财管家计划 ID。") plan_status: str = Field(default="needs_confirmation", description="计划状态。") planning_source: StewardPlanningSource = Field(default="rule_fallback", description="计划生成来源。") summary: str = Field(description="计划摘要。") thinking_events: list[StewardThinkingEvent] = Field(default_factory=list, description="过程摘要事件。") tasks: list[StewardTask] = Field(default_factory=list, description="拆解后的任务。") attachment_groups: list[StewardAttachmentGroup] = Field(default_factory=list, description="附件归集建议。") confirmation_groups: list[StewardConfirmationAction] = Field(default_factory=list, description="等待用户确认的动作。") model_call_traces: list[dict[str, Any]] = Field(default_factory=list, description="模型工具调用轨迹。")