diff --git a/apps/ai-game-creator-shell/src/App.tsx b/apps/ai-game-creator-shell/src/App.tsx index cc58ed5c8..3fefcbd56 100644 --- a/apps/ai-game-creator-shell/src/App.tsx +++ b/apps/ai-game-creator-shell/src/App.tsx @@ -731,7 +731,10 @@ export function App({ null, ); planningV2SessionRef.current = planningV2Session; - const [planningV2TransientReply, setPlanningV2TransientReply] = useState(''); + const [planningV2TransientReply, setPlanningV2TransientReplyVisible] = + useState(''); + const planningV2TransientReplyTargetRef = useRef(''); + const planningV2VisibleReplyRef = useRef(''); const [planningV2Reasoning, setPlanningV2Reasoning] = useState(''); const planningV2TurnRef = useRef<{ projectPath: string; @@ -752,6 +755,37 @@ export function App({ >(), ); + function setPlanningV2TransientReplyTarget(next: string) { + planningV2TransientReplyTargetRef.current = next; + if (!next) { + planningV2VisibleReplyRef.current = ''; + setPlanningV2TransientReplyVisible(''); + } + } + + useEffect(() => { + const timer = window.setInterval(() => { + const target = planningV2TransientReplyTargetRef.current; + setPlanningV2TransientReplyVisible((current) => { + if (!target) { + planningV2VisibleReplyRef.current = ''; + return ''; + } + const prefix = target.startsWith(current) ? current : ''; + if (prefix === target) { + planningV2VisibleReplyRef.current = target; + return target; + } + const remaining = target.length - prefix.length; + const step = remaining > 160 ? 8 : remaining > 48 ? 4 : 2; + const next = target.slice(0, prefix.length + step); + planningV2VisibleReplyRef.current = next; + return next; + }); + }, 32); + return () => window.clearInterval(timer); + }, []); + function applyPlanningV2CommandResult( result: PlanningSessionCommandResultV2, clientTurnId?: string, @@ -920,7 +954,7 @@ export function App({ }; setChatAgentBusy(true); setProjectSupervisorRuntimeError(''); - setPlanningV2TransientReply(''); + setPlanningV2TransientReplyTarget(''); try { const view = await invoke('continue_design_agent_session', { projectPath: nextProjectPath, @@ -943,7 +977,7 @@ export function App({ setPlanGddError(message); } finally { designAgentTurnRef.current = null; - setPlanningV2TransientReply(''); + setPlanningV2TransientReplyTarget(''); setChatAgentBusy(false); } } @@ -1434,7 +1468,7 @@ export function App({ setProjectSupervisorResponseStream(null); setProjectSupervisorRuntimeError(''); setPlanningV2Session(null); - setPlanningV2TransientReply(''); + setPlanningV2TransientReplyTarget(''); setPlanningV2Active(planningStartMode); planningV2ActiveRef.current = planningStartMode; designAgentLaneRef.current = planningStartMode; @@ -1821,7 +1855,7 @@ export function App({ return; } if (payload.status === 'started') { - setPlanningV2TransientReply( + setPlanningV2TransientReplyTarget( payload.accumulatedText || '正在生成策划方案…', ); setProjectSupervisorRuntimeError(''); @@ -1830,7 +1864,7 @@ export function App({ payload.status === 'delta' && (payload.accumulatedText || payload.deltaText) ) { - setPlanningV2TransientReply( + setPlanningV2TransientReplyTarget( payload.accumulatedText || payload.deltaText, ); setProjectSupervisorRuntimeError(''); @@ -1879,13 +1913,13 @@ export function App({ return; } if (payload.kind === 'text' && payload.text != null) { - setPlanningV2TransientReply(payload.text); + setPlanningV2TransientReplyTarget(payload.text); } if (payload.reasoningText != null) { setPlanningV2Reasoning(payload.reasoningText); } if (payload.kind === 'tool' && payload.text) { - setPlanningV2TransientReply(payload.text); + setPlanningV2TransientReplyTarget(payload.text); } if (payload.view) { applyDesignView(payload.view, payload.projectPath); @@ -5916,7 +5950,7 @@ export function App({ }; setChatAgentBusy(true); setProjectSupervisorRuntimeError(''); - setPlanningV2TransientReply(''); + setPlanningV2TransientReplyTarget(''); try { const result = currentSessionId ? await invoke( @@ -5969,7 +6003,7 @@ export function App({ ]); } finally { planningV2TurnRef.current = null; - setPlanningV2TransientReply(''); + setPlanningV2TransientReplyTarget(''); setChatAgentBusy(false); } } @@ -11639,7 +11673,7 @@ export function App({ projectPath: nextProjectPath, clientTurnId, }; - setPlanningV2TransientReply(''); + setPlanningV2TransientReplyTarget(''); setChatAgentBusy(true); setPlanGddDecisionBusy(true); void invoke('decide_design_phase', { @@ -11680,7 +11714,7 @@ export function App({ return; } designAgentTurnRef.current = null; - setPlanningV2TransientReply(''); + setPlanningV2TransientReplyTarget(''); setChatAgentBusy(false); setPlanGddDecisionBusy(false); });