From b101ee7fc9c0d95424fe2592a8ff71c26086ae57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=91=A3=E5=AE=8F=E5=87=AF?= Date: Mon, 8 Jun 2026 18:00:42 +0800 Subject: [PATCH] =?UTF-8?q?feat(roundtable):=20=E4=B8=9A=E5=8A=A1=E9=93=BE?= =?UTF-8?q?=E6=9D=A1=E5=B7=A6=E6=A0=8F=E5=8D=A1=E7=89=87=E6=8B=96=E5=8A=A8?= =?UTF-8?q?=E6=89=8B=E6=9F=84=20+=20=E5=8A=A0=E5=85=A5=E6=8C=89=E9=92=AE?= =?UTF-8?q?=20+=20=E6=99=BA=E8=83=BD=E4=BD=93=E8=AF=A6=E6=83=85=E6=8A=BD?= =?UTF-8?q?=E5=B1=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 左栏候选卡片加拖动手柄(与右栏席位一致),仅点手柄才拖动 - 加入改为显式「加入」按钮,点卡片本体改为打开详情抽屉 - 右栏席位操作区加「查看详情」按钮,打开同一抽屉 - 新增 AgentDetailSheet:按需拉取(useAgent)展示名称/模型/描述/ 标签/技能+工具组/人设,对齐智能体详情页内容 Co-Authored-By: Claude Opus 4.8 (1M context) --- .../components/AgentDetailSheet.tsx | 151 ++++++++++++++++++ .../pages/BusinessChainEditorPage.tsx | 115 ++++++++++--- 2 files changed, 241 insertions(+), 25 deletions(-) create mode 100644 frontend-web/src/roundtable-planning/components/AgentDetailSheet.tsx diff --git a/frontend-web/src/roundtable-planning/components/AgentDetailSheet.tsx b/frontend-web/src/roundtable-planning/components/AgentDetailSheet.tsx new file mode 100644 index 00000000..45165f8f --- /dev/null +++ b/frontend-web/src/roundtable-planning/components/AgentDetailSheet.tsx @@ -0,0 +1,151 @@ +/** + * 智能体详情抽屉(右侧 Sheet)。 + * + * 业务链条配置页:左栏候选卡片点击卡片本体、右栏席位点「查看详情」都打开这个抽屉, + * 展示该智能体的详情(与「智能体」详情页展示的内容差不多):名称 / 模型 / 描述 / + * 标签 / 技能 + 工具组 / 人设(SOUL.md)。 + * + * 详情按需拉取:`useAgent(open ? agentId : null)` —— 抽屉打开时才请求 `GET /api/agents/{id}` + * (该接口才返回 soul),关闭不请求。字段渲染对齐 `components/workspace/agents/agent-card.tsx`。 + */ +import { Bot, Globe, Loader2, Lock } from "lucide-react"; + +import { Badge } from "@/components/ui/badge"; +import { + Sheet, + SheetContent, + SheetDescription, + SheetHeader, + SheetTitle, +} from "@/components/ui/sheet"; +import { TagChipList } from "@/components/workspace/tags/tag-chip"; +import { useAgent } from "@/core/agents"; +import { desensitize } from "@/lib/desensitize"; + +export function AgentDetailSheet({ + agentId, + /** 卡片/席位上的名称快照,详情还没拉回来时先用它占位。 */ + fallbackName, + open, + onOpenChange, +}: { + agentId: string | null; + fallbackName?: string; + open: boolean; + onOpenChange: (open: boolean) => void; +}) { + // 抽屉打开时才拉详情(含 soul);关闭传 null 让 useAgent 不发请求。 + const { agent, isLoading } = useAgent(open ? agentId : null); + const name = agent?.name || fallbackName || agentId || ""; + const skillItems = agent?.skills ?? []; + const toolGroups = agent?.tool_groups ?? []; + const hasSkillsOrTools = skillItems.length > 0 || toolGroups.length > 0; + + return ( + + + + + + + + {name} + {agent?.model && ( + + {desensitize(agent.model)} + + )} + + 智能体详情 + + +
+ {isLoading && !agent ? ( +
+ + 正在加载详情… +
+ ) : !agent ? ( +
+ 未找到该智能体的详情(可能已被删除)。 +
+ ) : ( + <> + {/* 状态徽标 */} +
+ {agent.builtin && ( + 内置 + )} + {agent.published && ( + + + 已发布 + + )} + {agent.is_private && ( + + + 私密 + + )} +
+ + {/* 描述 */} +
+

+ 描述 +

+

+ {agent.description?.trim() || "(无描述)"} +

+
+ + {/* 标签 */} + {agent.tags && agent.tags.length > 0 && ( +
+

+ 标签 +

+ +
+ )} + + {/* 技能 / 工具组 */} + {hasSkillsOrTools && ( +
+

+ 技能与工具 +

+
+ {toolGroups.map((group) => ( + + {desensitize(group)} + + ))} + {skillItems.map((skill) => ( + + {desensitize(skill)} + + ))} +
+
+ )} + + {/* 人设(SOUL.md) */} + {agent.soul?.trim() && ( +
+

+ 人设 +

+
+                    {agent.soul}
+                  
+
+ )} + + )} +
+
+
+ ); +} diff --git a/frontend-web/src/roundtable-planning/pages/BusinessChainEditorPage.tsx b/frontend-web/src/roundtable-planning/pages/BusinessChainEditorPage.tsx index f92e329e..09ac5560 100644 --- a/frontend-web/src/roundtable-planning/pages/BusinessChainEditorPage.tsx +++ b/frontend-web/src/roundtable-planning/pages/BusinessChainEditorPage.tsx @@ -30,6 +30,7 @@ import { GitBranch, Globe, GripVertical, + Info, Layers, Loader2, Network, @@ -110,6 +111,7 @@ import { } from "@/roundtable-planning/lib/chain-stages"; import { getAvatarTypeFor } from "@/roundtable-planning/lib/roundtable-constants"; import { DagFlowChart } from "@/roundtable-planning/components/DagFlowChart"; +import { AgentDetailSheet } from "@/roundtable-planning/components/AgentDetailSheet"; const POOL_PREFIX = "pool::"; const SEAT_PREFIX = "seat::"; @@ -155,6 +157,11 @@ export default function BusinessChainEditorPage() { const [activeDrag, setActiveDrag] = useState(null); const [dropdownOpen, setDropdownOpen] = useState(false); const [flowOpen, setFlowOpen] = useState(false); + // 详情抽屉:左栏点卡片本体、右栏点「查看详情」都打开它,展示该智能体详情。 + const [detailAgent, setDetailAgent] = useState<{ id: string; name?: string } | null>(null); + const showDetail = useCallback((id: string, name?: string) => { + setDetailAgent({ id, name }); + }, []); const sensors = useSensors( useSensor(PointerSensor, { activationConstraint: { distance: 5 } }), @@ -763,7 +770,7 @@ export default function BusinessChainEditorPage() { {pool.length} - 拖到右侧 / 点击加入 + 拖手柄到右侧 / 点卡片看详情
@@ -794,6 +801,7 @@ export default function BusinessChainEditorPage() { agent={a} inChain={seatIdSet.has(a.agent_id)} onAdd={() => addAgentAsNewStage(a.agent_id)} + onShowDetail={() => showDetail(a.agent_id, a.name)} /> )) )} @@ -813,6 +821,7 @@ export default function BusinessChainEditorPage() { onMergeSeat={mergeSeatToStage} onSplitSeat={splitSeat} onStageGoalChange={setGoal} + onSeatDetail={showDetail} /> @@ -873,6 +882,16 @@ export default function BusinessChainEditorPage() { )} + {/* 智能体详情抽屉(左栏卡片 / 右栏席位共用) */} + { + if (!o) setDetailAgent(null); + }} + /> + {/* 页脚 */}