diff --git a/README.md b/README.md index a474367..289ff28 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ ⚡️ Delivers core agent functionality in just **~4,000** lines of code — **99% smaller** than Clawdbot's 430k+ lines. -📏 Real-time line count: **3,761 lines** (run `bash core_agent_lines.sh` to verify anytime) +📏 Real-time line count: **3,781 lines** (run `bash core_agent_lines.sh` to verify anytime) ## 📢 News diff --git a/tests/test_memory_consolidation_types.py b/tests/test_memory_consolidation_types.py deleted file mode 100644 index 3b76596..0000000 --- a/tests/test_memory_consolidation_types.py +++ /dev/null @@ -1,133 +0,0 @@ -"""Test memory consolidation handles non-string values from LLM. - -This test verifies the fix for the bug where memory consolidation fails -when LLM returns JSON objects instead of strings for history_entry or -memory_update fields. - -Related issue: Memory consolidation fails with TypeError when LLM returns dict -""" - -import json -import tempfile -from pathlib import Path - -import pytest - -from nanobot.agent.memory import MemoryStore - - -class TestMemoryConsolidationTypeHandling: - """Test that MemoryStore methods handle type conversion correctly.""" - - def test_append_history_accepts_string(self): - """MemoryStore.append_history should accept string values.""" - with tempfile.TemporaryDirectory() as tmpdir: - memory = MemoryStore(Path(tmpdir)) - - # Should not raise TypeError - memory.append_history("[2026-02-14] Test entry") - - # Verify content was written - history_content = memory.history_file.read_text() - assert "Test entry" in history_content - - def test_write_long_term_accepts_string(self): - """MemoryStore.write_long_term should accept string values.""" - with tempfile.TemporaryDirectory() as tmpdir: - memory = MemoryStore(Path(tmpdir)) - - # Should not raise TypeError - memory.write_long_term("- Fact 1\n- Fact 2") - - # Verify content was written - memory_content = memory.read_long_term() - assert "Fact 1" in memory_content - - def test_type_conversion_dict_to_str(self): - """Dict values should be converted to JSON strings.""" - input_val = {"timestamp": "2026-02-14", "summary": "test"} - expected = '{"timestamp": "2026-02-14", "summary": "test"}' - - # Simulate the fix logic - if not isinstance(input_val, str): - result = json.dumps(input_val, ensure_ascii=False) - else: - result = input_val - - assert result == expected - assert isinstance(result, str) - - def test_type_conversion_list_to_str(self): - """List values should be converted to JSON strings.""" - input_val = ["item1", "item2"] - expected = '["item1", "item2"]' - - # Simulate the fix logic - if not isinstance(input_val, str): - result = json.dumps(input_val, ensure_ascii=False) - else: - result = input_val - - assert result == expected - assert isinstance(result, str) - - def test_type_conversion_str_unchanged(self): - """String values should remain unchanged.""" - input_val = "already a string" - - # Simulate the fix logic - if not isinstance(input_val, str): - result = json.dumps(input_val, ensure_ascii=False) - else: - result = input_val - - assert result == input_val - assert isinstance(result, str) - - def test_memory_consolidation_simulation(self): - """Simulate full consolidation with dict values from LLM.""" - with tempfile.TemporaryDirectory() as tmpdir: - memory = MemoryStore(Path(tmpdir)) - - # Simulate LLM returning dict values (the bug scenario) - history_entry = {"timestamp": "2026-02-14", "summary": "User asked about..."} - memory_update = {"facts": ["Location: Beijing", "Skill: Python"]} - - # Apply the fix: convert to str - if not isinstance(history_entry, str): - history_entry = json.dumps(history_entry, ensure_ascii=False) - if not isinstance(memory_update, str): - memory_update = json.dumps(memory_update, ensure_ascii=False) - - # Should not raise TypeError after conversion - memory.append_history(history_entry) - memory.write_long_term(memory_update) - - # Verify content - assert memory.history_file.exists() - assert memory.memory_file.exists() - - history_content = memory.history_file.read_text() - memory_content = memory.read_long_term() - - assert "timestamp" in history_content - assert "facts" in memory_content - - -class TestPromptOptimization: - """Test that prompt optimization helps prevent the issue.""" - - def test_prompt_includes_string_requirement(self): - """The prompt should explicitly require string values.""" - # This is a documentation test - verify the fix is in place - # by checking the expected prompt content - expected_keywords = [ - "MUST be strings", - "not objects or arrays", - "Example:", - ] - - # The actual prompt content is in nanobot/agent/loop.py - # This test serves as documentation of the expected behavior - for keyword in expected_keywords: - assert keyword, f"Prompt should include: {keyword}"