import { ArrowDown, Brain, CheckCircle2, CircleDot, Database, GitBranch, Play, RefreshCcw, Route, SearchCheck, Wrench, } from "lucide-react"; import { buildTaskCycles, groupParallelSteps, statusLabel } from "@/lib/journey"; import type { JourneyEdge, JourneyStep, JourneyView, StepType, ZoomLevel } from "@/lib/types"; const STEP_META: Record = { plan: { label: "规划", icon: Route }, execute: { label: "执行", icon: Play }, validate: { label: "验收", icon: SearchCheck }, decide: { label: "决策", icon: GitBranch }, }; interface JourneyCanvasProps { journey: JourneyView; zoom: ZoomLevel; selectedStepId: string | null; onSelectStep: (stepId: string) => void; } export function JourneyCanvas({ journey, zoom, selectedStepId, onSelectStep }: JourneyCanvasProps) { if (zoom === "journey") { return ; } const groups = groupParallelSteps(journey.steps); const loops = new Map( journey.edges.filter((edge) => edge.relation === "loop").map((edge) => [edge.source, edge]), ); return (
按真实发生顺序

Planner 如何一步步完成目标

点击任何步骤后切换到“证据”,可查看对应的合同、工具调用和验收记录。

{groups.map((group, index) => (
{group.kind === "parallel" ? (
Host 并行派发 {group.steps.length} 个任务
{group.steps.map((step) => ( onSelectStep(step.step_id)} /> ))}
) : ( onSelectStep(group.steps[0].step_id)} /> )} {index < groups.length - 1 ? ( ) : null}
))}
{journey.warnings.map((warning) => (

{warning}

))}
); } function JourneyOverview({ journey, onSelectStep, }: { journey: JourneyView; onSelectStep: (stepId: string) => void; }) { const cycles = buildTaskCycles(journey.steps, journey.edges); return (

这次创作经过了 {cycles.length} 个任务回合

默认只看业务因果。点开一个回合,再看 Planner、Worker 和 Validator 如何协作。

    {cycles.map((cycle, index) => (
  1. ))}
); } function StepCard({ step, loop, selected, onSelect, }: { step: JourneyStep; loop?: JourneyEdge; selected: boolean; onSelect: () => void; }) { const meta = STEP_META[step.step_type]; const Icon = meta.icon; return (
); } function formatDuration(value: number): string { if (value < 1000) return `${value}ms`; if (value < 60_000) return `${(value / 1000).toFixed(1)}s`; return `${Math.floor(value / 60_000)}m ${Math.round((value % 60_000) / 1000)}s`; }