From deb9993a64f1d3384ee0bb2b3db47346d1ce8191 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=91=A3=E5=AE=8F=E5=87=AF?= Date: Wed, 27 May 2026 17:25:10 +0800 Subject: [PATCH] =?UTF-8?q?=E7=82=B9=E5=87=BB=E7=A1=AE=E8=AE=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/Step2Panel.tsx | 10 +-- .../hooks/useStep2Orchestration.ts | 50 +++++++++++---- .../pages/RoundtablePlanningPage.tsx | 64 ++++++++++--------- 3 files changed, 77 insertions(+), 47 deletions(-) diff --git a/frontend-web/src/roundtable-planning/components/Step2Panel.tsx b/frontend-web/src/roundtable-planning/components/Step2Panel.tsx index c347246d..425808dd 100644 --- a/frontend-web/src/roundtable-planning/components/Step2Panel.tsx +++ b/frontend-web/src/roundtable-planning/components/Step2Panel.tsx @@ -171,18 +171,18 @@ export function Step2Panel(props: Step2PanelProps) { ))} - {isRoundTableRunning && isOrchestrating ? ( + {isRoundTableRunning ? ( - ) : !isRoundTableRunning ? ( + ) : ( - ) : null} + )} diff --git a/frontend-web/src/roundtable-planning/hooks/useStep2Orchestration.ts b/frontend-web/src/roundtable-planning/hooks/useStep2Orchestration.ts index 4a661971..a3b45de2 100644 --- a/frontend-web/src/roundtable-planning/hooks/useStep2Orchestration.ts +++ b/frontend-web/src/roundtable-planning/hooks/useStep2Orchestration.ts @@ -280,6 +280,9 @@ export function useStep2Orchestration( const orchestrationCancelRef = useRef(false); const step2InitRef = useRef(false); const activeAbortersRef = useRef>(new Set()); + /** 干预研审:暂停当前轮次后待执行的 leader prompt。 */ + const pendingInjectPromptRef = useRef(null); + const [injectFlushToken, setInjectFlushToken] = useState(0); // selectedModel / agentConfigs / agentNameToRole / threadIds / coordinatorName // 等等被 runOrchestration 在循环里反复读取。把它们打到 ref 上,可以让 // runOrchestration 的 useCallback deps 大幅收窄,避免每次模型切换、agentConfigs @@ -1043,7 +1046,11 @@ export function useStep2Orchestration( useEffect(() => { if (currentStep !== 2) return; if (!isRoundTableRunning) { - stopOrchestration(); + // 干预研审会先写入 pending 再置 false;此时 stop 已在 handler 里触发, + // 避免 effect 再次 stop 误杀随后 flush 启动的 inject 编排。 + if (!pendingInjectPromptRef.current) { + stopOrchestration(); + } return; } if ( @@ -1061,6 +1068,21 @@ export function useStep2Orchestration( // eslint-disable-next-line react-hooks/exhaustive-deps }, [isRoundTableRunning]); + // 干预研审:当前轮次停止后 flush 待执行的 inject 编排(编排期间 UI 仍为「恢复会商」)。 + useEffect(() => { + if (isOrchestrating) return; + const pending = pendingInjectPromptRef.current; + if (!pending) return; + if (!threadIdsRef.current || !coordinatorNameRef.current) return; + pendingInjectPromptRef.current = null; + triggerToast("您的人工纠偏指令已同步至圆桌节点!"); + void runOrchestration( + pending, + threadIdsRef.current, + coordinatorNameRef.current, + ); + }, [isOrchestrating, injectFlushToken, runOrchestration, triggerToast]); + // ─── Public handlers ───────────────────────────────────────────── const handleInjectToRoundtable = useCallback(() => { if (!customAgentInput.trim()) return; @@ -1068,28 +1090,31 @@ export function useStep2Orchestration( triggerToast("⚠️ 圆桌尚未就绪,请稍候"); return; } - if (isOrchestratingRef.current) { - triggerToast("⏳ 当前轮次仍在进行中,请等待或暂停后再发送"); - return; - } const userText = customAgentInput.trim(); setCustomAgentInput(""); + const prompt = `用户人工干预新指令:${userText}\n\n请结合当前讨论状态,决定是否继续派活或直接给出更新后的结论。`; + pendingInjectPromptRef.current = prompt; + + // 与 Step2Panel 右上角「暂停会商 / 恢复会商」联动:立即进入挂起态。 + setIsRoundTableRunning(false); + stopOrchestration(); + appendDialogue({ sender: "用户 (插话干预)", avatarType: "human", content: `💡 (人工指令介入) ${userText}`, confidence: "最高指令", }); - triggerToast("您的人工纠偏指令已同步至圆桌节点!"); - void runOrchestration( - `用户人工干预新指令:${userText}\n\n请结合当前讨论状态,决定是否继续派活或直接给出更新后的结论。`, - threadIdsRef.current, - coordinatorNameRef.current, - ); - }, [appendDialogue, customAgentInput, runOrchestration, triggerToast]); + if (isOrchestratingRef.current) { + triggerToast("⏸️ 会商已暂停,当前轮次结束后将处理您的干预指令"); + } else { + triggerToast("⏸️ 会商已暂停,正在处理您的干预指令…"); + } + setInjectFlushToken((n) => n + 1); + }, [appendDialogue, customAgentInput, stopOrchestration, triggerToast]); const submitClarification = useCallback( (rawAnswer: string) => { @@ -1237,6 +1262,7 @@ export function useStep2Orchestration( setArtifacts([]); seatStubMessagesRef.current = {}; setSeatStubMessages({}); + pendingInjectPromptRef.current = null; deselectArtifact(); step2InitRef.current = false; }, [abortAllInFlight, deselectArtifact, setArtifacts]); diff --git a/frontend-web/src/roundtable-planning/pages/RoundtablePlanningPage.tsx b/frontend-web/src/roundtable-planning/pages/RoundtablePlanningPage.tsx index a598f0cc..63f8e4e1 100644 --- a/frontend-web/src/roundtable-planning/pages/RoundtablePlanningPage.tsx +++ b/frontend-web/src/roundtable-planning/pages/RoundtablePlanningPage.tsx @@ -351,37 +351,41 @@ export default function RoundtablePlanningPage() { 新建任务 - + {currentStep !== 2 && ( + <> + - + + + )}