diff options
Diffstat (limited to 'tests/test_memory_tools.py')
| -rw-r--r-- | tests/test_memory_tools.py | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/tests/test_memory_tools.py b/tests/test_memory_tools.py new file mode 100644 index 0000000..9e0fcb0 --- /dev/null +++ b/tests/test_memory_tools.py @@ -0,0 +1,169 @@ +from personal_agent.database.database import Database +from personal_agent.memory.models import MemoryCategory +from personal_agent.memory.store import LongTermMemoryStore +from personal_agent.tools.memory import ( + LongTermMemoryDeleteTool, + LongTermMemorySaveTool, + LongTermMemorySearchTool, + ToolError, +) + + +def create_store(tmp_path): + database = Database(tmp_path / "test.db") + database.migrate() + return LongTermMemoryStore(database) + + +def test_save_tool_persists_memory(tmp_path): + store = create_store(tmp_path) + tool = LongTermMemorySaveTool(store) + + result = tool.execute( + { + "content": "User prefers Rust for systems programming.", + "category": "semantic", + } + ) + + memories = store.list() + + assert len(memories) == 1 + assert memories[0].content == "User prefers Rust for systems programming." + assert memories[0].category is MemoryCategory.SEMANTIC + assert str(memories[0].id) in result.content + + +def test_save_tool_rejects_empty_content(tmp_path): + store = create_store(tmp_path) + tool = LongTermMemorySaveTool(store) + + try: + tool.execute({"content": " ", "category": "semantic"}) + except ToolError as error: + assert str(error) == "content must not be empty" + else: + raise AssertionError("Expected ToolError") + + +def test_save_tool_rejects_invalid_category(tmp_path): + store = create_store(tmp_path) + tool = LongTermMemorySaveTool(store) + + try: + tool.execute( + { + "content": "Something", + "category": "invalid", + } + ) + except ToolError as error: + assert str(error) == "category must be 'semantic' or 'episodic'" + else: + raise AssertionError("Expected ToolError") + + +def test_search_tool_returns_matching_memories(tmp_path): + store = create_store(tmp_path) + save_tool = LongTermMemorySaveTool(store) + search_tool = LongTermMemorySearchTool(store) + + save_tool.execute( + { + "content": "User prefers Rust for systems programming.", + "category": "semantic", + } + ) + save_tool.execute( + { + "content": "User visited Tokyo last year.", + "category": "episodic", + } + ) + + result = search_tool.execute({"query": "Rust"}) + + assert "User prefers Rust for systems programming." in result.content + assert "User visited Tokyo last year." not in result.content + + +def test_search_tool_can_filter_category(tmp_path): + store = create_store(tmp_path) + save_tool = LongTermMemorySaveTool(store) + search_tool = LongTermMemorySearchTool(store) + + save_tool.execute( + { + "content": "User likes Rust.", + "category": "semantic", + } + ) + save_tool.execute( + { + "content": "User worked on a Rust project last summer.", + "category": "episodic", + } + ) + + result = search_tool.execute( + { + "query": "Rust", + "category": "episodic", + } + ) + + assert "worked on a Rust project" in result.content + assert "User likes Rust." not in result.content + + +def test_search_tool_returns_no_matches(tmp_path): + store = create_store(tmp_path) + search_tool = LongTermMemorySearchTool(store) + + result = search_tool.execute({"query": "nonexistent"}) + + assert result.content == "No matching memories found." + + +def test_search_tool_rejects_empty_query(tmp_path): + store = create_store(tmp_path) + search_tool = LongTermMemorySearchTool(store) + + try: + search_tool.execute({"query": " "}) + except ToolError as error: + assert str(error) == "query must not be empty" + else: + raise AssertionError("Expected ToolError") + + +def test_delete_tool_removes_memory(tmp_path): + store = create_store(tmp_path) + save_tool = LongTermMemorySaveTool(store) + delete_tool = LongTermMemoryDeleteTool(store) + + result = save_tool.execute( + { + "content": "User likes Rust.", + "category": "semantic", + } + ) + + memory_id = result.content.removeprefix("Saved memory: ") + + delete_result = delete_tool.execute({"id": memory_id}) + + assert delete_result.content == f"Deleted memory: {memory_id}" + assert store.list() == [] + + +def test_delete_tool_rejects_invalid_id(tmp_path): + store = create_store(tmp_path) + delete_tool = LongTermMemoryDeleteTool(store) + + try: + delete_tool.execute({"id": "not-a-uuid"}) + except ToolError as error: + assert str(error) == "id must be a valid UUID" + else: + raise AssertionError("Expected ToolError") |
