Files
MoviePilot/tests/test_agent_llm_runtime_config.py
DDSRem 2de976f6b3 Merge pull request #7050 from DDSRem-Dev/codex-comment-migration
docs: 统一全项目中文注释和结构化契约说明
2026-10-17 19:26:29 +08:00

130 lines
4.6 KiB
Python

"""
验证系统与插件配置合并后使用的模型协议、思考级别和运行参数。
"""
import asyncio
from types import SimpleNamespace
from unittest.mock import AsyncMock, patch
from app.agent.orchestrator import MoviePilotAgent
from app.runtime.config import settings
from app.schemas.event import AgentLLMProviderEventData
from app.schemas.types import ChainEventType
def test_resolve_llm_runtime_config_uses_system_thinking_level(monkeypatch) -> None:
"""
插件未提供有效思考强度时应使用系统配置。
"""
monkeypatch.setattr(settings, "LLM_THINKING_LEVEL", "xhigh")
agent = MoviePilotAgent(session_id="thinking-level-default", user_id="user-1")
async def return_empty_config(event_type, event_data):
"""
模拟插件未返回有效运行时配置。
"""
assert event_type == ChainEventType.AgentLLMProvider
assert event_data.thinking_level == "xhigh"
return SimpleNamespace(event_data=AgentLLMProviderEventData())
with patch(
"app.agent.orchestrator.eventmanager.async_send_event",
new=AsyncMock(side_effect=return_empty_config),
):
runtime_config = asyncio.run(agent._resolve_llm_runtime_config())
assert runtime_config["thinking_level"] == "xhigh"
def test_resolve_llm_runtime_config_prefers_plugin_thinking_level(monkeypatch) -> None:
"""
插件显式覆盖思考强度时应优先使用插件值。
"""
monkeypatch.setattr(settings, "LLM_THINKING_LEVEL", "xhigh")
agent = MoviePilotAgent(session_id="thinking-level-plugin", user_id="user-1")
async def override_thinking_level(_event_type, event_data):
"""
模拟插件覆盖思考强度。
"""
event_data.thinking_level = "high"
return SimpleNamespace(event_data=event_data)
with patch(
"app.agent.orchestrator.eventmanager.async_send_event",
new=AsyncMock(side_effect=override_thinking_level),
):
runtime_config = asyncio.run(agent._resolve_llm_runtime_config())
assert runtime_config["thinking_level"] == "high"
def test_resolve_llm_runtime_config_uses_system_api_protocol(monkeypatch) -> None:
"""
插件未提供 API 协议时应使用系统配置。
"""
monkeypatch.setattr(settings, "LLM_API_PROTOCOL", "responses")
agent = MoviePilotAgent(session_id="api-protocol-default", user_id="user-1")
async def return_empty_config(event_type, event_data):
"""
模拟插件未返回有效运行时配置。
"""
assert event_type == ChainEventType.AgentLLMProvider
assert event_data.api_protocol == "responses"
return SimpleNamespace(event_data=AgentLLMProviderEventData())
with patch(
"app.agent.orchestrator.eventmanager.async_send_event",
new=AsyncMock(side_effect=return_empty_config),
):
runtime_config = asyncio.run(agent._resolve_llm_runtime_config())
assert runtime_config["api_protocol"] == "responses"
def test_resolve_llm_runtime_config_prefers_plugin_api_protocol(monkeypatch) -> None:
"""
插件显式覆盖 API 协议时应优先使用插件值。
"""
monkeypatch.setattr(settings, "LLM_API_PROTOCOL", "responses")
agent = MoviePilotAgent(session_id="api-protocol-plugin", user_id="user-1")
async def override_api_protocol(_event_type, event_data):
"""
模拟插件覆盖 API 协议。
"""
event_data.api_protocol = "chat_completions"
return SimpleNamespace(event_data=event_data)
with patch(
"app.agent.orchestrator.eventmanager.async_send_event",
new=AsyncMock(side_effect=override_api_protocol),
):
runtime_config = asyncio.run(agent._resolve_llm_runtime_config())
assert runtime_config["api_protocol"] == "chat_completions"
def test_resolve_llm_runtime_config_prefers_plugin_web_search_mode(monkeypatch) -> None:
"""
插件显式覆盖联网搜索模式时应优先使用插件值。
"""
monkeypatch.setattr(settings, "LLM_WEB_SEARCH_MODE", "local")
agent = MoviePilotAgent(session_id="web-search-plugin", user_id="user-1")
async def override_web_search_mode(_event_type, event_data):
"""
模拟插件覆盖联网搜索模式。
"""
event_data.web_search_mode = "builtin"
return SimpleNamespace(event_data=event_data)
with patch(
"app.agent.orchestrator.eventmanager.async_send_event",
new=AsyncMock(side_effect=override_web_search_mode),
):
runtime_config = asyncio.run(agent._resolve_llm_runtime_config())
assert runtime_config["web_search_mode"] == "builtin"