同步 AGC 0.1.6 主线
Project CI / Repository checks (pull_request) Successful in 3m52s
Project CI / Frontend tests (pull_request) Successful in 4m57s
Project CI / Backend tests (pull_request) Successful in 6m32s
Project CI / Native shell tests (pull_request) Successful in 15m32s

合并最新 master 的标准版版本升级

保留 Game Chat 完全删除并更新版本一致性门禁

纳入资源编辑与直接运行时修复
This commit is contained in:
2026-08-25 15:28:36 +08:00
11 changed files with 75 additions and 22 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@genarrative/ai-game-creator-shell",
"private": true,
"version": "0.1.5",
"version": "0.1.6",
"type": "module",
"scripts": {
"dev": "node scripts/start-tauri-dev.mjs",
@@ -1544,11 +1544,11 @@ if (
}
if (
tauriConfig.version !== '0.1.5' ||
packageConfig.version !== '0.1.5' ||
cargoPackageVersion !== '0.1.5'
tauriConfig.version !== '0.1.6' ||
packageConfig.version !== '0.1.6' ||
cargoPackageVersion !== '0.1.6'
) {
throw new Error('AI game creator standard release must remain version 0.1.5');
throw new Error('AI game creator standard release must remain version 0.1.6');
}
const devServerSource = fs.readFileSync(
+1 -1
View File
@@ -1695,7 +1695,7 @@ dependencies = [
[[package]]
name = "genarrative-ai-game-creator-shell"
version = "0.1.5"
version = "0.1.6"
dependencies = [
"agent-runtime-core",
"axum",
@@ -1,6 +1,6 @@
[package]
name = "genarrative-ai-game-creator-shell"
version = "0.1.5"
version = "0.1.6"
edition = "2021"
publish = false
@@ -13,7 +13,7 @@ const MAX_DIRECT_HOME_ATTACHMENT_MEDIA_TYPE_CHARS: usize = 96;
const MIN_DIRECT_CLIENT_TURN_ID_CHARS: usize = 6;
const MAX_DIRECT_CLIENT_TURN_ID_CHARS: usize = 160;
const DIRECT_TAONIER_IDENTITY_GUIDANCE: &str = "对外身份合同:你是“陶泥儿”,是 Genarrative 的游戏创作助手。用户询问你是谁、你的名称或能力时,以陶泥儿的身份回答;不要把 Codex、ChatGPT、OpenAI、模型、通用 AI 助手或内部执行智能体当作自己的名称或对外身份。Codex app-server 仅是客户端内部执行技术;只有用户明确询问底层实现时才可如实说明,同时仍以陶泥儿自称。";
const DIRECT_AGC_ENGINEERING_GUIDANCE: &str = "AGC 工程合同:当前 Codex cwd 是项目真实 `game/` 源码目录,只允许把项目源码写入该目录;`../assets/` 只能按审核 Skill 或 `agc_tools` 返回的相对路径使用,不要用原生文件/命令工具遍历父目录;`.agent/` 和项目根由客户端维护,不能请求扩权或直接改写。DirectProject 提供 Codex 原生文件、搜索、命令、图片查看、Skill,以及经审核的 `agc_tools` MCP;浏览器试玩、平台美术、资源登记和搜索等带 AGC 账本的动作使用 `agc_tools`。按用户意图自行选择并执行,不要等待 Supervisor、harness 或宿主规划器。不要读取或输出凭据、Token、Cookie、auth.json、.env 或宿主私密路径。项目锁、付费提交、幂等账本、下载校验和客户端投影仍由客户端确定性掌管。游戏文件真实变化后由客户端登记资源和版本,Codex 不直接保存或伪造项目版本。";
const DIRECT_AGC_ENGINEERING_GUIDANCE: &str = "AGC 工程合同:当前 Codex cwd 是项目真实 `game/` 源码目录,只允许把项目源码写入该目录;原生文件工具、原生 patch 和命令参数中的文件路径必须相对于当前 cwd:合法写法是 `index.html`、`style.css`、`game.js`,禁止写 `game/index.html`、`../game/index.html`、项目根绝对路径或任何其它父目录路径;`game/...` 只用于 AGC 回执、manifest 和客户端投影,不用于 cwd 内的原生 patch。`../assets/` 只能按审核 Skill 或 `agc_tools` 返回的相对路径使用,不要用原生文件/命令工具遍历父目录;`.agent/` 和项目根由客户端维护,不能请求扩权或直接改写。DirectProject 提供 Codex 原生文件、搜索、命令、图片查看、Skill,以及经审核的 `agc_tools` MCP;浏览器试玩、平台美术、资源登记和搜索等带 AGC 账本的动作使用 `agc_tools`。按用户意图自行选择并执行,不要等待 Supervisor、harness 或宿主规划器。不要读取或输出凭据、Token、Cookie、auth.json、.env 或宿主私密路径。项目锁、付费提交、幂等账本、下载校验和客户端投影仍由客户端确定性掌管。游戏文件真实变化后由客户端登记资源和版本,Codex 不直接保存或伪造项目版本。";
const DIRECT_CODEX_ART_SPEC_ASSET_PATH: &str = "assets/art-spec.png";
const DIRECT_CODEX_BACKGROUND_ASSET_PATH: &str = "assets/direct-game-background.png";
const DIRECT_CODEX_SPRITESHEET_ASSET_PATH: &str = "assets/art-spritesheet.png";
@@ -4406,6 +4406,8 @@ mod tests {
assert!(!prompt.contains("你是 Codex"));
assert!(prompt.contains("不要等待 Supervisor"));
assert!(prompt.contains("提示词与技能"));
assert!(prompt.contains("合法写法是 `index.html`、`style.css`、`game.js`"));
assert!(prompt.contains("禁止写 `game/index.html`、`../game/index.html`"));
}
#[test]
@@ -4732,6 +4732,21 @@ fn resource_edit_pending_is_visible_to_current_principal(
}
}
/// A task-scoped Developer Key is deliberately independent from the GUI's platform session.
/// When credentials are already resolved for the current operation, an absent session means
/// Developer mode and must not be filled from the process-global account snapshot.
fn select_resource_edit_frozen_platform_session(
remote_credentials: Option<&(String, String, Option<PlatformSessionSnapshot>)>,
is_remote_media: bool,
current_session: Option<PlatformSessionSnapshot>,
) -> Option<PlatformSessionSnapshot> {
match remote_credentials {
Some((_, _, frozen_session)) => frozen_session.clone(),
None if is_remote_media => current_session,
None => None,
}
}
pub(crate) async fn request_resource_edit_service_identity_confirmation_at(
input: RequestResourceEditServiceIdentityConfirmationInput,
) -> Result<ResourceEditServiceIdentityConfirmation, String> {
@@ -5201,16 +5216,11 @@ pub(crate) async fn derive_local_project_resource_at(
} else {
None
};
let frozen_platform_session = remote_credentials
.as_ref()
.and_then(|(_, _, session)| session.clone())
.or_else(|| {
input
.edit_kind
.is_remote_media()
.then(current_platform_session)
.flatten()
});
let frozen_platform_session = select_resource_edit_frozen_platform_session(
remote_credentials.as_ref(),
input.edit_kind.is_remote_media(),
current_platform_session(),
);
if input.edit_kind.is_remote_media()
&& ledger.platform_owner_user_id.is_some()
&& frozen_platform_session.is_none()
@@ -5337,6 +5347,41 @@ mod tests {
const PROJECT_ID: &str = "resource-editor-test-project";
#[test]
fn developer_credentials_do_not_inherit_gui_platform_session() {
let gui_session = PlatformSessionSnapshot {
user_id: "gui-owner".to_string(),
access_token: "gui-token".to_string(),
api_base_url: "https://dev.genarrative.world".to_string(),
generation: 7,
};
let developer_credentials = (
"https://dev.genarrative.world".to_string(),
"tnr_sk_direct_fixture".to_string(),
None,
);
assert_eq!(
select_resource_edit_frozen_platform_session(
Some(&developer_credentials),
true,
Some(gui_session.clone()),
),
None,
"Developer Key mode must not be paired with the GUI token snapshot"
);
let platform_credentials = (
gui_session.api_base_url.clone(),
gui_session.access_token.clone(),
Some(gui_session.clone()),
);
assert_eq!(
select_resource_edit_frozen_platform_session(Some(&platform_credentials), true, None,),
Some(gui_session),
"platform mode must retain the session captured with its credentials"
);
}
async fn with_test_external_editor_credentials<T>(
api_base_url: &str,
api_key: &str,
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "Genarrative AI Game Creator",
"version": "0.1.5",
"version": "0.1.6",
"identifier": "world.genarrative.ai-game-creator",
"build": {
"beforeDevCommand": "npm --prefix ../.. run agc:serve",
@@ -14734,3 +14734,9 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
- 客户端:画布点击 `ui-prototype` 先幂等桥接到 `UI` JSON,并立即刷新 manifest;关联查找按 canonical resource identity 且优先已完成 workflow 资源。全部页面完成后,工作台自动打开首个页面的 UI 编辑器 `visual-binding` 最终阶段。
- 完成门:`finalize` 必须为每个页面提供 `game/` 下真实 UTF-8 应用文件并安装当前 UI State revision 标记;缺少结构、组件、页面或标记时拒绝完成。详细输入、阶段与恢复契约见 [`docs/【技术方案】UI工作流资源桥接与Runtime执行-2026-08-24.md`](../../【技术方案】UI工作流资源桥接与Runtime执行-2026-08-24.md)。
- 验证:前端 bridge 6/6、资源实时集成 19/19、AppSurface 410/410、AGC typecheck、Rust workflow 定向测试覆盖 provider 前的 reference 阶段与真实调用失败关闭、Rust bridge 1/1、编码、格式和 diff 门禁通过;认证登录与真实 Provider 生成的桌面端 E2E 尚未具备可用会话,保持未验证。
## 2026-08-25 AGC DirectProject 直连路径与 Developer Key 身份隔离
- DirectProject 的 Codex cwd 固定为真实 `game/` 目录时,原生文件工具和 patch 必须使用 cwd 相对路径(`index.html``style.css``game.js`);`game/...` 仅用于 AGC manifest、回执和客户端投影,不能作为 cwd 内原生 patch 路径,以避免 `writing outside of the project`
- 直连 Runtime 已取得 Developer Key 时,资源编辑的 `remote_credentials` 是该操作的完整身份边界;其中冻结平台快照为空表示 Developer 模式,禁止再从进程全局 GUI 登录态补回账号快照。平台账号模式仍只使用同一组凭据捕获的快照。
- 回归覆盖 Direct 系统提示路径合同和 Developer Key / GUI 快照隔离;未触碰用户项目 `.agent` 锁、账本或凭据。
+1 -1
View File
@@ -93,7 +93,7 @@
},
"apps/ai-game-creator-shell": {
"name": "@genarrative/ai-game-creator-shell",
"version": "0.1.5",
"version": "0.1.6",
"dependencies": {
"@cubone/react-file-manager": "^1.35.0",
"@genarrative/image-canvas-core": "0.1.0",
+1 -1
View File
@@ -174,7 +174,7 @@ export function collectNpmWorkspaceErrors(rootDir) {
);
}
const expectedWorkspaceVersion =
workspacePath === 'apps/ai-game-creator-shell' ? '0.1.5' : '0.1.0';
workspacePath === 'apps/ai-game-creator-shell' ? '0.1.6' : '0.1.0';
if (manifest.version !== expectedWorkspaceVersion) {
errors.push(
`${manifestPath}: workspace version must be ${expectedWorkspaceVersion}`,
+1 -1
View File
@@ -79,7 +79,7 @@ function createValidFixture() {
name: workspaceNames[workspacePath],
private: true,
version:
workspacePath === 'apps/ai-game-creator-shell' ? '0.1.5' : '0.1.0',
workspacePath === 'apps/ai-game-creator-shell' ? '0.1.6' : '0.1.0',
dependencies: localDependencies[workspacePath],
};
writeJson(rootDir, `${workspacePath}/package.json`, manifest);