mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-08-31 00:03:01 +03:00
fix(memory): ignore empty consolidation summaries
This commit is contained in:
@@ -431,7 +431,11 @@ class MemoryStore:
|
|||||||
unified_session: bool = False,
|
unified_session: bool = False,
|
||||||
) -> list[dict[str, Any]]:
|
) -> list[dict[str, Any]]:
|
||||||
"""Return unprocessed history entries safe to inject into a turn prompt."""
|
"""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:
|
if session_key is None:
|
||||||
return entries
|
return entries
|
||||||
if not unified_session:
|
if not unified_session:
|
||||||
@@ -1023,6 +1027,8 @@ class Consolidator:
|
|||||||
logger.warning("Consolidation provider returned no summary, raw-dumping to history")
|
logger.warning("Consolidation provider returned no summary, raw-dumping to history")
|
||||||
self.store.raw_archive(messages, session_key=session_key)
|
self.store.raw_archive(messages, session_key=session_key)
|
||||||
return None
|
return None
|
||||||
|
if summary.strip() == "(nothing)":
|
||||||
|
return "(nothing)"
|
||||||
self.store.append_history(
|
self.store.append_history(
|
||||||
summary,
|
summary,
|
||||||
max_chars=_ARCHIVE_SUMMARY_MAX_CHARS,
|
max_chars=_ARCHIVE_SUMMARY_MAX_CHARS,
|
||||||
|
|||||||
@@ -873,7 +873,7 @@ class TestCompactIdleSession:
|
|||||||
async def test_nothing_summary_not_stored(
|
async def test_nothing_summary_not_stored(
|
||||||
self, real_consolidator, mock_provider, runtime
|
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(
|
mock_provider.chat_with_retry.return_value = MagicMock(
|
||||||
content="(nothing)", finish_reason="stop"
|
content="(nothing)", finish_reason="stop"
|
||||||
)
|
)
|
||||||
@@ -891,6 +891,7 @@ class TestCompactIdleSession:
|
|||||||
|
|
||||||
reloaded = sessions.get_or_create("cli:nothing")
|
reloaded = sessions.get_or_create("cli:nothing")
|
||||||
assert "_last_summary" not in reloaded.metadata
|
assert "_last_summary" not in reloaded.metadata
|
||||||
|
assert real_consolidator.store.read_unprocessed_history(0) == []
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_llm_failure_preserves_history_but_advances_replay_boundary(
|
async def test_llm_failure_preserves_history_but_advances_replay_boundary(
|
||||||
|
|||||||
@@ -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)
|
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:
|
def test_recent_history_injection_is_session_scoped(tmp_path) -> None:
|
||||||
workspace = _make_workspace(tmp_path)
|
workspace = _make_workspace(tmp_path)
|
||||||
builder = ContextBuilder(workspace)
|
builder = ContextBuilder(workspace)
|
||||||
|
|||||||
Reference in New Issue
Block a user