feat(agent): support inline subagent consultation
This commit is contained in:
@@ -19,6 +19,37 @@ def _runtime(provider: MagicMock, model: str = "test-model") -> LLMRuntime:
|
||||
return LLMRuntime.capture(provider, model, context_window_tokens=128_000)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_run_inline_returns_result_without_announcement(tmp_path):
|
||||
"""Inline subagents return directly instead of injecting a follow-up."""
|
||||
from nanobot.agent.subagent import SubagentManager
|
||||
from nanobot.bus.queue import MessageBus
|
||||
|
||||
provider = MagicMock()
|
||||
manager = SubagentManager(
|
||||
workspace=tmp_path,
|
||||
bus=MessageBus(),
|
||||
max_tool_result_chars=_MAX_TOOL_RESULT_CHARS,
|
||||
)
|
||||
manager.runner.run = AsyncMock(return_value=SimpleNamespace(
|
||||
stop_reason="done",
|
||||
final_content="review result",
|
||||
error=None,
|
||||
tool_events=[],
|
||||
))
|
||||
manager._announce_result = AsyncMock()
|
||||
|
||||
result = await manager.run_inline(
|
||||
task="review this",
|
||||
session_key="test:c1",
|
||||
runtime=_runtime(provider),
|
||||
)
|
||||
|
||||
assert result == "review result"
|
||||
manager._announce_result.assert_not_awaited()
|
||||
assert manager._task_statuses == {}
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_subagent_exec_tool_receives_allowed_env_keys(tmp_path):
|
||||
"""allowed_env_keys from ExecToolConfig must be forwarded to the subagent's ExecTool."""
|
||||
@@ -200,6 +231,40 @@ async def test_spawn_tool_rejects_when_at_concurrency_limit(tmp_path):
|
||||
await asyncio.gather(*mgr._running_tasks.values(), return_exceptions=True)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_spawn_tool_waits_for_inline_result():
|
||||
from nanobot.agent.tools.context import RequestContext, request_context
|
||||
from nanobot.agent.tools.spawn import SpawnTool
|
||||
|
||||
class Manager:
|
||||
max_concurrent_subagents = 1
|
||||
|
||||
def __init__(self):
|
||||
self.inline = AsyncMock(return_value="review result")
|
||||
self.spawn = AsyncMock(return_value="started")
|
||||
|
||||
def get_running_count(self):
|
||||
return 0
|
||||
|
||||
async def run_inline(self, **kwargs):
|
||||
return await self.inline(**kwargs)
|
||||
|
||||
manager = Manager()
|
||||
tool = SpawnTool(manager)
|
||||
runtime = _runtime(MagicMock())
|
||||
with request_context(RequestContext(
|
||||
channel="test",
|
||||
chat_id="c1",
|
||||
session_key="test:c1",
|
||||
runtime=runtime,
|
||||
)):
|
||||
result = await tool.execute(task="review this", wait=True)
|
||||
|
||||
assert result == "review result"
|
||||
manager.inline.assert_awaited_once()
|
||||
manager.spawn.assert_not_awaited()
|
||||
|
||||
|
||||
def test_subagent_default_max_concurrent_matches_agent_defaults(tmp_path):
|
||||
"""Direct SubagentManager construction should use the agent default concurrency limit."""
|
||||
from nanobot.agent.subagent import SubagentManager
|
||||
|
||||
Reference in New Issue
Block a user