diff --git a/apps/ai-game-creator-shell/src-tauri/src/agent/direct_tool_bridge.rs b/apps/ai-game-creator-shell/src-tauri/src/agent/direct_tool_bridge.rs index 510f1e309..889f805b3 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/agent/direct_tool_bridge.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/agent/direct_tool_bridge.rs @@ -1,6 +1,8 @@ use super::*; use crate::agent::tool::apply_patch::error::ApplyPatchError; -use crate::agent::tool::arguments::{optional_text, page, required_text, ToolPage, ToolTextField}; +use crate::agent::tool::arguments::{ + optional_text, page, required_text, ToolPage, ToolTextField, TOOL_PAGE_MAX_OFFSET, +}; use crate::agent::tool::browser_playtest::error::BrowserPlaytestError; #[cfg(all(windows, feature = "cocos-editor-execute"))] use crate::agent::tool::cocos_execute::error::CocosExecuteError; @@ -1191,7 +1193,7 @@ pub(in crate::agent) fn list_registered_assets_input( arguments, 50, DIRECT_TOOL_BRIDGE_MAX_RESOURCE_PAGE_SIZE, - None, + TOOL_PAGE_MAX_OFFSET, )?; Ok(ListRegisteredAssetsInput { kind, @@ -1537,7 +1539,7 @@ pub(in crate::agent) fn list_project_files_input( arguments, 100, DIRECT_TOOL_BRIDGE_MAX_RESOURCE_PAGE_SIZE, - Some(500), + TOOL_PAGE_MAX_OFFSET, )?; Ok(ListProjectFilesInput { path, @@ -1955,7 +1957,7 @@ pub(in crate::agent) fn list_account_assets_input( arguments, 100, DIRECT_TOOL_BRIDGE_MAX_RESOURCE_PAGE_SIZE, - Some(500), + TOOL_PAGE_MAX_OFFSET, )?; Ok(ListAccountAssetsInput { folder_id, 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 61e78b727..a0693b1ff 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 @@ -405,7 +405,7 @@ fn direct_tools_mcp_specs_for_plugins( "default": false, "description": prompt_text!("directTools.agc_list_registered_assets.parameters.includeSequenceFrames") }, - "offset": { "type": "integer", "minimum": 0, "default": 0 }, + "offset": { "type": "integer", "minimum": 0, "maximum": 500, "default": 0 }, "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 } }, "additionalProperties": false diff --git a/apps/ai-game-creator-shell/src-tauri/src/agent/tool/arguments.rs b/apps/ai-game-creator-shell/src-tauri/src/agent/tool/arguments.rs index 47f8c80c3..c3ff3e63a 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/agent/tool/arguments.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/agent/tool/arguments.rs @@ -53,12 +53,18 @@ pub(crate) struct ToolPage { pub limit: usize, } +/// 三个列表工具共用的 `offset` 上限:每个调用点都必须显式传值,避免某一路悄悄不设上限。 +/// +/// 取值与 `agc_list_project_files` / `agc_list_account_assets` 的 inputSchema +/// `offset.maximum` 一致;`agc_list_registered_assets` 的 schema 同步为同一个值。 +pub(crate) const TOOL_PAGE_MAX_OFFSET: usize = 500; + /// 解析 `offset`/`limit`。分页规则在三个列表工具之间一致,只有默认值与上限不同。 pub(crate) fn page( arguments: &Value, default_limit: usize, max_limit: usize, - max_offset: Option, + max_offset: usize, ) -> Result { let offset = arguments .get("offset") @@ -73,8 +79,11 @@ pub(crate) fn page( }) .transpose()? .unwrap_or(0); - if let Some(max) = max_offset.filter(|max| offset > *max) { - return Err(ToolPageRejection::OffsetTooLarge { got: offset, max }); + if offset > max_offset { + return Err(ToolPageRejection::OffsetTooLarge { + got: offset, + max: max_offset, + }); } let limit = arguments .get("limit")