mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-08-29 03:56:43 +08:00
fix(ci): restore lint and architecture gates
This commit is contained in:
@@ -5,15 +5,11 @@ from typing import Any, Optional, Tuple
|
||||
|
||||
from fastapi.concurrency import run_in_threadpool
|
||||
|
||||
from app.agent.policy import sanitize_for_host
|
||||
from app.agent.policy.sanitizer import sanitize_for_host
|
||||
from app.chain import ChainBase
|
||||
from app.runtime.log import logger
|
||||
from app.schemas.message import Message
|
||||
from app.schemas.message import (
|
||||
MessageResponse,
|
||||
ChannelCapabilityManager,
|
||||
ChannelCapability,
|
||||
)
|
||||
from app.schemas.message import Message, MessageResponse
|
||||
from app.schemas.notification import ChannelCapabilityManager, ChannelCapability
|
||||
from app.schemas.types import NotificationChannel, MessageType
|
||||
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ from langgraph.checkpoint.memory import InMemorySaver
|
||||
|
||||
from app.agent.callback import StreamingHandler
|
||||
from app.agent.contracts import ReplyMode, build_display_message
|
||||
from app.agent.llm import LLMHelper
|
||||
from app.agent.llm.helper import LLMHelper
|
||||
from app.agent.llm.server_tools import ServerToolRegistry
|
||||
from app.agent.memory import memory_manager
|
||||
from app.agent.middleware.activity_log import (
|
||||
@@ -51,7 +51,7 @@ from app.agent.middleware.subagents import (
|
||||
from app.agent.middleware.tool_selection import ToolSelectorMiddleware
|
||||
from app.agent.middleware.usage import UsageMiddleware
|
||||
from app.agent.prompt import prompt_manager
|
||||
from app.agent.policy import (
|
||||
from app.agent.policy.contracts import (
|
||||
AuthSource,
|
||||
PrincipalType,
|
||||
ToolOrigin,
|
||||
|
||||
@@ -65,6 +65,23 @@ def _check_auth(api_key: Optional[str]) -> Optional[JSONResponse]:
|
||||
return None
|
||||
|
||||
|
||||
def _manager_execution_error(error: BaseException) -> JSONResponse:
|
||||
"""把 AgentManager 稳定错误映射为 Anthropic 兼容错误响应。"""
|
||||
if _is_manager_unavailable(error):
|
||||
return _anthropic_error_response(
|
||||
"MoviePilot AI agent is unavailable.",
|
||||
503,
|
||||
error_type="api_error",
|
||||
)
|
||||
if _is_manager_queue_full(error):
|
||||
return _anthropic_error_response(
|
||||
str(error),
|
||||
429,
|
||||
error_type="rate_limit_error",
|
||||
)
|
||||
return _anthropic_error_response(str(error), 500, error_type="api_error")
|
||||
|
||||
|
||||
async def _stream_anthropic_response(
|
||||
manager,
|
||||
session_id: str,
|
||||
@@ -241,19 +258,7 @@ async def messages(
|
||||
stream_mode=False,
|
||||
)
|
||||
except Exception as exc:
|
||||
if _is_manager_unavailable(exc):
|
||||
return _anthropic_error_response(
|
||||
"MoviePilot AI agent is unavailable.",
|
||||
503,
|
||||
error_type="api_error",
|
||||
)
|
||||
if _is_manager_queue_full(exc):
|
||||
return _anthropic_error_response(
|
||||
str(exc),
|
||||
429,
|
||||
error_type="rate_limit_error",
|
||||
)
|
||||
return _anthropic_error_response(str(exc), 500, error_type="api_error")
|
||||
return _manager_execution_error(exc)
|
||||
finally:
|
||||
await manager.clear_session(session_id=session_id, user_id=session_id)
|
||||
|
||||
|
||||
+26
-40
@@ -351,6 +351,30 @@ def _is_manager_queue_full(error: BaseException) -> bool:
|
||||
return getattr(error, "code", None) == "agent_manager_queue_full"
|
||||
|
||||
|
||||
def _manager_execution_error(error: BaseException) -> JSONResponse:
|
||||
"""把 AgentManager 稳定错误映射为 OpenAI 兼容错误响应。"""
|
||||
if _is_manager_unavailable(error):
|
||||
return _error_response(
|
||||
"MoviePilot AI agent is unavailable.",
|
||||
503,
|
||||
error_type="server_error",
|
||||
code="ai_agent_unavailable",
|
||||
)
|
||||
if _is_manager_queue_full(error):
|
||||
return _error_response(
|
||||
str(error),
|
||||
429,
|
||||
error_type="rate_limit_error",
|
||||
code="ai_agent_queue_full",
|
||||
)
|
||||
return _error_response(
|
||||
str(error),
|
||||
500,
|
||||
error_type="server_error",
|
||||
code="agent_execution_failed",
|
||||
)
|
||||
|
||||
|
||||
async def _run_managed_agent(
|
||||
*,
|
||||
manager,
|
||||
@@ -550,26 +574,7 @@ async def chat_completions(
|
||||
stream_mode=False,
|
||||
)
|
||||
except Exception as exc:
|
||||
if _is_manager_unavailable(exc):
|
||||
return _error_response(
|
||||
"MoviePilot AI agent is unavailable.",
|
||||
503,
|
||||
error_type="server_error",
|
||||
code="ai_agent_unavailable",
|
||||
)
|
||||
if _is_manager_queue_full(exc):
|
||||
return _error_response(
|
||||
str(exc),
|
||||
429,
|
||||
error_type="rate_limit_error",
|
||||
code="ai_agent_queue_full",
|
||||
)
|
||||
return _error_response(
|
||||
str(exc),
|
||||
500,
|
||||
error_type="server_error",
|
||||
code="agent_execution_failed",
|
||||
)
|
||||
return _manager_execution_error(exc)
|
||||
finally:
|
||||
if not use_server_session:
|
||||
await manager.clear_session(session_id=session_id, user_id=session_key)
|
||||
@@ -657,26 +662,7 @@ async def responses(
|
||||
stream_mode=False,
|
||||
)
|
||||
except Exception as exc:
|
||||
if _is_manager_unavailable(exc):
|
||||
return _error_response(
|
||||
"MoviePilot AI agent is unavailable.",
|
||||
503,
|
||||
error_type="server_error",
|
||||
code="ai_agent_unavailable",
|
||||
)
|
||||
if _is_manager_queue_full(exc):
|
||||
return _error_response(
|
||||
str(exc),
|
||||
429,
|
||||
error_type="rate_limit_error",
|
||||
code="ai_agent_queue_full",
|
||||
)
|
||||
return _error_response(
|
||||
str(exc),
|
||||
500,
|
||||
error_type="server_error",
|
||||
code="agent_execution_failed",
|
||||
)
|
||||
return _manager_execution_error(exc)
|
||||
finally:
|
||||
if not payload.user:
|
||||
await manager.clear_session(session_id=session_id, user_id=session_key)
|
||||
|
||||
+26
-22
@@ -1353,6 +1353,28 @@ class SubscribeChain(MusicSubscribeMixin, InteractionChainMixin, ChainBase):
|
||||
"""
|
||||
return cls._subscription_query().exists(mediainfo, meta)
|
||||
|
||||
def _acquire_run_lock(
|
||||
self,
|
||||
operation: str,
|
||||
progress_callback: Optional[Callable[..., None]],
|
||||
) -> bool:
|
||||
"""获取订阅任务锁,超时时统一记录并结束本轮进度。"""
|
||||
if self._rlock.acquire(blocking=True, timeout=self._LOCK_TIMOUT):
|
||||
logger.debug(f"{operation} lock acquired at {datetime.now()}")
|
||||
return True
|
||||
operation_label = {"search": "搜索", "match": "匹配"}[operation]
|
||||
progress_text = {
|
||||
"search": "订阅搜索锁等待超时,已跳过本轮",
|
||||
"match": "订阅匹配锁等待超时,已跳过本轮",
|
||||
}[operation]
|
||||
logger.error(f"订阅{operation_label}锁等待超时,已中止本轮执行")
|
||||
if progress_callback:
|
||||
progress_callback(
|
||||
value=100,
|
||||
text=progress_text,
|
||||
)
|
||||
return False
|
||||
|
||||
def search(
|
||||
self,
|
||||
sid: Optional[int] = None,
|
||||
@@ -1370,17 +1392,8 @@ class SubscribeChain(MusicSubscribeMixin, InteractionChainMixin, ChainBase):
|
||||
"""
|
||||
lock_acquired = False
|
||||
try:
|
||||
if lock_acquired := self._rlock.acquire(
|
||||
blocking=True, timeout=self._LOCK_TIMOUT
|
||||
):
|
||||
logger.debug(f"search lock acquired at {datetime.now()}")
|
||||
else:
|
||||
logger.error("订阅搜索锁等待超时,已中止本轮执行")
|
||||
if progress_callback:
|
||||
progress_callback(
|
||||
value=100,
|
||||
text="订阅搜索锁等待超时,已跳过本轮",
|
||||
)
|
||||
lock_acquired = self._acquire_run_lock("search", progress_callback)
|
||||
if not lock_acquired:
|
||||
return
|
||||
|
||||
subscribeoper = SubscribeOper()
|
||||
@@ -1820,17 +1833,8 @@ class SubscribeChain(MusicSubscribeMixin, InteractionChainMixin, ChainBase):
|
||||
|
||||
lock_acquired = False
|
||||
try:
|
||||
if lock_acquired := self._rlock.acquire(
|
||||
blocking=True, timeout=self._LOCK_TIMOUT
|
||||
):
|
||||
logger.debug(f"match lock acquired at {datetime.now()}")
|
||||
else:
|
||||
logger.error("订阅匹配锁等待超时,已中止本轮执行")
|
||||
if progress_callback:
|
||||
progress_callback(
|
||||
value=100,
|
||||
text="订阅匹配锁等待超时,已跳过本轮",
|
||||
)
|
||||
lock_acquired = self._acquire_run_lock("match", progress_callback)
|
||||
if not lock_acquired:
|
||||
return
|
||||
|
||||
# 预识别所有未识别的种子
|
||||
|
||||
+6
-2
@@ -13,8 +13,8 @@
|
||||
"runtime_to_db": [],
|
||||
"workflow_to_db": []
|
||||
},
|
||||
"edge_count": 6313,
|
||||
"edge_sha256": "25292ce04e33206f713eb24cff2397931124fcb22f55ab0d78f94314581161d4",
|
||||
"edge_count": 6317,
|
||||
"edge_sha256": "11978842b2fd9bd6ccec86c01c5f1b9389d959bc53aab5e16e29e3c121b3dab9",
|
||||
"edges": [
|
||||
"app -> app.runtime",
|
||||
"app -> app.runtime.compat",
|
||||
@@ -169,11 +169,13 @@
|
||||
"app.adapters.web.security.access -> app.schemas.token",
|
||||
"app.agent.callback -> app.agent",
|
||||
"app.agent.callback -> app.agent.policy",
|
||||
"app.agent.callback -> app.agent.policy.sanitizer",
|
||||
"app.agent.callback -> app.chain",
|
||||
"app.agent.callback -> app.runtime",
|
||||
"app.agent.callback -> app.runtime.log",
|
||||
"app.agent.callback -> app.schemas",
|
||||
"app.agent.callback -> app.schemas.message",
|
||||
"app.agent.callback -> app.schemas.notification",
|
||||
"app.agent.callback -> app.schemas.types",
|
||||
"app.agent.capabilities.adapter -> app.agent",
|
||||
"app.agent.capabilities.adapter -> app.agent.capabilities",
|
||||
@@ -303,6 +305,7 @@
|
||||
"app.agent.orchestrator -> app.agent.callback",
|
||||
"app.agent.orchestrator -> app.agent.contracts",
|
||||
"app.agent.orchestrator -> app.agent.llm",
|
||||
"app.agent.orchestrator -> app.agent.llm.helper",
|
||||
"app.agent.orchestrator -> app.agent.llm.server_tools",
|
||||
"app.agent.orchestrator -> app.agent.mcp",
|
||||
"app.agent.orchestrator -> app.agent.memory",
|
||||
@@ -319,6 +322,7 @@
|
||||
"app.agent.orchestrator -> app.agent.middleware.tool_selection",
|
||||
"app.agent.orchestrator -> app.agent.middleware.usage",
|
||||
"app.agent.orchestrator -> app.agent.policy",
|
||||
"app.agent.orchestrator -> app.agent.policy.contracts",
|
||||
"app.agent.orchestrator -> app.agent.prompt",
|
||||
"app.agent.orchestrator -> app.agent.runtime",
|
||||
"app.agent.orchestrator -> app.agent.runtime_loader",
|
||||
|
||||
@@ -7,7 +7,7 @@ import langchain.agents as langchain_agents
|
||||
if not hasattr(langchain_agents, "create_agent"):
|
||||
langchain_agents.create_agent = lambda *args, **kwargs: None
|
||||
|
||||
from app.agent import _ThinkTagStripper
|
||||
from app.agent.orchestrator import _ThinkTagStripper
|
||||
from app.agent.callback import StreamingHandler
|
||||
from app.agent.middleware.subagents import is_subagent_stream_metadata
|
||||
from app.agent.tools.base import MoviePilotTool
|
||||
|
||||
@@ -11,9 +11,9 @@ import pytest
|
||||
|
||||
from app.domain.context import MediaInfo, Context, TorrentInfo
|
||||
from app.domain.metainfo import MetaInfo
|
||||
from app.modules.telegram import TelegramModule
|
||||
from app.modules.telegram.module import TelegramModule
|
||||
from app.modules.telegram.telegram import Telegram
|
||||
from app.schemas import Message
|
||||
from app.schemas.message import Message
|
||||
from app.schemas.types import NotificationChannel
|
||||
from app.schemas.types import MediaType
|
||||
|
||||
|
||||
Reference in New Issue
Block a user