diff --git a/app/agent/tools/impl/api.py b/app/agent/tools/impl/api.py index 1e038cfbf..5a2c26fa9 100644 --- a/app/agent/tools/impl/api.py +++ b/app/agent/tools/impl/api.py @@ -16,6 +16,7 @@ from app.agent.policy.sanitizer import summarize_input from app.agent.tools.base import MoviePilotTool from app.agent.tools.result import inspect_tool_result from app.agent.tools.tags import ToolTag +from app.schemas.common import JsonData from app.schemas.types import NotificationChannel _TOOL_MESSAGE_OPERATION_MAX_CHARS = 96 @@ -55,11 +56,13 @@ class MoviePilotApiInput(BaseModel): # type: ignore[misc] default_factory=dict, description="Query-string fields declared by the selected operation.", ) - body: Any = Field( + body: JsonData = Field( default=None, description=( "JSON request value declared by the selected operation and its loaded Skill contract. " - "Most operations use an object; a oneOf branch may require an exact scalar." + "Most operations use an object; a oneOf branch may require an exact scalar. " + "Keep objects and arrays, including nested file items, as native JSON values; " + "never JSON-encode them into strings." ), ) diff --git a/tests/test_agent_api_gateway.py b/tests/test_agent_api_gateway.py index 6e2a6b2fd..874a009f9 100644 --- a/tests/test_agent_api_gateway.py +++ b/tests/test_agent_api_gateway.py @@ -194,6 +194,16 @@ def test_mcp_tools_list_preserves_all_moviepilot_api_operation_branches() -> Non assert operation_ids == set(API_OPERATION_ROUTES) +def test_local_agent_tool_uses_the_same_precise_operation_schema() -> None: + """本地 Agent 绑定的工具 schema 至少必须提示 body 是 JSON 结构值。""" + tool = MoviePilotApiTool(session_id="session", user_id="api_user") + schema = tool.tool_call_schema + assert not isinstance(schema, dict) + body = schema.model_json_schema()["properties"]["body"] + + assert body["$ref"].endswith("/JsonData") + + def test_mcp_collection_contract_distinguishes_exact_and_unavailable_totals() -> None: """MCP 必须说明缺省全量、精确总数和外部无总数三种集合语义。""" schema = MoviePilotApiTool(session_id="session", user_id="api_user").get_mcp_input_schema()