'use client'; import Link from 'next/link'; import React from 'react'; import { Activity, ArrowRight, Clock3, FolderKanban, Loader2, Sparkles, Users, } from 'lucide-react'; import { OfficeStatusBadge, formatOfficeTime, progressPercent } from '@/components/office/OfficeShared'; import { TaskManagementTabs } from '@/components/task-management/TaskManagementTabs'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { buildOfficeTaskList, isOfficeTaskTerminal } from '@/lib/office'; import { useChatStore } from '@/lib/store'; function TaskCard({ taskId, title, sessionLabel, rootActorName, status, updatedAt, memberCount, activeRuns, artifactCount, errorCount, currentStageLabel, progressLabel, progressValue, }: { taskId: string; title: string; sessionLabel: string; rootActorName: string; status: Parameters[0]['status']; updatedAt: string; memberCount: number; activeRuns: number; artifactCount: number; errorCount: number; currentStageLabel: string | null; progressLabel: string; progressValue: number; }) { return (
{title} 会话: {sessionLabel} 主 Agent: {rootActorName} 更新于 {formatOfficeTime(updatedAt)}
{progressLabel} {currentStageLabel ? {currentStageLabel} : null}
); } function Metric({ icon: Icon, label, value, }: { icon: React.ComponentType<{ className?: string }>; label: string; value: string; }) { return (
{label}
{value}
); } export default function OfficeListPage() { const sessionId = useChatStore((state) => state.sessionId); const sessions = useChatStore((state) => state.sessions); const processRuns = useChatStore((state) => state.processRuns); const processEvents = useChatStore((state) => state.processEvents); const processArtifacts = useChatStore((state) => state.processArtifacts); const wsStatus = useChatStore((state) => state.wsStatus); const tasks = React.useMemo( () => buildOfficeTaskList({ sessionId, sessions, processRuns, processEvents, processArtifacts, }), [processArtifacts, processEvents, processRuns, sessionId, sessions] ); const activeTasks = tasks.filter((task) => !isOfficeTaskTerminal(task.status)); const recentTasks = tasks.filter((task) => isOfficeTaskTerminal(task.status)); return (

Office

基于当前会话的真实运行数据,展示主 Agent 与子 Agent 的任务现场。任务结束后会从活跃现场移除,但保留回看入口。

当前会话
{sessionId}
连接状态
{wsStatus === 'connected' ? '已连接' : wsStatus}
{wsStatus === 'connecting' && tasks.length === 0 ? (
正在等待运行时数据...
) : null} {tasks.length === 0 ? (

当前没有可展示的任务现场

先回到对话页发起一次主 Agent 任务。开始执行后,这里会出现活跃的 office 卡片。

) : ( <>

活跃 Office

正在运行中的任务现场会优先显示。

{activeTasks.length} 个任务
{activeTasks.length === 0 ? ( 当前没有活跃任务,下面可以查看最近结束的任务。 ) : (
{activeTasks.map((task) => ( ))}
)}

最近结束

已完成、失败或取消的任务仍保留回看入口。

{recentTasks.length} 个任务
{recentTasks.length === 0 ? ( 还没有历史任务。 ) : (
{recentTasks.map((task) => ( ))}
)}
)}
); }