Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion mesa_llm/memory/st_lt_memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,6 @@ def _process_step_core(self, pre_step: bool):
> self.capacity + (self.consolidation_capacity or 0)
and self.consolidation_capacity
):
self.short_term_memory.popleft()
should_consolidate = True

elif (
Expand All @@ -155,6 +154,7 @@ def process_step(self, pre_step: bool = False):

if should_consolidate:
self._update_long_term_memory()
self.short_term_memory.popleft()

if new_entry and self.display:
new_entry.display()
Expand All @@ -167,6 +167,7 @@ async def aprocess_step(self, pre_step: bool = False):

if should_consolidate:
await self._aupdate_long_term_memory()
self.short_term_memory.popleft()

if new_entry and self.display:
new_entry.display()
Expand Down
47 changes: 47 additions & 0 deletions tests/test_memory/test_STLT_memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,3 +200,50 @@ def test_get_prompt_ready_returns_str_when_empty(self, mock_agent):
)
assert "Short term memory:" in result
assert "Long term memory:" in result

def test_consolidation_includes_evicted_entry(
self, mock_agent, mock_llm, llm_response_factory
):
"""Test that the entry being evicted from short-term memory is included
in the consolidation prompt so its content is preserved in long-term
memory.

Before the fix, popleft() removed the oldest entry *before*
consolidation ran, so the evicted entry was permanently lost.
"""
mock_llm.generate.return_value = llm_response_factory("Consolidated summary")

memory = STLTMemory(
agent=mock_agent,
short_term_capacity=2,
consolidation_capacity=1,
llm_model="provider/test_model",
)
memory.llm = mock_llm

with patch("rich.console.Console"):
# Fill memory to just below consolidation threshold
for i in range(3):
memory.add_to_memory("observation", {"content": f"event_{i}"})
memory.process_step(pre_step=True)
memory.process_step(pre_step=False)

# At this point, capacity(2) + consolidation_capacity(1) = 3
# We have 3 entries, so no consolidation yet.
assert not mock_llm.generate.called

# Add one more entry to trigger consolidation
memory.add_to_memory("observation", {"content": "event_3"})
memory.process_step(pre_step=True)
memory.process_step(pre_step=False)

# Consolidation should have been triggered
assert mock_llm.generate.called

# The consolidation prompt must contain the oldest entry
# (event_0) that is about to be evicted
prompt_sent = mock_llm.generate.call_args[0][0]
assert "event_0" in prompt_sent, (
"The evicted entry's content must appear in the consolidation "
"prompt so the LLM can preserve it in long-term memory"
)