feat(desktop): 多智能体「团队」视图(运行·观测新增,轨迹仍默认)
把多智能体协调画成「协调者居中 + 专家工位环绕」,让最难读的一段——并行派发与综合
——变得一眼可读。执行轨迹保持默认视图;「团队」tab 只在多智能体运行时出现,
普通任务不塞多余 tab。
- lib/run.ts 加 isMultiAgent()(据 coordinator: 节点判定) + deriveTeam():
从现有执行事件流派生协调者/工位模型。与 deriveNodes 的区别是保留 start/end 时间戳,
才能画并发时间轴;并解析专家收尾 detail("简报 X → Y")还原简报与产出。
- components/TeamView.tsx:径向布局(工位按角度均分环绕,>6 个降级为网格)、
协调者实时思考流(接 token 流 + 闪烁光标)、并发时间轴(重叠一眼可见)。
动效只标活跃态(派发链路流动/工位脉冲)——是状态编码不是装饰,带 prefers-reduced-motion 守卫。
专家(kind=agent)与工具(kind=tool)图标区分。
- 零后端改动:数据全部来自现有 exec 事件(coordinator:/agent:/tool:)。
补 9 个单测覆盖派生逻辑(简报解析/失败态/时间窗/lead 不混入工位)。
实机经回放路径验证渲染(径向布局/简报/并发条/tab 条件出现)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,14 +1,15 @@
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { Activity, FileText, History, Users, Wrench } from "lucide-react";
|
||||
import { ExecTrace } from "../components/ExecTrace";
|
||||
import { TeamView } from "../components/TeamView";
|
||||
import { Markdown } from "../components/Markdown";
|
||||
import { ChartView } from "../components/ChartView";
|
||||
import { extractChartBlocks, hasChart } from "../lib/chartspec";
|
||||
import { deriveNodes, emptyRun, type RunState } from "../lib/run";
|
||||
import { deriveNodes, isMultiAgent, emptyRun, type RunState } from "../lib/run";
|
||||
import { listRuns, taskEval, runReplay, type RunSummary, type EvalResult } from "../lib/api";
|
||||
import { Tabs, Panel, Dot, Badge, EmptyState, cn, type TabDef } from "../ui";
|
||||
|
||||
type DetailTab = "trace" | "tools" | "eval";
|
||||
type DetailTab = "trace" | "team" | "tools" | "eval";
|
||||
|
||||
const STATUS_DOT: Record<string, "success" | "danger" | "warn" | "running" | "neutral"> = {
|
||||
done: "success", failed: "danger", timeout: "danger", rejected: "danger",
|
||||
@@ -68,8 +69,13 @@ export function RunsView({ run }: { run: RunState }) {
|
||||
const nodes = deriveNodes(cur.exec);
|
||||
// 工具调用面板纳入专家派发:MCP 工具(kind=tool)与多智能体协调里的子智能体派发(kind=agent)都是「调用」。
|
||||
const calls = nodes.filter((n) => n.kind === "tool" || n.kind === "agent");
|
||||
// 「团队」视图只在多智能体协调的运行里出现(普通任务轨迹已足够,不塞多余 tab)。
|
||||
const multi = isMultiAgent(cur.exec);
|
||||
// 切到非多智能体运行时,「团队」tab 会消失——此时停在它上面要回落轨迹,否则内容悬空。
|
||||
const activeTab: DetailTab = !multi && tab === "team" ? "trace" : tab;
|
||||
const tabs: TabDef<DetailTab>[] = [
|
||||
{ key: "trace", label: "执行轨迹", count: nodes.length },
|
||||
...(multi ? ([{ key: "team", label: "团队" }] as TabDef<DetailTab>[]) : []),
|
||||
{ key: "tools", label: "工具/专家", count: calls.length },
|
||||
{ key: "eval", label: "评测" },
|
||||
];
|
||||
@@ -124,15 +130,17 @@ export function RunsView({ run }: { run: RunState }) {
|
||||
{/* 中:tab 切换 轨迹/工具/评测 + 状态指示 */}
|
||||
<div className="flex min-h-0 flex-col rounded-lg border border-line bg-ink-900">
|
||||
<div className="flex items-center border-b border-line px-2">
|
||||
<Tabs tabs={tabs} value={tab} onChange={setTab} />
|
||||
<Tabs tabs={tabs} value={activeTab} onChange={setTab} />
|
||||
<span className={cn("ml-auto pr-2 text-[11px]", statusCls)}>{statusText}</span>
|
||||
</div>
|
||||
<div className="min-h-0 flex-1 overflow-auto p-4">
|
||||
{empty ? (
|
||||
<EmptyState icon={Activity} title="选择一次运行" desc="左侧点选历史运行即可回放轨迹;或在编排/报告页发起新运行。" />
|
||||
) : tab === "trace" ? (
|
||||
) : activeTab === "trace" ? (
|
||||
<ExecTrace events={cur.exec} phase={cur.phase} />
|
||||
) : tab === "tools" ? (
|
||||
) : activeTab === "team" ? (
|
||||
<TeamView events={cur.exec} output={cur.output} phase={cur.phase} />
|
||||
) : activeTab === "tools" ? (
|
||||
<ToolCalls run={cur} />
|
||||
) : (
|
||||
<EvalView ev={evalRes} />
|
||||
|
||||
Reference in New Issue
Block a user