import { useCallback, useRef, useState } from "react"; import { TopBar } from "./shell/TopBar"; import { LeftNav, type ViewKey } from "./shell/LeftNav"; import { BottomDrawer } from "./shell/BottomDrawer"; import { StudioView } from "./studio/StudioView"; import { MemoryView } from "./views/MemoryView"; import { KbView } from "./views/KbView"; import { ReportView } from "./views/ReportView"; import { RunsView } from "./views/RunsView"; import { Home } from "./views/Home"; import { Placeholder } from "./views/Placeholder"; import { submitTask, streamTokens, streamExec, type Identity } from "./lib/api"; import type { TaskDsl } from "./lib/dsl"; import { emptyRun, type RunState } from "./lib/run"; import { ToastProvider } from "./ui"; const PLACEHOLDERS: Partial> = { home: { title: "工作台", desc: "概览:知识库 / 文档 / 近期运行 / 待办报告 / 配额计费 + 快捷入口。" }, kb: { title: "知识库 (RAG)", desc: "入库流水线监控 · 检索调试台(带来源徽标) · 文档/块浏览 · 知识图谱 · 检索评测。依赖 embedding + 入库 worker + 真实混合检索。" }, report: { title: "报告生成", desc: "模板库 · 大纲编辑 · 章节并行生成进度 · 实时预览(含引用) · 导出 docx/pdf。依赖 RAG 核心链 + UniOffice。" }, runs: { title: "运行 · 观测", desc: "实时执行 · 节点轨迹 · 工具调用 · 运行历史复盘。当前运行结果见底部抽屉。" }, market: { title: "市场 · Packs", desc: "垂直包(法律/医疗/金融) · Agent 模板 · 开通向导(建租户→入库→注册模板→应用配置)。依赖多租户 + Pack 格式。" }, admin: { title: "管理", desc: "租户/工作区 · 用户计费 · 护栏 · 模型与连接 · 设置。" }, }; export default function App() { const [view, setView] = useState("home"); const [identity, setIdentity] = useState({ userId: "wt", sessionId: "sess-ui" }); const [run, setRun] = useState(emptyRun); const closeRef = useRef<(() => void) | null>(null); const execCloseRef = useRef<(() => void) | null>(null); const onRun = useCallback( async (dsl: TaskDsl) => { closeRef.current?.(); execCloseRef.current?.(); const t0 = Date.now(); setRun({ phase: "submitting", output: "", events: [{ t: 0, label: "提交任务" }], exec: [] }); try { const taskId = await submitTask(dsl, identity); let first = true; setRun((r) => ({ ...r, phase: "streaming", taskId, events: [...r.events, { t: Date.now() - t0, label: `已发布 ${taskId}` }], })); // 执行轨迹(运行·观测):与 token 流并行订阅,逐节点点亮。 execCloseRef.current = streamExec( taskId, (ev) => setRun((r) => ({ ...r, exec: [...r.exec, ev] })), () => {}, () => {}, ); closeRef.current = streamTokens( taskId, (tok) => setRun((r) => { const ev = first ? [...r.events, { t: Date.now() - t0, label: "首 token" }] : r.events; first = false; return { ...r, output: r.output + tok, events: ev }; }), () => setRun((r) => ({ ...r, phase: "done", events: [...r.events, { t: Date.now() - t0, label: "完成" }], })), () => setRun((r) => ({ ...r, phase: "error", error: "连接中断" })), ); } catch (e) { setRun((r) => ({ ...r, phase: "error", error: (e as Error).message })); } }, [identity], ); return (
{/* 顶部柔光,增加纵深 */}
{view === "home" ? ( ) : view === "studio" ? ( ) : view === "kb" ? ( ) : view === "report" ? ( ) : view === "runs" ? ( ) : view === "memory" ? ( ) : ( )}
); }