拆分游戏创作壳 Tauri 入口

拆出 CLI、命令、配置、Agent、素材、项目、预览和窗口模块
拆出 Rust 单测并保留 main.rs 作为 Tauri 薄入口
扩展壳配置与原生壳门禁的 Rust 源码扫描范围
同步 AI 游戏创作 App 技术方案和决策记录
This commit is contained in:
AIGameCreator App
2026-07-04 16:25:45 +08:00
parent 3340b307d6
commit 7afec12958
14 changed files with 13211 additions and 13100 deletions
+30 -17
View File
@@ -29,9 +29,9 @@ const aiGameCreatorShellAppSource = fs.readFileSync(
const aiGameCreatorShellTauriConfig = JSON.parse(
fs.readFileSync('apps/ai-game-creator-shell/src-tauri/tauri.conf.json', 'utf8'),
);
const aiGameCreatorShellTauriSource = fs.readFileSync(
'apps/ai-game-creator-shell/src-tauri/src/main.rs',
'utf8',
const aiGameCreatorShellTauriSource = readSourceTree(
'apps/ai-game-creator-shell/src-tauri/src',
'.rs',
);
const productionShellScanRoots = [
@@ -80,6 +80,21 @@ const h5HostBridgeScannedFacadeImports = new Set([
'writeHostClipboardText',
]);
function readSourceTree(entryPath, extension) {
const stats = fs.statSync(entryPath);
if (stats.isDirectory()) {
return fs
.readdirSync(entryPath, { withFileTypes: true })
.sort((left, right) => left.name.localeCompare(right.name))
.map((entry) => readSourceTree(path.join(entryPath, entry.name), extension))
.join('\n');
}
if (path.extname(entryPath) !== extension) {
return '';
}
return fs.readFileSync(entryPath, 'utf8');
}
function assertRootNativeShellCheckScripts() {
if (rootPackageJson.scripts?.['check:native-shells'] !== 'node scripts/check-native-shells.mjs') {
throw new Error('root check:native-shells script must run scripts/check-native-shells.mjs');
@@ -2000,7 +2015,7 @@ function assertAiGameCreatorShellUserDevBoundary() {
"await invoke<LocalPreviewStatus>('open_local_game_preview'",
"return '已交给外部浏览器打开。';",
'const openMessage = await openPreviewInExternalBrowser(',
"appendLocalPermissionLog(\n result.projectPath,\n 'permission.confirm',\n 'project.create',",
"appendLocalPermissionLog(\n openedProject.projectPath,\n 'permission.confirm',\n 'project.create',",
]) {
if (!aiGameCreatorShellAppSource.includes(snippet)) {
throw new Error(`AI game creator external preview boundary drifted: missing ${snippet}`);
@@ -2008,15 +2023,20 @@ function assertAiGameCreatorShellUserDevBoundary() {
}
for (const snippet of [
'#[cfg(debug_assertions)]\nfn developer_window_url()',
'tauri::WebviewUrl::App(PathBuf::from("index.html?dev"))',
'WebviewWindowBuilder::new(app, "developer", developer_window_url())',
'#[cfg(debug_assertions)]\n open_developer_window(app)?;',
'fn open_local_game_preview(',
'.open_url(&url, None::<&str>)',
]) {
if (!aiGameCreatorShellTauriSource.includes(snippet)) {
throw new Error(`AI game creator developer window boundary drifted: missing ${snippet}`);
throw new Error(`AI game creator external preview boundary drifted: missing ${snippet}`);
}
}
for (const snippet of [
'fn open_developer_window(',
'WebviewWindowBuilder::new(app, "developer"',
'open_developer_window(app)?',
]) {
if (aiGameCreatorShellTauriSource.includes(snippet)) {
throw new Error(`AI game creator release shell must not auto-open developer windows: ${snippet}`);
}
}
@@ -2026,21 +2046,14 @@ function assertAiGameCreatorShellUserDevBoundary() {
const launcherWindowCommandIndex = aiGameCreatorShellTauriSource.indexOf(
'fn open_game_creator_launcher_window(',
);
const developerWindowIndex = aiGameCreatorShellTauriSource.indexOf(
'#[cfg(debug_assertions)]\nfn open_developer_window(',
);
const workspaceWindowCommandSource = aiGameCreatorShellTauriSource.slice(
workspaceWindowCommandIndex,
launcherWindowCommandIndex,
);
const launcherWindowCommandSource = aiGameCreatorShellTauriSource.slice(
launcherWindowCommandIndex,
developerWindowIndex,
);
const launcherWindowCommandSource = aiGameCreatorShellTauriSource.slice(launcherWindowCommandIndex);
if (
workspaceWindowCommandIndex < 0 ||
launcherWindowCommandIndex < 0 ||
developerWindowIndex < 0 ||
!workspaceWindowCommandSource.includes('window.close().map_err(|error| error.to_string())?;') ||
!launcherWindowCommandSource.includes('window.close().map_err(|error| error.to_string())?;')
) {