| 1 | import sys |
| 2 | from pathlib import Path |
| 3 | |
| 4 | import pytest |
| 5 | |
| 6 | |
| 7 | PROJECT_ROOT = Path(__file__).resolve().parents[1] |
| 8 | if str(PROJECT_ROOT) not in sys.path: |
| 9 | sys.path.insert(0, str(PROJECT_ROOT)) |
| 10 | |
| 11 | from helpers.errors import RepairableException |
| 12 | from tools.response import ResponseTool |
| 13 | |
| 14 | |
| 15 | @pytest.mark.asyncio |
| 16 | @pytest.mark.parametrize("args", [{"text": "ok"}, {"message": "ok"}]) |
| 17 | async def test_response_tool_accepts_text_or_message(args) -> None: |
| 18 | tool = ResponseTool(None, "response", None, args, "", None) |
| 19 | |
| 20 | response = await tool.execute() |
| 21 | |
| 22 | assert response.message == "ok" |
| 23 | assert response.break_loop is True |
| 24 | |
| 25 | |
| 26 | @pytest.mark.asyncio |
| 27 | async def test_response_tool_uses_non_empty_legacy_message_fallback() -> None: |
| 28 | tool = ResponseTool( |
| 29 | None, |
| 30 | "response", |
| 31 | None, |
| 32 | {"text": "", "message": "legacy"}, |
| 33 | "", |
| 34 | None, |
| 35 | ) |
| 36 | |
| 37 | response = await tool.execute() |
| 38 | |
| 39 | assert response.message == "legacy" |
| 40 | assert response.break_loop is True |
| 41 | |
| 42 | |
| 43 | @pytest.mark.asyncio |
| 44 | @pytest.mark.parametrize( |
| 45 | "args", |
| 46 | [ |
| 47 | {}, |
| 48 | {"text": ""}, |
| 49 | {"text": " "}, |
| 50 | {"text": None}, |
| 51 | {"message": "\n\t"}, |
| 52 | ], |
| 53 | ) |
| 54 | async def test_response_tool_rejects_empty_arguments(args) -> None: |
| 55 | tool = ResponseTool(None, "response", None, args, "", None) |
| 56 | |
| 57 | with pytest.raises(RepairableException, match="non-empty top-level"): |
| 58 | await tool.execute() |
| 59 | |
| 60 | |
| 61 | @pytest.mark.asyncio |
| 62 | async def test_response_tool_rejects_nested_response_args() -> None: |
| 63 | tool = ResponseTool( |
| 64 | None, |
| 65 | "response", |
| 66 | None, |
| 67 | { |
| 68 | "thoughts": [], |
| 69 | "headline": "Providing exact payload", |
| 70 | "tool_name": "response", |
| 71 | "tool_args": {"text": "nested"}, |
| 72 | }, |
| 73 | "", |
| 74 | None, |
| 75 | ) |
| 76 | |
| 77 | with pytest.raises(RepairableException, match="non-empty top-level"): |
| 78 | await tool.execute() |