瀏覽代碼

可视化:定义 Journey 展示数据模型

用 Mission、Phase、Task、Attempt、Validation、Evidence 和运行摘要模型表达真实脚本构建旅程,替代旧版面向 MissionControl 的扁平响应结构。
SamLee 9 小時之前
父節點
當前提交
d059fe3931
共有 1 個文件被更改,包括 76 次插入105 次删除
  1. 76 105
      visualization/backend/app/models.py

+ 76 - 105
visualization/backend/app/models.py

@@ -2,7 +2,7 @@ from __future__ import annotations
 
 from typing import Any, Literal, Optional
 
-from pydantic import BaseModel, ConfigDict
+from pydantic import BaseModel, ConfigDict, Field
 
 
 class ViewModel(BaseModel):
@@ -11,125 +11,96 @@ class ViewModel(BaseModel):
 
 class RunSummary(ViewModel):
     script_build_id: int
-    title: str
     status: str
-    checkpoint: str
-    root_trace_id: str
-    revision: int
-    task_count: int
-    attempt_count: int
-    planner_turn_count: int
-    current_focus_task_id: Optional[str]
-    current_gap: str
-    created_at: str
-    updated_at: str
+    summary: str
+    started_at: Optional[str] = None
+    completed_at: Optional[str] = None
 
 
-class TaskNode(ViewModel):
-    task_id: str
-    display_path: str
-    parent_task_id: Optional[str]
-    child_task_ids: list[str]
-    task_kind: str
-    phase: str
-    objective: str
-    status: str
-    blocked_reason: Optional[str]
-    attempt_count: int
-    validation_count: int
-    decision_count: int
-    current_spec_version: int
-    acceptance_criteria: list[dict[str, Any]]
-    context_refs: list[str]
-    created_at: str
-    updated_at: str
+class InputSummary(ViewModel):
+    topic: str
+    account_name: Optional[str] = None
+    persona_point_count: int = 0
+    strategy_names: list[str] = Field(default_factory=list)
+    snapshot_id: str
+    digest: str
+
 
+class DataRef(ViewModel):
+    label: str
+    kind: str
+    ref: Optional[str] = None
+    detail: Optional[str] = None
 
-class PlannerTurn(ViewModel):
-    turn_id: str
-    order: int
-    message_sequence: int
-    phase: str
+
+class ContractNarration(ViewModel):
     action: str
-    action_label: str
-    summary: str
-    observable_reasoning: str
-    result_summary: str
-    status: Literal["succeeded", "failed", "unknown"]
-    focus_task_id: Optional[str]
-    affected_task_ids: list[str]
-    visible_task_ids: list[str]
-    tool_name: str
-    tool_arguments: dict[str, Any]
-    tokens: int
-    cost: float
-    created_at: str
+    reasoning: str
+    goals: list[str]
+    inputs: list[str]
+    output: str
+    criteria: list[str]
 
 
-class LifecycleEvent(ViewModel):
-    event_id: str
-    kind: Literal["task", "attempt", "validation", "decision"]
-    title: str
-    status: str
-    summary: str
-    created_at: str
-    attempt_id: Optional[str] = None
+class ProcessView(ViewModel):
+    label: str
+    actor: str
+    tool_name: Optional[str] = None
+    trace_id: Optional[str] = None
+    details: dict[str, Any] = Field(default_factory=dict)
+
 
+class StepEvidence(ViewModel):
+    contract: Optional[dict[str, Any]] = None
+    tool_calls: list[dict[str, Any]] = Field(default_factory=list)
+    artifact_refs: list[dict[str, Any]] = Field(default_factory=list)
+    validation: Optional[dict[str, Any]] = None
+    decision: Optional[dict[str, Any]] = None
 
-class AgentStep(ViewModel):
-    sequence: int
-    role: str
-    step_kind: Literal["instruction", "explanation", "tool_call", "tool_result"]
+
+class JourneyStep(ViewModel):
+    step_id: str
+    sequence: int = 0
+    step_type: Literal["plan", "execute", "validate", "decide"]
     title: str
-    text: str
-    tool_name: Optional[str]
-    tool_arguments: Optional[dict[str, Any]]
-    tokens: int
-    cost: float
-    duration_ms: Optional[float]
+    status: str
+    task_id: str
+    attempt_id: Optional[str] = None
+    validation_id: Optional[str] = None
+    decision_id: Optional[str] = None
+    reasoning: str
+    reasoning_source: Literal["observable", "contract", "validation", "decision", "system"]
+    process: ProcessView
+    input_data: list[DataRef] = Field(default_factory=list)
+    output_data: list[DataRef] = Field(default_factory=list)
+    contract: Optional[ContractNarration] = None
+    parallel_group_id: Optional[str] = None
+    parallel_position: Optional[int] = None
+    parallel_total: Optional[int] = None
+    model: Optional[str] = None
+    tokens: Optional[int] = None
+    cost: Optional[float] = None
+    duration_ms: Optional[int] = None
     created_at: str
+    evidence: StepEvidence
 
 
-class DataUsage(ViewModel):
-    inherited_inputs: list[dict[str, Any]]
-    confirmed_reads: list[dict[str, Any]]
-    produced_outputs: list[dict[str, Any]]
-    adoption: list[dict[str, Any]]
+class JourneyEdge(ViewModel):
+    edge_id: str
+    source: str
+    target: str
+    relation: Literal["sequence", "creates", "validates", "decides", "loop"]
+    label: str
 
 
-class AttemptDetail(ViewModel):
-    attempt_id: str
-    task_id: str
-    status: str
-    worker_preset: Optional[str]
-    worker_trace_id: Optional[str]
-    execution_mode: Optional[str]
-    started_at: Optional[str]
-    completed_at: Optional[str]
-    total_tokens: int
-    total_cost: float
-    error: Optional[Any]
-    submission: Optional[dict[str, Any]]
-    validation: Optional[dict[str, Any]]
-    decision: Optional[dict[str, Any]]
-    prompt: str
-    steps: list[AgentStep]
-
-
-class TaskDetail(ViewModel):
-    task: TaskNode
-    contract: Optional[dict[str, Any]]
-    lifecycle: list[LifecycleEvent]
-    attempts: list[AttemptDetail]
-    data_usage: DataUsage
-
-
-class ExecutionView(ViewModel):
-    schema_version: Literal["script-build-execution-view/v1"]
-    data_mode: Literal["persisted-real-run"]
+class JourneyView(ViewModel):
+    schema_version: Literal["script-build-journey/v1"]
     generated_at: str
-    run: RunSummary
-    planner_turns: list[PlannerTurn]
-    tasks: list[TaskNode]
-    snapshot_basis: str
+    script_build_id: int
+    root_trace_id: str
+    status: str
+    objective: str
+    input_summary: InputSummary
+    steps: list[JourneyStep]
+    edges: list[JourneyEdge]
     warnings: list[str]