feat(desktop): MVP 驾驶舱外壳 + 类型化节点 Studio + 运行抽屉

按 desktop-ui-plan.md 落 MVP:五区外壳 + 编排 Studio + 底部抽屉 + 健康灯。

- shell: TopBar(垂直切换/健康灯[Gateway/DB 实时,余规划]/身份会话) +
  LeftNav(BUILD/RUN/MANAGE 分组,未就绪模块灰显) + BottomDrawer(输出/轨迹/工具调用/引用/评测)
- studio: 类型化节点目录(输入/检索RAG/Agent/工具/记忆/分支/并行/汇聚/渲染/输出,
  按类配色) + 自定义 TypedNode(状态徽标) + Inspector(按类型渲染配置表单) +
  校验(孤立节点/必填项) + 运行
- views: MemoryView(复用偏好面板) + Placeholder(规划中模块,露出 IA 与依赖)
- lib: run(运行状态机) + health(轮询 billing) + dsl(导出类型化 DSL + validate)
- 删旧 AgentCanvas(被 StudioView 取代)

验证: npm run build(tsc+vite)✓; 真实浏览器跑通——加类型化节点→校验(标出孤立)→运行
→SSE 注入画像(老王)+历史 流入抽屉, 健康灯 Gateway/DB 实时绿

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Blizzard
2026-06-10 15:00:32 +08:00
parent a8e210cd96
commit 61c1177eba
14 changed files with 850 additions and 146 deletions
@@ -0,0 +1,156 @@
// 节点类型目录 —— Studio 画布的"类型化节点"定义(决定面板、配色、检查器字段)。
// 与后端 DSL / Eino 图节点对齐:输入 / 检索(RAG) / Agent / 工具 / 记忆 / 分支 / 并行 / 汇聚 / 渲染 / 输出。
export type FieldType = "text" | "textarea" | "number" | "select" | "checkbox";
export interface Field {
key: string;
label: string;
type: FieldType;
options?: string[];
placeholder?: string;
required?: boolean;
}
export interface NodeKind {
kind: string;
label: string;
accent: string; // 左色条 / 标签配色(tailwind 类)
badge: string;
desc: string;
fields: Field[];
defaults: Record<string, unknown>;
}
export const NODE_KINDS: Record<string, NodeKind> = {
input: {
kind: "input",
label: "输入",
accent: "border-l-amber-500",
badge: "bg-amber-100 text-amber-700",
desc: "用户提问 / 文件 / 变量",
fields: [
{ key: "source", label: "来源", type: "select", options: ["用户输入", "本地文件", "变量"] },
{ key: "placeholder", label: "占位文案", type: "text", placeholder: "请输入…" },
],
defaults: { source: "用户输入", placeholder: "请输入…" },
},
retriever: {
kind: "retriever",
label: "检索 (RAG)",
accent: "border-l-sky-500",
badge: "bg-sky-100 text-sky-700",
desc: "绑定知识库做混合检索",
fields: [
{ key: "kb", label: "知识库", type: "select", options: ["(未建库)", "合同库", "判例库"], required: true },
{ key: "topK", label: "TopK", type: "number" },
{ key: "rerank", label: "重排 Rerank", type: "checkbox" },
],
defaults: { kb: "(未建库)", topK: 5, rerank: true },
},
agent: {
kind: "agent",
label: "Agent / LLM",
accent: "border-l-violet-500",
badge: "bg-violet-100 text-violet-700",
desc: "调模型生成",
fields: [
{ key: "model", label: "模型", type: "select", options: ["占位 Pool", "ollama:qwen", "vllm:custom"], required: true },
{ key: "system", label: "系统提示词", type: "textarea", placeholder: "你是…" },
{ key: "temperature", label: "温度", type: "number" },
],
defaults: { model: "占位 Pool", system: "", temperature: 0.7 },
},
tool: {
kind: "tool",
label: "工具",
accent: "border-l-blue-500",
badge: "bg-blue-100 text-blue-700",
desc: "绑定 MCP 工具",
fields: [
{
key: "tool",
label: "工具",
type: "select",
options: ["wiki_search", "parse_document", "render_doc", "memory_get", "external_api"],
required: true,
},
{ key: "args", label: "参数(JSON)", type: "textarea", placeholder: '{"q":"..."}' },
],
defaults: { tool: "wiki_search", args: "{}" },
},
memory: {
kind: "memory",
label: "记忆",
accent: "border-l-emerald-500",
badge: "bg-emerald-100 text-emerald-700",
desc: "注入画像 / 历史 / 语义",
fields: [
{ key: "profile", label: "注入画像", type: "checkbox" },
{ key: "history", label: "注入历史", type: "checkbox" },
{ key: "semantic", label: "语义召回", type: "checkbox" },
],
defaults: { profile: true, history: true, semantic: false },
},
branch: {
kind: "branch",
label: "分支",
accent: "border-l-rose-500",
badge: "bg-rose-100 text-rose-700",
desc: "条件路由",
fields: [{ key: "condition", label: "条件", type: "text", placeholder: "score > 0.8" }],
defaults: { condition: "" },
},
map: {
kind: "map",
label: "并行 / Map",
accent: "border-l-fuchsia-500",
badge: "bg-fuchsia-100 text-fuchsia-700",
desc: "fan-out(逐章节)",
fields: [{ key: "splitBy", label: "拆分依据", type: "text", placeholder: "sections" }],
defaults: { splitBy: "sections" },
},
aggregate: {
kind: "aggregate",
label: "汇聚",
accent: "border-l-fuchsia-700",
badge: "bg-fuchsia-100 text-fuchsia-800",
desc: "reduce / 合并",
fields: [{ key: "strategy", label: "合并策略", type: "select", options: ["拼接", "去重合并", "摘要"] }],
defaults: { strategy: "拼接" },
},
render: {
kind: "render",
label: "渲染",
accent: "border-l-cyan-600",
badge: "bg-cyan-100 text-cyan-700",
desc: "UniOffice 出 docx/pdf",
fields: [
{ key: "format", label: "格式", type: "select", options: ["docx", "pdf"] },
{ key: "template", label: "模板", type: "text", placeholder: "默认" },
],
defaults: { format: "docx", template: "默认" },
},
output: {
kind: "output",
label: "输出",
accent: "border-l-gray-500",
badge: "bg-gray-100 text-gray-700",
desc: "展示 / 导出 / 落盘",
fields: [{ key: "target", label: "目标", type: "select", options: ["屏幕", "本地文件"] }],
defaults: { target: "屏幕" },
},
};
export const NODE_ORDER = [
"input",
"retriever",
"agent",
"tool",
"memory",
"branch",
"map",
"aggregate",
"render",
"output",
];