支持 AI 游戏创作打开现有 Godot 项目
Project CI / Repository checks (push) Failing after 44s
Project CI / Native shell tests (push) Failing after 1m42s
Project CI / Frontend tests (push) Successful in 2m50s
Project CI / Backend tests (push) Successful in 3m41s

新增 Godot 项目选择、校验、导入和项目上下文切换入口。

只在所选项目根保留 .agent 元数据,并让总控使用标准运行档。

修复发布版原生 API 访问和 React runtime 重复加载问题。

收紧 Provider 工具 Schema 子集并增加回归门禁。

补充 Rust、前端测试及 PRD、技术方案和共享决策记录。
This commit is contained in:
kdletters
2026-08-11 13:25:02 +08:00
parent 4c0fdf1806
commit 755bf80858
32 changed files with 932 additions and 79 deletions
+76 -7
View File
@@ -64,6 +64,24 @@ const aiGameCreatorShellTauriSource = readSourceTree(
'apps/ai-game-creator-shell/src-tauri/src',
'.rs',
);
const aiGameCreatorClientHttpSource = fs.readFileSync(
'apps/ai-game-creator-shell/src/services/clientHttp.ts',
'utf8',
);
const aiGameCreatorMainCapability = JSON.parse(
fs.readFileSync(
'apps/ai-game-creator-shell/src-tauri/capabilities/main.json',
'utf8',
),
);
const aiGameCreatorCargoManifestSource = fs.readFileSync(
'apps/ai-game-creator-shell/src-tauri/Cargo.toml',
'utf8',
);
const aiGameCreatorViteConfigSource = fs.readFileSync(
'apps/ai-game-creator-shell/vite.config.ts',
'utf8',
);
const productionShellScanRoots = [
'apps/mobile-shell',
@@ -2355,6 +2373,46 @@ function assertAiGameCreatorShellUserDevBoundary() {
'AI game creator dev shell must keep local preview iframe access for the developer window',
);
}
if (
!aiGameCreatorClientHttpSource.includes(
"'https://dev.genarrative.world'",
) ||
!aiGameCreatorClientHttpSource.includes("transport: 'tauri-http'") ||
!aiGameCreatorClientHttpSource.includes('target.origin !==')
) {
throw new Error(
'AI game creator release dev API transport boundary drifted',
);
}
if (
!aiGameCreatorCargoManifestSource.includes('tauri-plugin-http = "2.5.9"') ||
!aiGameCreatorShellTauriSource.includes('tauri_plugin_http::init()')
) {
throw new Error(
'AI game creator release must register the native HTTP plugin',
);
}
if (
!aiGameCreatorViteConfigSource.includes("dedupe: ['react', 'react-dom']")
) {
throw new Error(
'AI game creator monorepo build must dedupe React runtime packages',
);
}
const httpPermission = (aiGameCreatorMainCapability.permissions ?? []).find(
(permission) =>
typeof permission === 'object' &&
permission?.identifier === 'http:default',
);
if (
!httpPermission ||
JSON.stringify(httpPermission.allow ?? []) !==
JSON.stringify([{ url: 'https://dev.genarrative.world/api/*' }])
) {
throw new Error(
'AI game creator native HTTP scope must stay limited to the dev API',
);
}
for (const snippet of [
'function isDeveloperMode()',
@@ -2369,11 +2427,13 @@ function assertAiGameCreatorShellUserDevBoundary() {
}
for (const snippet of [
'projectSupervisorOnly ? false : isDeveloperMode()',
"{devMode ? (",
'{devMode ? (',
'className="developer-pane"',
]) {
if (!aiGameCreatorShellAppSource.includes(snippet)) {
throw new Error(`AI game creator user/dev UI boundary drifted: missing ${snippet}`);
throw new Error(
`AI game creator user/dev UI boundary drifted: missing ${snippet}`,
);
}
}
if (
@@ -2391,13 +2451,20 @@ function assertAiGameCreatorShellUserDevBoundary() {
const previewFrameCount = [
...aiGameCreatorShellDeveloperProjectPanelsSource.matchAll(/<iframe\b/g),
].length;
const devModeBranchIndex = aiGameCreatorShellAppSource.indexOf('{devMode ? (');
const developerPaneIndex = aiGameCreatorShellAppSource.indexOf('className="developer-pane"');
const devModeBranchIndex =
aiGameCreatorShellAppSource.indexOf('{devMode ? (');
const developerPaneIndex = aiGameCreatorShellAppSource.indexOf(
'className="developer-pane"',
);
if (previewFrameCount !== 1) {
throw new Error('AI game creator developer pane preview frame count drifted');
throw new Error(
'AI game creator developer pane preview frame count drifted',
);
}
if (developerProjectPanelIndexes.length !== 1) {
throw new Error('AI game creator developer project panels mount count drifted');
throw new Error(
'AI game creator developer project panels mount count drifted',
);
}
if (
devModeBranchIndex < 0 ||
@@ -2406,7 +2473,9 @@ function assertAiGameCreatorShellUserDevBoundary() {
(index) => index < devModeBranchIndex || index < developerPaneIndex,
)
) {
throw new Error('AI game creator preview panels must stay inside the dev-only pane');
throw new Error(
'AI game creator preview panels must stay inside the dev-only pane',
);
}
// 上面几条只约束 DeveloperProjectPanels 自身的 iframe 数量和挂载位置,管不到 App.tsx
// 直接内嵌 iframe 的情况——预览必须一律委托给客户端工作台,外壳自己不持有预览框。