From f7c8b9f21784608178c3d0e0dc922b85bd808e5e Mon Sep 17 00:00:00 2001 From: Linghong Date: Mon, 14 Sep 2026 14:27:22 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=AD=96=E5=88=92=20Agent=20?= =?UTF-8?q?=E6=AD=A3=E6=96=87=E6=B5=81=E5=BC=8F=E6=94=B6=E5=B0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 让最终 DesignView 等待临时正文播放完成后再提交正式消息 为非流式返回复用策划 Agent 的前端伪流式显示 保持 reasoning、GameAgent 和其他 Agent 路径不变 --- apps/ai-game-creator-shell/src/App.tsx | 94 ++++++++++++++++++++++++-- 1 file changed, 87 insertions(+), 7 deletions(-) diff --git a/apps/ai-game-creator-shell/src/App.tsx b/apps/ai-game-creator-shell/src/App.tsx index 434fe8e84..fc4bee85b 100644 --- a/apps/ai-game-creator-shell/src/App.tsx +++ b/apps/ai-game-creator-shell/src/App.tsx @@ -827,6 +827,11 @@ export function App({ useState(''); const planningV2TransientReplyTargetRef = useRef(''); const planningV2VisibleReplyRef = useRef(''); + const designAgentPendingViewRef = useRef<{ + clientTurnId: string; + projectPath: string; + view: DesignView; + } | null>(null); const [planningV2Reasoning, setPlanningV2Reasoning] = useState(''); const planningV2TurnRef = useRef<{ projectPath: string; @@ -1027,6 +1032,66 @@ export function App({ latestMessagesRef.current = conversation; } + function commitDesignAgentView(view: DesignView, projectPath: string) { + const pendingTurnId = designAgentPendingViewRef.current?.clientTurnId; + designAgentPendingViewRef.current = null; + applyDesignView(view, projectPath); + setPlanningV2TransientReplyTarget(''); + if (designAgentTurnRef.current?.clientTurnId === pendingTurnId) { + designAgentTurnRef.current = null; + } + } + + function applyDesignAgentViewAfterTransient( + view: DesignView, + projectPath: string, + clientTurnId: string, + ) { + let target = planningV2TransientReplyTargetRef.current; + const tracked = designAgentTurnRef.current; + if (!target.trim() && !view.running) { + const latestAssistantText = [...view.messages] + .reverse() + .find((message) => message.role !== 'user' && message.text.trim()) + ?.text.trim(); + if (latestAssistantText) { + setPlanningV2TransientReplyTarget(latestAssistantText); + target = latestAssistantText; + } + } + if ( + !view.running && + tracked?.clientTurnId === clientTurnId && + target.trim() && + planningV2VisibleReplyRef.current !== target + ) { + designAgentPendingViewRef.current = { + clientTurnId, + projectPath, + view, + }; + return; + } + commitDesignAgentView(view, projectPath); + } + + useEffect(() => { + const timer = window.setInterval(() => { + const pending = designAgentPendingViewRef.current; + if (!pending) { + return; + } + const target = planningV2TransientReplyTargetRef.current; + if (target && planningV2VisibleReplyRef.current !== target) { + return; + } + commitDesignAgentView(pending.view, pending.projectPath); + }, 50); + return () => window.clearInterval(timer); + // 收尾定时器只需注册一次;它读取 refs,避免随每次渲染重建。 + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + async function hydrateDesignAgentSession(nextProjectPath: string) { const invoke = resolveTauriInvoke(); if (!invoke || !nextProjectPath.trim()) { @@ -1060,6 +1125,7 @@ export function App({ projectPath: nextProjectPath, clientTurnId, }; + designAgentPendingViewRef.current = null; await designAgentEventSubscriptionReady(); setChatAgentBusy(true); setProjectSupervisorRuntimeError(''); @@ -1074,7 +1140,7 @@ export function App({ if (localProjectPathRef.current !== nextProjectPath) { return; } - applyDesignView(view, nextProjectPath); + applyDesignAgentViewAfterTransient(view, nextProjectPath, clientTurnId); } catch (error) { if (localProjectPathRef.current !== nextProjectPath) { return; @@ -1086,8 +1152,10 @@ export function App({ setProjectSupervisorRuntimeError(message); setPlanGddError(message); } finally { - designAgentTurnRef.current = null; - setPlanningV2TransientReplyTarget(''); + if (!designAgentPendingViewRef.current) { + designAgentTurnRef.current = null; + setPlanningV2TransientReplyTarget(''); + } setChatAgentBusy(false); } } @@ -1579,6 +1647,7 @@ export function App({ setProjectSupervisorRuntimeError(''); setPlanningV2Session(null); setPlanningV2TransientReplyTarget(''); + designAgentPendingViewRef.current = null; setPlanningV2Reasoning(''); setPlanningV2Active(planningStartMode); planningV2ActiveRef.current = planningStartMode; @@ -2045,7 +2114,11 @@ export function App({ setPlanningV2TransientReplyTarget(payload.text); } if (payload.view) { - applyDesignView(payload.view, payload.projectPath); + applyDesignAgentViewAfterTransient( + payload.view, + payload.projectPath, + payload.clientTurnId, + ); } }) .then((unlisten) => { @@ -11863,6 +11936,7 @@ export function App({ projectPath: nextProjectPath, clientTurnId, }; + designAgentPendingViewRef.current = null; setPlanningV2TransientReplyTarget(''); setPlanningV2Reasoning(''); setChatAgentBusy(true); @@ -11885,7 +11959,11 @@ export function App({ ) { return; } - applyDesignView(view, nextProjectPath); + applyDesignAgentViewAfterTransient( + view, + nextProjectPath, + clientTurnId, + ); }) .catch((error) => { if ( @@ -11907,8 +11985,10 @@ export function App({ ) { return; } - designAgentTurnRef.current = null; - setPlanningV2TransientReplyTarget(''); + if (!designAgentPendingViewRef.current) { + designAgentTurnRef.current = null; + setPlanningV2TransientReplyTarget(''); + } setChatAgentBusy(false); setPlanGddDecisionBusy(false); });