实现资源画布布局持久化 #116

Merged
kdletters merged 13 commits from codex/canvas-layout-persistence into codex/ai-game-creator-app 2026-07-31 12:00:48 +08:00
Showing only changes of commit 3318be3da0 - Show all commits
+29 -3
View File
@@ -42,6 +42,14 @@ const aiGameCreatorProjectDevelopmentSource = fs.readFileSync(
'apps/ai-game-creator-shell/src/view/project-development/index.tsx',
'utf8',
);
const aiGameCreatorLocalGamePreviewFrameSource = fs.readFileSync(
'apps/ai-game-creator-shell/src/features/project-workspace/LocalGamePreviewFrame.tsx',
'utf8',
);
const aiGameCreatorSupervisorChatOnlyViewSource = fs.readFileSync(
'apps/ai-game-creator-shell/src/features/project-workspace/SupervisorChatOnlyView.tsx',
'utf8',
);
const aiGameCreatorPreviewRustSource = fs.readFileSync(
'apps/ai-game-creator-shell/src-tauri/src/preview.rs',
'utf8',
@@ -2409,20 +2417,38 @@ function assertAiGameCreatorShellUserDevBoundary() {
}
const clientPreviewFrameCount = [
...aiGameCreatorProjectDevelopmentSource.matchAll(/<iframe\b/g),
...aiGameCreatorLocalGamePreviewFrameSource.matchAll(/<iframe\b/g),
].length;
if (clientPreviewFrameCount !== 1) {
throw new Error(
'AI game creator client workbench must own exactly one local preview frame',
);
}
const projectDevelopmentPreviewMountCount = [
...aiGameCreatorProjectDevelopmentSource.matchAll(
/<LocalGamePreviewFrame\b/g,
),
].length;
const supervisorChatPreviewMountCount = [
...aiGameCreatorSupervisorChatOnlyViewSource.matchAll(
/<LocalGamePreviewFrame\b/g,
),
].length;
if (
projectDevelopmentPreviewMountCount !== 1 ||
supervisorChatPreviewMountCount !== 1
) {
throw new Error(
'AI game creator client views must delegate preview rendering to the shared local preview frame',
);
}
for (const snippet of [
'function resolveEmbeddedPreviewUrl(',
"url.protocol !== 'http:' || url.hostname !== '127.0.0.1'",
'sandbox="allow-scripts allow-same-origin allow-forms allow-pointer-lock"',
'src={embeddedPreviewUrl}',
'src={embeddedUrl}',
]) {
if (!aiGameCreatorProjectDevelopmentSource.includes(snippet)) {
if (!aiGameCreatorLocalGamePreviewFrameSource.includes(snippet)) {
throw new Error(
`AI game creator embedded preview boundary drifted: missing ${snippet}`,
);