Files
liqiang b119135836
Build latest book artifacts / build (push) Canceled after 0s
dependency resolution / resolve (3.11) (push) Canceled after 0s
dependency resolution / resolve (3.13) (push) Canceled after 0s
deploy-pages / build (push) Canceled after 0s
deploy-pages / deploy (push) Canceled after 0s
i18n consistency check / check (push) Canceled after 0s
provider adoption tests / test (chapter2/context-compression) (push) Canceled after 0s
provider adoption tests / test (chapter2/prompt-injection) (push) Canceled after 0s
provider adoption tests / test (chapter2/system-hint) (push) Canceled after 0s
provider adoption tests / test (chapter3/log-sanitization) (push) Canceled after 0s
web-search-agent tests / test (push) Canceled after 0s
web-search-agent tests / agentbook (push) Canceled after 0s
ai-agent-book 精选快照(<2MB 代码与文档,来自 github.com/bojieli/ai-agent-book)
2026-08-20 13:12:50 +00:00

124 lines
4.4 KiB
Python

# coding: utf-8
# Copyright (c) 2025 inclusionAI.
import abc
from typing import AsyncGenerator
from aworld.config import ConfigDict
from aworld.core.agent.base import is_agent
from aworld.core.common import ActionModel, TaskItem
from aworld.core.event.base import Message, Constants, TopicType
from aworld.core.tool.base import AsyncTool, Tool, ToolFactory
from aworld.logs.util import logger
from aworld.runners import HandlerFactory
from aworld.runners.handler.base import DefaultHandler
class ToolHandler(DefaultHandler):
__metaclass__ = abc.ABCMeta
def __init__(self, runner: 'TaskEventRunner'):
super().__init__(runner)
self.tools = runner.tools
self.tools_conf = runner.tools_conf
@classmethod
def name(cls):
return "_tool_handler"
@HandlerFactory.register(name=f'__{Constants.TOOL}__')
class DefaultToolHandler(ToolHandler):
def is_valid_message(self, message: Message):
if message.category != Constants.TOOL:
return False
return True
async def _do_handle(self, message: Message) -> AsyncGenerator[Message, None]:
if not self.is_valid_message(message):
return
headers = {"context": message.context}
# data is List[ActionModel]
data = message.payload
if not data:
# error message, p2p
yield Message(
category=Constants.TASK,
payload=TaskItem(msg="no data to process.", data=data, stop=True),
sender='agent_handler',
session_id=message.session_id,
topic=TopicType.ERROR,
headers=headers
)
return
for action in data:
if not isinstance(action, ActionModel):
# error message, p2p
yield Message(
category=Constants.TASK,
payload=TaskItem(msg="action not a ActionModel.", data=data, stop=True),
sender=self.name(),
session_id=message.session_id,
topic=TopicType.ERROR,
headers=headers
)
return
new_tools = dict()
tool_mapping = dict()
# Directly use or use tools after creation.
for act in data:
if is_agent(act):
logger.warning(f"somethings wrong, {act} is an agent.")
continue
if not self.tools or (self.tools and act.tool_name not in self.tools):
# dynamic only use default config in module.
conf = self.tools_conf.get(act.tool_name)
if isinstance(conf, dict):
conf = ConfigDict(conf)
tool = ToolFactory(act.tool_name, conf=conf, asyn=conf.use_async if conf else False)
tool.event_driven = True
if isinstance(tool, Tool):
tool.reset()
elif isinstance(tool, AsyncTool):
await tool.reset()
tool_mapping[act.tool_name] = []
self.tools[act.tool_name] = tool
new_tools[act.tool_name] = tool
if act.tool_name not in tool_mapping:
tool_mapping[act.tool_name] = []
tool_mapping[act.tool_name].append(act)
if new_tools:
yield Message(
category=Constants.TASK,
payload=TaskItem(data=new_tools),
sender=self.name(),
session_id=message.session_id,
topic=TopicType.SUBSCRIBE_TOOL,
headers=headers
)
for tool_name, actions in tool_mapping.items():
if not (isinstance(self.tools[tool_name], Tool) or isinstance(self.tools[tool_name], AsyncTool)):
logger.warning(f"Unsupported tool type: {self.tools[tool_name]}")
continue
# send to the tool
yield Message(
category=Constants.TOOL,
payload=actions,
sender=actions[0].agent_name if actions else '',
session_id=message.session_id,
receiver=tool_name,
headers=message.headers
)
async def post_handle(self, input:Message, output: Message) -> Message:
new_context = output.context.deep_copy()
new_context._task = output.context.get_task()
output.context = new_context
return output