refactor(agent): add turn hook factories

This commit is contained in:
chengyongru
2026-07-08 21:02:12 +08:00
committed by Xubin Ren
parent 04dbf17426
commit 8559458258
7 changed files with 248 additions and 32 deletions
+60 -2
View File
@@ -1,6 +1,6 @@
import pytest
from nanobot.agent.hook import AgentHook, AgentHookContext
from nanobot.agent.hook import AgentHook, AgentHookContext, AgentTurnHookContext
from nanobot.agent.turn_hooks import AgentTurnHookSpec, build_agent_turn_hook
@@ -44,10 +44,67 @@ async def test_turn_hook_builder_runs_registered_hooks_before_turn_hooks() -> No
@pytest.mark.asyncio
async def test_turn_hook_builder_skips_extra_hooks_for_ephemeral_turns_by_default() -> None:
async def test_turn_hook_builder_runs_factories_with_matching_registration_order(
tmp_path,
) -> None:
events: list[str] = []
captured: list[AgentTurnHookContext] = []
def factory(label: str):
def _create(context: AgentTurnHookContext) -> AgentHook:
captured.append(context)
return RecordingHook(events, label)
return _create
hook = build_agent_turn_hook(AgentTurnHookSpec(
on_iteration=lambda iteration: events.append(f"progress:{iteration}"),
channel="websocket",
chat_id="chat-1",
message_id="msg-1",
session_key="websocket:chat-1",
workspace=tmp_path,
metadata={"source": "test"},
registered_hook_factories=[factory("registered_factory")],
registered_hooks=[RecordingHook(events, "registered")],
turn_hook_factories=[factory("turn_factory")],
turn_hooks=[RecordingHook(events, "turn")],
))
await hook.before_iteration(AgentHookContext(iteration=2, messages=[]))
assert events == [
"progress:2",
"registered_factory:2",
"registered:2",
"turn_factory:2",
"turn:2",
]
assert [context.workspace for context in captured] == [tmp_path, tmp_path]
assert [context.channel for context in captured] == ["websocket", "websocket"]
assert [context.chat_id for context in captured] == ["chat-1", "chat-1"]
assert [context.message_id for context in captured] == ["msg-1", "msg-1"]
assert [context.session_key for context in captured] == [
"websocket:chat-1",
"websocket:chat-1",
]
assert [context.metadata for context in captured] == [
{"source": "test"},
{"source": "test"},
]
@pytest.mark.asyncio
async def test_turn_hook_builder_skips_extra_hooks_for_ephemeral_turns_by_default() -> None:
events: list[str] = []
factory_calls: list[str] = []
def factory(context: AgentTurnHookContext) -> AgentHook:
factory_calls.append(context.channel)
return RecordingHook(events, "factory")
hook = build_agent_turn_hook(AgentTurnHookSpec(
registered_hook_factories=[factory],
registered_hooks=[RecordingHook(events)],
ephemeral=True,
))
@@ -55,6 +112,7 @@ async def test_turn_hook_builder_skips_extra_hooks_for_ephemeral_turns_by_defaul
await hook.before_iteration(AgentHookContext(iteration=1, messages=[]))
assert events == []
assert factory_calls == []
@pytest.mark.asyncio