完善游戏创作工作台与智能体恢复闭环
实现横屏项目开发工作台、资源画布、Supervisor 对话与专业 Agent 状态展示 修复总控和专业 Agent 重试、Runner 接管、历史成果跨 Run 持久展示及确认流程 补齐画板图片产物合同、客户端内预览、共享契约与安全边界 新增完整回归测试、工作台 PRD、技术方案与待解决事项
This commit is contained in:
@@ -26,6 +26,14 @@ const aiGameCreatorShellAppSource = fs.readFileSync(
|
||||
'apps/ai-game-creator-shell/src/App.tsx',
|
||||
'utf8',
|
||||
);
|
||||
const aiGameCreatorProjectDevelopmentSource = fs.readFileSync(
|
||||
'apps/ai-game-creator-shell/src/view/project-development/index.tsx',
|
||||
'utf8',
|
||||
);
|
||||
const aiGameCreatorPreviewRustSource = fs.readFileSync(
|
||||
'apps/ai-game-creator-shell/src-tauri/src/preview.rs',
|
||||
'utf8',
|
||||
);
|
||||
const aiGameCreatorShellTauriConfig = JSON.parse(
|
||||
fs.readFileSync('apps/ai-game-creator-shell/src-tauri/tauri.conf.json', 'utf8'),
|
||||
);
|
||||
@@ -1972,8 +1980,8 @@ function assertAiGameCreatorShellUserDevBoundary() {
|
||||
.split(';')
|
||||
.map((directive) => directive.trim())
|
||||
.find((directive) => directive.startsWith('frame-src ')) ?? '';
|
||||
if (releaseFrameSrc.includes('http://127.0.0.1:*')) {
|
||||
throw new Error('AI game creator release shell must not allow embedded local preview frames');
|
||||
if (!releaseFrameSrc.includes('http://127.0.0.1:*')) {
|
||||
throw new Error('AI game creator release shell must allow the client-local preview frame');
|
||||
}
|
||||
if (!devFrameSrc.includes('http://127.0.0.1:*')) {
|
||||
throw new Error('AI game creator dev shell must keep local preview iframe access for the developer window');
|
||||
@@ -1998,7 +2006,7 @@ function assertAiGameCreatorShellUserDevBoundary() {
|
||||
const devModeBranchIndex = aiGameCreatorShellAppSource.indexOf('{devMode ? (');
|
||||
const developerPaneIndex = aiGameCreatorShellAppSource.indexOf('className="developer-pane"');
|
||||
if (previewFrameIndexes.length !== 1) {
|
||||
throw new Error('AI game creator user shell must not embed game preview frames');
|
||||
throw new Error('AI game creator developer pane preview frame count drifted');
|
||||
}
|
||||
if (
|
||||
devModeBranchIndex < 0 ||
|
||||
@@ -2010,26 +2018,45 @@ function assertAiGameCreatorShellUserDevBoundary() {
|
||||
throw new Error('AI game creator preview iframe must stay inside the dev-only pane');
|
||||
}
|
||||
|
||||
const clientPreviewFrameCount = [
|
||||
...aiGameCreatorProjectDevelopmentSource.matchAll(/<iframe\b/g),
|
||||
].length;
|
||||
if (clientPreviewFrameCount !== 1) {
|
||||
throw new Error('AI game creator client workbench must own exactly one local preview frame');
|
||||
}
|
||||
for (const snippet of [
|
||||
'async function openPreviewInExternalBrowser(',
|
||||
"await invoke<LocalPreviewStatus>('open_local_game_preview'",
|
||||
"return '已交给外部浏览器打开。';",
|
||||
'const openMessage = await openPreviewInExternalBrowser(',
|
||||
"appendLocalPermissionLog(\n openedProject.projectPath,\n 'permission.confirm',\n 'project.create',",
|
||||
'function resolveEmbeddedPreviewUrl(',
|
||||
"url.protocol !== 'http:' || url.hostname !== '127.0.0.1'",
|
||||
'sandbox="allow-scripts allow-same-origin allow-forms allow-pointer-lock"',
|
||||
'src={embeddedPreviewUrl}',
|
||||
]) {
|
||||
if (!aiGameCreatorShellAppSource.includes(snippet)) {
|
||||
throw new Error(`AI game creator external preview boundary drifted: missing ${snippet}`);
|
||||
if (!aiGameCreatorProjectDevelopmentSource.includes(snippet)) {
|
||||
throw new Error(`AI game creator embedded preview boundary drifted: missing ${snippet}`);
|
||||
}
|
||||
}
|
||||
|
||||
for (const snippet of [
|
||||
'fn open_local_game_preview(',
|
||||
'.open_url(&url, None::<&str>)',
|
||||
"await invoke<LocalPreviewStatus>(\n 'activate_local_game_preview'",
|
||||
'已切换到客户端运行视图',
|
||||
]) {
|
||||
if (!aiGameCreatorShellTauriSource.includes(snippet)) {
|
||||
throw new Error(`AI game creator external preview boundary drifted: missing ${snippet}`);
|
||||
if (!aiGameCreatorShellAppSource.includes(snippet)) {
|
||||
throw new Error(`AI game creator client preview activation drifted: missing ${snippet}`);
|
||||
}
|
||||
}
|
||||
for (const snippet of [
|
||||
'fn activate_local_game_preview(',
|
||||
'preview_open_url(&status)?;',
|
||||
]) {
|
||||
if (!aiGameCreatorPreviewRustSource.includes(snippet)) {
|
||||
throw new Error(`AI game creator client preview command drifted: missing ${snippet}`);
|
||||
}
|
||||
}
|
||||
if (
|
||||
aiGameCreatorShellAppSource.includes('openPreviewInExternalBrowser') ||
|
||||
aiGameCreatorShellAppSource.includes('open_local_game_preview') ||
|
||||
aiGameCreatorPreviewRustSource.includes('.open_url(&url')
|
||||
) {
|
||||
throw new Error('AI game creator preview must not invoke the external browser');
|
||||
}
|
||||
for (const snippet of [
|
||||
'#[cfg(all(debug_assertions, not(test)))]\npub(crate) fn open_developer_window(',
|
||||
'#[cfg(all(debug_assertions, not(test)))]\n open_developer_window(app.handle())?;',
|
||||
|
||||
Reference in New Issue
Block a user