合并远端 master(直连 Codex 改造)
冲突 19 处 / 6 个文件,逐处判定归属而不是二选一:
· commands.rs —— 保留本分支的 hydrate_game_creator_plan_gdd_state 输入解析,
丢掉与 master 重复的项目根定义(master 把它挪到了后面)。
· types.ts / useHomeProjectCreation.ts —— 取 master 把 mode/prompt/attachments
重构成 HomeDraft 的形状,保留本分支新增的 startMode。
· App.tsx —— directGameChatRuntime(master)与 !planningStartMode(本分支)是两个
互不相干的条件,合并保留;refreshDirectProjectSurface 在 merge base 里就带预览
逻辑,是 master 主动删掉并改名成 refreshDirectProjectManifest 的,取 master;
capturePendingGameChatStageManifestBeforeNextRun 是分支新增且仍被调用,保留。
· SupervisorChatOnlyView.tsx —— master 的 directCodex 短路与本分支的
projectedRuntime / descendantsStillActive 正交,逐处合成。
· project-development.suite.ts —— 那段专业 Agent 断言 base 里就有、master 主动
删除(直连 Codex 之后不再适用),取 master。
两处语义缺口一并补上:master 新增的 codex_app_server 构造
AgentRuntimeProviderRequestSnapshot 时缺本分支新增的 planning_session_binding
字段(首页直连对话不属于任何立项 session,填 None);首页提交按钮的 aria-label
还引用着已被删除的 homeAgentMode,取 master 的固定文案。
**做方案 UI 入口暂时缺失,待定。** master 在 bacd7a9da 里把 HomeAgentMode 整个删了,
首页的「做游戏 / 做素材 / 做方案」模式选择不再存在,而 startMode 在前端只有那一个
来源(homeDraftStartMode(mode))。立项策划链路的代码全部保留——后端、prompt、
澄清卡、审批卡、E2E 都在——但首页现在统一按 direct-build 进入
(HOME_DRAFT_START_MODE 常量,已在原处留注释)。入口放哪由产品侧决定后另做一笔。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,7 +4,6 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- codex/ai-game-creator-app
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
@@ -59,6 +58,16 @@ jobs:
|
||||
else
|
||||
base_ref="$(git merge-base HEAD origin/master 2>/dev/null || git rev-parse HEAD)"
|
||||
fi
|
||||
resolved_base_ref="$(git rev-parse --verify "${base_ref}^{commit}" 2>/dev/null || true)"
|
||||
head_ref="$(git rev-parse HEAD)"
|
||||
if [[ "${resolved_base_ref}" == "${head_ref}" ]]; then
|
||||
resolved_base_ref="$(git rev-parse --verify HEAD^ 2>/dev/null || true)"
|
||||
fi
|
||||
if [[ -z "${resolved_base_ref}" ]]; then
|
||||
echo 'comparison base must resolve to a commit distinct from HEAD.' >&2
|
||||
exit 1
|
||||
fi
|
||||
base_ref="${resolved_base_ref}"
|
||||
if [[ "${GITHUB_EVENT_NAME:-}" == 'pull_request' ]] \
|
||||
&& ! git merge-base --is-ancestor "${base_ref}" HEAD; then
|
||||
echo 'pull request head does not contain the latest base commit; update the branch and rerun CI.' >&2
|
||||
@@ -139,6 +148,16 @@ jobs:
|
||||
else
|
||||
base_ref="$(git merge-base HEAD origin/master 2>/dev/null || git rev-parse HEAD)"
|
||||
fi
|
||||
resolved_base_ref="$(git rev-parse --verify "${base_ref}^{commit}" 2>/dev/null || true)"
|
||||
head_ref="$(git rev-parse HEAD)"
|
||||
if [[ "${resolved_base_ref}" == "${head_ref}" ]]; then
|
||||
resolved_base_ref="$(git rev-parse --verify HEAD^ 2>/dev/null || true)"
|
||||
fi
|
||||
if [[ -z "${resolved_base_ref}" ]]; then
|
||||
echo 'comparison base must resolve to a commit distinct from HEAD.' >&2
|
||||
exit 1
|
||||
fi
|
||||
base_ref="${resolved_base_ref}"
|
||||
if [[ "${GITHUB_EVENT_NAME:-}" == 'pull_request' ]] \
|
||||
&& ! git merge-base --is-ancestor "${base_ref}" HEAD; then
|
||||
echo 'pull request head does not contain the latest base commit; update the branch and rerun CI.' >&2
|
||||
|
||||
@@ -34,6 +34,12 @@ temp*build*/
|
||||
/apps/ai-game-creator-shell/src-tauri/target/
|
||||
/apps/ai-game-creator-shell/src-tauri/gen/
|
||||
/apps/ai-game-creator-shell/src-tauri/logs/
|
||||
/apps/ai-game-creator-shell/src-tauri/resources/codex/win-x64/codex.exe
|
||||
/apps/ai-game-creator-shell/src-tauri/resources/codex/win-x64/manifest.json
|
||||
/apps/ai-game-creator-shell/src-tauri/resources/codex/win-x64/bin/
|
||||
/apps/ai-game-creator-shell/src-tauri/resources/codex/win-x64/codex-path/
|
||||
/apps/ai-game-creator-shell/src-tauri/resources/codex/win-x64/codex-resources/
|
||||
/apps/ai-game-creator-shell/src-tauri/resources/codex/win-x64/codex-package.json
|
||||
/apps/ai-game-creator-shell/logs/
|
||||
/apps/ai-game-creator-shell/.llm-drafts/
|
||||
/apps/ai-game-creator-shell/game-creator.config.local.json
|
||||
@@ -48,6 +54,8 @@ temp*build*/
|
||||
/public/generated-characters
|
||||
/.codex-temp
|
||||
/.app/
|
||||
/.jenkins-source-commit
|
||||
/.jenkins-spacetime-schema-base
|
||||
/target/
|
||||
/logs
|
||||
/.claude/settings.local.json
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
# AI Native Visual RPG
|
||||
# Genarrative / 陶泥儿
|
||||
|
||||
一个以“AI 叙事 + 本地规则 + 像素演出”为核心的视觉 RPG 原型。
|
||||
一个 AI 原生互动内容与小游戏平台,当前主站聚焦图片画布创作、项目与素材管理,以及账号、钱包和后台管理等平台公共能力。
|
||||
|
||||
当前已经具备这些主要能力:
|
||||
|
||||
- 世界与角色选择
|
||||
- AI 剧情推进与流式对话
|
||||
- 战斗演出、NPC 战斗、切磋
|
||||
- NPC 交易、送礼、求助、招募
|
||||
- 宝藏交互
|
||||
- 同伴跟随与战斗
|
||||
- 游戏主流程内嵌的角色资产工坊、自定义世界实体编辑与角色形象编辑
|
||||
- 自动存档与继续游戏
|
||||
- 图片画布编辑、项目与素材管理
|
||||
- 图片、视频、音频等外部生成任务
|
||||
- 账号、钱包、充值、兑换码与个人资料
|
||||
- 后台运营、配置与生产运维工具
|
||||
- AI 游戏创作独立 App
|
||||
|
||||
## 运行
|
||||
|
||||
@@ -30,11 +27,8 @@ npm install
|
||||
准备环境变量:
|
||||
|
||||
- 复制 `.env.example` 为 `.env.local`
|
||||
- 填入 `LLM_API_KEY` / `ARK_API_KEY`
|
||||
- 按需设置 `VITE_LLM_MODEL`
|
||||
- 如需启用阿里云短信验证码登录,填写 `ALIYUN_SMS_ACCESS_KEY_ID`、`ALIYUN_SMS_ACCESS_KEY_SECRET`,并确认 `SMS_AUTH_PROVIDER="aliyun"`
|
||||
- 本地联调短信登录时,建议将 `VITE_AUTH_ALLOW_DEV_GUEST` 设为 `false`,避免开发模式自动进入游客账号而跳过登录页
|
||||
- 如需打印完整 prompt/output,可把 `VITE_LLM_DEBUG_LOG` 设为 `true`
|
||||
- 只填写本次联调所需配置;不要提交 `.env.local`、密钥、Token 或其它本地认证信息
|
||||
- api-server 环境变量和 Provider 配置以 `.env.example` 及当前开发运维文档为准
|
||||
|
||||
启动开发环境:
|
||||
|
||||
@@ -69,51 +63,21 @@ npm run lint
|
||||
npm run check:encoding
|
||||
```
|
||||
|
||||
内容引用校验:
|
||||
|
||||
```bash
|
||||
npm run check:data
|
||||
```
|
||||
|
||||
编辑器 override 校验:
|
||||
|
||||
```bash
|
||||
npm run check:overrides
|
||||
```
|
||||
|
||||
关键内容 smoke 检查:
|
||||
|
||||
```bash
|
||||
npm run check:smoke
|
||||
```
|
||||
|
||||
一键内容检查:
|
||||
|
||||
```bash
|
||||
npm run check:content
|
||||
```
|
||||
|
||||
## 主要结构
|
||||
|
||||
主运行时:
|
||||
|
||||
- [src/App.tsx](./src/App.tsx)
|
||||
- [src/active-main.tsx](./src/active-main.tsx)
|
||||
- [src/ActiveApp.tsx](./src/ActiveApp.tsx)
|
||||
- [src/AuthenticatedApp.tsx](./src/AuthenticatedApp.tsx)
|
||||
- [src/routing/appRoutes.tsx](./src/routing/appRoutes.tsx)
|
||||
- [src/hooks/useCombatFlow.ts](./src/hooks/useCombatFlow.ts)
|
||||
- [src/routing/activeAppRoutes.tsx](./src/routing/activeAppRoutes.tsx)
|
||||
- [src/components/platform-entry/PlatformEntryActiveFlowShell.tsx](./src/components/platform-entry/PlatformEntryActiveFlowShell.tsx)
|
||||
|
||||
主流程内嵌编辑能力:
|
||||
创作与项目能力:
|
||||
|
||||
- [src/components/image-editor/ImageCanvasEditorView.tsx](./src/components/image-editor/ImageCanvasEditorView.tsx)
|
||||
- [src/components/rpg-creation-editor/RpgCreationEntityEditorModal.tsx](./src/components/rpg-creation-editor/RpgCreationEntityEditorModal.tsx)
|
||||
- [src/components/rpg-creation-asset-studio/RpgCreationRoleAssetStudioModal.tsx](./src/components/rpg-creation-asset-studio/RpgCreationRoleAssetStudioModal.tsx)
|
||||
|
||||
核心数据:
|
||||
|
||||
- [src/data/scenePresets.ts](./src/data/scenePresets.ts)
|
||||
- [src/data/characterPresets.ts](./src/data/characterPresets.ts)
|
||||
- [src/data/npcInteractions.ts](./src/data/npcInteractions.ts)
|
||||
- [src/data/treasureInteractions.ts](./src/data/treasureInteractions.ts)
|
||||
- [src/components/creation-home/CreationLandingView.tsx](./src/components/creation-home/CreationLandingView.tsx)
|
||||
- [src/components/project/ProjectGalleryView.tsx](./src/components/project/ProjectGalleryView.tsx)
|
||||
|
||||
## 文档入口
|
||||
|
||||
|
||||
+141
@@ -30,6 +30,7 @@
|
||||
"zustand": "^5.0.14"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@openai/codex": "0.147.0",
|
||||
"@tailwindcss/vite": "^4.1.14",
|
||||
"@tauri-apps/cli": "^2.11.2",
|
||||
"@types/react": "^19.2.14",
|
||||
@@ -1342,6 +1343,135 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@openai/codex": {
|
||||
"version": "0.147.0",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.147.0.tgz",
|
||||
"integrity": "sha512-EQLEXecAG2ptxI7UpBMo2TR/ga5596/c/OsYF/0LoUDh5JANZ7IoGqlzBEWbuEVQ76JePIbtTW/ihCkp1a7Z3w==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"codex": "bin/codex.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@openai/codex-darwin-arm64": "npm:@openai/codex@0.147.0-darwin-arm64",
|
||||
"@openai/codex-darwin-x64": "npm:@openai/codex@0.147.0-darwin-x64",
|
||||
"@openai/codex-linux-arm64": "npm:@openai/codex@0.147.0-linux-arm64",
|
||||
"@openai/codex-linux-x64": "npm:@openai/codex@0.147.0-linux-x64",
|
||||
"@openai/codex-win32-arm64": "npm:@openai/codex@0.147.0-win32-arm64",
|
||||
"@openai/codex-win32-x64": "npm:@openai/codex@0.147.0-win32-x64"
|
||||
}
|
||||
},
|
||||
"node_modules/@openai/codex-darwin-arm64": {
|
||||
"name": "@openai/codex",
|
||||
"version": "0.147.0-darwin-arm64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.147.0-darwin-arm64.tgz",
|
||||
"integrity": "sha512-BEUVkiOW7kLcRyrMLfAr/h9wF8sRVJyZDy6OHtVn6QGDXiv3BvAZVTY1Pu9xF7KdIdkYXbp4uayN0aDQQaAUJw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/@openai/codex-darwin-x64": {
|
||||
"name": "@openai/codex",
|
||||
"version": "0.147.0-darwin-x64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.147.0-darwin-x64.tgz",
|
||||
"integrity": "sha512-Tb8McE5SvJIH0Vs5R6sq7u+quiC931yan2KOOl6km1OdZ82+Wi7eF5XrSFPs5CF7xCgoIK4Vs+byMbT5hN+ZUw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/@openai/codex-linux-arm64": {
|
||||
"name": "@openai/codex",
|
||||
"version": "0.147.0-linux-arm64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.147.0-linux-arm64.tgz",
|
||||
"integrity": "sha512-SLC1JXw2TYfr/c3HhrJubyyLelq7vTOLWVmiThFA+z0+WgzCPmaseJ/kzDD3Gge/TO7fCnnj7UcPmC0d2c8XAg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/@openai/codex-linux-x64": {
|
||||
"name": "@openai/codex",
|
||||
"version": "0.147.0-linux-x64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.147.0-linux-x64.tgz",
|
||||
"integrity": "sha512-0W9MBxPpWW0cSkNqrTDN2jR7rzzT7oNMhQY5446lT2Lw5cz5yhDTck4Va9rjkQEm+HlFzP/dmEMSZbXfJsINmw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/@openai/codex-win32-arm64": {
|
||||
"name": "@openai/codex",
|
||||
"version": "0.147.0-win32-arm64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.147.0-win32-arm64.tgz",
|
||||
"integrity": "sha512-e2ZstJ8zT8Rm1nvR7CUVO+Gr3cTChE41+VfOzGhynzDXEoW0wfbjUQbc2bWbh1arG94LMm4y3dqBtUIbSrfeGA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/@openai/codex-win32-x64": {
|
||||
"name": "@openai/codex",
|
||||
"version": "0.147.0-win32-x64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.147.0-win32-x64.tgz",
|
||||
"integrity": "sha512-oT7Ss5fAPf2fiWE9QNURqZcQGAAawSVxmIUdgPzckq4KFZAM+pRz9JbM4Rr498CjtbNgTOjWvDJ+DXvIBSfOPA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/@preact/signals-core": {
|
||||
"version": "1.14.4",
|
||||
"resolved": "https://registry.npmjs.org/@preact/signals-core/-/signals-core-1.14.4.tgz",
|
||||
@@ -3131,6 +3261,7 @@
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -3151,6 +3282,7 @@
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -3171,6 +3303,7 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -3191,6 +3324,7 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -3211,6 +3345,7 @@
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -3231,6 +3366,7 @@
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -3251,6 +3387,7 @@
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -3271,6 +3408,7 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -3291,6 +3429,7 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -3311,6 +3450,7 @@
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -3331,6 +3471,7 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
"zustand": "^5.0.14"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@openai/codex": "0.147.0",
|
||||
"@tailwindcss/vite": "^4.1.14",
|
||||
"@tauri-apps/cli": "^2.11.2",
|
||||
"@types/react": "^19.2.14",
|
||||
|
||||
@@ -27,6 +27,12 @@ const tauriConfig = JSON.parse(
|
||||
'utf8',
|
||||
),
|
||||
);
|
||||
const windowsTauriConfig = JSON.parse(
|
||||
fs.readFileSync(
|
||||
new URL('../src-tauri/tauri.windows.conf.json', import.meta.url),
|
||||
'utf8',
|
||||
),
|
||||
);
|
||||
const gameChatReleaseTauriConfig = JSON.parse(
|
||||
fs.readFileSync(
|
||||
new URL('../src-tauri/tauri.game-chat-release.conf.json', import.meta.url),
|
||||
@@ -894,6 +900,7 @@ assertNoOpenAiApiKeys([
|
||||
new URL('../vite.config.ts', import.meta.url),
|
||||
new URL('../src-tauri/Cargo.toml', import.meta.url),
|
||||
new URL('../src-tauri/tauri.conf.json', import.meta.url),
|
||||
new URL('../src-tauri/tauri.windows.conf.json', import.meta.url),
|
||||
new URL(
|
||||
'../../../packages/shared/src/contracts/gameCreationApp.ts',
|
||||
import.meta.url,
|
||||
@@ -926,6 +933,7 @@ assertNoEnvironmentConfigFallbacks([
|
||||
new URL('../vite.config.ts', import.meta.url),
|
||||
new URL('../src-tauri/Cargo.toml', import.meta.url),
|
||||
new URL('../src-tauri/tauri.conf.json', import.meta.url),
|
||||
new URL('../src-tauri/tauri.windows.conf.json', import.meta.url),
|
||||
]);
|
||||
|
||||
assertNoNativeBrowserConfirm([new URL('../src/', import.meta.url)]);
|
||||
@@ -970,6 +978,21 @@ assertCommandNamesSubset(
|
||||
parseTauriHandlerCommandNames(tauriHandlerSource),
|
||||
);
|
||||
|
||||
const tauriHandlerCommandNames =
|
||||
parseTauriHandlerCommandNames(tauriHandlerSource);
|
||||
if (!tauriHandlerCommandNames.includes('create_automatic_local_game_project')) {
|
||||
throw new Error(
|
||||
'AI game creator shell home creation must expose automatic project creation',
|
||||
);
|
||||
}
|
||||
if (
|
||||
tauriHandlerCommandNames.includes('chat_with_game_creator_home_direct_codex')
|
||||
) {
|
||||
throw new Error(
|
||||
'AI game creator shell home surface must not expose a projectless Codex conversation',
|
||||
);
|
||||
}
|
||||
|
||||
if (packageConfig.name !== '@genarrative/ai-game-creator-shell') {
|
||||
throw new Error('AI game creator shell package name drifted');
|
||||
}
|
||||
@@ -1114,6 +1137,32 @@ if (tauriConfig.identifier !== 'world.genarrative.ai-game-creator') {
|
||||
throw new Error('AI game creator shell identifier drifted');
|
||||
}
|
||||
|
||||
const expectedBundledCodexResources = {
|
||||
'resources/codex/win-x64/bin/codex.exe': 'codex/win-x64/bin/codex.exe',
|
||||
'resources/codex/win-x64/bin/codex-code-mode-host.exe':
|
||||
'codex/win-x64/bin/codex-code-mode-host.exe',
|
||||
'resources/codex/win-x64/codex-path/rg.exe':
|
||||
'codex/win-x64/codex-path/rg.exe',
|
||||
'resources/codex/win-x64/codex-resources/codex-command-runner.exe':
|
||||
'codex/win-x64/codex-resources/codex-command-runner.exe',
|
||||
'resources/codex/win-x64/codex-resources/codex-windows-sandbox-setup.exe':
|
||||
'codex/win-x64/codex-resources/codex-windows-sandbox-setup.exe',
|
||||
'resources/codex/win-x64/codex-package.json':
|
||||
'codex/win-x64/codex-package.json',
|
||||
'resources/codex/win-x64/NOTICE.md': 'codex/win-x64/NOTICE.md',
|
||||
'resources/codex/win-x64/manifest.json': 'codex/win-x64/manifest.json',
|
||||
};
|
||||
if (tauriConfig.bundle?.resources !== undefined) {
|
||||
throw new Error(
|
||||
'AI game creator shell base Tauri config must not require Windows-only Codex resources',
|
||||
);
|
||||
}
|
||||
assert.deepEqual(
|
||||
windowsTauriConfig.bundle?.resources,
|
||||
expectedBundledCodexResources,
|
||||
'AI game creator shell Windows Tauri config must bundle the complete pinned Codex resource set',
|
||||
);
|
||||
|
||||
if (tauriConfig.app?.withGlobalTauri !== true) {
|
||||
throw new Error(
|
||||
'AI game creator shell must expose window.__TAURI__ for local commands',
|
||||
@@ -1636,6 +1685,9 @@ for (const snippet of [
|
||||
'fn append_local_permission_log_at(',
|
||||
'"command.auto"',
|
||||
'GameCreationAppPermission::Auto',
|
||||
'GAME_CREATOR_BUNDLED_CODEX_CLI_RELATIVE_PATH',
|
||||
'validate_game_creator_bundled_codex_cli',
|
||||
'内置 Codex CLI 完整性校验失败',
|
||||
]) {
|
||||
if (!tauriRustSource.includes(snippet)) {
|
||||
throw new Error(
|
||||
|
||||
+79
@@ -297,6 +297,58 @@ version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
||||
|
||||
[[package]]
|
||||
name = "axum"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31b698c5f9a010f6573133b09e0de5408834d0c82f8d7475a89fc1867a71cd90"
|
||||
dependencies = [
|
||||
"axum-core",
|
||||
"bytes",
|
||||
"form_urlencoded",
|
||||
"futures-util",
|
||||
"http",
|
||||
"http-body",
|
||||
"http-body-util",
|
||||
"hyper",
|
||||
"hyper-util",
|
||||
"itoa",
|
||||
"matchit",
|
||||
"memchr",
|
||||
"mime",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"serde_core",
|
||||
"serde_json",
|
||||
"serde_path_to_error",
|
||||
"serde_urlencoded",
|
||||
"sync_wrapper",
|
||||
"tokio",
|
||||
"tower",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "axum-core"
|
||||
version = "0.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-core",
|
||||
"http",
|
||||
"http-body",
|
||||
"http-body-util",
|
||||
"mime",
|
||||
"pin-project-lite",
|
||||
"sync_wrapper",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.21.7"
|
||||
@@ -1646,6 +1698,7 @@ name = "genarrative-ai-game-creator-shell"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"agent-runtime-core",
|
||||
"axum",
|
||||
"base64 0.22.1",
|
||||
"chromiumoxide",
|
||||
"futures",
|
||||
@@ -2053,6 +2106,12 @@ version = "1.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
|
||||
|
||||
[[package]]
|
||||
name = "httpdate"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "1.10.1"
|
||||
@@ -2067,6 +2126,7 @@ dependencies = [
|
||||
"http",
|
||||
"http-body",
|
||||
"httparse",
|
||||
"httpdate",
|
||||
"itoa",
|
||||
"pin-project-lite",
|
||||
"smallvec",
|
||||
@@ -2649,6 +2709,12 @@ dependencies = [
|
||||
"web_atoms",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matchit"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
|
||||
|
||||
[[package]]
|
||||
name = "matrixmultiply"
|
||||
version = "0.3.11"
|
||||
@@ -4647,6 +4713,17 @@ dependencies = [
|
||||
"zmij",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_path_to_error"
|
||||
version = "0.1.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"serde",
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_repr"
|
||||
version = "0.1.20"
|
||||
@@ -5850,6 +5927,7 @@ dependencies = [
|
||||
"tokio",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5888,6 +5966,7 @@ version = "0.1.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100"
|
||||
dependencies = [
|
||||
"log",
|
||||
"pin-project-lite",
|
||||
"tracing-attributes",
|
||||
"tracing-core",
|
||||
|
||||
@@ -11,6 +11,7 @@ game-chat-release = []
|
||||
[build-dependencies]
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
sha2 = "0.10"
|
||||
shared-contracts = { path = "../../../server-rs/crates/shared-contracts", default-features = false }
|
||||
tauri-build = { version = "2.6.2", features = [] }
|
||||
|
||||
@@ -20,6 +21,7 @@ typed_floats = { version = "1.0.7", features = ["serde"] }
|
||||
nalgebra = { version = "0.35.0", features = ["serde-serialize"] }
|
||||
agent-runtime-core = { path = "../../../server-rs/crates/agent-runtime-core" }
|
||||
base64 = "0.22"
|
||||
axum = "0.8"
|
||||
chromiumoxide = "0.9.1"
|
||||
futures = "0.3"
|
||||
getrandom = "0.3"
|
||||
@@ -42,7 +44,7 @@ similar = "2.7"
|
||||
platform-llm = { path = "../../../server-rs/crates/platform-llm" }
|
||||
platform-agent = { path = "../../../server-rs/crates/platform-agent" }
|
||||
portable-pty = "0.9"
|
||||
reqwest = { version = "0.12", default-features = false, features = ["json", "multipart", "native-tls"] }
|
||||
reqwest = { version = "0.12", default-features = false, features = ["json", "multipart", "native-tls", "stream"] }
|
||||
shared-contracts = { path = "../../../server-rs/crates/shared-contracts", default-features = false }
|
||||
tauri = { version = "2.11.2", features = [] }
|
||||
tauri-plugin-dialog = "2.7.1"
|
||||
|
||||
@@ -3,11 +3,126 @@ mod frontend_dist_guard;
|
||||
#[path = "build_support/runtime_prompt_bundle.rs"]
|
||||
mod runtime_prompt_bundle;
|
||||
|
||||
#[cfg(windows)]
|
||||
use sha2::{Digest, Sha256};
|
||||
use std::collections::BTreeSet;
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[cfg(windows)]
|
||||
use std::io::{BufReader, Read};
|
||||
|
||||
const BUNDLED_CODEX_CLI_VERSION: &str = "codex-cli 0.147.0";
|
||||
|
||||
#[cfg(windows)]
|
||||
const BUNDLED_CODEX_FILES: [&str; 6] = [
|
||||
"bin/codex.exe",
|
||||
"bin/codex-code-mode-host.exe",
|
||||
"codex-path/rg.exe",
|
||||
"codex-resources/codex-command-runner.exe",
|
||||
"codex-resources/codex-windows-sandbox-setup.exe",
|
||||
"codex-package.json",
|
||||
];
|
||||
|
||||
#[cfg(windows)]
|
||||
fn sha256_file(path: &std::path::Path) -> Result<String, std::io::Error> {
|
||||
let file = fs::File::open(path)?;
|
||||
let mut reader = BufReader::new(file);
|
||||
let mut hasher = Sha256::new();
|
||||
let mut buffer = [0_u8; 64 * 1024];
|
||||
loop {
|
||||
let read = reader.read(&mut buffer)?;
|
||||
if read == 0 {
|
||||
break;
|
||||
}
|
||||
hasher.update(&buffer[..read]);
|
||||
}
|
||||
Ok(format!("{:x}", hasher.finalize()))
|
||||
}
|
||||
|
||||
fn stage_bundled_codex_cli(manifest_dir: &std::path::Path) {
|
||||
#[cfg(windows)]
|
||||
{
|
||||
let app_root = manifest_dir
|
||||
.parent()
|
||||
.expect("AI 游戏创作 Tauri manifest 必须位于应用目录下");
|
||||
let source_candidates = [
|
||||
app_root.join(
|
||||
"node_modules/@openai/codex-win32-x64/vendor/x86_64-pc-windows-msvc",
|
||||
),
|
||||
app_root.join(
|
||||
"node_modules/@openai/codex/node_modules/@openai/codex-win32-x64/vendor/x86_64-pc-windows-msvc",
|
||||
),
|
||||
];
|
||||
let source = source_candidates
|
||||
.iter()
|
||||
.find(|path| {
|
||||
BUNDLED_CODEX_FILES
|
||||
.iter()
|
||||
.all(|relative| path.join(relative).is_file())
|
||||
})
|
||||
.cloned()
|
||||
.unwrap_or_else(|| {
|
||||
panic!(
|
||||
"内置 Codex CLI 缺失;请先在 apps/ai-game-creator-shell 执行 npm ci(已检查:{})",
|
||||
source_candidates
|
||||
.iter()
|
||||
.map(|path| path.display().to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(";")
|
||||
)
|
||||
});
|
||||
let target_dir = manifest_dir.join("resources/codex/win-x64");
|
||||
let notice = target_dir.join("NOTICE.md");
|
||||
if !notice.is_file() {
|
||||
panic!("内置 Codex CLI 第三方声明缺失:{}", notice.display());
|
||||
}
|
||||
fs::create_dir_all(&target_dir).expect("创建内置 Codex CLI 资源目录失败");
|
||||
let mut file_hashes = serde_json::Map::new();
|
||||
for relative in BUNDLED_CODEX_FILES {
|
||||
let source_path = source.join(relative);
|
||||
let target_path = target_dir.join(relative);
|
||||
if let Some(parent) = target_path.parent() {
|
||||
fs::create_dir_all(parent).expect("创建内置 Codex CLI 资源子目录失败");
|
||||
}
|
||||
let source_sha256 = sha256_file(&source_path).expect("读取内置 Codex CLI 资源失败");
|
||||
let target_matches_source = target_path.is_file()
|
||||
&& sha256_file(&target_path)
|
||||
.map(|target_sha256| target_sha256 == source_sha256)
|
||||
.unwrap_or(false);
|
||||
if !target_matches_source {
|
||||
fs::copy(&source_path, &target_path).expect("复制内置 Codex CLI 资源失败");
|
||||
}
|
||||
file_hashes.insert(
|
||||
relative.to_string(),
|
||||
serde_json::Value::String(source_sha256),
|
||||
);
|
||||
}
|
||||
let manifest = serde_json::json!({
|
||||
"schemaVersion": "genarrative-codex-sidecar.v2",
|
||||
"platform": "win32-x64",
|
||||
"version": BUNDLED_CODEX_CLI_VERSION,
|
||||
"files": file_hashes,
|
||||
});
|
||||
let manifest_path = target_dir.join("manifest.json");
|
||||
let manifest_payload = format!(
|
||||
"{}\n",
|
||||
serde_json::to_string_pretty(&manifest).expect("序列化内置 Codex CLI 清单失败")
|
||||
);
|
||||
if fs::read_to_string(&manifest_path)
|
||||
.map(|current| current != manifest_payload)
|
||||
.unwrap_or(true)
|
||||
{
|
||||
fs::write(&manifest_path, manifest_payload).expect("写入内置 Codex CLI 清单失败");
|
||||
}
|
||||
for relative in BUNDLED_CODEX_FILES {
|
||||
println!("cargo:rerun-if-changed={}", source.join(relative).display());
|
||||
}
|
||||
println!("cargo:rerun-if-changed={}", notice.display());
|
||||
}
|
||||
}
|
||||
|
||||
fn seed_task_group_id(
|
||||
group: &shared_contracts::game_creation_app::GameCreationAppAgentGroup,
|
||||
) -> &'static str {
|
||||
@@ -56,6 +171,7 @@ fn main() {
|
||||
env::var_os("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR must be available"),
|
||||
);
|
||||
let manifest_path = manifest_dir.join("prompts/runtime/manifest.json");
|
||||
stage_bundled_codex_cli(&manifest_dir);
|
||||
let compiled = runtime_prompt_bundle::compile_manifest(&manifest_path)
|
||||
.unwrap_or_else(|error| panic!("Prompt Bundle 编译失败:{error}"));
|
||||
validate_seed_task_catalog(&compiled);
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
---
|
||||
name: agc-browser-playtest
|
||||
description: Run and interpret real AGC desktop and mobile browser evidence through the approved client tool. Use after meaningful game creation or modification, when diagnosing runtime or layout problems, or before claiming a playable game is complete.
|
||||
---
|
||||
|
||||
# AGC Browser Playtest
|
||||
|
||||
Use `agc_browser_playtest` from the `agc_tools` MCP server. Do not replace it with static source inspection or a statement that the page should work.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Call the tool after the current game files are ready to run. Start with attempt `1`; increment the attempt only after a real corrective edit.
|
||||
2. Inspect both desktop and mobile results, including page readiness, visible text, screenshots, console errors, exceptions, failed requests, Canvas probes, blocked actions, and interaction evidence.
|
||||
3. Compare screenshots with the user's request. Check that the active game fills its intended area, HUD elements do not cover gameplay, controls are visible, and requested platform art appears in the core experience.
|
||||
4. If evidence exposes a defect, edit the actual game files and call the tool again. Keep the loop bounded to three attempts per user request unless the user explicitly asks to continue.
|
||||
5. Treat browser infrastructure failure, an unloaded page, an unhandled exception, or missing evidence as a failed validation. Do not claim success from a partial result.
|
||||
6. Use game-specific reasoning for quality. Do not require a fixed board, fixed text, fixed number of slices, or a legacy harness scenario.
|
||||
|
||||
Call `agc_read_skill_resource` with `skillName="agc-browser-playtest"` and `relativePath="references/browser-evidence-contract.md"` before interpreting screenshots or Canvas/WebGL asset observations.
|
||||
|
||||
## Reporting
|
||||
|
||||
Summarize the real actions exercised, desktop and mobile observations, defects fixed, platform art actually observed, and remaining risks. Keep internal absolute paths and diagnostic-only details out of the user reply.
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
interface:
|
||||
display_name: "浏览器试玩验收"
|
||||
short_description: "调用客户端真实双视口浏览器工具试玩,并依据结构化运行证据持续修复"
|
||||
default_prompt: "Use $agc-browser-playtest to run real desktop and mobile browser validation and fix observed issues."
|
||||
|
||||
dependencies:
|
||||
tools:
|
||||
- type: "mcp"
|
||||
value: "agc_tools"
|
||||
description: "陶泥儿客户端提供的受限双视口浏览器试玩工具"
|
||||
transport: "stdio"
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
# Browser Evidence Contract
|
||||
|
||||
The browser tool launches the current project through an AGC-owned loopback preview and a restricted Chromium profile. It blocks external proxy traffic, new windows, downloads, permissions, notifications, and service workers.
|
||||
|
||||
Treat each viewport independently. A global pass requires both desktop and mobile to load and remain free of configured blocking diagnostics. Screenshots are observation evidence, not proof of platform provenance.
|
||||
|
||||
Canvas/WebGL probes can show whether registered image sources entered a core renderer. A visible `<img>` beside the game proves only page visibility. Use source files, runtime probes, and screenshots together before claiming that platform art is part of gameplay.
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
---
|
||||
name: agc-client-projection
|
||||
description: Preserve AGC client resource and version projection semantics after real project changes. Use when adding, replacing, or removing game files or registered art, when reasoning about project revisions and versions, or when client-visible resources appear out of sync.
|
||||
---
|
||||
|
||||
# AGC Client Projection
|
||||
|
||||
Let the client derive projections from real disk changes and trusted tool results.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Write executable source to the current `game/` files and media to the relative paths returned by approved tools.
|
||||
2. Preserve existing relative paths when a small edit is sufficient so client resource identities remain stable.
|
||||
3. Do not edit `.agent/manifest.json`, revision counters, version records, resource IDs, canvas identities, source provenance, generation ledgers, or browser receipts by hand.
|
||||
4. Do not create a version when no game file changed. The client compares content fingerprints and advances revision only after an actual source change.
|
||||
5. Do not claim a resource or version is visible before the client projects it. If projection is missing, report the changed relative files and let the client re-read durable state.
|
||||
6. Never move HTML, CSS, or JavaScript into documentation folders. They belong to the game-code projection; prose, design notes, and instructions remain documents.
|
||||
|
||||
Call `agc_read_skill_resource` with `skillName="agc-client-projection"` and `relativePath="references/projection-contract.md"` when a request touches asset identity, revision behavior, or version history.
|
||||
|
||||
## Boundaries
|
||||
|
||||
- Platform provenance comes only from the approved art tool.
|
||||
- Browser evidence proves runtime behavior, not resource ownership.
|
||||
- Source changes, resource registration, and version projection are distinct facts; report each accurately.
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
interface:
|
||||
display_name: "客户端资源投影"
|
||||
short_description: "遵守游戏代码、美术资源、项目 revision 与正式版本的客户端投影契约"
|
||||
default_prompt: "Use $agc-client-projection to keep AGC resource and version projection consistent after file changes."
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
# Projection Contract
|
||||
|
||||
The client projects three distinct facts:
|
||||
|
||||
1. Game-code resources come from actual source files such as `game/index.html`, `game/style.css`, and `game/game.js`.
|
||||
2. Art resources come from approved tool registration with durable platform provenance.
|
||||
3. A project version is created only after a real game-source fingerprint change and a monotonic project revision update.
|
||||
|
||||
Do not collapse these facts. A playable file can exist before projection refresh, a registered image can exist without being used by the game, and browser success does not create platform provenance.
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
---
|
||||
name: agc-project-structure
|
||||
description: Work safely inside the current Taonier AGC game project. Use when Codex needs to inspect, create, or modify game code, local art references, project documentation, or other project-bound files without creating a parallel workspace or rewriting client-owned state.
|
||||
---
|
||||
|
||||
# AGC Project Structure
|
||||
|
||||
Treat the current working directory as the only project root.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Inspect the existing files needed for the request before editing.
|
||||
2. Put the playable entry in `game/index.html`, styles in `game/style.css`, and game logic in `game/game.js` unless the existing project deliberately uses another in-project structure.
|
||||
3. Keep reusable media under `assets/` and reference it with paths that resolve from the game entry.
|
||||
4. Treat `.agent/` as client-owned durable state. Read it only when project identity or registered asset evidence is needed. Do not hand-edit manifests, revisions, versions, ledgers, receipts, or provenance records.
|
||||
5. Reuse existing files and asset identities. Do not create a second project root, hidden harness, Supervisor workspace, or parallel implementation.
|
||||
6. Make the smallest coherent change that satisfies the user request, then inspect the actual changed files.
|
||||
|
||||
Call `agc_read_skill_resource` with `skillName="agc-project-structure"` and `relativePath="references/structure-contract.md"` when deciding where a new file belongs or whether a state file may be edited.
|
||||
|
||||
## Boundaries
|
||||
|
||||
- Stay inside the current project root.
|
||||
- Do not read credentials, `.env`, authentication files, browser profiles, or unrelated host paths.
|
||||
- Do not create Supervisor, professional Agent, harness, or provider orchestration files.
|
||||
- Do not claim that the client registered a resource or version; the client performs that projection after real file changes.
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
interface:
|
||||
display_name: "陶泥儿项目结构"
|
||||
short_description: "约束当前项目根、游戏代码、美术素材与状态文件的职责边界"
|
||||
default_prompt: "Use $agc-project-structure to inspect and work within the current AGC game project structure."
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
# Structure Contract
|
||||
|
||||
| Path | Owner | Allowed Codex action |
|
||||
| --- | --- | --- |
|
||||
| `game/index.html` | Game source | Read and edit |
|
||||
| `game/style.css` | Game source | Read and edit |
|
||||
| `game/game.js` | Game source | Read and edit |
|
||||
| `assets/` | Project media | Read; write only through approved project or art workflows |
|
||||
| `.agent/manifest.json` | AGC client | Read only |
|
||||
| `.agent/generation-ledgers/` | AGC client | Do not edit |
|
||||
| `.agent/runtime/` | AGC client evidence | Read only unless an approved tool writes it |
|
||||
|
||||
Keep every new path relative to the current project root. Reject a path containing `..`, a drive prefix, a UNC prefix, or a leading slash when it would escape the project.
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
---
|
||||
name: agc-web-game-development
|
||||
description: Build or modify a playable web game in the current AGC project. Use for gameplay creation, bug fixes, UI or layout changes, responsive behavior, asset integration, controls, scoring, reset flows, and other HTML, CSS, JavaScript, DOM, Canvas, or WebGL work.
|
||||
---
|
||||
|
||||
# AGC Web Game Development
|
||||
|
||||
Implement the user's actual game request in the current project. Choose DOM, Canvas, WebGL, or a combination based on the game rather than a fixed code template.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Read the existing `game/index.html`, `game/style.css`, and `game/game.js` before modifying an existing game.
|
||||
2. Keep the entry self-contained and runnable from the AGC loopback preview. Avoid CDN-only dependencies and network-required runtime assets.
|
||||
3. Build a complete playable loop: visible objective, responsive input, meaningful state changes, success or failure feedback, and a reliable restart path where the game needs one.
|
||||
4. Fit the active game scene to desktop and mobile viewports without accidental page scrollbars. Reserve deliberate safe space for HUD elements instead of covering interactive content.
|
||||
5. Reuse registered Taonier art when available. Load media defensively and keep gameplay usable when an optional derivative is absent; never relabel a local placeholder as platform art.
|
||||
6. Avoid undefined animation callbacks, duplicate loops, stale event listeners, and state that survives restart unintentionally.
|
||||
7. After a meaningful game change, use the browser playtest Skill and fix issues shown by real evidence before reporting completion.
|
||||
|
||||
Call `agc_read_skill_resource` with `skillName="agc-web-game-development"` and `relativePath="references/game-quality-checklist.md"` when implementing a new game loop or a broad gameplay revision.
|
||||
|
||||
## Reporting
|
||||
|
||||
Report the files changed, observable gameplay behavior, real validation performed, and any remaining limitation. Do not report a test or browser pass that did not run.
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
interface:
|
||||
display_name: "Web 游戏实现"
|
||||
short_description: "在当前项目内设计、实现并验证可玩的 HTML、CSS 与 JavaScript 游戏"
|
||||
default_prompt: "Use $agc-web-game-development to build or modify the current playable web game."
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
# Game Quality Checklist
|
||||
|
||||
- The entry loads without uncaught exceptions or failed required requests.
|
||||
- The user can understand the objective from the visible game, not from developer prose.
|
||||
- Pointer and touch input both reach the intended controls.
|
||||
- A valid action changes game state and an invalid action has understandable feedback.
|
||||
- Score, steps, health, timer, or other core state updates consistently.
|
||||
- Restart restores all state and does not duplicate timers, animation loops, or event listeners.
|
||||
- Desktop and mobile layouts keep the core scene visible without accidental document scrolling.
|
||||
- HUD and overlays reserve space and do not cover essential interactive content.
|
||||
- Requested Taonier art is visibly integrated into the core experience when available.
|
||||
@@ -0,0 +1,93 @@
|
||||
{
|
||||
"schemaVersion": "agc-skill-pack.v1",
|
||||
"version": "2026-08-21.1",
|
||||
"skills": [
|
||||
{
|
||||
"name": "agc-project-structure",
|
||||
"purpose": "约束当前项目根、游戏代码、美术素材与客户端状态的职责边界",
|
||||
"triggers": [
|
||||
"创建或修改游戏文件",
|
||||
"判断文件应放置的位置",
|
||||
"读取项目状态证据"
|
||||
],
|
||||
"requiredTools": ["agc_tools.agc_read_skill_resource"],
|
||||
"files": [
|
||||
"SKILL.md",
|
||||
"agents/openai.yaml",
|
||||
"references/structure-contract.md"
|
||||
],
|
||||
"sha256": "348e5e9fc7b2c628223caeb7fe9c0f15477cf97967b90777d3e0462589e13688"
|
||||
},
|
||||
{
|
||||
"name": "taonier-art-assets",
|
||||
"purpose": "通过受控平台工具生成、恢复、登记并使用真实陶泥儿游戏美术",
|
||||
"triggers": [
|
||||
"用户要求新美术或重做美术",
|
||||
"新游戏需要平台素材",
|
||||
"已有陶泥儿素材需要接入玩法"
|
||||
],
|
||||
"requiredTools": [
|
||||
"agc_tools.agc_read_skill_resource",
|
||||
"agc_tools.taonier_prepare_game_art"
|
||||
],
|
||||
"files": [
|
||||
"SKILL.md",
|
||||
"agents/openai.yaml",
|
||||
"references/platform-art-contract.md"
|
||||
],
|
||||
"sha256": "325bbca875aac3d3504ea61519944f3e4f695d3a389e29de5011b5095c74eaa9"
|
||||
},
|
||||
{
|
||||
"name": "agc-web-game-development",
|
||||
"purpose": "在当前项目实现或修改可玩的 HTML、CSS 与 JavaScript 游戏",
|
||||
"triggers": [
|
||||
"创建玩法",
|
||||
"修复游戏逻辑",
|
||||
"调整布局与交互",
|
||||
"接入已有素材"
|
||||
],
|
||||
"requiredTools": ["agc_tools.agc_read_skill_resource"],
|
||||
"files": [
|
||||
"SKILL.md",
|
||||
"agents/openai.yaml",
|
||||
"references/game-quality-checklist.md"
|
||||
],
|
||||
"sha256": "4ecff75e30701d78d65522dd3218d2465b3114a3937c82d538bda1103efd58e4"
|
||||
},
|
||||
{
|
||||
"name": "agc-browser-playtest",
|
||||
"purpose": "调用客户端真实 desktop/mobile 浏览器试玩并依据证据修复",
|
||||
"triggers": [
|
||||
"游戏代码发生实质修改",
|
||||
"诊断运行或布局问题",
|
||||
"声明游戏可玩前验收"
|
||||
],
|
||||
"requiredTools": [
|
||||
"agc_tools.agc_read_skill_resource",
|
||||
"agc_tools.agc_browser_playtest"
|
||||
],
|
||||
"files": [
|
||||
"SKILL.md",
|
||||
"agents/openai.yaml",
|
||||
"references/browser-evidence-contract.md"
|
||||
],
|
||||
"sha256": "bc818bcd9a97b7e408d4c81de57a3e52e3e61d858a8d5fb84589e6e47a51cc65"
|
||||
},
|
||||
{
|
||||
"name": "agc-client-projection",
|
||||
"purpose": "保持游戏代码、美术资源、revision 与正式版本的客户端投影一致",
|
||||
"triggers": [
|
||||
"新增或替换游戏文件",
|
||||
"素材或版本未显示",
|
||||
"推理 revision 与版本关系"
|
||||
],
|
||||
"requiredTools": ["agc_tools.agc_read_skill_resource"],
|
||||
"files": [
|
||||
"SKILL.md",
|
||||
"agents/openai.yaml",
|
||||
"references/projection-contract.md"
|
||||
],
|
||||
"sha256": "e9da95c2f371620e045a3ab9f4721078c805e108263f479b4e01b1af96d462d3"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
---
|
||||
name: taonier-art-assets
|
||||
description: Prepare, recover, inspect, and integrate real Taonier platform game art through the approved AGC tool. Use when the user requests new or changed visual assets, when a new game needs platform art, or when existing registered Taonier art must be connected to the playable game.
|
||||
---
|
||||
|
||||
# Taonier Art Assets
|
||||
|
||||
Use real platform assets only through `taonier_prepare_game_art` from the `agc_tools` MCP server.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Inspect existing `assets/` and registered project evidence before requesting new art. Reuse suitable assets when the user did not ask to regenerate them.
|
||||
2. Call `taonier_prepare_game_art` only when the current intent requires new or recoverable platform art. Pass a concise game-specific visual brief; do not call it for greetings, date questions, text-only code fixes, or layout changes that can reuse current art.
|
||||
3. Treat the tool result as authoritative. Use only returned relative paths and warnings. Never invent a resource, slice, platform identity, or successful generation.
|
||||
4. If a complete trusted spritesheet is returned without slices, keep using the complete sheet. `grid-2x2`, four fixed slices, fixed filenames, and a fixed number of `drawImage` calls are recommendations, not universal completion rules.
|
||||
5. Integrate at least one suitable Taonier asset into the game's actual visible experience when platform art was requested. A hidden or side-panel preview does not count as gameplay use.
|
||||
6. Preserve warning details in the final report. If the tool reports missing credentials, uncertain operation state, invalid provenance, download failure, or decode failure, stop and report the actionable reason; do not substitute generated CSS shapes and call the platform step complete.
|
||||
|
||||
Call `agc_read_skill_resource` with `skillName="taonier-art-assets"` and `relativePath="references/platform-art-contract.md"` before interpreting async recovery, source-preserved warnings, or slice warnings.
|
||||
|
||||
## Boundaries
|
||||
|
||||
- Do not call remote generation endpoints directly.
|
||||
- Do not create or rotate API keys.
|
||||
- Do not place credentials, signed URLs, operation internals, or provider diagnostics in files or replies.
|
||||
- Do not edit `.agent` provenance, ledgers, manifests, or version records.
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
interface:
|
||||
display_name: "陶泥儿美术素材"
|
||||
short_description: "通过受控平台工具生成、恢复、登记并使用真实陶泥儿游戏美术素材"
|
||||
default_prompt: "Use $taonier-art-assets to prepare and integrate real Taonier game art safely."
|
||||
|
||||
dependencies:
|
||||
tools:
|
||||
- type: "mcp"
|
||||
value: "agc_tools"
|
||||
description: "陶泥儿客户端提供的受控平台美术工具"
|
||||
transport: "stdio"
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
# Platform Art Contract
|
||||
|
||||
`taonier_prepare_game_art` is the only paid art entry exposed to the AGC Codex thread. The client owns authentication, stable idempotency keys, durable `operationId` recovery, download, PNG decoding, source identity, and asset registration.
|
||||
|
||||
- A submission acknowledgement is not a completed image.
|
||||
- On timeout or uncertain delivery, reuse the recorded operation; never create a replacement request.
|
||||
- `postprocess-failed-source-preserved` means the complete provider source remains usable, but the requested transparent derivative is absent.
|
||||
- `sliceWarning` means the complete transparent sheet remains usable, but individual slices are absent.
|
||||
- General and slice warnings can coexist and must both be reported.
|
||||
- A trusted complete image may be used without fixed slices. Never fabricate missing derivatives.
|
||||
- A tool error about credentials, provenance, decoding, or operation identity is terminal for that tool call and must be surfaced accurately.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user