ai-agent-book 精选快照(<2MB 代码与文档,来自 github.com/bojieli/ai-agent-book)
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

This commit is contained in:
2026-08-20 13:12:50 +00:00
commit b119135836
10275 changed files with 3284984 additions and 0 deletions
@@ -0,0 +1,14 @@
# coding: utf-8
# Copyright (c) 2025 inclusionAI.
from aworld.tools.human.human import HumanTool
from aworld.tools.human.human_handler import DefaultHumanHandler
from aworld.tools.human.actions import ExecuteAction
from aworld.tools.tool_action import HumanExecuteAction
__all__ = [
"HumanTool",
"DefaultHumanHandler",
"ExecuteAction",
"HumanExecuteAction"
]
@@ -0,0 +1,13 @@
# coding: utf-8
# Copyright (c) 2025 inclusionAI.
from aworld.core.tool.action_factory import ActionFactory
from aworld.core.tool.action import ExecutableAction
from aworld.tools.tool_action import HumanExecuteAction
@ActionFactory.register(name=HumanExecuteAction.HUMAN_CONFIRM.value.name,
desc=HumanExecuteAction.HUMAN_CONFIRM.value.desc,
tool_name="human_confirm")
class ExecuteAction(ExecutableAction):
"""Only one action, define it, implemented can be omitted. Act in tool."""
@@ -0,0 +1,136 @@
# coding: utf-8
# Copyright (c) 2025 inclusionAI.
import traceback
from typing import Any, Dict, Tuple
from aworld.config import ToolConfig
from aworld.core.common import Observation, ActionModel, ActionResult
from aworld.core.event.base import Constants, TopicType, HumanMessage, Message
from aworld.core.tool.base import ToolFactory, AsyncTool
from aworld.events.util import send_message
from aworld.logs.util import logger
from aworld.tools.human.actions import HumanExecuteAction
from aworld.tools.utils import build_observation
HUMAN = "human"
@ToolFactory.register(name=HUMAN,
desc=HUMAN,
supported_action=HumanExecuteAction)
class HumanTool(AsyncTool):
def __init__(self, conf: ToolConfig, **kwargs) -> None:
"""Init document tool."""
super(HumanTool, self).__init__(conf, **kwargs)
self.cur_observation = None
self.content = None
self.keyframes = []
self.init()
self.step_finished = True
async def reset(self, *, seed: int | None = None, options: Dict[str, str] | None = None) -> Tuple[
Observation, dict[str, Any]]:
await super().reset(seed=seed, options=options)
await self.close()
self.step_finished = True
return build_observation(observer=self.name(),
ability=HumanExecuteAction.HUMAN_CONFIRM.value.name), {}
def init(self) -> None:
self.initialized = True
async def close(self) -> None:
pass
async def finished(self) -> bool:
return self.step_finished
async def do_step(self, actions: list[ActionModel], **kwargs) -> Tuple[
Observation, float, bool, bool, Dict[str, Any]]:
self.step_finished = False
reward = 0.
fail_error = ""
observation = build_observation(observer=self.name(),
ability=HumanExecuteAction.HUMAN_CONFIRM.value.name)
info = {}
try:
if not actions:
raise ValueError("actions is empty")
action = actions[0]
confirm_content = action.params.get("confirm_content", "")
if not confirm_content:
raise ValueError("content invalid")
# send human message to read human input
message, error = await self.send_human_message(confirm_content=confirm_content)
if error:
raise ValueError(f"HumanTool|send human message failed: {error}")
# hanging on human message
logger.info(f"HumanTool|waiting for human input")
result = await self.long_wait_message_state(message=message)
logger.info(f"HumanTool|human input succeed: {message.payload}")
observation.content = result
observation.action_result.append(
ActionResult(is_done=True,
success=False if error else True,
content=f"{result}",
error=f"{error}",
keep=False))
reward = 1.
except Exception as e:
fail_error = str(e)
logger.warn(f"HumanTool|failed do_step: {traceback.format_exc()}")
finally:
self.step_finished = True
info["exception"] = fail_error
info.update(kwargs)
return (observation, reward, kwargs.get("terminated", False),
kwargs.get("truncated", False), info)
async def long_wait_message_state(self, message: Message):
from aworld.runners.state_manager import HandleResult, RunNodeBusiType
from aworld.runners.state_manager import RuntimeStateManager, RunNodeStatus
state_mng = RuntimeStateManager.instance()
msg_id = message.id
# init node
state_mng.create_node(
node_id=msg_id,
busi_type=RunNodeBusiType.from_message_category(Constants.HUMAN),
busi_id=message.receiver or "",
session_id=message.session_id,
task_id=message.task_id,
msg_id=msg_id,
msg_from=message.sender)
# wait for message node completion
res_node = await state_mng.wait_for_node_completion(node_id=msg_id)
if res_node.status == RunNodeStatus.SUCCESS or res_node.results:
# get result and status from node
handle_result: HandleResult = res_node.results[0]
logger.info(f"HumanTool|human input origin result: {res_node.results}")
return handle_result.result.payload
else:
logger.debug(f"HumanTool|tool {self.name()} callback failed with node: {res_node}.")
raise ValueError(f"HumanTool|send human message failed: {res_node}")
async def send_human_message(self, confirm_content):
error = None
try:
message = HumanMessage(
category=Constants.HUMAN,
payload=confirm_content,
sender=self.name(),
session_id=self.context.session_id,
topic=TopicType.HUMAN_CONFIRM,
headers={"context": self.context}
)
await send_message(message)
return message, error
except Exception as e:
error = str(e)
logger.warning(f"HumanTool|human_confirm error: {str(e)} {traceback.format_exc()}")
return None, error
finally:
pass
@@ -0,0 +1,76 @@
# coding: utf-8
# Copyright (c) 2025 inclusionAI.
import abc
from typing import AsyncGenerator
from aworld.core.agent.base import AgentFactory
from aworld.core.event.base import Message, Constants
from aworld.runners import HandlerFactory
from aworld.runners.handler import DefaultHandler
from aworld.runners.state_manager import RuntimeStateManager, HandleResult, RunNodeStatus
@HandlerFactory.register(name=f'__{Constants.HUMAN}__')
class DefaultHumanHandler(DefaultHandler):
__metaclass__ = abc.ABCMeta
def __init__(self, runner: 'TaskEventRunner'):
super().__init__(runner)
self.runner = runner
self.swarm = runner.swarm
self.endless_threshold = runner.endless_threshold
self.task_id = runner.task.id
self.agent_calls = []
def is_valid_message(self, message: Message):
if message.category != Constants.HUMAN:
if self.swarm and message.sender in self.swarm.agents and message.sender in AgentFactory:
if self.agent_calls:
if self.agent_calls[-1] != message.sender:
self.agent_calls.append(message.sender)
else:
self.agent_calls.append(message.sender)
return False
return True
async def handle_user_input(self, data):
# rewrite this method to handle user input
return input(f"Human Confirm Info: {data}\nPlease Input:")
async def _do_handle(self, message: Message) -> AsyncGenerator[Message, None]:
if not self.is_valid_message(message):
return
headers = {"context": message.context}
session_id = message.session_id
human_input = await self.handle_user_input(message)
yield Message(
category=Constants.HUMAN_RESPONSE,
sender=self.name(),
receiver=message.sender,
session_id=session_id,
payload=human_input,
headers=headers,
)
return
async def post_handle(self, input:Message, output: Message) -> Message:
if not self.is_valid_message(input):
return output
if output.category is not Constants.HUMAN_RESPONSE:
return output
# update handle_result to state manager
results = [HandleResult(
name = output.category,
status = RunNodeStatus.SUCCESS,
result = output
)]
state_mng = RuntimeStateManager.instance()
state_mng.run_succeed(node_id=input.id,
result_msg="run DefaultHumanHandler succeed",
results=results)
return output