From 80c9139a20275dc4a3c7d9726e30b53034b7c6da Mon Sep 17 00:00:00 2001 From: ZHENG Zian Date: Thu, 21 May 2026 08:46:45 +0800 Subject: [PATCH] fix(hindsight): clear _session_turns after retain to stop transcript duplication MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sync_turn() method appends each turn to _session_turns and, when the retain interval fires, constructs content from all accumulated turns before enqueueing the async retain. However _session_turns was never cleared after enqueue, so every subsequent retain re-sent every prior turn — causing quadratic transcript duplication over the session lifetime. Fix: clear self._session_turns = [] immediately after enqueueing. The async writer thread uses frozen snapshot variables (content, metadata_snapshot, num_turns) captured in the _do_retain closure, so clearing the source list has no effect on the in-flight retain. Closes: #23724 (transcript duplication) --- plugins/memory/hindsight/__init__.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/memory/hindsight/__init__.py b/plugins/memory/hindsight/__init__.py index 40772f79d8a09..a75c569dd11bb 100644 --- a/plugins/memory/hindsight/__init__.py +++ b/plugins/memory/hindsight/__init__.py @@ -1489,6 +1489,10 @@ def _do_retain() -> None: self._ensure_writer() self._register_atexit() self._retain_queue.put(_do_retain) + # Clear accumulated turns. The async writer captured a + # snapshot via closure at enqueue time. Without this + # _session_turns grows unbounded, causing duplication (#23724). + self._session_turns = [] def get_tool_schemas(self) -> List[Dict[str, Any]]: if self._memory_mode == "context":