From 8e3628207d1fe8f9fa69c3c9555fd66a3e4caa5e Mon Sep 17 00:00:00 2001 From: Dt8333 Date: Mon, 17 Nov 2025 17:35:09 +0800 Subject: [PATCH] =?UTF-8?q?chore(core):=20=E4=BF=AE=E6=94=B9=E5=A3=B0?= =?UTF-8?q?=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- astrbot/core/agent/tool.py | 9 ++++++-- astrbot/core/astr_agent_tool_exec.py | 6 +++++- astrbot/core/core_lifecycle.py | 2 ++ astrbot/core/pipeline/context_utils.py | 1 + .../core/pipeline/result_decorate/stage.py | 2 ++ astrbot/core/platform/manager.py | 2 ++ astrbot/core/provider/func_tool_manager.py | 6 +++--- astrbot/core/star/context.py | 4 ++-- astrbot/core/star/register/star_handler.py | 21 +++++++++++++++---- astrbot/core/star/star_handler.py | 4 ++-- astrbot/core/updator.py | 4 ++-- 11 files changed, 45 insertions(+), 16 deletions(-) diff --git a/astrbot/core/agent/tool.py b/astrbot/core/agent/tool.py index b60088609..7f30f44ef 100644 --- a/astrbot/core/agent/tool.py +++ b/astrbot/core/agent/tool.py @@ -1,4 +1,4 @@ -from collections.abc import Awaitable, Callable +from collections.abc import AsyncGenerator, Awaitable, Callable from typing import Any, Generic import jsonschema @@ -7,6 +7,8 @@ from deprecated import deprecated from pydantic import Field, model_validator from pydantic.dataclasses import dataclass +from astrbot.core.message.message_event_result import MessageEventResult + from .run_context import ContextWrapper, TContext ParametersType = dict[str, Any] @@ -38,7 +40,10 @@ class ToolSchema: class FunctionTool(ToolSchema, Generic[TContext]): """A callable tool, for function calling.""" - handler: Callable[..., Awaitable[Any]] | None = None + handler: ( + Callable[..., Awaitable[str | None] | AsyncGenerator[MessageEventResult, None]] + | None + ) = None """a callable that implements the tool's functionality. It should be an async function.""" handler_module_path: str | None = None diff --git a/astrbot/core/astr_agent_tool_exec.py b/astrbot/core/astr_agent_tool_exec.py index 440dea2d1..ed08e90a9 100644 --- a/astrbot/core/astr_agent_tool_exec.py +++ b/astrbot/core/astr_agent_tool_exec.py @@ -185,7 +185,11 @@ class FunctionToolExecutor(BaseFunctionToolExecutor[AstrAgentContext]): async def call_local_llm_tool( context: ContextWrapper[AstrAgentContext], - handler: T.Callable[..., T.Awaitable[T.Any]], + handler: T.Callable[ + ..., + T.Awaitable[MessageEventResult | mcp.types.CallToolResult | str | None] + | T.AsyncGenerator[MessageEventResult | CommandResult | str | None, None], + ], method_name: str, *args, **kwargs, diff --git a/astrbot/core/core_lifecycle.py b/astrbot/core/core_lifecycle.py index cd519eb77..5788d1e90 100644 --- a/astrbot/core/core_lifecycle.py +++ b/astrbot/core/core_lifecycle.py @@ -10,6 +10,7 @@ """ import asyncio +import inspect import os import threading import time @@ -233,6 +234,7 @@ class AstrBotCoreLifecycle: ) for handler in handlers: try: + assert inspect.iscoroutinefunction(handler.handler) logger.info( f"hook(on_astrbot_loaded) -> {star_map[handler.handler_module_path].name} - {handler.handler_name}", ) diff --git a/astrbot/core/pipeline/context_utils.py b/astrbot/core/pipeline/context_utils.py index e5b1b52ef..1f5ba43a0 100644 --- a/astrbot/core/pipeline/context_utils.py +++ b/astrbot/core/pipeline/context_utils.py @@ -91,6 +91,7 @@ async def call_event_hook( ) for handler in handlers: try: + assert inspect.iscoroutinefunction(handler.handler) logger.debug( f"hook({hook_type.name}) -> {star_map[handler.handler_module_path].name} - {handler.handler_name}", ) diff --git a/astrbot/core/pipeline/result_decorate/stage.py b/astrbot/core/pipeline/result_decorate/stage.py index 73abaee67..3b65f3448 100644 --- a/astrbot/core/pipeline/result_decorate/stage.py +++ b/astrbot/core/pipeline/result_decorate/stage.py @@ -1,3 +1,4 @@ +import inspect import re import time import traceback @@ -110,6 +111,7 @@ class ResultDecorateStage(Stage): ) for handler in handlers: try: + assert inspect.iscoroutinefunction(handler.handler) logger.debug( f"hook(on_decorating_result) -> {star_map[handler.handler_module_path].name} - {handler.handler_name}", ) diff --git a/astrbot/core/platform/manager.py b/astrbot/core/platform/manager.py index 9ff892025..ac222aed4 100644 --- a/astrbot/core/platform/manager.py +++ b/astrbot/core/platform/manager.py @@ -1,4 +1,5 @@ import asyncio +import inspect import traceback from asyncio import Queue @@ -138,6 +139,7 @@ class PlatformManager: ) for handler in handlers: try: + assert inspect.iscoroutinefunction(handler.handler) logger.info( f"hook(on_platform_loaded) -> {star_map[handler.handler_module_path].name} - {handler.handler_name}", ) diff --git a/astrbot/core/provider/func_tool_manager.py b/astrbot/core/provider/func_tool_manager.py index 7cdbeec01..ac25b6daf 100644 --- a/astrbot/core/provider/func_tool_manager.py +++ b/astrbot/core/provider/func_tool_manager.py @@ -4,7 +4,7 @@ import asyncio import copy import json import os -from collections.abc import Awaitable, Callable +from collections.abc import AsyncGenerator, Awaitable, Callable from typing import Any import aiohttp @@ -118,7 +118,7 @@ class FunctionToolManager: name: str, func_args: list[dict], desc: str, - handler: Callable[..., Awaitable[Any]], + handler: Callable[..., Awaitable[Any] | AsyncGenerator[Any]], ) -> FuncTool: params = { "type": "object", # hard-coded here @@ -140,7 +140,7 @@ class FunctionToolManager: name: str, func_args: list, desc: str, - handler: Callable[..., Awaitable[Any]], + handler: Callable[..., Awaitable[Any] | AsyncGenerator[Any]], ) -> None: """添加函数调用工具 diff --git a/astrbot/core/star/context.py b/astrbot/core/star/context.py index 21c1ad8fd..9a52ec8bc 100644 --- a/astrbot/core/star/context.py +++ b/astrbot/core/star/context.py @@ -285,7 +285,7 @@ class Context: """获取所有用于 Embedding 任务的 Provider。""" return self.provider_manager.embedding_provider_insts - def get_using_provider(self, umo: str | None = None) -> Provider | None: + def get_using_provider(self, umo: str | None = None) -> Provider: """获取当前使用的用于文本生成任务的 LLM Provider(Chat_Completion 类型)。通过 /provider 指令切换。 Args: @@ -296,7 +296,7 @@ class Context: provider_type=ProviderType.CHAT_COMPLETION, umo=umo, ) - if prov and not isinstance(prov, Provider): + if not isinstance(prov, Provider): raise ValueError("返回的 Provider 不是 Provider 类型") return prov diff --git a/astrbot/core/star/register/star_handler.py b/astrbot/core/star/register/star_handler.py index 5ab728e1a..daf36a8f6 100644 --- a/astrbot/core/star/register/star_handler.py +++ b/astrbot/core/star/register/star_handler.py @@ -1,7 +1,7 @@ from __future__ import annotations import re -from collections.abc import Awaitable, Callable +from collections.abc import AsyncGenerator, Awaitable, Callable from typing import Any import docstring_parser @@ -12,6 +12,7 @@ from astrbot.core.agent.handoff import HandoffTool from astrbot.core.agent.hooks import BaseAgentRunHooks from astrbot.core.agent.tool import FunctionTool from astrbot.core.astr_agent_context import AstrAgentContext +from astrbot.core.message.message_event_result import MessageEventResult from astrbot.core.provider.func_tool_manager import PY_TO_JSON_TYPE, SUPPORTED_TYPES from astrbot.core.provider.register import llm_tools @@ -28,13 +29,19 @@ from ..filter.regex import RegexFilter from ..star_handler import EventType, StarHandlerMetadata, star_handlers_registry -def get_handler_full_name(awaitable: Callable[..., Awaitable[Any]]) -> str: +def get_handler_full_name( + awaitable: Callable[..., Awaitable[Any] | AsyncGenerator[Any]], +) -> str: """获取 Handler 的全名""" return f"{awaitable.__module__}_{awaitable.__name__}" def get_handler_or_create( - handler: Callable[..., Awaitable[Any]], + handler: Callable[ + ..., + Awaitable[MessageEventResult | str | None] + | AsyncGenerator[MessageEventResult | str | None], + ], event_type: EventType, dont_add=False, **kwargs, @@ -416,7 +423,13 @@ def register_llm_tool(name: str | None = None, **kwargs): if kwargs.get("registering_agent"): registering_agent = kwargs["registering_agent"] - def decorator(awaitable: Callable[..., Awaitable[Any]]): + def decorator( + awaitable: Callable[ + ..., + AsyncGenerator[MessageEventResult | str | None] + | Awaitable[MessageEventResult | str | None], + ], + ): llm_tool_name = name_ if name_ else awaitable.__name__ func_doc = awaitable.__doc__ or "" docstring = docstring_parser.parse(func_doc) diff --git a/astrbot/core/star/star_handler.py b/astrbot/core/star/star_handler.py index 141f9180a..55f91dd48 100644 --- a/astrbot/core/star/star_handler.py +++ b/astrbot/core/star/star_handler.py @@ -1,7 +1,7 @@ from __future__ import annotations import enum -from collections.abc import Awaitable, Callable +from collections.abc import AsyncGenerator, Awaitable, Callable from dataclasses import dataclass, field from typing import Any, Generic, TypeVar @@ -127,7 +127,7 @@ class StarHandlerMetadata: handler_module_path: str """Handler 所在的模块路径。""" - handler: Callable[..., Awaitable[Any]] + handler: Callable[..., Awaitable[Any] | AsyncGenerator[Any]] """Handler 的函数对象,应当是一个异步函数""" event_filters: list[HandlerFilter] diff --git a/astrbot/core/updator.py b/astrbot/core/updator.py index 5c1c2e0a4..0a7116a0d 100644 --- a/astrbot/core/updator.py +++ b/astrbot/core/updator.py @@ -71,8 +71,8 @@ class AstrBotUpdator(RepoZipUpdator): async def check_update( self, - url: str, - current_version: str, + url: str | None, + current_version: str | None, consider_prerelease: bool = True, ) -> ReleaseInfo | None: """检查更新"""