diff --git a/app/api/endpoints/agent.py b/app/api/endpoints/agent.py index 64ca42ebb..eaa5bf218 100644 --- a/app/api/endpoints/agent.py +++ b/app/api/endpoints/agent.py @@ -1957,19 +1957,7 @@ async def stop_web_agent_session_task( ) -@router.post( - "/stream", - summary="Web智能助手流式对话", - response_model=None, - response_class=StreamingResponse, - responses={ - 200: { - "description": "Agent SSE 事件流", - "content": {"text/event-stream": {"schema": {"type": "string"}}}, - } - }, -) -async def web_agent_stream( +async def _web_agent_stream_impl( payload: _SchemaAgentWebChatRequest, request: Request, current_user: ApiPrincipal = Depends(get_current_active_user), @@ -2315,3 +2303,24 @@ async def web_agent_stream( ), }, ) + + +@router.post( + "/stream", + summary="Web智能助手流式对话", + response_model=None, + response_class=StreamingResponse, + responses={ + 200: { + "description": "Agent SSE 事件流", + "content": {"text/event-stream": {"schema": {"type": "string"}}}, + } + }, +) +async def web_agent_stream( + payload: _SchemaAgentWebChatRequest, + request: Request, + current_user: ApiPrincipal = Depends(get_current_active_user), +) -> StreamingResponse: + """Web 智能助手流式对话的稳定公开路由入口。""" + return await _web_agent_stream_impl(payload, request, current_user) diff --git a/app/api/endpoints/media.py b/app/api/endpoints/media.py index 2c724d2b9..06513b494 100644 --- a/app/api/endpoints/media.py +++ b/app/api/endpoints/media.py @@ -388,10 +388,7 @@ def source(_: _SchemaTokenPayload = Depends(verify_token)) -> list[_SchemaMediaS return _registered_media_sources() -@router.post( - "/scrape/{storage}", summary="刮削媒体信息", response_model=_SchemaResponse[None] -) -def scrape( +def _scrape_impl( fileitem: _SchemaFileItem, storage: Optional[str] = "local", media_source: Optional[MediaSource] = None, @@ -498,6 +495,22 @@ def scrape( return _SchemaResponse(success=True, message=f"{fileitem.path} 刮削完成") +@router.post( + "/scrape/{storage}", summary="刮削媒体信息", response_model=_SchemaResponse[None] +) +def scrape( + fileitem: _SchemaFileItem, + storage: Optional[str] = "local", + media_source: Optional[MediaSource] = None, + media_id: Optional[str] = None, + type_name: Optional[MediaType] = None, + music_type: Optional[str] = None, + _: _SchemaTokenPayload = Depends(verify_token), +) -> Any: + """刮削媒体信息的兼容公开入口。""" + return _scrape_impl(fileitem, storage, media_source, media_id, type_name, music_type, _) + + @router.get( "/category/config", summary="获取分类策略配置", diff --git a/app/api/endpoints/openai.py b/app/api/endpoints/openai.py index 1a6413ba0..2a65b0a3e 100644 --- a/app/api/endpoints/openai.py +++ b/app/api/endpoints/openai.py @@ -482,20 +482,7 @@ async def list_models( ) -@router.post( - "/chat/completions", - summary="OpenAI compatible chat completions", - response_model=_SchemaOpenAIChatCompletionResponse, - responses={ - 200: { - "description": "OpenAI chat completion 或 SSE 数据流", - "content": { - "text/event-stream": {"schema": {"type": "string"}}, - }, - } - }, -) -async def chat_completions( +async def _chat_completions_impl( payload: _SchemaOpenAIChatCompletionsRequest, request: Request, credentials: Optional[HTTPAuthorizationCredentials] = Security( @@ -592,12 +579,7 @@ async def chat_completions( return JSONResponse(content=build_completion_payload(content, MODEL_ID)) -@router.post( - "/responses", - summary="OpenAI compatible responses", - response_model=_SchemaOpenAIResponsesResponse, -) -async def responses( +async def _responses_impl( payload: _SchemaOpenAIResponsesRequest, credentials: Optional[HTTPAuthorizationCredentials] = Security( openai_bearer_scheme @@ -690,3 +672,31 @@ async def responses( output=[output_message], usage=_SchemaOpenAIUsage(), ) + + +@router.post( + "/chat/completions", + summary="OpenAI compatible chat completions", + response_model=_SchemaOpenAIChatCompletionResponse, + responses={200: {"description": "OpenAI chat completion 或 SSE 数据流", "content": {"text/event-stream": {"schema": {"type": "string"}}}}}, +) +async def chat_completions( + payload: _SchemaOpenAIChatCompletionsRequest, + request: Request, + credentials: Optional[HTTPAuthorizationCredentials] = Security(openai_bearer_scheme), +): + """OpenAI Chat Completions 兼容公开入口。""" + return await _chat_completions_impl(payload, request, credentials) + + +@router.post( + "/responses", + summary="OpenAI compatible responses", + response_model=_SchemaOpenAIResponsesResponse, +) +async def responses( + payload: _SchemaOpenAIResponsesRequest, + credentials: Optional[HTTPAuthorizationCredentials] = Security(openai_bearer_scheme), +): + """OpenAI Responses 兼容公开入口。""" + return await _responses_impl(payload, credentials) diff --git a/app/api/endpoints/system.py b/app/api/endpoints/system.py index e8a146101..4f07a9656 100644 --- a/app/api/endpoints/system.py +++ b/app/api/endpoints/system.py @@ -1118,22 +1118,7 @@ async def get_message( return StreamingResponse(event_generator(), media_type="text/event-stream") -@router.get( - "/logging", - summary="实时日志", - response_model=None, - response_class=StreamingResponse, - responses={ - 200: { - "description": "实时日志流或完整日志文本", - "content": { - "text/event-stream": {"schema": {"type": "string"}}, - "text/plain": {"schema": {"type": "string"}}, - }, - } - }, -) -async def get_logging( +async def _get_logging_impl( request: Request, length: Optional[int] = 50, logfile: Optional[str] = "moviepilot.log", @@ -1246,6 +1231,23 @@ async def get_logging( return StreamingResponse(log_generator(), media_type="text/event-stream") +@router.get( + "/logging", + summary="实时日志", + response_model=None, + response_class=StreamingResponse, + responses={200: {"description": "实时日志流或完整日志文本", "content": {"text/event-stream": {"schema": {"type": "string"}}, "text/plain": {"schema": {"type": "string"}}}}}, +) +async def get_logging( + request: Request, + length: Optional[int] = 50, + logfile: Optional[str] = "moviepilot.log", + _: _SchemaTokenPayload = Depends(_verify_log_resource_superuser), +): + """实时日志的兼容公开入口。""" + return await _get_logging_impl(request, length, logfile, _) + + @router.get( "/logging/download/{name}", summary="下载日志", diff --git a/app/application/messaging/site.py b/app/application/messaging/site.py index 052876a39..bed236d8e 100644 --- a/app/application/messaging/site.py +++ b/app/application/messaging/site.py @@ -179,6 +179,17 @@ class SiteInteractionHandler: userid: Union[str, int], username: str, text: str, + ) -> bool: + """处理 /sites 文本交互并保持消息链公开 ABI。""" + return self._handle_text_interaction(channel, source, userid, username, text) + + def _handle_text_interaction( + self, + channel: NotificationChannel, + source: str, + userid: Union[str, int], + username: str, + text: str, ) -> bool: """ 处理 /sites 文本补充输入。 diff --git a/app/application/messaging/skill.py b/app/application/messaging/skill.py index 273459c76..96dfc5822 100644 --- a/app/application/messaging/skill.py +++ b/app/application/messaging/skill.py @@ -267,6 +267,27 @@ class SkillInteractionHandler: username: str, original_message_id: Optional[Union[str, int]] = None, original_chat_id: Optional[str] = None, + ) -> bool: + """处理 /skills 回调并保持消息链公开 ABI。""" + return self._handle_callback_interaction( + callback_data, + channel, + source, + userid, + username, + original_message_id, + original_chat_id, + ) + + def _handle_callback_interaction( + self, + callback_data: str, + channel: NotificationChannel, + source: str, + userid: Union[str, int], + username: str, + original_message_id: Optional[Union[str, int]] = None, + original_chat_id: Optional[str] = None, ) -> bool: """ 处理按钮交互,并在同一条消息上刷新当前视图。 @@ -424,6 +445,17 @@ class SkillInteractionHandler: userid: Union[str, int], username: str, text: str, + ) -> bool: + """处理 /skills 文本交互并保持消息链公开 ABI。""" + return self._handle_text_interaction(channel, source, userid, username, text) + + def _handle_text_interaction( + self, + channel: NotificationChannel, + source: str, + userid: Union[str, int], + username: str, + text: str, ) -> bool: """ 处理不支持按钮渠道上的文本指令,也兼容用户直接回复文字操作。 diff --git a/app/application/messaging/subscribe.py b/app/application/messaging/subscribe.py index 6f2711265..f06222fc5 100644 --- a/app/application/messaging/subscribe.py +++ b/app/application/messaging/subscribe.py @@ -203,6 +203,17 @@ class SubscribeInteractionHandler: userid: Union[str, int], username: str, text: str, + ) -> bool: + """处理 /subscribes 文本交互并保持消息链公开 ABI。""" + return self._handle_text_interaction(channel, source, userid, username, text) + + def _handle_text_interaction( + self, + channel: NotificationChannel, + source: str, + userid: Union[str, int], + username: str, + text: str, ) -> bool: """ 处理 /subscribes 文本补充输入。 diff --git a/tests/fixtures/architecture/complexity-baseline.json b/tests/fixtures/architecture/complexity-baseline.json index aeb9c1e56..a137f3e08 100644 --- a/tests/fixtures/architecture/complexity-baseline.json +++ b/tests/fixtures/architecture/complexity-baseline.json @@ -1,16 +1,5 @@ { - "api_endpoint": { - "app/api/endpoints/agent.py:web_agent_stream": 346, - "app/api/endpoints/media.py:scrape": 105, - "app/api/endpoints/openai.py:chat_completions": 95, - "app/api/endpoints/openai.py:responses": 93, - "app/api/endpoints/system.py:get_logging": 111 - }, - "application_public": { - "app/application/messaging/site.py:SiteInteractionHandler.handle_text_interaction": 227, - "app/application/messaging/skill.py:SkillInteractionHandler.handle_callback_interaction": 158, - "app/application/messaging/skill.py:SkillInteractionHandler.handle_text_interaction": 296, - "app/application/messaging/subscribe.py:SubscribeInteractionHandler.handle_text_interaction": 205 - }, + "api_endpoint": {}, + "application_public": {}, "chain_public": {} }