From 69aaf09ac86c879ddb8250f17c2194e69c6c29bd Mon Sep 17 00:00:00 2001 From: Soulter <905617992@qq.com> Date: Sun, 24 Aug 2025 00:23:08 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E4=BF=AE=E5=A4=8D=E5=BD=93=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E6=9B=B4=E6=96=B0=20webchat=20title=20=E6=97=B6?= =?UTF-8?q?=EF=BC=8Chistory=20=E8=A2=AB=E9=87=8D=E7=BD=AE=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- astrbot/api/__init__.py | 16 +++++++++++++++- astrbot/core/agent/tool.py | 14 +++++++------- astrbot/core/conversation_mgr.py | 2 +- .../pipeline/process_stage/method/llm_request.py | 8 +++++++- astrbot/core/star/__init__.py | 2 +- 5 files changed, 31 insertions(+), 11 deletions(-) diff --git a/astrbot/api/__init__.py b/astrbot/api/__init__.py index 9fd62222f..7b84f5156 100644 --- a/astrbot/api/__init__.py +++ b/astrbot/api/__init__.py @@ -4,5 +4,19 @@ from astrbot.core import html_renderer from astrbot.core import sp from astrbot.core.star.register import register_llm_tool as llm_tool from astrbot.core.star.register import register_agent as agent +from astrbot.core.agent.tool import ToolSet, FunctionTool +from astrbot.core.agent.tool_executor import BaseFunctionToolExecutor +from astrbot.core.pipeline.process_stage.method.llm_request import FunctionToolExecutor -__all__ = ["AstrBotConfig", "logger", "html_renderer", "llm_tool", "agent", "sp"] +__all__ = [ + "AstrBotConfig", + "logger", + "html_renderer", + "llm_tool", + "agent", + "sp", + "ToolSet", + "FunctionTool", + "FunctionToolExecutor", + "BaseFunctionToolExecutor", +] diff --git a/astrbot/core/agent/tool.py b/astrbot/core/agent/tool.py index 7dfd99b02..743deae1f 100644 --- a/astrbot/core/agent/tool.py +++ b/astrbot/core/agent/tool.py @@ -8,12 +8,12 @@ from .mcp_client import MCPClient class FunctionTool: """A class representing a function tool that can be used in function calling.""" - name: str - parameters: dict - description: str - handler: Awaitable = None + name: str | None = None + parameters: dict | None = None + description: str | None = None + handler: Awaitable | None = None """处理函数, 当 origin 为 mcp 时,这个为空""" - handler_module_path: str = None + handler_module_path: str | None = None """处理函数的模块路径,当 origin 为 mcp 时,这个为空 必须要保留这个字段, handler 在初始化会被 functools.partial 包装,导致 handler 的 __module__ 为 functools @@ -25,9 +25,9 @@ class FunctionTool: """函数工具的来源, local 为本地函数工具, mcp 为 MCP 服务""" # MCP 相关字段 - mcp_server_name: str = None + mcp_server_name: str | None = None """MCP 服务名称,当 origin 为 mcp 时有效""" - mcp_client: MCPClient = None + mcp_client: MCPClient | None = None """MCP 客户端,当 origin 为 mcp 时有效""" def __repr__(self): diff --git a/astrbot/core/conversation_mgr.py b/astrbot/core/conversation_mgr.py index 1e04e4b30..76112fa60 100644 --- a/astrbot/core/conversation_mgr.py +++ b/astrbot/core/conversation_mgr.py @@ -211,7 +211,7 @@ class ConversationManager: cid=conversation_id, title=title, persona_id=persona_id, - content=history or [], + content=history, ) async def update_conversation_title( diff --git a/astrbot/core/pipeline/process_stage/method/llm_request.py b/astrbot/core/pipeline/process_stage/method/llm_request.py index f3e7cd2df..c07ba0d70 100644 --- a/astrbot/core/pipeline/process_stage/method/llm_request.py +++ b/astrbot/core/pipeline/process_stage/method/llm_request.py @@ -164,9 +164,15 @@ class FunctionToolExecutor(BaseFunctionToolExecutor[AstrAgentContext]): ): if not run_context.event: raise ValueError("Event must be provided for local function tools.") + + # 检查 tool 下有没有 run 方法 + if not tool.handler and not hasattr(tool, "run"): + raise ValueError("Tool must have a valid handler or 'run' method.") + awaitable = tool.handler or getattr(tool, "run") + wrapper = call_handler( event=run_context.event, - handler=tool.handler, + handler=awaitable, **tool_args, ) async for resp in wrapper: diff --git a/astrbot/core/star/__init__.py b/astrbot/core/star/__init__.py index 86318f8b7..fab39294b 100644 --- a/astrbot/core/star/__init__.py +++ b/astrbot/core/star/__init__.py @@ -34,7 +34,7 @@ class Star(CommandParserMixin): @staticmethod async def html_render( - tmpl: str, data: dict, return_url=True, options: dict = None + tmpl: str, data: dict, return_url=True, options: dict | None = None ) -> str: """渲染 HTML""" return await html_renderer.render_custom_template(