diff --git a/frontend-web/src/roundtable-planning/components/Step2Panel.tsx b/frontend-web/src/roundtable-planning/components/Step2Panel.tsx
index 4fbbb315..b872c93c 100644
--- a/frontend-web/src/roundtable-planning/components/Step2Panel.tsx
+++ b/frontend-web/src/roundtable-planning/components/Step2Panel.tsx
@@ -2,7 +2,7 @@
* Step 2 主面板 —— 多智能体圆桌研讨。
*
* 包含 4 块:
- * 1) 顶部 Headline + 挂起/恢复按钮
+ * 1) 顶部 Headline + 推理模型下拉 + 挂起/恢复按钮
* 2) Persona 抽屉(点击席位头像后展开,见 `PersonaDrawer.tsx`)
* 3) 对话流(初始化占位 + 气泡列表 + ChainOfThought 折叠卡 + markdown)
* 4) 底部澄清条 + 用户干预输入 + 「达成共识」入口
@@ -68,6 +68,7 @@ export interface Step2PanelProps {
selectedModel: string;
availableModels: ModelOption[];
modelsLoading: boolean;
+ setSelectedModel: React.Dispatch>;
// ─── Setters ──────────────────────────────────────────────────
setIsRoundTableRunning: React.Dispatch>;
setClarificationDraft: React.Dispatch>;
@@ -100,6 +101,7 @@ export function Step2Panel(props: Step2PanelProps) {
selectedModel,
availableModels,
modelsLoading,
+ setSelectedModel,
setIsRoundTableRunning,
setClarificationDraft,
setCustomAgentInput,
@@ -129,7 +131,32 @@ export function Step2Panel(props: Step2PanelProps) {
-
+
+
{isRoundTableRunning && isOrchestrating ? (
>
- ) : (
- <>
- {/* 任务概览 */}
-
-
-
-
任务概览
-
-
-
-
- 当前节点
-
-
- 初始任务
-
- {currentStep === 1 ? "待澄清" : currentStep === 2 ? "研讨中" : "已规划交付"}
-
-
-
- 围绕某复杂任务制定规划方案
-
+ ) : currentStep === 2 ? (
+ sidebarExpanded ? (
+ <>
+
setSidebarExpanded((v) => !v),
+ }}
+ />
+
+
+
+
+
参与角色
+
+
+ {roles.map((role) => (
+
+ ))}
-
- {/* 参与角色 */}
+
+
+ >
+ ) : (
+ <>
+
+
+
+
+
+
+ {roles.map((role) => (
+
+ ))}
+
+
+
+
+
+
+
+
+
+
+ >
+ )
+ ) : (
+ <>
+
+
@@ -896,32 +948,317 @@ function LeftSidebar({
- {/* 人工参与 */}
-
-
-
-
-
- 用户
-
-
-
-
-
-
- 在线
-
-
-
+
>
)}
);
}
+function TaskOverviewCard({ currentStep }: { currentStep: number }) {
+ return (
+
+
+
+
任务概览
+
+
+
+
+ 当前节点
+
+
+ 初始任务
+
+ {currentStep === 1 ? "待澄清" : currentStep === 2 ? "研讨中" : "已规划交付"}
+
+
+
+ 围绕某复杂任务制定规划方案
+
+
+
+
+ );
+}
+
+function HumanParticipationCard() {
+ return (
+
+
+
+
+
+ 用户
+
+
+
+
+
+
+ 在线
+
+
+
+ );
+}
+
+interface ModelSelectorCardProps {
+ selectedModel: string;
+ setSelectedModel: React.Dispatch
>;
+ availableModels: ReadonlyArray<{ name: string; display_name?: string }>;
+ modelsLoading: boolean;
+}
+
+function ModelSelectorCard({
+ selectedModel,
+ setSelectedModel,
+ availableModels,
+ modelsLoading,
+}: ModelSelectorCardProps) {
+ return (
+
+
+
+
推理模型
+
+
+
+ );
+}
+
+interface IntentSummaryCardProps {
+ intentReady: ReturnType["intentReady"];
+ title?: string;
+ /** Step 2 侧栏: 收起时仅展示目标,展开后显示约束与假设。 */
+ collapsible?: boolean;
+ /** 侧栏整体收起按钮,放在标题栏右侧。 */
+ sidebarToggle?: {
+ expanded: boolean;
+ onToggle: () => void;
+ };
+}
+
+function IntentSummaryCard({
+ intentReady,
+ title = "当前意图摘要",
+ collapsible = false,
+ sidebarToggle,
+}: IntentSummaryCardProps) {
+ const [expanded, setExpanded] = useState(!collapsible);
+ const showFullDetail = !collapsible || expanded;
+
+ return (
+
+
+
+
+
{title}
+
+ {sidebarToggle && (
+
+ )}
+
+
+
+ {intentReady ? (
+ <>
+
+ -
+ •
+
+ 目标: {intentReady.objective}
+
+
+
+ {collapsible && (
+
+ )}
+ {showFullDetail && (
+
+ {intentReady.constraints.map((c, i) => (
+ -
+ •
+
+ 约束: {c}
+
+
+ ))}
+ {(intentReady.assumptions ?? []).map((a, i) => (
+ -
+ •
+
+ 假设: {a}
+
+
+ ))}
+
+ )}
+ >
+ ) : (
+
+ 等待任务理解智能体澄清完成...
+
+ )}
+
+
+ );
+}
+
+function IntentSectionIcon({ className }: { className?: string }) {
+ return (
+
+ );
+}
+
+function CollapsedSidebarSection({
+ title,
+ children,
+ className,
+}: {
+ title: string;
+ children: React.ReactNode;
+ className?: string;
+}) {
+ return (
+
+ {children}
+
+ );
+}
+
+function renderRoleAvatar(
+ role: RoleEntry,
+ agentNameToRole: Record<
+ string,
+ { speakerId: number; avatarType: string; displayName: string }
+ >,
+ size: string,
+) {
+ if (role.type === "human") {
+ return ;
+ }
+ return getAvatar(
+ role.agentId ? agentNameToRole[role.agentId]?.avatarType ?? "blue" : "blue",
+ size,
+ );
+}
+
+function RoleAvatarBadge({
+ role,
+ agentNameToRole,
+ size = "h-7 w-7",
+ showSpeakingAnimation = false,
+}: {
+ role: RoleEntry;
+ agentNameToRole: Record<
+ string,
+ { speakerId: number; avatarType: string; displayName: string }
+ >;
+ size?: string;
+ showSpeakingAnimation?: boolean;
+}) {
+ const isOngoing = role.status === "研讨中";
+ const animate = showSpeakingAnimation && isOngoing;
+
+ return (
+
+ {animate && (
+
+ )}
+
+ {renderRoleAvatar(role, agentNameToRole, size)}
+
+
+ );
+}
+
function RoleRow({
role,
agentNameToRole,
@@ -949,14 +1286,7 @@ function RoleRow({
}`}
>
- {role.type === "human" ? (
-
- ) : (
- getAvatar(
- role.agentId ? agentNameToRole[role.agentId]?.avatarType ?? "blue" : "blue",
- "h-7 w-7",
- )
- )}
+
{role.name}
{role.type === "agent" && (
@@ -1024,89 +1354,21 @@ function RightSidebar({
timelineEntries,
triggerToast,
}: RightSidebarProps) {
- if (currentStep === 3) return null;
+ // Step 2 侧栏内容已迁至左侧;Step 3 沿用原逻辑不展示右侧栏。
+ if (currentStep !== 1) return null;
return (