summaryrefslogtreecommitdiff
path: root/tests/test_memory_tools.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_memory_tools.py')
-rw-r--r--tests/test_memory_tools.py169
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")