From 4da1494a1d77a4db59ecdef9924686ae96503aae Mon Sep 17 00:00:00 2001 From: Linghong Date: Wed, 16 Sep 2026 13:55:02 +0800 Subject: [PATCH 1/6] =?UTF-8?q?=E6=8E=A5=E5=85=A5=E5=81=9A=E6=88=90?= =?UTF-8?q?=E6=B8=B8=E6=88=8F=E5=90=8E=E7=9A=84=E7=AD=96=E5=88=92=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E6=8C=87=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 切换到 GameAgent 后自动请求读取 design_artifacts 文档 为切换消息增加独立去重键,避免策划首轮占用 --- apps/ai-game-creator-shell/src/App.tsx | 12 ++++++++---- .../features/app-shell/WorkspaceLauncher.tsx | 19 +++++++++++++------ 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/apps/ai-game-creator-shell/src/App.tsx b/apps/ai-game-creator-shell/src/App.tsx index ee075cfa5..5bf3330e9 100644 --- a/apps/ai-game-creator-shell/src/App.tsx +++ b/apps/ai-game-creator-shell/src/App.tsx @@ -605,16 +605,20 @@ function isPersistableDirectCodexConversationMessage(message: ChatMessage) { return /^[a-z0-9][a-z0-9-]{5,159}$/iu.test(turnId); } -function claimInitialSupervisorMessageForPage(projectPath: string) { +function claimInitialSupervisorMessageForPage( + projectPath: string, + messageKey = '', +) { let claimedProjectPaths = initialSupervisorMessageClaimsByPage.get(window); if (!claimedProjectPaths) { claimedProjectPaths = new Set(); initialSupervisorMessageClaimsByPage.set(window, claimedProjectPaths); } - if (claimedProjectPaths.has(projectPath)) { + const claimKey = `${projectPath}\u0000${messageKey}`; + if (claimedProjectPaths.has(claimKey)) { return false; } - claimedProjectPaths.add(projectPath); + claimedProjectPaths.add(claimKey); return true; } @@ -7501,7 +7505,7 @@ export function App({ } if ( chatAgentBusy || - !claimInitialSupervisorMessageForPage(latch.projectPath) + !claimInitialSupervisorMessageForPage(latch.projectPath, latch.prompt) ) { return; } diff --git a/apps/ai-game-creator-shell/src/features/app-shell/WorkspaceLauncher.tsx b/apps/ai-game-creator-shell/src/features/app-shell/WorkspaceLauncher.tsx index 4727bf323..8b64a4505 100644 --- a/apps/ai-game-creator-shell/src/features/app-shell/WorkspaceLauncher.tsx +++ b/apps/ai-game-creator-shell/src/features/app-shell/WorkspaceLauncher.tsx @@ -495,6 +495,9 @@ export function WorkspaceLauncherShell({ }); } + const approvedDesignBuildPrompt = + '查看当前项目 design_artifacts/ 目录及其子目录下的文档,理解其游戏设计,并按照这些文档将游戏实现出来。'; + const currentHelpTitle = launcherView === 'guide' ? '使用指南' @@ -661,14 +664,18 @@ export function WorkspaceLauncherShell({ initialProjectManifest={currentProjectContext.manifest} initialProjectKind={currentProjectContext.projectKind} initialSupervisorMessage={ - !suppressInitialGameTurn - ? currentProjectContext.initialPrompt - : '' + switchedToGameRuntime + ? approvedDesignBuildPrompt + : !suppressInitialGameTurn + ? currentProjectContext.initialPrompt + : '' } initialCreationType={ - !suppressInitialGameTurn - ? currentProjectContext.creationType - : null + switchedToGameRuntime + ? 'game' + : !suppressInitialGameTurn + ? currentProjectContext.creationType + : null } initialAttachments={ !suppressInitialGameTurn -- 2.52.0 From bfc06920141edf11889ed16519b7c632085b7549 Mon Sep 17 00:00:00 2001 From: Linghong Date: Wed, 16 Sep 2026 15:19:07 +0800 Subject: [PATCH 2/6] =?UTF-8?q?=E9=9A=90=E8=97=8F=E7=AD=96=E5=88=92?= =?UTF-8?q?=E5=AF=B9=E8=AF=9D=E7=B4=A0=E6=9D=90=E5=BC=95=E7=94=A8=E6=8C=89?= =?UTF-8?q?=E9=92=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 策划 Agent 输入框不显示 @ 素材引用入口 --- .../src/features/project-workspace/ProjectSupervisorView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ai-game-creator-shell/src/features/project-workspace/ProjectSupervisorView.tsx b/apps/ai-game-creator-shell/src/features/project-workspace/ProjectSupervisorView.tsx index d222b1fbd..0f1060026 100644 --- a/apps/ai-game-creator-shell/src/features/project-workspace/ProjectSupervisorView.tsx +++ b/apps/ai-game-creator-shell/src/features/project-workspace/ProjectSupervisorView.tsx @@ -918,7 +918,7 @@ export function ProjectSupervisorView({ rows={3} value={chatInput} references={chatReferences} - showTriggerButton={!directCodex} + showTriggerButton={!directCodex && !planningSurfaceActive} placeholder={ directCodex ? '描述你的想法,或 @ 引用素材' -- 2.52.0 From ad8579b053442fdaa36570a8e12e0d78362b49ba Mon Sep 17 00:00:00 2001 From: Linghong Date: Wed, 16 Sep 2026 15:26:09 +0800 Subject: [PATCH 3/6] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E5=81=9A=E6=88=90?= =?UTF-8?q?=E6=B8=B8=E6=88=8F=E5=88=9D=E5=A7=8B=E6=B6=88=E6=81=AF=E5=8E=BB?= =?UTF-8?q?=E9=87=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 恢复普通项目按路径只自动开局一次 为做成游戏使用独立 claim scope 并整理提示词命名 --- apps/ai-game-creator-shell/src/App.tsx | 12 +++++------ .../features/app-shell/WorkspaceLauncher.tsx | 21 +++++++++++-------- .../src/features/app-shell/model.ts | 1 + .../app-shell/useHomeProjectCreation.ts | 5 ++++- 4 files changed, 23 insertions(+), 16 deletions(-) diff --git a/apps/ai-game-creator-shell/src/App.tsx b/apps/ai-game-creator-shell/src/App.tsx index 5bf3330e9..9523363ac 100644 --- a/apps/ai-game-creator-shell/src/App.tsx +++ b/apps/ai-game-creator-shell/src/App.tsx @@ -605,16 +605,13 @@ function isPersistableDirectCodexConversationMessage(message: ChatMessage) { return /^[a-z0-9][a-z0-9-]{5,159}$/iu.test(turnId); } -function claimInitialSupervisorMessageForPage( - projectPath: string, - messageKey = '', -) { +function claimInitialSupervisorMessageForPage(projectPath: string, scope = '') { let claimedProjectPaths = initialSupervisorMessageClaimsByPage.get(window); if (!claimedProjectPaths) { claimedProjectPaths = new Set(); initialSupervisorMessageClaimsByPage.set(window, claimedProjectPaths); } - const claimKey = `${projectPath}\u0000${messageKey}`; + const claimKey = `${projectPath}\u0000${scope}`; if (claimedProjectPaths.has(claimKey)) { return false; } @@ -687,6 +684,7 @@ type AppProps = { activeVersionId?: ProjectSupervisorComponentProps['activeVersionId']; supervisorChatOnly?: boolean; initialSupervisorMessage?: string; + initialSupervisorMessageClaimScope?: string; initialCreationType?: HomeCreationType | null; initialAttachments?: LauncherImportedAttachment[]; playRequest?: ProjectSupervisorComponentProps['playRequest']; @@ -737,6 +735,7 @@ export function App({ activeVersionId = null, supervisorChatOnly = false, initialSupervisorMessage = '', + initialSupervisorMessageClaimScope = '', initialCreationType = null, initialAttachments = [], playRequest = null, @@ -874,6 +873,7 @@ export function App({ const initialSupervisorMessageLatchRef = useRef({ projectPath: initialProjectPath, prompt: initialSupervisorMessage.trim(), + claimScope: initialSupervisorMessageClaimScope, creationType: initialCreationType, attachments: toDirectCodexTurnAttachments(initialAttachments), }); @@ -7505,7 +7505,7 @@ export function App({ } if ( chatAgentBusy || - !claimInitialSupervisorMessageForPage(latch.projectPath, latch.prompt) + !claimInitialSupervisorMessageForPage(latch.projectPath, latch.claimScope) ) { return; } diff --git a/apps/ai-game-creator-shell/src/features/app-shell/WorkspaceLauncher.tsx b/apps/ai-game-creator-shell/src/features/app-shell/WorkspaceLauncher.tsx index 8b64a4505..c40dca2e4 100644 --- a/apps/ai-game-creator-shell/src/features/app-shell/WorkspaceLauncher.tsx +++ b/apps/ai-game-creator-shell/src/features/app-shell/WorkspaceLauncher.tsx @@ -36,7 +36,10 @@ import type { WorkspaceLauncherShellProps } from './model'; import { NonEmptyProjectDialog, ProjectsPage } from './ProjectCreation'; import { useAccountWallet } from './useAccountWallet'; import { useDeveloperAgentPanel } from './useDeveloperAgentPanel'; -import { useHomeProjectCreation } from './useHomeProjectCreation'; +import { + DESIGN_ARTIFACTS_BUILD_PROMPT, + useHomeProjectCreation, +} from './useHomeProjectCreation'; import { useRecentProjects } from './useRecentProjects'; export function WorkspaceLauncherShell({ @@ -113,7 +116,7 @@ export function WorkspaceLauncherShell({ const agentRuntimeMode: 'design' | 'game' = planningStartMode ? 'design' : 'game'; - const suppressInitialGameTurn = switchedToGameRuntime; + const omitOriginalPlanningTurnInputs = switchedToGameRuntime; const activeProjectContextRef = useRef(currentProjectContext); const manifestMergeRef = useRef(null); activeProjectContextRef.current = currentProjectContext; @@ -495,9 +498,6 @@ export function WorkspaceLauncherShell({ }); } - const approvedDesignBuildPrompt = - '查看当前项目 design_artifacts/ 目录及其子目录下的文档,理解其游戏设计,并按照这些文档将游戏实现出来。'; - const currentHelpTitle = launcherView === 'guide' ? '使用指南' @@ -665,23 +665,26 @@ export function WorkspaceLauncherShell({ initialProjectKind={currentProjectContext.projectKind} initialSupervisorMessage={ switchedToGameRuntime - ? approvedDesignBuildPrompt - : !suppressInitialGameTurn + ? DESIGN_ARTIFACTS_BUILD_PROMPT + : !omitOriginalPlanningTurnInputs ? currentProjectContext.initialPrompt : '' } initialCreationType={ switchedToGameRuntime ? 'game' - : !suppressInitialGameTurn + : !omitOriginalPlanningTurnInputs ? currentProjectContext.creationType : null } initialAttachments={ - !suppressInitialGameTurn + !omitOriginalPlanningTurnInputs ? currentProjectContext.attachments : [] } + initialSupervisorMessageClaimScope={ + switchedToGameRuntime ? 'approved-design-build' : '' + } activeVersionId={activeVersionId} orchestrationMode="single-supervisor" projectSupervisorOnly diff --git a/apps/ai-game-creator-shell/src/features/app-shell/model.ts b/apps/ai-game-creator-shell/src/features/app-shell/model.ts index 5c54a5055..90ace801c 100644 --- a/apps/ai-game-creator-shell/src/features/app-shell/model.ts +++ b/apps/ai-game-creator-shell/src/features/app-shell/model.ts @@ -35,6 +35,7 @@ export type ProjectSupervisorComponentProps = { initialProjectManifest?: GameCreationAppManifest; initialProjectKind?: 'web' | 'godot' | 'cocos'; initialSupervisorMessage?: string; + initialSupervisorMessageClaimScope?: string; initialCreationType?: HomeCreationType | null; initialAttachments?: LauncherImportedAttachment[]; orchestrationMode?: 'single-supervisor' | 'professional-dag'; diff --git a/apps/ai-game-creator-shell/src/features/app-shell/useHomeProjectCreation.ts b/apps/ai-game-creator-shell/src/features/app-shell/useHomeProjectCreation.ts index 56201d7d3..27059edca 100644 --- a/apps/ai-game-creator-shell/src/features/app-shell/useHomeProjectCreation.ts +++ b/apps/ai-game-creator-shell/src/features/app-shell/useHomeProjectCreation.ts @@ -66,7 +66,7 @@ type UseHomeProjectCreationOptions = { rememberRecentWorkspace: (projectPath: string) => void; }; -const APPROVED_GDD_BUILD_PROMPT = [ +export const APPROVED_GDD_BUILD_PROMPT = [ '请按照附件中的已批准 GDD 开始建造这款游戏。', '', '这份 GDD 已覆盖游戏定位与一句话概念、类型与美术方向、游戏支柱、核心循环、目标用户、平台与输入事实、MVP 系统、暂不纳入范围、创作者提示和原型验证项。', @@ -74,6 +74,9 @@ const APPROVED_GDD_BUILD_PROMPT = [ '请先阅读并理解附件中的 fast_gdd.md,以它作为本次建造的主要依据,优先实现其中 MVP 范围内的可运行游戏原型。', ].join('\n'); +export const DESIGN_ARTIFACTS_BUILD_PROMPT = + '查看当前项目 design_artifacts/ 目录及其子目录下的文档,理解其游戏设计,并按照这些文档将游戏实现出来。'; + function createTextAttachmentFile(content: string) { const file = new File([content], 'fast_gdd.md', { type: 'text/markdown', -- 2.52.0 From 31aa169a0c905da78af3cc91314c3a46ade98781 Mon Sep 17 00:00:00 2001 From: Linghong Date: Wed, 16 Sep 2026 15:29:35 +0800 Subject: [PATCH 4/6] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=AD=96=E5=88=92?= =?UTF-8?q?=E5=AF=B9=E8=AF=9D=E6=A0=87=E9=A2=98=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 策划工作台恢复标题与内容的两行布局 仅将策划对话面板固定到第二行,避免影响 GameAgent 共用布局 已通过 git diff --check --- apps/ai-game-creator-shell/src/styles.css | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/apps/ai-game-creator-shell/src/styles.css b/apps/ai-game-creator-shell/src/styles.css index 0f8ee6817..419f899af 100644 --- a/apps/ai-game-creator-shell/src/styles.css +++ b/apps/ai-game-creator-shell/src/styles.css @@ -10271,6 +10271,15 @@ button.design-workspace-tree__entry:hover, /* 策划聊天区包含阶段控制卡、消息、Runtime 状态和输入框。GameAgent 资源工作台的 消息列表默认占满整个聊天区,策划模式需要单独恢复五行布局,避免输入框被推到视口外。 */ +/* 策划工作台保留标题行,避免共用跨行规则将标题挤到底部。 */ +.game-workbench-layout--design .game-workbench-chat { + grid-template-rows: auto minmax(0, 1fr); +} + +.game-workbench-layout--design .game-workbench-chat .project-supervisor-surface { + grid-row: 2; +} + .game-workbench-layout--design .project-supervisor-surface { display: block; height: 100%; -- 2.52.0 From c3a115d79410bb4b73a1fc55b827ab73ac440c5d Mon Sep 17 00:00:00 2001 From: Linghong Date: Wed, 16 Sep 2026 15:33:09 +0800 Subject: [PATCH 5/6] =?UTF-8?q?=E9=9A=90=E8=97=8F=E7=AD=96=E5=88=92?= =?UTF-8?q?=E5=AF=B9=E8=AF=9D=E6=B6=A6=E8=89=B2=E6=8C=89=E9=92=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 策划 Agent 输入框同时隐藏素材引用与 AI 润色入口 --- .../src/features/project-workspace/ProjectSupervisorView.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/ai-game-creator-shell/src/features/project-workspace/ProjectSupervisorView.tsx b/apps/ai-game-creator-shell/src/features/project-workspace/ProjectSupervisorView.tsx index 0f1060026..604b908e0 100644 --- a/apps/ai-game-creator-shell/src/features/project-workspace/ProjectSupervisorView.tsx +++ b/apps/ai-game-creator-shell/src/features/project-workspace/ProjectSupervisorView.tsx @@ -919,6 +919,7 @@ export function ProjectSupervisorView({ value={chatInput} references={chatReferences} showTriggerButton={!directCodex && !planningSurfaceActive} + showPolishAction={!planningSurfaceActive} placeholder={ directCodex ? '描述你的想法,或 @ 引用素材' -- 2.52.0 From e81548576ca25c2bc6f1d6363ec54982d22e4666 Mon Sep 17 00:00:00 2001 From: Linghong Date: Wed, 16 Sep 2026 08:21:59 +0000 Subject: [PATCH 6/6] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20CI=20=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E5=8F=A3=E5=BE=84=E4=B8=8E=E8=B6=85=E6=97=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将素材标签刷新用例切回 game Agent 场景,保留策划 Agent 隐藏 @ 入口后的既有链路验证 将删除文件后验证请求等待窗口从 2 秒放宽到同类用例的 10 秒,避免固定等待导致 CI 偶发超时 --- .../src/tests/runtime_actions/action_execution.rs | 2 +- .../tests/resourceTagStatsRefresh.test.tsx | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/ai-game-creator-shell/src-tauri/src/tests/runtime_actions/action_execution.rs b/apps/ai-game-creator-shell/src-tauri/src/tests/runtime_actions/action_execution.rs index 762b67983..db84a285b 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/tests/runtime_actions/action_execution.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/tests/runtime_actions/action_execution.rs @@ -1494,7 +1494,7 @@ async fn background_agent_runtime_deletes_file_then_verifies_before_completion() assert!(prompt_input.contains("只删除项目内普通文件")); let verification_request = receiver - .recv_timeout(Duration::from_secs(2)) + .recv_timeout(Duration::from_secs(10)) .expect("verification plan request"); assert!(verification_request.contains("file.delete")); assert!(verification_request.contains("已删除 game/obsolete-runtime-file.txt")); diff --git a/apps/ai-game-creator-shell/tests/resourceTagStatsRefresh.test.tsx b/apps/ai-game-creator-shell/tests/resourceTagStatsRefresh.test.tsx index b21591830..950c78f6e 100644 --- a/apps/ai-game-creator-shell/tests/resourceTagStatsRefresh.test.tsx +++ b/apps/ai-game-creator-shell/tests/resourceTagStatsRefresh.test.tsx @@ -89,9 +89,10 @@ function graphFor(manifest: GameCreationAppManifest) { * * 这里只把壳换成用例自己的 `useState`(壳那份 CAS 归并由 * `workspaceLauncherManifestMerge.test.tsx` 单独钉住),画布、聊天输入区、 - * 标签统计与候选全部是被测的真实实现。 + * 标签统计与候选全部是被测的真实实现。策划 Agent 会隐藏 @ 入口,这条链路钉住 + * game Agent 的既有行为。 */ -function TagStatsHost({ planningStartMode }: { planningStartMode: boolean }) { +function TagStatsHost() { const [manifest, setManifest] = useState(() => { const initial = createFixtureManifest(); disk.manifest = initial; @@ -117,7 +118,6 @@ function TagStatsHost({ planningStartMode }: { planningStartMode: boolean }) { initialProjectPath={PROJECT_PATH} initialProjectManifest={manifest} projectSupervisorOnly - planningStartMode={planningStartMode} onManifestChange={onManifestChange} /> } @@ -251,7 +251,7 @@ describe('改完素材标签后聊天 @ 选择器的标签统计与候选跟着 it('在资源画布改完标签保存后,聊天 @ 选择器出现该标签及其计数,并按它收窄候选', async () => { const { classificationWrites } = installHostTauri(); - render(); + render(); // 先在画布上打开「编辑素材标签」面板改标签:与用户的操作路径一致。 fireEvent.click( @@ -294,7 +294,7 @@ describe('改完素材标签后聊天 @ 选择器的标签统计与候选跟着 it('未标注标签时聊天 @ 选择器不渲染任何标签 chip', async () => { installHostTauri(); - render(); + render(); await openChatPicker(); expect(pickerTagChips()).toEqual([]); -- 2.52.0