From aa973ea34d8d6478f74e055bf1abcd9392df607e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Tue, 22 Sep 2026 17:12:02 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=8C=E7=B1=BB=E9=97=AE=E9=A2=98=EF=BC=9A?= =?UTF-8?q?=E5=8F=A6=E5=A4=96=E4=B8=A4=E4=B8=AA=E5=AE=BF=E4=B8=BB=E7=9A=84?= =?UTF-8?q?=E5=BC=95=E7=94=A8=20provider=20=E4=B9=9F=E6=8C=89=E5=86=85?= =?UTF-8?q?=E5=AE=B9=E7=AD=BE=E5=90=8D=E8=AE=B0=E5=BF=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PlanningChatView 的 chatProjectAssets 由工作台壳每次渲染重新 .filter() 派生、DirectProjectComposer 的 assets 由 manifest 订阅每次渲染重新派生,两处的 [assets] 依赖同样从不命中缓存 - 两处改用 assetsSignature(...) 做依赖,provider 身份不再随宿主渲染抖动(流式回复时每帧都换),输入区不再每帧重注册 Lexical 更新监听 --- .../DirectProjectComposer/DirectProjectComposer.tsx | 8 +++++++- .../project-development/planning/PlanningChatView.tsx | 7 ++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/apps/ai-game-creator-shell/src/view/project-development/chat/components/DirectProjectComposer/DirectProjectComposer.tsx b/apps/ai-game-creator-shell/src/view/project-development/chat/components/DirectProjectComposer/DirectProjectComposer.tsx index ea336a19d..c92cd74d1 100644 --- a/apps/ai-game-creator-shell/src/view/project-development/chat/components/DirectProjectComposer/DirectProjectComposer.tsx +++ b/apps/ai-game-creator-shell/src/view/project-development/chat/components/DirectProjectComposer/DirectProjectComposer.tsx @@ -21,6 +21,7 @@ import { ResourceReferencePicker, type ResourceReferencePickerHandle, } from '../../../../../features/project-workspace/ResourceReferencePicker'; +import { assetsSignature } from '../../../../../features/project-workspace/resourceReferences'; import type { DirectCodexTurnAttachment } from '../../conversation/directCodexTurnAttachments'; import type { DirectCodexUserContentPart } from '../../generated/DirectCodexUserContentPart'; import type { QueuedChatTurn } from './chatComposerQueue'; @@ -107,6 +108,7 @@ export function DirectProjectComposer({ (Rust `direct_codex_user_item_to_codex_turn_input`),所以只有这里注入 Skill provider。 */ const skillProvider = useSkillReferenceProvider(); + const assetsContentSignature = assetsSignature(assets); const referenceProviders = useMemo( () => [ createResourceReferenceProvider({ assets }), @@ -114,7 +116,11 @@ export function DirectProjectComposer({ attachmentReferenceProvider, runtimeRegionReferenceProvider, ], - [assets, skillProvider], + // `assets` 由 manifest 订阅每次渲染重新 `.filter()` 派生,依赖它等于从不命中缓存: + // provider 身份一变,输入区就重新注册 Lexical 更新监听(流式回复时每帧都换)。 + // 按内容签名取依赖才真的能跳过重建。 + // eslint-disable-next-line react-hooks/exhaustive-deps + [assetsContentSignature, skillProvider], ); const openPicker = useCallback(() => { onReferencePickerOpen?.(); diff --git a/apps/ai-game-creator-shell/src/view/project-development/planning/PlanningChatView.tsx b/apps/ai-game-creator-shell/src/view/project-development/planning/PlanningChatView.tsx index 00f769090..cca6c5918 100644 --- a/apps/ai-game-creator-shell/src/view/project-development/planning/PlanningChatView.tsx +++ b/apps/ai-game-creator-shell/src/view/project-development/planning/PlanningChatView.tsx @@ -23,6 +23,7 @@ import { ResourceReferenceInput, type ResourceReferenceInputHandle, } from '../../../features/project-workspace/ResourceReferenceInput'; +import { assetsSignature } from '../../../features/project-workspace/resourceReferences'; import { AgentReasoning } from '../chat/components/AgentReasoning/AgentReasoning'; import { ComposerReasoningEffortSelect } from '../chat/components/DirectProjectComposer/ComposerControls'; import { formatClockTime } from '../chat/components/ToolCallGroup/toolCallGroupPresentation'; @@ -135,13 +136,17 @@ export function PlanningChatView({ `$` Skill 候选只有 DirectProject 回合那条路径会把 `agc_skill_reference` 解析成真 Skill, 这里注入 Skill provider 只会得到一个退化成本文的误导入口,所以不注入。 */ + const chatProjectAssetsSignature = assetsSignature(chatProjectAssets); const referenceProviders = useMemo( () => [ createResourceReferenceProvider({ assets: chatProjectAssets }), attachmentReferenceProvider, runtimeRegionReferenceProvider, ], - [chatProjectAssets], + // `chatProjectAssets` 由工作台壳每次渲染重新 `.filter()` 派生,依赖它等于从不命中缓存: + // provider 身份一变,输入区就重新注册 Lexical 更新监听。按内容签名取依赖才真的能跳过重建。 + // eslint-disable-next-line react-hooks/exhaustive-deps + [chatProjectAssetsSignature], ); let submitLabel = '发送'; if (needsUserInput) {