mirror of
https://github.com/AstrBotDevs/AstrBot
synced 2026-07-16 17:47:06 +08:00
146 lines
4.9 KiB
Python
146 lines
4.9 KiB
Python
from typing import Any
|
|
|
|
from mcp.types import CallToolResult
|
|
|
|
from astrbot.core.agent.hooks import BaseAgentRunHooks
|
|
from astrbot.core.agent.run_context import ContextWrapper
|
|
from astrbot.core.agent.tool import FunctionTool
|
|
from astrbot.core.astr_agent_context import AstrAgentContext
|
|
from astrbot.core.pipeline.context_utils import call_event_hook
|
|
from astrbot.core.star.star_handler import EventType
|
|
|
|
|
|
def _sdk_safe_payload(value: Any) -> Any:
|
|
if value is None or isinstance(value, (str, int, float, bool)):
|
|
return value
|
|
if isinstance(value, list):
|
|
return [_sdk_safe_payload(item) for item in value]
|
|
if isinstance(value, dict):
|
|
return {str(key): _sdk_safe_payload(item) for key, item in value.items()}
|
|
model_dump = getattr(value, "model_dump", None)
|
|
if callable(model_dump):
|
|
try:
|
|
dumped = model_dump()
|
|
except Exception:
|
|
return str(value)
|
|
return _sdk_safe_payload(dumped)
|
|
return str(value)
|
|
|
|
|
|
class MainAgentHooks(BaseAgentRunHooks[AstrAgentContext]):
|
|
async def on_agent_done(self, run_context, llm_response) -> None:
|
|
# 执行事件钩子
|
|
if llm_response and llm_response.reasoning_content:
|
|
# we will use this in result_decorate stage to inject reasoning content to chain
|
|
run_context.context.event.set_extra(
|
|
"_llm_reasoning_content",
|
|
llm_response.reasoning_content,
|
|
)
|
|
|
|
await call_event_hook(
|
|
run_context.context.event,
|
|
EventType.OnLLMResponseEvent,
|
|
llm_response,
|
|
)
|
|
sdk_plugin_bridge = getattr(
|
|
run_context.context.context,
|
|
"sdk_plugin_bridge",
|
|
None,
|
|
)
|
|
if sdk_plugin_bridge is not None:
|
|
try:
|
|
await sdk_plugin_bridge.dispatch_message_event(
|
|
"llm_response",
|
|
run_context.context.event,
|
|
{
|
|
"completion_text": (
|
|
llm_response.completion_text if llm_response else ""
|
|
),
|
|
"tool_call_names": (
|
|
list(llm_response.tools_call_name)
|
|
if llm_response and llm_response.tools_call_name
|
|
else []
|
|
),
|
|
},
|
|
llm_response=llm_response,
|
|
)
|
|
except Exception as exc:
|
|
from astrbot.core import logger
|
|
|
|
logger.warning("SDK llm_response dispatch failed: %s", exc)
|
|
|
|
async def on_tool_start(
|
|
self,
|
|
run_context: ContextWrapper[AstrAgentContext],
|
|
tool: FunctionTool[Any],
|
|
tool_args: dict | None,
|
|
) -> None:
|
|
await call_event_hook(
|
|
run_context.context.event,
|
|
EventType.OnUsingLLMToolEvent,
|
|
tool,
|
|
tool_args,
|
|
)
|
|
sdk_plugin_bridge = getattr(
|
|
run_context.context.context,
|
|
"sdk_plugin_bridge",
|
|
None,
|
|
)
|
|
if sdk_plugin_bridge is not None:
|
|
try:
|
|
await sdk_plugin_bridge.dispatch_message_event(
|
|
"using_llm_tool",
|
|
run_context.context.event,
|
|
{
|
|
"tool_name": tool.name,
|
|
"tool_args": _sdk_safe_payload(tool_args),
|
|
},
|
|
)
|
|
except Exception as exc:
|
|
from astrbot.core import logger
|
|
|
|
logger.warning("SDK using_llm_tool dispatch failed: %s", exc)
|
|
|
|
async def on_tool_end(
|
|
self,
|
|
run_context: ContextWrapper[AstrAgentContext],
|
|
tool: FunctionTool[Any],
|
|
tool_args: dict | None,
|
|
tool_result: CallToolResult | None,
|
|
) -> None:
|
|
run_context.context.event.clear_result()
|
|
await call_event_hook(
|
|
run_context.context.event,
|
|
EventType.OnLLMToolRespondEvent,
|
|
tool,
|
|
tool_args,
|
|
tool_result,
|
|
)
|
|
sdk_plugin_bridge = getattr(
|
|
run_context.context.context,
|
|
"sdk_plugin_bridge",
|
|
None,
|
|
)
|
|
if sdk_plugin_bridge is not None:
|
|
try:
|
|
await sdk_plugin_bridge.dispatch_message_event(
|
|
"llm_tool_respond",
|
|
run_context.context.event,
|
|
{
|
|
"tool_name": tool.name,
|
|
"tool_args": _sdk_safe_payload(tool_args),
|
|
"tool_result": _sdk_safe_payload(tool_result),
|
|
},
|
|
)
|
|
except Exception as exc:
|
|
from astrbot.core import logger
|
|
|
|
logger.warning("SDK llm_tool_respond dispatch failed: %s", exc)
|
|
|
|
|
|
class EmptyAgentHooks(BaseAgentRunHooks[AstrAgentContext]):
|
|
pass
|
|
|
|
|
|
MAIN_AGENT_HOOKS = MainAgentHooks()
|