修复游戏聊天前端Lint门禁
Project CI / Frontend tests (push) Failing after 24s
Project CI / Repository checks (push) Successful in 2m21s
Project CI / Backend tests (push) Successful in 3m36s
Project CI / Native shell tests (push) Failing after 5m35s

整理游戏聊天相关导入顺序
稳定专业Agent最终回复回调并补齐Effect依赖
This commit is contained in:
2026-08-03 10:27:04 +08:00
parent 964b883466
commit 7309adb4f0
3 changed files with 66 additions and 61 deletions
+63 -58
View File
@@ -229,9 +229,9 @@ import { ProjectWorkspaceChatPane } from './features/project-workspace/ProjectWo
import {
buildGameChatProgressEvidence,
collectGameChatResultImages,
formatGameChatStageRecord,
gameChatFinalReplyMessages,
gameChatRuntimeEventMessages,
formatGameChatStageRecord,
mergeGameChatFinalReplyMessagesIntoHistory,
mergeGameChatRuntimeEventMessagesIntoHistory,
SupervisorChatOnlyView,
@@ -1074,65 +1074,65 @@ export function App({
});
}
function appendGameChatFinalReplyMessages(
nextProjectPath: string,
runtimeResults: AgentRuntimeResult[],
) {
if (!gameChatOnly || runtimeResults.length === 0) {
return;
}
// A professional Runtime is only part of the active game-chat turn when
// it was delegated by the current Project Supervisor run. This prevents
// a stale child Runtime (or a different app mode) from leaking into the
// project transcript after a restart.
const supervisorRunId =
projectSupervisorRuntimeRef.current?.runId ??
runtimeResults.find(
(result) => result.state.agentId === PROJECT_SUPERVISOR_AGENT_ID,
)?.state.runId;
if (!supervisorRunId) {
return;
}
const messages = runtimeResults.flatMap((result) => {
const runtime = agentRuntimeStateFromResult(result);
if (
runtime.parentAgentId !== PROJECT_SUPERVISOR_AGENT_ID ||
runtime.parentRunId !== supervisorRunId
) {
return [];
const appendGameChatFinalReplyMessages = useCallback(
(nextProjectPath: string, runtimeResults: AgentRuntimeResult[]) => {
if (!gameChatOnly || runtimeResults.length === 0) {
return;
}
return gameChatFinalReplyMessages([result.responseStream]);
});
if (messages.length === 0) {
return;
}
setMessages((current) => {
const currentMessageIds = new Set(
current
.map((message) => message.messageId?.trim())
.filter((messageId): messageId is string => Boolean(messageId)),
);
const missingMessages = messages.filter(
(message) =>
message.messageId && !currentMessageIds.has(message.messageId),
);
if (missingMessages.length === 0) {
return current;
// A professional Runtime is only part of the active game-chat turn when
// it was delegated by the current Project Supervisor run. This prevents
// a stale child Runtime (or a different app mode) from leaking into the
// project transcript after a restart.
const supervisorRunId =
projectSupervisorRuntimeRef.current?.runId ??
runtimeResults.find(
(result) => result.state.agentId === PROJECT_SUPERVISOR_AGENT_ID,
)?.state.runId;
if (!supervisorRunId) {
return;
}
if (savedConversationProjectPathRef.current === nextProjectPath) {
savedConversationCountRef.current = Math.min(
savedConversationCountRef.current,
current.length,
const messages = runtimeResults.flatMap((result) => {
const runtime = agentRuntimeStateFromResult(result);
if (
runtime.parentAgentId !== PROJECT_SUPERVISOR_AGENT_ID ||
runtime.parentRunId !== supervisorRunId
) {
return [];
}
return gameChatFinalReplyMessages([result.responseStream]);
});
if (messages.length === 0) {
return;
}
setMessages((current) => {
const currentMessageIds = new Set(
current
.map((message) => message.messageId?.trim())
.filter((messageId): messageId is string => Boolean(messageId)),
);
}
const orderedMissingMessages = [...missingMessages].sort(
(left, right) => (left.updatedAt ?? 0) - (right.updatedAt ?? 0),
);
const nextMessages = [...current, ...orderedMissingMessages];
latestMessagesRef.current = nextMessages;
return nextMessages;
});
}
const missingMessages = messages.filter(
(message) =>
message.messageId && !currentMessageIds.has(message.messageId),
);
if (missingMessages.length === 0) {
return current;
}
if (savedConversationProjectPathRef.current === nextProjectPath) {
savedConversationCountRef.current = Math.min(
savedConversationCountRef.current,
current.length,
);
}
const orderedMissingMessages = [...missingMessages].sort(
(left, right) => (left.updatedAt ?? 0) - (right.updatedAt ?? 0),
);
const nextMessages = [...current, ...orderedMissingMessages];
latestMessagesRef.current = nextMessages;
return nextMessages;
});
},
[gameChatOnly],
);
function appendGameChatStageRecord(
nextProjectPath: string,
@@ -1384,7 +1384,12 @@ export function App({
disposed = true;
cleanup?.();
};
}, [updateProjectSupervisorResponseStream, updateProjectSupervisorRuntime]);
}, [
appendGameChatFinalReplyMessages,
gameChatOnly,
updateProjectSupervisorResponseStream,
updateProjectSupervisorRuntime,
]);
useEffect(() => {
const invoke = resolveTauriInvoke();
@@ -13,8 +13,8 @@ import { useEffect, useMemo, useState } from 'react';
import type { GameCreationAppManifest } from '../../../../../packages/shared/src/contracts/gameCreationApp';
import type {
AgentRuntimeResponseStream,
AgentRuntimeEventRecord,
AgentRuntimeResponseStream,
AgentRuntimeState,
ChatMessage,
LocalPreviewResult,
@@ -14,11 +14,11 @@ import {
buildGameChatProgressEvidence,
collectGameChatResultImages,
collectGameChatRuntimeEvents,
formatGameChatStageRecord,
gameChatFinalReplyMessages,
gameChatRuntimeEventMessages,
mergeGameChatFinalReplyMessagesIntoHistory,
formatGameChatStageRecord,
isGameChatStageRecordMessage,
mergeGameChatFinalReplyMessagesIntoHistory,
SupervisorChatOnlyView,
} from '../../src/features/project-workspace/SupervisorChatOnlyView';
import {