mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-04 23:17:20 +08:00
feat: add moviepilot-explorer subagent for source-code inspection and troubleshooting
This commit is contained in:
@@ -52,7 +52,7 @@ Delegation modes:
|
|||||||
batch and wait for the batch in one tool call.
|
batch and wait for the batch in one tool call.
|
||||||
|
|
||||||
Rules:
|
Rules:
|
||||||
- Delegate when a task benefits from focused investigation, such as media identity checks, site/resource search, subscription analysis, download/transfer diagnosis, or read-only system inspection.
|
- Delegate when a task benefits from focused investigation, such as media identity checks, site/resource search, subscription analysis, download/transfer diagnosis, MoviePilot code/config exploration, or read-only system inspection.
|
||||||
- Subagent output is private context for your decision-making. Do not expose a subagent's process or final report verbatim to the user.
|
- Subagent output is private context for your decision-making. Do not expose a subagent's process or final report verbatim to the user.
|
||||||
- Subagents must not send messages to the user, ask for interaction, or reveal their internal tool activity.
|
- Subagents must not send messages to the user, ask for interaction, or reveal their internal tool activity.
|
||||||
- Give the user only your synthesized final answer and the minimum necessary next step.
|
- Give the user only your synthesized final answer and the minimum necessary next step.
|
||||||
@@ -260,6 +260,25 @@ def _builtin_subagent_profiles() -> tuple[_SubAgentProfile, ...]:
|
|||||||
),
|
),
|
||||||
exclude_tags=default_exclude_tags,
|
exclude_tags=default_exclude_tags,
|
||||||
),
|
),
|
||||||
|
_SubAgentProfile(
|
||||||
|
name="moviepilot-explorer",
|
||||||
|
description="MoviePilot exploration subagent for source-code inspection, configuration structure analysis, logs, and code-level troubleshooting clues.",
|
||||||
|
prompt=(
|
||||||
|
f"{SUBAGENT_BASE_PROMPT}\n"
|
||||||
|
"You specialize in MoviePilot source-code structure, local configuration files, directory layout, logs or read-only command output, and code-level root-cause troubleshooting. "
|
||||||
|
"Prefer reading relevant code paths before judging behavior, and distinguish code/config evidence from runtime system state."
|
||||||
|
),
|
||||||
|
include_tags=frozenset(
|
||||||
|
{
|
||||||
|
ToolTag.System.value,
|
||||||
|
ToolTag.Settings.value,
|
||||||
|
ToolTag.File.value,
|
||||||
|
ToolTag.Directory.value,
|
||||||
|
ToolTag.Command.value,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
exclude_tags=default_exclude_tags,
|
||||||
|
),
|
||||||
_SubAgentProfile(
|
_SubAgentProfile(
|
||||||
name="resource-searcher",
|
name="resource-searcher",
|
||||||
description="Site and resource search subagent for site checks, torrent search, and resource quality analysis.",
|
description="Site and resource search subagent for site checks, torrent search, and resource quality analysis.",
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ class TestAgentSubagents(unittest.TestCase):
|
|||||||
[SUBAGENT_TASK_TOOL_NAME, SUBAGENT_CONTROL_TOOL_NAME],
|
[SUBAGENT_TASK_TOOL_NAME, SUBAGENT_CONTROL_TOOL_NAME],
|
||||||
)
|
)
|
||||||
self.assertIn("media-researcher", task_tools[0].description)
|
self.assertIn("media-researcher", task_tools[0].description)
|
||||||
|
self.assertIn("moviepilot-explorer", task_tools[0].description)
|
||||||
self.assertIn("system-diagnostician", task_tools[0].description)
|
self.assertIn("system-diagnostician", task_tools[0].description)
|
||||||
self.assertIn("action=start", task_tools[1].description)
|
self.assertIn("action=start", task_tools[1].description)
|
||||||
self.assertIn("action=wait", task_tools[1].description)
|
self.assertIn("action=wait", task_tools[1].description)
|
||||||
@@ -77,6 +78,56 @@ class TestAgentSubagents(unittest.TestCase):
|
|||||||
["custom_media_lookup"],
|
["custom_media_lookup"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_moviepilot_explorer_selects_code_and_settings_tools(self):
|
||||||
|
"""MoviePilot 探索子代理应能读取代码、目录、设置和命令诊断工具。"""
|
||||||
|
model = FakeListChatModel(responses=["ok"])
|
||||||
|
tools = [
|
||||||
|
SimpleNamespace(
|
||||||
|
name="custom_code_reader",
|
||||||
|
tags=[ToolTag.Read.value, ToolTag.File.value],
|
||||||
|
),
|
||||||
|
SimpleNamespace(
|
||||||
|
name="custom_directory_lister",
|
||||||
|
tags=[ToolTag.Read.value, ToolTag.Directory.value],
|
||||||
|
),
|
||||||
|
SimpleNamespace(
|
||||||
|
name="custom_settings_reader",
|
||||||
|
tags=[ToolTag.Read.value, ToolTag.Settings.value],
|
||||||
|
),
|
||||||
|
SimpleNamespace(
|
||||||
|
name="custom_command_runner",
|
||||||
|
tags=[ToolTag.Read.value, ToolTag.Command.value],
|
||||||
|
),
|
||||||
|
SimpleNamespace(
|
||||||
|
name="custom_code_writer",
|
||||||
|
tags=[ToolTag.Read.value, ToolTag.Write.value, ToolTag.File.value],
|
||||||
|
),
|
||||||
|
]
|
||||||
|
captured = {}
|
||||||
|
|
||||||
|
def _fake_create_agent(**kwargs):
|
||||||
|
captured.update(kwargs)
|
||||||
|
return kwargs
|
||||||
|
|
||||||
|
middleware = MoviePilotSubAgentMiddleware(
|
||||||
|
model=model,
|
||||||
|
profiles=subagent_module._builtin_subagent_profiles(),
|
||||||
|
tools=tools,
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch.object(subagent_module, "create_agent", side_effect=_fake_create_agent):
|
||||||
|
middleware._get_agent("moviepilot-explorer")
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
[tool.name for tool in captured["tools"]],
|
||||||
|
[
|
||||||
|
"custom_code_reader",
|
||||||
|
"custom_directory_lister",
|
||||||
|
"custom_settings_reader",
|
||||||
|
"custom_command_runner",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
def test_builtin_tools_declare_tags_in_implementation(self):
|
def test_builtin_tools_declare_tags_in_implementation(self):
|
||||||
"""所有内置工具实现都应显式声明 tags。"""
|
"""所有内置工具实现都应显式声明 tags。"""
|
||||||
impl_dir = Path(__file__).resolve().parents[1] / "app" / "agent" / "tools" / "impl"
|
impl_dir = Path(__file__).resolve().parents[1] / "app" / "agent" / "tools" / "impl"
|
||||||
|
|||||||
Reference in New Issue
Block a user