diff --git a/nanobot/agent/memory.py b/nanobot/agent/memory.py index eba81a36f..f893424c6 100644 --- a/nanobot/agent/memory.py +++ b/nanobot/agent/memory.py @@ -431,7 +431,11 @@ class MemoryStore: unified_session: bool = False, ) -> list[dict[str, Any]]: """Return unprocessed history entries safe to inject into a turn prompt.""" - entries = self.read_unprocessed_history(since_cursor=since_cursor) + entries = [ + entry + for entry in self.read_unprocessed_history(since_cursor=since_cursor) + if str(entry.get("content", "")).strip() != "(nothing)" + ] if session_key is None: return entries if not unified_session: @@ -1023,6 +1027,8 @@ class Consolidator: logger.warning("Consolidation provider returned no summary, raw-dumping to history") self.store.raw_archive(messages, session_key=session_key) return None + if summary.strip() == "(nothing)": + return "(nothing)" self.store.append_history( summary, max_chars=_ARCHIVE_SUMMARY_MAX_CHARS, diff --git a/tests/agent/test_consolidator.py b/tests/agent/test_consolidator.py index 7c9f1cfd8..192af9240 100644 --- a/tests/agent/test_consolidator.py +++ b/tests/agent/test_consolidator.py @@ -873,7 +873,7 @@ class TestCompactIdleSession: async def test_nothing_summary_not_stored( self, real_consolidator, mock_provider, runtime ): - """LLM returns '(nothing)' → _last_summary NOT in metadata.""" + """LLM returns '(nothing)' → neither history nor metadata stores it.""" mock_provider.chat_with_retry.return_value = MagicMock( content="(nothing)", finish_reason="stop" ) @@ -891,6 +891,7 @@ class TestCompactIdleSession: reloaded = sessions.get_or_create("cli:nothing") assert "_last_summary" not in reloaded.metadata + assert real_consolidator.store.read_unprocessed_history(0) == [] @pytest.mark.asyncio async def test_llm_failure_preserves_history_but_advances_replay_boundary( diff --git a/tests/agent/test_context_prompt_cache.py b/tests/agent/test_context_prompt_cache.py index f9393f1c2..a0d378d46 100644 --- a/tests/agent/test_context_prompt_cache.py +++ b/tests/agent/test_context_prompt_cache.py @@ -96,6 +96,17 @@ def test_unprocessed_history_injected_into_system_prompt(tmp_path) -> None: assert re.search(r"\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}\]", prompt) +def test_nothing_history_entry_is_not_injected(tmp_path) -> None: + workspace = _make_workspace(tmp_path) + builder = ContextBuilder(workspace) + builder.memory.append_history("(nothing)") + + prompt = builder.build_system_prompt() + + assert "# Recent History" not in prompt + assert "(nothing)" not in prompt + + def test_recent_history_injection_is_session_scoped(tmp_path) -> None: workspace = _make_workspace(tmp_path) builder = ContextBuilder(workspace)