"use client";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import {
ArrowDownToLine,
ArrowUpFromLine,
Braces,
Check,
ChevronRight,
CircleDot,
Database,
FileCode2,
LoaderCircle,
RefreshCw,
Search,
X,
} from "lucide-react";
import { fetchExecution, fetchRuns, fetchTaskDetail } from "@/lib/api";
import { buildTaskForest, statusLabel, taskKindLabel, type TaskBranch } from "@/lib/task-tree";
import type { AttemptDetail, ExecutionView, PlannerTurn, RunSummary, TaskDetail, TaskNode } from "@/lib/types";
type DetailTab = "lifecycle" | "attempt" | "data" | "code";
function shortId(value: string | null) {
return value ? `${value.slice(0, 8)}…` : "—";
}
function formatTime(value: string) {
if (!value) return "—";
const parsed = new Date(value);
return Number.isNaN(parsed.valueOf()) ? value : parsed.toLocaleTimeString("zh-CN", { hour: "2-digit", minute: "2-digit", second: "2-digit" });
}
function JsonBlock({ value }: { value: unknown }) {
return
{JSON.stringify(value, null, 2)};
}
function Empty({ children }: { children: React.ReactNode }) {
return {children}
;
}
function StatusMark({ status }: { status: string }) {
const complete = ["completed", "passed", "accept", "submitted", "succeeded"].includes(status);
return {complete ? : }{statusLabel(status)};
}
function Header({ runs, view, selectedId, onSelect, onRefresh, refreshing }: {
runs: RunSummary[];
view: ExecutionView;
selectedId: number;
onSelect: (id: number) => void;
onRefresh: () => void;
refreshing: boolean;
}) {
return
REAL EXECUTION OBSERVER
TaskLedger revision {view.run.revision}
每 15 秒只读刷新
{view.run.checkpoint}
当前缺口:{view.run.current_gap}
{view.run.task_count} Tasks / {view.run.attempt_count} Attempts / {view.run.planner_turn_count} Planner moves
;
}
function PlannerAxis({ turns, selectedId, tasks, onSelect }: {
turns: PlannerTurn[];
selectedId: string | null;
tasks: TaskNode[];
onSelect: (id: string) => void;
}) {
const selectedRef = useRef(null);
const taskById = useMemo(() => new Map(tasks.map((task) => [task.task_id, task])), [tasks]);
useEffect(() => {
selectedRef.current?.scrollIntoView({ block: "nearest" });
}, [selectedId]);
return
01 / GLOBAL PLANNER
全局 Planner 在树上移动焦点
选择一步,右侧回看当时已经长出的 Task
PLAN→EXECUTE→VALIDATE→DECIDE↻
{turns.map((turn) => {
const focus = turn.focus_task_id ? taskById.get(turn.focus_task_id) : null;
const active = turn.turn_id === selectedId;
return -
;
})}
;
}
function TaskRecord({ task, selected, focused, changed, onSelect }: {
task: TaskNode;
selected: boolean;
focused: boolean;
changed: boolean;
onSelect: (task: TaskNode) => void;
}) {
return ;
}
function TaskBranchView({ branch, selectedTaskId, focusedId, changedIds, onSelect }: {
branch: TaskBranch;
selectedTaskId: string | null;
focusedId: string | null;
changedIds: Set;
onSelect: (task: TaskNode) => void;
}) {
return
{branch.children.length ? {branch.children.map((child) => )}
: null}
;
}
function PlannerTurnNote({ turn, taskById }: { turn: PlannerTurn; taskById: Map }) {
const focus = turn.focus_task_id ? taskById.get(turn.focus_task_id) : null;
return
Planner move {turn.order}
{turn.action_label}{focus ? `:${focus.display_path} ${taskKindLabel(focus.task_kind)}` : ""}
{turn.summary}
查看这一步的可观察说明与工具输入
模型主动输出的说明(不是隐藏思维链)
{turn.observable_reasoning || "本步没有输出文字说明。"}
{turn.tool_name} arguments
工具结果摘要
{turn.result_summary}
;
}
function TaskTreePanel({ view, turn, query, onQuery, selectedTaskId, onSelect }: {
view: ExecutionView;
turn: PlannerTurn | null;
query: string;
onQuery: (value: string) => void;
selectedTaskId: string | null;
onSelect: (task: TaskNode) => void;
}) {
const allVisible = useMemo(() => new Set(turn?.visible_task_ids ?? view.tasks.map((task) => task.task_id)), [turn, view.tasks]);
const matching = useMemo(() => {
if (!query.trim()) return allVisible;
const needle = query.trim().toLowerCase();
const matches = new Set();
const byId = new Map(view.tasks.map((task) => [task.task_id, task]));
for (const task of view.tasks) {
if (!allVisible.has(task.task_id)) continue;
if (`${task.display_path} ${task.task_kind} ${task.objective}`.toLowerCase().includes(needle)) {
let current: TaskNode | undefined = task;
while (current) {
matches.add(current.task_id);
current = current.parent_task_id ? byId.get(current.parent_task_id) : undefined;
}
}
}
return matches;
}, [allVisible, query, view.tasks]);
const forest = useMemo(() => buildTaskForest(view.tasks, matching), [matching, view.tasks]);
const changedIds = useMemo(() => new Set(turn?.affected_task_ids ?? []), [turn]);
const taskById = useMemo(() => new Map(view.tasks.map((task) => [task.task_id, task])), [view.tasks]);
return
{turn ? : null}
Planner 当前焦点本步涉及当前 ledger 状态
{forest.length ?
{forest.map((branch) => )}
:
没有符合条件的 Task。}
;
}
function LifecycleView({ detail }: { detail: TaskDetail }) {
return
Planner创建 / 决定Worker提交Validator验收Planner↻
{detail.lifecycle.map((event) => -
{formatTime(event.created_at)} · {event.kind}{event.title}{event.summary || "无补充说明"}
)}
;
}
function AttemptLoop({ attempt }: { attempt: AttemptDetail | null }) {
if (!attempt) return 这个 Task 还没有 Attempt。;
return
{attempt.worker_preset}{attempt.total_tokens.toLocaleString()} tokens¥/cost {attempt.total_cost.toFixed(4)}
{attempt.steps.map((step, index) => -
{String(index + 1).padStart(2, "0")}
{step.role} · seq {step.sequence}{step.title}{step.text ?
{step.text} : null}{step.tool_arguments ?
: null}
)}
;
}
function DataView({ detail }: { detail: TaskDetail }) {
const groups = [
{ icon: ArrowDownToLine, title: "进入 Task 的数据", note: "在冻结输入闭包中,不代表 Worker 一定逐项读取", values: detail.data_usage.inherited_inputs },
{ icon: Database, title: "Worker 确认读取", note: "来自真实 worker_trace 的 read/get/search/query 工具调用", values: detail.data_usage.confirmed_reads },
{ icon: ArrowUpFromLine, title: "Task 产生的数据", note: "来自 Attempt submission 的 Artifact 引用", values: detail.data_usage.produced_outputs },
{ icon: Check, title: "采用与回退", note: "来自 PlannerDecision 持久化记录", values: detail.data_usage.adoption },
];
return {groups.map((group) =>
{group.title}
{group.note}
{group.values.length}
{group.values.length ? group.values.map((value, index) => ) : 没有对应记录。}
)}
;
}
function CodePromptView({ detail, attempt }: { detail: TaskDetail; attempt: AttemptDetail | null }) {
const explanations = attempt?.steps.filter((step) => step.step_kind === "explanation") ?? [];
return
Process / Contract
Task 的执行边界与输入输出约束。
{detail.contract ? : Root Task 没有独立 ScriptTaskContract。}
Prompt
当前 Attempt 实际持久化的 Worker system prompt。
{attempt?.prompt || "尚无 Worker Prompt。"}
Observable reasoning
只展示模型主动输出文字、工具动作和验收理由;不把它命名为隐藏思维链。
{explanations.length ? explanations.map((step, index) => {step.text}) : 这个 Attempt 没有主动输出说明文字。}
;
}
function TaskInspector({ detail, loading, tab, onTab, attemptId, onAttempt, onClose }: {
detail: TaskDetail | null;
loading: boolean;
tab: DetailTab;
onTab: (tab: DetailTab) => void;
attemptId: string | null;
onAttempt: (id: string) => void;
onClose: () => void;
}) {
if (loading || !detail) return ;
const attempt = detail.attempts.find((item) => item.attempt_id === attemptId) ?? detail.attempts.at(-1) ?? null;
return ;
}
function LoadingState() {
return 正在读取真实 E2E 持久化数据
TaskLedger · Planner Trace · Worker Attempt
;
}
function ErrorState({ message, retry }: { message: string; retry: () => void }) {
return 真实运行数据暂时不可读
{message}
;
}
export function MissionControl() {
const [runs, setRuns] = useState([]);
const [selectedRunId, setSelectedRunId] = useState(900031);
const [view, setView] = useState(null);
const [selectedTurnId, setSelectedTurnId] = useState(null);
const [selectedTaskId, setSelectedTaskId] = useState(null);
const [detail, setDetail] = useState(null);
const [detailLoading, setDetailLoading] = useState(false);
const [detailTab, setDetailTab] = useState("lifecycle");
const [attemptId, setAttemptId] = useState(null);
const [query, setQuery] = useState("");
const [loading, setLoading] = useState(true);
const [refreshing, setRefreshing] = useState(false);
const [error, setError] = useState(null);
const loadExecution = useCallback(async (runId: number, quiet = false) => {
if (!quiet) setLoading(true);
else setRefreshing(true);
try {
const execution = await fetchExecution(runId);
setView(execution);
setSelectedTurnId((current) => current && execution.planner_turns.some((turn) => turn.turn_id === current) ? current : execution.planner_turns.at(-1)?.turn_id ?? null);
setError(null);
} catch (reason) {
setError(reason instanceof Error ? reason.message : String(reason));
} finally {
setLoading(false);
setRefreshing(false);
}
}, []);
useEffect(() => {
const controller = new AbortController();
fetchRuns(controller.signal).then((available) => {
setRuns(available);
const preferred = available.find((run) => run.script_build_id === 900031) ?? available[0];
if (!preferred) throw new Error("没有发现真实持久化 Run");
setSelectedRunId(preferred.script_build_id);
return loadExecution(preferred.script_build_id);
}).catch((reason) => {
if (reason instanceof DOMException && reason.name === "AbortError") return;
setError(reason instanceof Error ? reason.message : String(reason));
setLoading(false);
});
return () => controller.abort();
}, [loadExecution]);
useEffect(() => {
const timer = window.setInterval(() => void loadExecution(selectedRunId, true), 15_000);
return () => window.clearInterval(timer);
}, [loadExecution, selectedRunId]);
useEffect(() => {
if (!selectedTaskId) {
setDetail(null);
return;
}
const controller = new AbortController();
setDetailLoading(true);
fetchTaskDetail(selectedRunId, selectedTaskId, controller.signal).then((value) => {
setDetail(value);
setAttemptId(value.attempts.at(-1)?.attempt_id ?? null);
}).catch((reason) => {
if (!(reason instanceof DOMException && reason.name === "AbortError")) setError(reason instanceof Error ? reason.message : String(reason));
}).finally(() => setDetailLoading(false));
return () => controller.abort();
}, [selectedRunId, selectedTaskId]);
const changeRun = (id: number) => {
setSelectedRunId(id);
setSelectedTaskId(null);
setDetail(null);
setSelectedTurnId(null);
void loadExecution(id);
};
const selectedTurn = view?.planner_turns.find((turn) => turn.turn_id === selectedTurnId) ?? null;
if (loading && !view) return ;
if (error && !view) return void loadExecution(selectedRunId)} />;
if (!view) return null;
return
void loadExecution(selectedRunId, true)} refreshing={refreshing} />
{ setSelectedTaskId(task.task_id); setDetailTab("lifecycle"); }} />
{selectedTaskId ? setSelectedTaskId(null)} /> : null}
;
}