refactor(session): return RetentionResult instead of bare tuple
Replace the tuple(list[dict], int) return of Session.retain_recent_legal_suffix with a named RetentionResult dataclass that exposes retained, dropped, already_consolidated_count, and new_last_consolidated fields. The tuple return was easy to misuse because the second value only made sense relative to the first and the old last_consolidated cursor. The named fields make the archive-skip semantics explicit at every call site. No behavior change. All existing tests pass unchanged in semantics. Refs #4136 Signed-off-by: axelray-dev <110029405+axelray-dev@users.noreply.github.com>
This commit is contained in:
+33
-13
@@ -110,6 +110,14 @@ def _metadata_title(metadata: Any) -> str:
|
||||
return strip_think(title)
|
||||
|
||||
|
||||
@dataclass
|
||||
class RetentionResult:
|
||||
retained: list[dict]
|
||||
dropped: list[dict]
|
||||
already_consolidated_count: int
|
||||
new_last_consolidated: int
|
||||
|
||||
|
||||
@dataclass
|
||||
class Session:
|
||||
"""A conversation session."""
|
||||
@@ -289,22 +297,29 @@ class Session:
|
||||
max_messages: int,
|
||||
*,
|
||||
extend_to_user: bool = False,
|
||||
) -> tuple[list[dict], int]:
|
||||
) -> RetentionResult:
|
||||
"""Keep a legal recent suffix, optionally extending it back to a user turn.
|
||||
|
||||
Returns ``(dropped, already_consolidated_count)`` where *dropped* is
|
||||
the list of removed messages (in original order) and
|
||||
*already_consolidated_count* is how many of those were inside the
|
||||
pre-existing ``last_consolidated`` prefix and therefore do not need
|
||||
raw archiving.
|
||||
Returns a RetentionResult describing retained messages, removed messages,
|
||||
and how the last_consolidated cursor changed.
|
||||
"""
|
||||
if max_messages <= 0:
|
||||
dropped = list(self.messages)
|
||||
lc = self.last_consolidated
|
||||
self.clear()
|
||||
return dropped, min(lc, len(dropped))
|
||||
return RetentionResult(
|
||||
retained=self.messages,
|
||||
dropped=dropped,
|
||||
already_consolidated_count=min(lc, len(dropped)),
|
||||
new_last_consolidated=self.last_consolidated,
|
||||
)
|
||||
if len(self.messages) <= max_messages:
|
||||
return [], 0
|
||||
return RetentionResult(
|
||||
retained=self.messages,
|
||||
dropped=[],
|
||||
already_consolidated_count=0,
|
||||
new_last_consolidated=self.last_consolidated,
|
||||
)
|
||||
|
||||
original = list(self.messages)
|
||||
before_lc = self.last_consolidated
|
||||
@@ -370,7 +385,12 @@ class Session:
|
||||
self.messages = retained
|
||||
self.last_consolidated = new_lc
|
||||
self.updated_at = datetime.now()
|
||||
return dropped, already_consolidated
|
||||
return RetentionResult(
|
||||
retained=retained,
|
||||
dropped=dropped,
|
||||
already_consolidated_count=already_consolidated,
|
||||
new_last_consolidated=new_lc,
|
||||
)
|
||||
|
||||
def enforce_file_cap(
|
||||
self,
|
||||
@@ -381,17 +401,17 @@ class Session:
|
||||
if limit <= 0 or len(self.messages) <= limit:
|
||||
return
|
||||
|
||||
dropped, already_consolidated = self.retain_recent_legal_suffix(limit)
|
||||
if not dropped:
|
||||
result = self.retain_recent_legal_suffix(limit)
|
||||
if not result.dropped:
|
||||
return
|
||||
|
||||
archive_chunk = dropped[already_consolidated:]
|
||||
archive_chunk = result.dropped[result.already_consolidated_count:]
|
||||
if archive_chunk and on_archive:
|
||||
on_archive(archive_chunk)
|
||||
logger.info(
|
||||
"Session file cap hit for {}: dropped {}, raw-archived {}, kept {}",
|
||||
self.key,
|
||||
len(dropped),
|
||||
len(result.dropped),
|
||||
len(archive_chunk),
|
||||
len(self.messages),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user