From 6fe91a169c719020f8f0fb94fe4856221dd22584 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Wed, 2 Sep 2026 19:00:31 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E7=A7=BB=E9=99=A4=20AGC=20Skill=20?= =?UTF-8?q?=E5=8F=97=E6=8E=A7=E5=BC=95=E7=94=A8=E8=AF=BB=E5=8F=96=E5=B7=A5?= =?UTF-8?q?=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 删除 agc_read_skill_resource 的实现、MCP 暴露、审计分支与专用测试 将内置 Skill references 改为 Codex 原生相对路径读取 同步 Skill manifest 指纹、Runtime 提示词与 AGC 项目文档 保留既有 references 安装与隔离 HOME 校验 --- .../agc-skills/agc-browser-playtest/SKILL.md | 2 +- .../agc-skills/agc-client-projection/SKILL.md | 2 +- .../agc-skills/agc-project-structure/SKILL.md | 2 +- .../agc-web-game-development/SKILL.md | 2 +- .../resources/agc-skills/manifest.json | 20 +++---- .../agc-skills/taonier-art-assets/SKILL.md | 2 +- .../src-tauri/src/agent/direct_codex_audit.rs | 4 -- .../src-tauri/src/agent/direct_runtime.rs | 2 +- .../src-tauri/src/agent/direct_tools_mcp.rs | 58 +------------------ .../src-tauri/src/agent/skill_pack.rs | 50 ++-------------- docs/project-memory/shared-memory/pitfalls.md | 10 ++-- .../shared-memory/project-overview.md | 2 +- ...案】AI游戏创作智能体App实施计划-2026-06-24.md | 4 +- ...术方案】Direct回合行为审计账本-2026-08-31.md | 1 - 14 files changed, 26 insertions(+), 135 deletions(-) diff --git a/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/agc-browser-playtest/SKILL.md b/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/agc-browser-playtest/SKILL.md index 2624814af..577d9e606 100644 --- a/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/agc-browser-playtest/SKILL.md +++ b/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/agc-browser-playtest/SKILL.md @@ -16,7 +16,7 @@ Use `agc_browser_playtest` from the `agc_tools` MCP server. Do not replace it wi 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; the tool result is evidence for Codex to interpret. -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. +Before interpreting screenshots or Canvas/WebGL asset observations, read `references/browser-evidence-contract.md`. ## Reporting diff --git a/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/agc-client-projection/SKILL.md b/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/agc-client-projection/SKILL.md index bc4fa72f6..07cbe9c1b 100644 --- a/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/agc-client-projection/SKILL.md +++ b/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/agc-client-projection/SKILL.md @@ -21,7 +21,7 @@ Let the client derive projections from real disk changes and trusted tool result 10. 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. 11. 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. +When a request touches asset identity, revision behavior, or version history, read `references/projection-contract.md`. ## Boundaries diff --git a/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/agc-project-structure/SKILL.md b/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/agc-project-structure/SKILL.md index 836ac2194..e0293d163 100644 --- a/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/agc-project-structure/SKILL.md +++ b/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/agc-project-structure/SKILL.md @@ -17,7 +17,7 @@ Treat the current working directory as the only project root. 6. Reuse existing files and asset identities. Do not create a second project root, hidden harness, Supervisor workspace, or parallel implementation. 7. 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. +When deciding where a new file belongs or whether a state file may be edited, read `references/structure-contract.md`. ## Boundaries diff --git a/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/agc-web-game-development/SKILL.md b/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/agc-web-game-development/SKILL.md index c7aa068b8..24ad9799a 100644 --- a/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/agc-web-game-development/SKILL.md +++ b/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/agc-web-game-development/SKILL.md @@ -17,7 +17,7 @@ Implement the user's actual game request in the current project. Choose DOM, Can 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. +When implementing a new game loop or a broad gameplay revision, read `references/game-quality-checklist.md`. # Notes * UI Editor's JSON formated is a special kind asset; Never edit it or read it directly. User can export to `ui/generated-.js` and want u to use it; diff --git a/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/manifest.json b/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/manifest.json index 281abf9c1..1fd0458a6 100644 --- a/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/manifest.json +++ b/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/manifest.json @@ -1,6 +1,6 @@ { "schemaVersion": "agc-skill-pack.v1", - "version": "2026-08-26.9", + "version": "2026-08-26.10", "skills": [ { "name": "agc-project-structure", @@ -11,7 +11,6 @@ "读取项目状态证据" ], "requiredTools": [ - "agc_tools.agc_read_skill_resource", "agc_tools.agc_list_project_files", "agc_tools.agc_import_account_assets", "agc_tools.agc_list_registered_assets" @@ -21,7 +20,7 @@ "agents/openai.yaml", "references/structure-contract.md" ], - "sha256": "85dd861201d7b9a5d34b702b7b79ce18012e06784dddf2fb8e836e085fee4b00" + "sha256": "54cfe7da2e7e1f631788e87c5ccc481f29e5b0d70cd32f9fe8092a5aed4549ac" }, { "name": "taonier-art-assets", @@ -32,7 +31,6 @@ "已有陶泥儿素材需要接入玩法" ], "requiredTools": [ - "agc_tools.agc_read_skill_resource", "agc_tools.agc_generate_image", "agc_tools.agc_edit_image", "agc_tools.taonier_prepare_game_art" @@ -42,7 +40,7 @@ "agents/openai.yaml", "references/platform-art-contract.md" ], - "sha256": "600c758662de7c85186402fd09ba3e76407ad2f6084d4090a2a38f455da7ea09" + "sha256": "82e4b2ee8ca8147b51ca206b0565b3cc244dc5d3cddb8343875001c0beb4711f" }, { "name": "agc-web-game-development", @@ -53,15 +51,13 @@ "调整布局与交互", "接入已有素材" ], - "requiredTools": [ - "agc_tools.agc_read_skill_resource" - ], + "requiredTools": [], "files": [ "SKILL.md", "agents/openai.yaml", "references/game-quality-checklist.md" ], - "sha256": "b197a242b75dc5e39739693e793acd25ac62dd2c72bc264305797936da47f356" + "sha256": "d7748d9ebf4324add0541daf16a2bbec09c4862b85af55bfb369c7f3b99aedff" }, { "name": "agc-browser-playtest", @@ -72,7 +68,6 @@ "声明游戏可玩前验收" ], "requiredTools": [ - "agc_tools.agc_read_skill_resource", "agc_tools.agc_browser_playtest" ], "files": [ @@ -80,7 +75,7 @@ "agents/openai.yaml", "references/browser-evidence-contract.md" ], - "sha256": "a68fc43f460ec1b8f999bda089c8e67a7229ef70365cfe89b92030e7661c47d5" + "sha256": "4437cd8a927a1c79a5faf4bcd40e9946676c08a3b460ab171298cabf899f49ad" }, { "name": "agc-client-projection", @@ -93,7 +88,6 @@ "推理 revision 与版本关系" ], "requiredTools": [ - "agc_tools.agc_read_skill_resource", "agc_tools.agc_list_registered_assets", "agc_tools.agc_list_project_files", "agc_tools.agc_list_account_assets", @@ -106,7 +100,7 @@ "agents/openai.yaml", "references/projection-contract.md" ], - "sha256": "7800e8ee4b5baa6f473b904f262197f5320a46150ae5e51c56a298fc21674e30" + "sha256": "96b5bf9e2ed150bbe934a888867c1bb500b214a131f8b36c4830f51ca30267b6" } ] } diff --git a/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/taonier-art-assets/SKILL.md b/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/taonier-art-assets/SKILL.md index 919a579cc..d069fe9d8 100644 --- a/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/taonier-art-assets/SKILL.md +++ b/apps/ai-game-creator-shell/src-tauri/resources/agc-skills/taonier-art-assets/SKILL.md @@ -24,7 +24,7 @@ the complete game-art package and its canonical slices. 5. Inspect the returned background, complete sheet, and available slice previews before integrating them. Then use suitable returned runtime assets in the game's actual visible experience and confirm their visible use in desktop and mobile playtest evidence. `art-spec.png` is a reference specification, not a runtime background, character, prop, or effect. Background exclusions, seamless tiling, entity semantics, and final draw dimensions are visual/runtime acceptance checks; a prompt alone does not prove them. 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. +Before interpreting async recovery, source-preserved warnings, or slice warnings, read `references/platform-art-contract.md`. ## Boundaries diff --git a/apps/ai-game-creator-shell/src-tauri/src/agent/direct_codex_audit.rs b/apps/ai-game-creator-shell/src-tauri/src/agent/direct_codex_audit.rs index bc34a6b4c..43ab7c7ba 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/agent/direct_codex_audit.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/agent/direct_codex_audit.rs @@ -639,10 +639,6 @@ fn extract_mcp_arguments(root: &Path, tool: &str, arguments: &Value) -> Value { copy_truncated_string(object, "query", DIRECT_CODEX_AUDIT_QUERY_CHARS, &mut out); copy_number(object, "maxResults", &mut out); } - "agc_read_skill_resource" => { - copy_string(object, "skillName", &mut out); - copy_string(object, "relativePath", &mut out); - } _ => {} } Value::Object(out) diff --git a/apps/ai-game-creator-shell/src-tauri/src/agent/direct_runtime.rs b/apps/ai-game-creator-shell/src-tauri/src/agent/direct_runtime.rs index 6189558e7..fcd96667b 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/agent/direct_runtime.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/agent/direct_runtime.rs @@ -10,7 +10,7 @@ const MAX_DIRECT_SYSTEM_PROMPT_CHARS: usize = 16 * 1024; 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 是用户选择的项目目录(工作区根),源码、素材、音效和其它资源按项目现有结构放置;先按需读取当前 cwd 下适用的 `AGENTS.md`、README 或项目说明,把它们当作项目规范参考。原生文件工具、patch 和命令参数使用 cwd 相对路径,例如 `index.html`、`style.css`、`game.js`、`assets/hero.png`;如果 Codex 原生文件修改不可用,可以按需用客户端 `agc_write_file` 把文本写入项目相对路径。调用 `agc_write_file` 时,content 必须是目标文件的完整原始 UTF-8 正文;不得把 command.exec 的 Exit code、Wall time、Output 包装、终端日志或解释文字一起复制进 content,命令结果只能用于判断,不能当作文件正文。`../`、绝对路径、`.agent/`、`.git/`、密钥文件和 Runtime 控制面属于客户端边界,不能请求扩权或直接改写。DirectProject 提供 Codex 原生文件、搜索、命令、图片查看、Skill、经客户端注入的 `agc_tools` MCP,以及客户端扩展列表中用户已启用的第三方 MCP。用户明确指定第三方 MCP Server 或工具时,先在当前可用工具中查找并直接调用;找不到时如实说明,不得伪造。你可以按需选择这些能力:`agc_write_file` 写入代码、配置、资源依赖清单或说明文件;`agc_generate_image` 生成普通图片、角色图、视觉规范图(icon-spec)、UI 设计图或发布宣传图;`agc_edit_image` 修改已登记图片;`taonier_prepare_game_art` 准备完整游戏美术包及可用的 canonical 切片;`agc_list_registered_assets`、`agc_list_project_files`、`agc_list_account_assets`、`agc_import_account_assets` 用于发现和接入资源依赖;`agc_create_or_derive_resource` 用于视频、角色动画、音效或背景音乐;`agc_browser_playtest` 用于需要时的本地试玩观察;`agc_read_skill_resource` 用于按需读取审核 Skill。切图、资源依赖、规范图和试玩都只是可选工具提示,不要求调用、固定顺序或特定产物,AGC 不会据此替你拆任务、编排 DAG、做强验收或阻止继续执行;不要等待 Supervisor、harness 或宿主规划器。不要读取或输出凭据、Token、Cookie、auth.json、.env 或宿主私密路径;项目锁、付费提交、幂等键、下载校验和客户端投影由客户端处理。游戏文件真实变化后客户端可登记资源和版本,Codex 不直接保存或伪造项目版本。"; +const DIRECT_AGC_ENGINEERING_GUIDANCE: &str = "AGC 工程合同(仅说明项目边界,不是流程门槛):当前 Codex cwd 是用户选择的项目目录(工作区根),源码、素材、音效和其它资源按项目现有结构放置;先按需读取当前 cwd 下适用的 `AGENTS.md`、README 或项目说明,把它们当作项目规范参考。原生文件工具、patch 和命令参数使用 cwd 相对路径,例如 `index.html`、`style.css`、`game.js`、`assets/hero.png`;如果 Codex 原生文件修改不可用,可以按需用客户端 `agc_write_file` 把文本写入项目相对路径。调用 `agc_write_file` 时,content 必须是目标文件的完整原始 UTF-8 正文;不得把 command.exec 的 Exit code、Wall time、Output 包装、终端日志或解释文字一起复制进 content,命令结果只能用于判断,不能当作文件正文。`../`、绝对路径、`.agent/`、`.git/`、密钥文件和 Runtime 控制面属于客户端边界,不能请求扩权或直接改写。DirectProject 提供 Codex 原生文件、搜索、命令、图片查看、Skill、经客户端注入的 `agc_tools` MCP,以及客户端扩展列表中用户已启用的第三方 MCP。用户明确指定第三方 MCP Server 或工具时,先在当前可用工具中查找并直接调用;找不到时如实说明,不得伪造。你可以按需选择这些能力:`agc_write_file` 写入代码、配置、资源依赖清单或说明文件;`agc_generate_image` 生成普通图片、角色图、视觉规范图(icon-spec)、UI 设计图或发布宣传图;`agc_edit_image` 修改已登记图片;`taonier_prepare_game_art` 准备完整游戏美术包及可用的 canonical 切片;`agc_list_registered_assets`、`agc_list_project_files`、`agc_list_account_assets`、`agc_import_account_assets` 用于发现和接入资源依赖;`agc_create_or_derive_resource` 用于视频、角色动画、音效或背景音乐;`agc_browser_playtest` 用于需要时的本地试玩观察;Skill references 按需使用相对路径直接读取。切图、资源依赖、规范图和试玩都只是可选工具提示,不要求调用、固定顺序或特定产物,AGC 不会据此替你拆任务、编排 DAG、做强验收或阻止继续执行;不要等待 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"; diff --git a/apps/ai-game-creator-shell/src-tauri/src/agent/direct_tools_mcp.rs b/apps/ai-game-creator-shell/src-tauri/src/agent/direct_tools_mcp.rs index d739961aa..226432b91 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/agent/direct_tools_mcp.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/agent/direct_tools_mcp.rs @@ -43,26 +43,6 @@ fn direct_tools_mcp_specs() -> Value { fn direct_tools_mcp_specs_for(controlled_web_search: bool) -> Value { let tools = vec![ - json!({ - "name": "agc_read_skill_resource", - "description": "按需读取审核 AGC Skill 直接引用的一层 Markdown 文件。只能访问内置清单声明的 Skill 与 references 路径,不能读取项目、宿主或凭据文件。", - "inputSchema": { - "type": "object", - "properties": { - "skillName": { - "type": "string", - "enum": AGC_SKILL_PACK_EXPECTED_NAMES - }, - "relativePath": { - "type": "string", - "minLength": 1, - "maxLength": 256 - } - }, - "required": ["skillName", "relativePath"], - "additionalProperties": false - } - }), json!({ "name": "agc_write_file", "description": "把文本写入当前 AGC 项目的相对路径。Codex 可以按需使用它直接推进代码、配置、资源依赖或说明文件;客户端只负责项目路径和基本控制面边界,不要求固定文件、任务顺序、验证或完成回执。", @@ -392,18 +372,6 @@ pub(in crate::agent) fn controlled_web_search_enabled() -> bool { .unwrap_or(false) } -fn call_agc_read_skill_resource(arguments: &Value) -> Value { - let result = (|| { - let skill_name = bounded_tool_string(arguments, "skillName", 64)?; - let relative_path = bounded_tool_string(arguments, "relativePath", 256)?; - read_agc_skill_resource(&skill_name, &relative_path) - })(); - match result { - Ok(text) => mcp_tool_result(text, Vec::new(), false), - Err(error) => mcp_tool_result(error, Vec::new(), true), - } -} - async fn call_agc_write_file(arguments: &Value) -> Value { if let Err(error) = validate_write_file_arguments(arguments) { return mcp_tool_result(error, Vec::new(), true); @@ -1059,7 +1027,6 @@ async fn handle_direct_tools_mcp_request(_root: &Path, request: Value) -> Option .cloned() .unwrap_or_else(|| json!({})); let result = match tool { - "agc_read_skill_resource" => call_agc_read_skill_resource(&arguments), "agc_write_file" => call_agc_write_file(&arguments).await, "taonier_prepare_game_art" => call_taonier_prepare_game_art(&arguments).await, "agc_generate_image" => call_agc_generate_image(&arguments).await, @@ -1236,7 +1203,6 @@ mod tests { assert_eq!( names, vec![ - "agc_read_skill_resource", "agc_write_file", "taonier_prepare_game_art", "agc_generate_image", @@ -1517,7 +1483,7 @@ mod tests { "jsonrpc": "2.0", "id": 1, "method": "tools/call", - "params": { "name": "unreviewed_tool", "arguments": {} } + "params": { "name": "agc_read_skill_resource", "arguments": {} } }), ) .await @@ -1525,26 +1491,4 @@ mod tests { assert_eq!(response["result"]["isError"], true); assert!(response.to_string().contains("未知或未审核")); } - - #[test] - fn skill_resource_tool_rejects_unreviewed_paths() { - let accepted = call_agc_read_skill_resource(&json!({ - "skillName": "agc-project-structure", - "relativePath": "references/structure-contract.md" - })); - assert_eq!(accepted["isError"], false); - assert!(accepted.to_string().contains("drive prefix")); - - let denied = call_agc_read_skill_resource(&json!({ - "skillName": "agc-project-structure", - "relativePath": "../../auth.json" - })); - assert_eq!(denied["isError"], true); - - let denied_windows_absolute = call_agc_read_skill_resource(&json!({ - "skillName": "agc-project-structure", - "relativePath": r"C:\temp\SKILL.md" - })); - assert_eq!(denied_windows_absolute["isError"], true); - } } diff --git a/apps/ai-game-creator-shell/src-tauri/src/agent/skill_pack.rs b/apps/ai-game-creator-shell/src-tauri/src/agent/skill_pack.rs index b8ec6932a..aec1efbc2 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/agent/skill_pack.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/agent/skill_pack.rs @@ -242,36 +242,6 @@ pub(crate) fn render_agc_skill_pack_index() -> Result { Ok(lines.join("\n")) } -pub(crate) fn read_agc_skill_resource( - skill_name: &str, - relative_path: &str, -) -> Result { - let manifest = validated_skill_pack_manifest()?; - if !is_safe_skill_relative_path(relative_path) - || !relative_path.starts_with("references/") - || Path::new(&relative_path) - .extension() - .and_then(|value| value.to_str()) - != Some("md") - { - return Err("AGC Skill 引用路径不在审核的一层 Markdown 边界内".to_string()); - } - let entry = manifest - .skills - .iter() - .find(|entry| entry.name == skill_name) - .ok_or_else(|| "AGC Skill 不在审核白名单内".to_string())?; - if !entry.files.iter().any(|file| file == &relative_path) { - return Err("AGC Skill 引用文件未在审核清单中声明".to_string()); - } - let bundled_path = format!("{skill_name}/{relative_path}"); - let bytes = bundled_skill_file(&bundled_path) - .ok_or_else(|| "AGC Skill 引用文件未编译进客户端".to_string())?; - let text = - std::str::from_utf8(bytes).map_err(|_| "AGC Skill 引用文件不是 UTF-8 文本".to_string())?; - Ok(text.to_string()) -} - pub(crate) fn install_agc_skill_pack(isolated_os_home: &Path) -> Result { let manifest = validated_skill_pack_manifest()?; let skills_root = isolated_os_home.join(".agents").join("skills"); @@ -351,6 +321,10 @@ mod tests { .path() .join(".agents/skills/taonier-art-assets/SKILL.md") .is_file()); + assert!(home + .path() + .join(".agents/skills/agc-project-structure/references/structure-contract.md") + .is_file()); let installed_agent_metadata = std::fs::read( home.path() .join(".agents/skills/agc-project-structure/agents/openai.yaml"), @@ -381,20 +355,4 @@ mod tests { assert!(!is_safe_skill_relative_path(r"\\server\share\SKILL.md")); assert!(!is_safe_skill_relative_path(r"references\contract.md")); } - - #[test] - fn skill_resource_reader_allows_only_manifest_references() { - let text = - read_agc_skill_resource("agc-project-structure", "references/structure-contract.md") - .expect("read reviewed reference"); - assert!(text.contains("drive prefix")); - assert!(read_agc_skill_resource("agc-project-structure", "SKILL.md").is_err()); - assert!( - read_agc_skill_resource("agc-project-structure", "references/../../private.md") - .is_err() - ); - assert!( - read_agc_skill_resource("wechatpay-basic-payment", "references/anything.md").is_err() - ); - } } diff --git a/docs/project-memory/shared-memory/pitfalls.md b/docs/project-memory/shared-memory/pitfalls.md index f8c2a40ab..7d6b77777 100644 --- a/docs/project-memory/shared-memory/pitfalls.md +++ b/docs/project-memory/shared-memory/pitfalls.md @@ -4296,13 +4296,13 @@ - 处理:通用配置只保留跨平台 bundle 项;Windows 原生侧车的完整白名单放入 Tauri 自动合并的 `tauri.windows.conf.json`。不要提交二进制占位文件,也不要让非 Windows build script 下载或伪造 Windows 资源。 - 验证:配置门禁断言通用配置没有 Windows resource、Windows 平台配置保留完整固定白名单;Linux 运行原生壳门禁必须越过 Tauri resource 校验,Windows release 仍由 build script 对 npm 原生包、SHA-256 清单和目标布局失败关闭。 -## AGC Skill 指纹与相对路径校验必须跨平台一致(2026-08-21) +## AGC Skill 指纹与安装内容必须跨平台一致(2026-08-21) -- 现象:内置 Skill 文件集合没有缺失,原生测试却统一报内容指纹不匹配;另一个测试在 Linux 上把 `C:\\temp\\SKILL.md` 判为安全相对路径,受控资源工具可能继续处理 Windows 盘符或反斜杠遍历形式。 -- 原因:审核文件定稿后未按最终字节重新生成 manifest SHA-256;同时 `std::path::Path` 只按当前宿主语义解析路径,Linux 不会把 Windows 盘符和反斜杠视为绝对路径或分隔符。 -- 处理:Skill 文件变化与 manifest 指纹更新必须同次提交,并提升审核包版本;资源引用只接受使用 `/` 的普通相对段,显式拒绝反斜杠、冒号盘符、UNC、绝对路径和父目录段,再查询审核清单。不要先把反斜杠替换成 `/` 后再做安全检查。 +- 现象:内置 Skill 文件集合没有缺失,原生测试却统一报内容指纹不匹配;安装后的 Skill 文件与 manifest 摘要不一致会导致构建校验失败。 +- 原因:审核文件定稿后未按最终字节重新生成 manifest SHA-256;安装和原生 Skill loader 必须看到与清单一致的 UTF-8 文件集合。 +- 处理:Skill 文件变化与 manifest 指纹更新必须同次提交,并提升审核包版本;references 由 Codex 原生按 Skill 声明的相对路径读取,不再经过 AGC 自定义资源读取器。 - 回归补充:即使 Skill 文件本轮没有变化,也不能从旧提交或旧构建结果复制清单指纹;必须对当前工作树按 UTF-8 读取、将 CRLF 规范为 LF 后现场重算,并在提交前运行原生 Skill Pack 校验。Git 的 `eol=lf` 不能阻止编辑器在干净工作树里留下少量混合 CRLF,而 Cargo `include_bytes!` 会读取这些原始字节;因此运行时计算与安装也必须使用同一规范化函数。运行时只报告排序后的首个不匹配项,不能据此假定其余 Skill 已通过。 -- 验证:逐项按排序后的 `relativePath + NUL + canonical UTF-8 LF bytes + NUL` 重算并核对 manifest;Rust 单测同时覆盖 LF / CRLF 指纹等价、安装结果只含 LF、POSIX 绝对路径、`..`、`C:\\...`、`C:/...`、UNC 和反斜杠相对路径,受控 MCP 工具也必须把 Windows 绝对路径投影为 `isError=true`。 +- 验证:逐项按排序后的 `relativePath + NUL + canonical UTF-8 LF bytes + NUL` 重算并核对 manifest;Rust 单测覆盖 LF / CRLF 指纹等价和安装结果只含 LF,并确认隔离 HOME 中的根 Skill 与 references 可由 Codex 原生读取。 ## Gitea CI 预构建镜像不能只靠 tag 判断内容 diff --git a/docs/project-memory/shared-memory/project-overview.md b/docs/project-memory/shared-memory/project-overview.md index 8190254eb..765f3a318 100644 --- a/docs/project-memory/shared-memory/project-overview.md +++ b/docs/project-memory/shared-memory/project-overview.md @@ -52,7 +52,7 @@ SpacetimeDB crate、SDK、CLI / standalone 与生成 bindings 按 `2.8.3` 对齐 ## AGC DirectProject 与 UI workflow - 通用 Agent Rust 分层为 `agent-runtime-core`(catalog、执行生命周期、ToolHost/spawn/all-join/Provider 契约)、`agent-runtime-orchestration`(动态无环任务图、ready、依赖波次、返工下游闭包和受限自主扩图提案)与 `platform-agent` 游戏适配器;循环返工通过新 pass / epoch 表达,不在单张依赖图中建立回边。LLM 可经宿主结构化 function call 提出新增节点/边,编排层只生成经校验的新候选图,epoch 与持久化仍由宿主掌控。 -- DirectProject 始终连接客户端内置的 `agc_tools` STDIO MCP,并在启动时额外读取客户端扩展仓库中已启用的第三方 MCP 独立项。第三方 STDIO/HTTP 配置只写入本次隔离 `CODEX_HOME`,单项非 required,启停、重命名和内容指纹进入 app-server pool identity;完整 Plugin Runtime、hooks/apps 和单文件脚本手动指定入口仍关闭。`agc_tools` 继续负责审核引用读取、标准美术准备、已登记资源有界查询、视频 / 角色动画 / 音效 / BGM 的 create-or-derive、已登记图片去背景、desktop/mobile 浏览器试玩和受控 `agc_web_search`;付费资源调用仍由客户端绑定回合、幂等账本、请求上限和投影权威。 +- DirectProject 始终连接客户端内置的 `agc_tools` STDIO MCP,并在启动时额外读取客户端扩展仓库中已启用的第三方 MCP 独立项。第三方 STDIO/HTTP 配置只写入本次隔离 `CODEX_HOME`,单项非 required,启停、重命名和内容指纹进入 app-server pool identity;完整 Plugin Runtime、hooks/apps 和单文件脚本手动指定入口仍关闭。Skill 正文与 references 由 Codex 原生按需读取;`agc_tools` 负责标准美术准备、已登记资源有界查询、视频 / 角色动画 / 音效 / BGM 的 create-or-derive、已登记图片去背景、desktop/mobile 浏览器试玩和受控 `agc_web_search`;付费资源调用仍由客户端绑定回合、幂等账本、请求上限和投影权威。 - DirectProject 的 Codex 原生文件、搜索、命令、图片查看和 Skill 仅在真实 `game/` cwd 与 `workspaceWrite(writableRoots=[game])` 内可用;原生命令网络保持关闭。多 Agent、Apps、插件、hooks、图片生成、Goals、Workspace Dependencies、Tool Suggestion 和原生浏览器/电脑控制保持关闭。app-server 使用隔离 `CODEX_HOME`,provider 凭据只由 AGC 客户端代理持有,不能进入模型上下文或 shell 环境。 - `ui-prototype`(设计图片)与 UI 编辑器 `UI` JSON 是不同资源。白名单 `ui.workflow.run` 按页面执行 `prepare → recognize → status → finalize`,由 provider-backed 识别、合并和组件绑定持久化 State/revision,并把 `reference-ready → structure-ready → merge-ready → binding-ready → application-ready → completed` 投影到 manifest。Provider 缺失、请求失败、工具缺失、结果不匹配或仍有待审节点时保留真实阶段并返回 blocker,不得用 deterministic seed 伪造完成。 - UI workflow 的资源桥接与 Runtime 边界以 `docs/【技术方案】UI工作流资源桥接与Runtime执行-2026-08-24.md` 和 AGC 实施计划的 2026-08-24 覆盖段为准;只生成图片、登记空 JSON 或进入普通图片画布都不构成 workflow 完成。 diff --git a/docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md b/docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md index fda4e384c..894ff5fd4 100644 --- a/docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md +++ b/docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md @@ -1183,8 +1183,8 @@ game-project/ - 普通项目对话只由一个 project-bound Codex app-server thread 执行。客户端系统提示词只放最小工程合同、当前游戏源码有界快照、项目 prompts 和审核 Skill 索引;不再批量读取项目 `.codex/.agents` Skill 正文,也不恢复 Supervisor、专业 Agent 或 harness。 - 首页恢复“做游戏 / 做素材 / 做方案”三个创作类型,默认“做游戏”。该选择与设置页的 Agent Runtime 模式无关;每次首页提交仍只自动创建一个新项目并进入项目工作台。用户正文原样进入项目对话,`game|art|doc` 仅作为受限结构化首轮上下文传给同一 Codex thread,不拼接“初始意图”文案、不产生首页对话、不切换 Provider 或恢复旧 Runtime 编排。 -- `agc-skill-pack.v1` 只包含项目结构、陶泥儿美术、Web 游戏实现、真实浏览器试玩、客户端资源投影五项 Skill。清单记录用途、触发条件、所需工具、版本和内容 SHA-256;审核文本按 UTF-8 读取并将 CRLF 规范为 LF 后计算指纹和安装,避免混合换行造成 Windows / Linux 构建结果漂移,语义内容变化时必须同步重算对应清单指纹并提升版本。同步统一运行 `npm run agc:skill-pack:sync`,只读校验由 AGC `typecheck` 和 release build 自动执行,发现漂移时直接列出 Skill 与实际摘要,不让失配内容进入构建产物。客户端把审核文件安装到隔离目录后通过 app-server `skills/extraRoots/set + skills/list` 注册并复核,完整正文由 Codex 原生 Skill 机制按意图加载,一层引用只能经 `agc_read_skill_resource` 读取清单内 Markdown。引用路径按平台无关规则拒绝反斜杠、盘符、UNC、绝对路径和 `..`,不能依赖当前宿主的 `std::path` 语义判断其它平台路径。 -- DirectProject 始终连接客户端内置的 `agc_tools` STDIO MCP;2026-08-31 起还会在启动时接入客户端扩展仓库中用户已启用的独立第三方 STDIO/HTTP MCP 配置,但不读取用户全局 Codex MCP、不开启完整 Plugin Runtime。`agc_tools` 工具固定为审核引用读取、标准陶泥儿美术准备、已登记资源有界查询、视频 / 角色动画 / 音效 / BGM 的 create-or-derive 语义生成、已登记图片去背景和 desktop/mobile 浏览器试玩。内置 MCP 进程只做协议;真实浏览器与付费 External v1 调用通过随机 loopback 地址回到客户端主进程,因此不复制 GUI 登录态、开发者 Key、项目路径、revision、operation 或幂等键到模型上下文。内置与用户启用的第三方 MCP 工具都沿用 DirectProject 自动批准方式,但付费资源工具仍由客户端绑定稳定回合身份、限制单回合请求数、串行执行并优先恢复匹配账本;Codex 原生 webSearch、任意原生命令网络、多 Agent 和完整插件能力继续关闭。 +- `agc-skill-pack.v1` 只包含项目结构、陶泥儿美术、Web 游戏实现、真实浏览器试玩、客户端资源投影五项 Skill。清单记录用途、触发条件、所需工具、版本和内容 SHA-256;审核文本按 UTF-8 读取并将 CRLF 规范为 LF 后计算指纹和安装,避免混合换行造成 Windows / Linux 构建结果漂移,语义内容变化时必须同步重算对应清单指纹并提升版本。同步统一运行 `npm run agc:skill-pack:sync`,只读校验由 AGC `typecheck` 和 release build 自动执行,发现漂移时直接列出 Skill 与实际摘要,不让失配内容进入构建产物。客户端把审核文件安装到隔离目录后通过 app-server `skills/extraRoots/set + skills/list` 注册并复核,完整正文与 references 均由 Codex 原生 Skill 机制按意图和声明的相对路径按需读取。 +- DirectProject 始终连接客户端内置的 `agc_tools` STDIO MCP;2026-08-31 起还会在启动时接入客户端扩展仓库中用户已启用的独立第三方 STDIO/HTTP MCP 配置,但不读取用户全局 Codex MCP、不开启完整 Plugin Runtime。`agc_tools` 工具固定为标准陶泥儿美术准备、已登记资源有界查询、视频 / 角色动画 / 音效 / BGM 的 create-or-derive 语义生成、已登记图片去背景和 desktop/mobile 浏览器试玩。内置 MCP 进程只做协议;真实浏览器与付费 External v1 调用通过随机 loopback 地址回到客户端主进程,因此不复制 GUI 登录态、开发者 Key、项目路径、revision、operation 或幂等键到模型上下文。内置与用户启用的第三方 MCP 工具都沿用 DirectProject 自动批准方式,但付费资源工具仍由客户端绑定稳定回合身份、限制单回合请求数、串行执行并优先恢复匹配账本;Codex 原生 webSearch、任意原生命令网络、多 Agent 和完整插件能力继续关闭。 - 陶泥儿生成继续复用持久幂等账本、operation 恢复、来源/下载/PNG 解码和 manifest 登记;普通客户端优先使用当前 AGC 登录会话及账号路由,只有受控的 ExternalDeveloper 发布模式才在客户端内部使用按服务器 origin 隔离的私有 Key。用户和模型都不需要提供或配置 API Key;凭据失效、来源不明或结果未知时失败关闭,不能自动换 Key 或重新扣费。 - 自定义 LLM API Key 路由只在 DirectHome/DirectProject 经 loopback `/responses` 流式代理转发。代理不注入 Key,只要求请求自带 Bearer,并剥离开发网关错误携带的 `X-Codex-*` ChatGPT 账户额度头,防止隔离 app-server 把 API Provider 误判为余额 0;旧 ToolHost 保持原 Provider 行为。 diff --git a/docs/technical/【技术方案】Direct回合行为审计账本-2026-08-31.md b/docs/technical/【技术方案】Direct回合行为审计账本-2026-08-31.md index 58546f9fa..f16a4a5dc 100644 --- a/docs/technical/【技术方案】Direct回合行为审计账本-2026-08-31.md +++ b/docs/technical/【技术方案】Direct回合行为审计账本-2026-08-31.md @@ -190,7 +190,6 @@ camelCase JSON。禁止出现附件正文、命令 stdout、patch diff、宿主 | `agc_remove_background` | `sourceLocalAssetId`、`assetName` | 无 | | `agc_browser_playtest` | `attempt` | 无 | | `agc_web_search` | `query` 截断 400、`maxResults` | 无 | -| `agc_read_skill_resource` | `skillName`、`relativePath` | 不落 Skill 正文 | | 未知 MCP 名 | 只留 `tool` + `status` | 不落 `arguments` | `brief` / 截断后的 `prompt` 是 **模型自己写的设计文本**,不是用户 GDD 转储。这是分析「仍走收集类」的关键,允许进 jsonl。`agent.db` 摘要只留 `briefPreview` 240 字。 From 1e6772895326e7c455e4c175a21c33b5a80d36a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Wed, 2 Sep 2026 19:12:38 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E6=B8=85=E7=90=86=E5=B7=B2=E7=A7=BB?= =?UTF-8?q?=E9=99=A4=E5=B7=A5=E5=85=B7=E5=90=8D=E7=A7=B0=E6=AE=8B=E7=95=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 删除 unknown-tool 测试中对旧 AGC 工具名的硬编码引用 --- .../src-tauri/src/agent/direct_tools_mcp.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ai-game-creator-shell/src-tauri/src/agent/direct_tools_mcp.rs b/apps/ai-game-creator-shell/src-tauri/src/agent/direct_tools_mcp.rs index 226432b91..b12fe889a 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/agent/direct_tools_mcp.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/agent/direct_tools_mcp.rs @@ -1483,7 +1483,7 @@ mod tests { "jsonrpc": "2.0", "id": 1, "method": "tools/call", - "params": { "name": "agc_read_skill_resource", "arguments": {} } + "params": { "name": "unreviewed_tool", "arguments": {} } }), ) .await