console: React 生产级重写(左列表 + 中对话 + 右详情)

旧单页 console.html 换成 Vite + React + TypeScript 单文件构建产物
(309525 字节,sha 90345ec8…,重建字节一致),源码在
cloud/console-react/,改页面只改 src 再 npm run build:console,
产物不手改。布局:左侧列表(模块导航 + 任务列表)、中间标准对话
(实时链路时间线 + 继续会话聊天框,共用 Chat 组件)、右侧详情
(元数据、操作、评审、审批、协调子任务、子代理、线程)。
API 与后端语义未改,key 只存浏览器 localStorage。
6 个 console 标记单测随实现改名更新(意图不变:壳确实调了
这些接口、turn 信息仍在详情里、旧 goal 输入仍不存在);
P1 标记单测未动且通过。
This commit is contained in:
host committed 2026-10-29 06:32:38 +08:00
1 parent 3f4e849a93
commit ebc5624893
57 files changed
+4789 -1746

No files matched your search

@@ -0,0 +1,37 @@
import { useMemo } from "react";
import { useConsole } from "../../context";
import { Bar } from "../../components/ui";
import { ChatList } from "../../components/chat/Chat";
import { traceEntryToChatMessage, type ChatMessage } from "../../components/chat/mapTrace";
export default function TracePanel() {
const ctx = useConsole();
const messages = useMemo<ChatMessage[]>(() => {
const t = ctx.currentTask;
const head: ChatMessage[] = t && t.prompt ? [{ id: "task-prompt", role: "user", text: t.prompt }] : [];
const pool = ctx.traceKind ? ctx.traceEntries.filter((e) => e.kind === ctx.traceKind) : ctx.traceEntries;
const body = pool.map((e, i) => traceEntryToChatMessage(e, i));
const tail: ChatMessage[] = ctx.traceDone ? [{ id: "trace-done", role: "status", text: "链路已结束(" + ctx.traceDone + ")" }] : [];
return [...head, ...body, ...tail];
}, [ctx.currentTask, ctx.traceEntries, ctx.traceKind, ctx.traceDone]);
return (
<>
<h3>实时链路</h3>
<Bar>
<select aria-label="链路类型" value={ctx.traceKind} onChange={(e) => ctx.setTraceKind(e.target.value)}>
<option value="">链路类型:全部</option>
{["exec", "file", "call", "tool", "message", "reasoning", "plan", "agent-start", "agent-done"].map((k) => (
<option key={k} value={k}>{k === "exec" ? "命令" : k === "file" ? "文件" : k === "call" ? "调用" : k === "tool" ? "工具" : k === "message" ? "消息" : k === "reasoning" ? "思考" : k === "plan" ? "计划" : "子代理"}</option>
))}
</select>
<button onClick={ctx.downloadTrace}>下载完整链路</button>
<span className="muted">{ctx.traceMsg}</span>
</Bar>
{ctx.traceNote ? <div><span className="err">{ctx.traceNote}</span></div> : null}
<div className="chat-column">
<ChatList messages={messages} empty="(暂无链路条目)" />
</div>
<div className="muted">对话时间线:首条是本任务 prompt(用户);助手回复来自 message 条目,命令/文件/工具/调用是工具气泡,计划/思考/子代理开始结束是居中状态提示。流式进行中时新条目实时追加;你在底部时自动跟随,往上翻时暂停跟随,点“回到最新”恢复。</div>
</>
);
}