import { useState } from "react"; import { useAppStore } from "../../store/useAppStore"; import type { AgentInfo, AgentStatus } from "../../lib/types"; import { Notice, PageHeader } from "../components"; import { Button, EmptyState, Surface, Tag, type TagTone } from "../../components/primitives"; import { sendUp } from "../../lib/ws"; import { useAuditStore } from "../audit"; const statusTone: Record = { idle: { label: "空闲", tone: "neutral" }, running: { label: "运行中", tone: "accent" }, blocked: { label: "阻塞", tone: "warn" }, done: { label: "完成", tone: "ok" }, error: { label: "错误", tone: "err" }, }; function AgentCard({ agent, onKill }: { agent: AgentInfo; onKill: (id: string) => void }): React.ReactNode { const meta = statusTone[agent.status] ?? statusTone.idle; return (
{agent.name} {agent.role ? {agent.role} : null} {meta.label}
{typeof agent.progress === "number" ? (
) : null} {agent.thinking ? (
{agent.thinking}
) : null} {agent.tools?.map((t, i) => (
⚙ {t.name}{t.ok === false ? " ✗" : ""}
))} {agent.message ?
{agent.message}
: null}
); } export function AgentsModule(): React.ReactNode { const agents = useAppStore((s) => s.agents); const flowGraph = useAppStore((s) => s.flowGraph); const taskLogs = useAppStore((s) => s.taskLogs); const clearTaskLog = useAppStore((s) => s.clearTaskLog); const log = useAuditStore((s) => s.log); const [tab, setTab] = useState<"main" | "sub">("main"); const subAgents = agents.filter((a) => a.id !== "main"); const list = tab === "main" ? agents.filter((a) => a.id === "main") : subAgents; return (
{ log("agent.respawn", "ok"); alert("重派(占位):后端 M10+ 提供子代理重派。"); }} > 重派 } />
setTab("main")}>主会话 setTab("sub")}>子代理 ({subAgents.length})
{flowGraph ? ( {flowGraph.nodes.map((n, i) => (
{n.label} {i < flowGraph.nodes.length - 1 ? → : null}
))}
) : ( 流程图占位 —— 连接 /ws/chat 后按 graph_update 事件渲染。 )} {list.length === 0 ? ( ) : (
{list.map((a) => ( { log(`agent.kill:${id}`, "ok"); alert(`终止 ${id}(占位)`); }} /> ))}
)}

Agent 消息流 / 后台任务日志

{Object.keys(taskLogs).length === 0 ? (
暂无任务日志。
) : ( Object.entries(taskLogs).map(([id, text]) => (
{id}
{text}
)) )} 子代理链上下文查询、终止/重派、流程图导出需后端 M10+ 提供。
); } function TabPill({ active, onClick, children }: { active: boolean; onClick: () => void; children: React.ReactNode }): React.ReactNode { return ( ); }