修复策划 Agent 正文流式收尾
让最终 DesignView 等待临时正文播放完成后再提交正式消息 为非流式返回复用策划 Agent 的前端伪流式显示 保持 reasoning、GameAgent 和其他 Agent 路径不变
This commit is contained in:
@@ -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);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user