Files
beaver_project/app-instance/frontend/components/chat-workbench/ChatWorkbench.tsx
steven_li 29dfd14aa6 ```
feat(agent): 添加对持久化子智能体的支持并增强委派管理

添加了持久化子智能体的完整生命周期管理功能,包括创建、更新、删除和查询API接口。
新增了子智能体的JSON-RPC通信协议支持,实现了远程调用和任务管理功能。

同时增强了委派管理器的功能:
- 添加了对本地委派、插件委派和本地回退的开关控制
- 实现了持久化子智能体任务的自动检测和本地执行保护
- 增加了对不同委派类型的权限验证机制

修改了智能体注册表以支持插件智能体的条件性包含,并更新了工具注册逻辑以支持可选工具。

BREAKING CHANGE: 委派管理器的构造函数签名已更改,添加了新的控制参数。
```
2026-03-27 10:15:35 +08:00

133 lines
4.3 KiB
TypeScript

'use client';
import React from 'react';
import type { ChatMessage, ProcessArtifact, ProcessEvent, ProcessRun } from '@/types';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { MessageList } from '@/components/chat-workbench/MessageList';
import { ArtifactSidebar } from '@/components/chat-workbench/ArtifactSidebar';
export function ChatWorkbench({
messages,
isThinking,
messagesEndRef,
messageViewportRef,
processRuns,
processEvents,
processArtifacts,
selectedRunId,
onSelectRun,
onCancelRun,
}: {
messages: ChatMessage[];
isThinking: boolean;
messagesEndRef: React.RefObject<HTMLDivElement>;
messageViewportRef: React.RefObject<HTMLDivElement>;
processRuns: ProcessRun[];
processEvents: ProcessEvent[];
processArtifacts: ProcessArtifact[];
selectedRunId: string | null;
onSelectRun: (runId: string) => void;
onCancelRun: (runId: string) => void;
}) {
const selectedRun = selectedRunId
? processRuns.find((item) => item.run_id === selectedRunId) || null
: null;
const selectedRunEvents = selectedRun
? processEvents.filter((item) => item.run_id === selectedRun.run_id)
: [];
const selectedRunArtifacts = selectedRun
? processArtifacts.filter((item) => item.run_id === selectedRun.run_id)
: [];
const hasResultsPanel = Boolean(
selectedRun &&
(
selectedRun.summary ||
selectedRunEvents.length > 0 ||
selectedRunArtifacts.length > 0
)
);
const desktopColumns = hasResultsPanel
? 'lg:grid-cols-[minmax(0,1fr)_360px]'
: 'lg:grid-cols-[minmax(0,1fr)]';
return (
<>
<div className={`hidden lg:grid h-full ${desktopColumns}`}>
<div className="min-h-0">
<MessageList
messages={messages}
isThinking={isThinking}
messagesEndRef={messagesEndRef}
viewportRef={messageViewportRef}
processRuns={processRuns}
processEvents={processEvents}
processArtifacts={processArtifacts}
selectedRunId={selectedRun?.run_id || null}
onSelectRun={onSelectRun}
onCancelRun={onCancelRun}
/>
</div>
{hasResultsPanel && (
<div className="min-h-0">
<ArtifactSidebar
selectedRun={selectedRun}
events={processEvents}
artifacts={processArtifacts}
/>
</div>
)}
</div>
<div className="lg:hidden h-full">
{!hasResultsPanel ? (
<MessageList
messages={messages}
isThinking={isThinking}
messagesEndRef={messagesEndRef}
viewportRef={messageViewportRef}
processRuns={processRuns}
processEvents={processEvents}
processArtifacts={processArtifacts}
selectedRunId={selectedRun?.run_id || null}
onSelectRun={onSelectRun}
onCancelRun={onCancelRun}
/>
) : (
<Tabs defaultValue="chat" className="h-full flex flex-col">
<div className="px-4 pt-3 border-b border-border">
<TabsList className="grid w-full grid-cols-2">
<TabsTrigger value="chat"></TabsTrigger>
{hasResultsPanel && <TabsTrigger value="results"></TabsTrigger>}
</TabsList>
</div>
<TabsContent value="chat" className="flex-1 min-h-0 mt-0">
<MessageList
messages={messages}
isThinking={isThinking}
messagesEndRef={messagesEndRef}
viewportRef={messageViewportRef}
processRuns={processRuns}
processEvents={processEvents}
processArtifacts={processArtifacts}
selectedRunId={selectedRun?.run_id || null}
onSelectRun={onSelectRun}
onCancelRun={onCancelRun}
/>
</TabsContent>
{hasResultsPanel && (
<TabsContent value="results" className="flex-1 min-h-0 mt-0">
<ArtifactSidebar
selectedRun={selectedRun}
events={processEvents}
artifacts={processArtifacts}
/>
</TabsContent>
)}
</Tabs>
)}
</div>
</>
);
}