From 337d4d76198d22784ec46012a21f262105161cdc Mon Sep 17 00:00:00 2001 From: Blizzard Date: Sat, 13 Jun 2026 16:14:54 +0800 Subject: [PATCH] =?UTF-8?q?feat(studio):=20=E5=AE=8C=E5=96=84=E7=BC=96?= =?UTF-8?q?=E6=8E=92=20=E2=80=94=E2=80=94=20=E6=A3=80=E7=B4=A2=E6=8E=A5?= =?UTF-8?q?=E6=9C=AC=E4=BA=BA=E7=9F=A5=E8=AF=86=E5=BA=93=20+=20=E7=9C=9F?= =?UTF-8?q?=E5=AE=9E=E6=A8=A1=E5=9E=8B=E4=B8=8B=E6=8B=89=20+=20=E6=A8=A1?= =?UTF-8?q?=E6=9D=BF/=E7=A4=BA=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 把编排从"演示桩"接到真实平台:检索节点查本人 owner 隔离的知识库,节点下拉用真实数据。 - dispatcher:makeToolNode 用 task user_id 给检索类工具的 kb 加 owner 前缀("uid/kb"), 编排里的「检索(RAG)」节点真正命中本人知识库(与隔离对齐)。 - 前端 StudioView:加 identity,载入 /kb/list 与 chat 模型作为「检索.kb」「Agent.model」下拉真值; Inspector 支持 dynamicOptions(无真值时提示去创建)。 - 编辑体验:示例(一键加载 输入→检索→Agent→输出 可运行图)/ 清空 / 模板名+保存(localStorage, 含布局)/ 载入下拉;ReactFlow deleteKeyCode 支持 Del/Backspace 删节点。 验证:示例图运行 → gateway 发布任务 → dispatcher 编译 → mcp-go 日志 `tool=wiki_search args=[kb:wt/default ...]`(kb 已按 owner 作用域)→ 命中本人库 → DeepSeek 流式作答; 底部抽屉 完成 ✓ · 工具调用 1。tsc+vite+dispatcher build 通过;重建 .app。 Co-Authored-By: Claude Opus 4.8 --- sundynix-desktop/frontend/src/App.tsx | 2 +- sundynix-desktop/frontend/src/lib/api.ts | 11 ++ .../frontend/src/studio/Inspector.tsx | 19 +- .../frontend/src/studio/StudioView.tsx | 163 +++++++++++++++--- sundynix-dispatcher/internal/eino/compile.go | 12 +- 5 files changed, 172 insertions(+), 35 deletions(-) diff --git a/sundynix-desktop/frontend/src/App.tsx b/sundynix-desktop/frontend/src/App.tsx index df6c76b..c5eaf4e 100644 --- a/sundynix-desktop/frontend/src/App.tsx +++ b/sundynix-desktop/frontend/src/App.tsx @@ -124,7 +124,7 @@ export default function App() { {view === "home" ? ( ) : view === "studio" ? ( - + ) : view === "kb" ? ( ) : view === "report" ? ( diff --git a/sundynix-desktop/frontend/src/lib/api.ts b/sundynix-desktop/frontend/src/lib/api.ts index 909ffbe..e8ca819 100644 --- a/sundynix-desktop/frontend/src/lib/api.ts +++ b/sundynix-desktop/frontend/src/lib/api.ts @@ -126,6 +126,17 @@ export interface VaultDoc { content: string; } +// listChatModels: GET /api/v1/admin/models?kind=chat —— 已登记的对话模型名(供编排 Agent 节点选择)。 +export async function listChatModels(): Promise { + try { + const res = await fetch(`${GATEWAY}/api/v1/admin/models?kind=chat`); + const data = (await res.json()) as { models?: Array<{ model: string }> }; + return (data.models ?? []).map((m) => m.model); + } catch { + return []; + } +} + // listVault: GET /api/v1/kb/vault —— 某知识库的原始文档(Obsidian 式文库浏览)。 export async function listVault(id: Identity, kb: string): Promise { const res = await fetch(`${GATEWAY}/api/v1/kb/vault?kb=${encodeURIComponent(kb)}`, { headers: idHeaders(id) }); diff --git a/sundynix-desktop/frontend/src/studio/Inspector.tsx b/sundynix-desktop/frontend/src/studio/Inspector.tsx index fc5df2e..2763279 100644 --- a/sundynix-desktop/frontend/src/studio/Inspector.tsx +++ b/sundynix-desktop/frontend/src/studio/Inspector.tsx @@ -9,10 +9,12 @@ export function Inspector({ node, onChange, onDelete, + dynamicOptions, }: { node: Node | null; onChange: (id: string, patch: Record) => void; onDelete: (id: string) => void; + dynamicOptions?: Record; // 运行时选项(如 kb=真实知识库、model=已登记模型) }) { if (!node) { return ( @@ -48,11 +50,18 @@ export function Inspector({ {f.label} {f.required && *} {f.type === "select" ? ( - + (() => { + const dyn = dynamicOptions?.[f.key]; + const opts = dyn && dyn.length ? dyn : f.options ?? []; + return ( + + ); + })() ) : f.type === "textarea" ? (