From 5b6b4c9744598a842f4df53d615bdafdddd2c105 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Wed, 27 May 2026 08:48:56 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=86=E5=8F=91=E9=80=81=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E5=B7=A5=E5=85=B7=E8=AE=BE=E4=B8=BA=E5=BF=85=E9=80=89=E5=B7=A5?= =?UTF-8?q?=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/agent/__init__.py | 6 ----- app/agent/tools/factory.py | 3 ++- tests/test_agent_background_output.py | 39 +++++---------------------- 3 files changed, 8 insertions(+), 40 deletions(-) diff --git a/app/agent/__init__.py b/app/agent/__init__.py index 85722f46..582c68be 100644 --- a/app/agent/__init__.py +++ b/app/agent/__init__.py @@ -798,12 +798,6 @@ class MoviePilotAgent: always_include_tools = ( MoviePilotToolFactory.get_tool_selector_always_include_names(tools) ) - if self.is_heartbeat_session: - available_tool_names = { - tool.name for tool in tools if getattr(tool, "name", None) - } - if "send_message" in available_tool_names: - always_include_tools.append("send_message") # 中间件 middlewares = [ diff --git a/app/agent/tools/factory.py b/app/agent/tools/factory.py index e44810ef..2f53ce69 100644 --- a/app/agent/tools/factory.py +++ b/app/agent/tools/factory.py @@ -91,7 +91,7 @@ class MoviePilotToolFactory: """ # 这些通用工具需要始终保留,避免大工具集裁剪后让 Agent 丢失基础的 - # 文件系统、命令执行或交互确认能力。AskUserChoiceTool 仅在支持按钮 + # 文件系统、命令执行、主动消息发送或交互确认能力。AskUserChoiceTool 仅在支持按钮 # 的渠道中才会实际注入,因此后续会再按已加载工具做一次求交集。 TOOL_SELECTOR_ALWAYS_INCLUDE_NAMES = ( "list_directory", @@ -99,6 +99,7 @@ class MoviePilotToolFactory: "read_file", "edit_file", "execute_command", + "send_message", "ask_user_choice", ) diff --git a/tests/test_agent_background_output.py b/tests/test_agent_background_output.py index d68187c5..3e76aa43 100644 --- a/tests/test_agent_background_output.py +++ b/tests/test_agent_background_output.py @@ -12,6 +12,7 @@ from app.agent import ( UNSUPPORTED_IMAGE_INPUT_MESSAGE, ) from app.agent.memory import memory_manager +from app.agent.tools.factory import MoviePilotToolFactory from app.core.config import settings from app.utils.identity import SYSTEM_INTERNAL_USER_ID @@ -320,42 +321,14 @@ class AgentBackgroundOutputTest(unittest.IsolatedAsyncioTestCase): created["middleware"], ) - async def test_heartbeat_session_always_keeps_send_message_tool(self): - agent = MoviePilotAgent( - session_id=f"{HEARTBEAT_SESSION_PREFIX}test__", - user_id="system", - ) + def test_send_message_tool_is_always_included_by_tool_selector(self): send_message_tool = SimpleNamespace(name="send_message") - agent._initialize_tools = lambda: [send_message_tool] - captured = {} + always_include = MoviePilotToolFactory.get_tool_selector_always_include_names( + [send_message_tool] + ) - def fake_tool_selector(*args, **kwargs): - captured["always_include"] = kwargs["always_include"] - return "selector" - - with ( - patch.object(settings, "LLM_MAX_TOOLS", 1), - patch.object(agent, "_initialize_llm", new=AsyncMock(return_value=object())), - patch("app.agent.prompt_manager.get_agent_prompt", return_value="PROMPT"), - patch( - "app.agent.MoviePilotToolFactory.get_tool_selector_always_include_names", - return_value=[], - ), - patch("app.agent.SkillsMiddleware", side_effect=lambda *args, **kwargs: "skills"), - patch("app.agent.JobsMiddleware", side_effect=lambda *args, **kwargs: "jobs"), - patch("app.agent.RuntimeConfigMiddleware", side_effect=lambda *args, **kwargs: "runtime"), - patch("app.agent.MemoryMiddleware", side_effect=lambda *args, **kwargs: "memory"), - patch("app.agent.SummarizationMiddleware", side_effect=lambda *args, **kwargs: "summary"), - patch("app.agent.PatchToolCallsMiddleware", side_effect=lambda *args, **kwargs: "patch"), - patch("app.agent.UsageMiddleware", side_effect=lambda *args, **kwargs: "usage"), - patch("app.agent.ToolSelectorMiddleware", side_effect=fake_tool_selector), - patch("app.agent.InMemorySaver", return_value="checkpointer"), - patch("app.agent.create_agent", side_effect=lambda **kwargs: kwargs), - ): - await agent._create_agent(streaming=False) - - self.assertIn("send_message", captured["always_include"]) + self.assertIn("send_message", always_include) async def test_create_agent_keeps_activity_log_for_normal_session(self): agent = MoviePilotAgent(session_id="normal-session", user_id="system")