"""Tests for AskHumanTool.""" import asyncio import pytest from agentkit.tools.ask_human import AskHumanTool class TestAskHumanToolBasic: def test_tool_properties(self): tool = AskHumanTool() assert tool.name == "ask_human" assert "question" in str(tool.parameters) assert tool.parameters["required"] == ["question"] @pytest.mark.asyncio async def test_no_chat_mode_returns_default(self): tool = AskHumanTool() result = await tool.execute(question="What should I do?") assert result == {"reply": "confirmed"} @pytest.mark.asyncio async def test_no_chat_mode_with_options(self): tool = AskHumanTool() result = await tool.execute(question="Choose:", options=["A", "B", "C"]) assert result == {"reply": "A"} class TestAskHumanToolChatMode: @pytest.mark.asyncio async def test_ask_and_receive_reply(self): tool = AskHumanTool(timeout=5.0) pending: dict[str, asyncio.Future] = {} ask_calls: list[tuple[str, str, list[str] | None]] = [] async def mock_ask_callback(request_id, question, options): ask_calls.append((request_id, question, options)) tool.configure(pending_replies=pending, ask_callback=mock_ask_callback) # Start the execute in a task task = asyncio.create_task( tool.execute(question="Continue?", options=["yes", "no"]) ) # Wait for the ask to be pushed await asyncio.sleep(0.1) assert len(ask_calls) == 1 request_id = ask_calls[0][0] assert ask_calls[0][1] == "Continue?" assert ask_calls[0][2] == ["yes", "no"] # Simulate user reply assert request_id in pending pending[request_id].set_result("yes") result = await task assert result == {"reply": "yes"} @pytest.mark.asyncio async def test_timeout_returns_default(self): tool = AskHumanTool(timeout=0.1) pending: dict[str, asyncio.Future] = {} async def mock_ask_callback(request_id, question, options): pass # Never reply tool.configure(pending_replies=pending, ask_callback=mock_ask_callback) result = await tool.execute(question="Continue?", options=["yes", "no"]) assert result == {"reply": "yes"} @pytest.mark.asyncio async def test_timeout_no_options(self): tool = AskHumanTool(timeout=0.1) pending: dict[str, asyncio.Future] = {} async def mock_ask_callback(request_id, question, options): pass tool.configure(pending_replies=pending, ask_callback=mock_ask_callback) result = await tool.execute(question="Continue?") assert "timeout" in result["reply"] @pytest.mark.asyncio async def test_cleanup_on_reply(self): tool = AskHumanTool(timeout=5.0) pending: dict[str, asyncio.Future] = {} async def mock_ask_callback(request_id, question, options): # Immediately reply await asyncio.sleep(0.05) pending[request_id].set_result("ok") tool.configure(pending_replies=pending, ask_callback=mock_ask_callback) await tool.execute(question="Test?") # Pending should be cleaned up assert len(pending) == 0