Skip to content

fix(gateway): preserve transcript on /compress and hygiene auto-compress - #21313

Closed
SandroHub013 wants to merge 1 commit into
NousResearch:mainfrom
SandroHub013:fix/gateway-compress-preserve-transcript
Closed

fix(gateway): preserve transcript on /compress and hygiene auto-compress#21313
SandroHub013 wants to merge 1 commit into
NousResearch:mainfrom
SandroHub013:fix/gateway-compress-preserve-transcript

Conversation

@SandroHub013

Copy link
Copy Markdown

Closes #21301.

Problem

Manual /compress and Gateway Session Hygiene auto-compress both physically destroy the original transcript. Reproduction (per the issue):

  1. Telegram/Discord gateway, 60+ message session.
  2. Send /compress.
  3. state.db shows the original session's message_count collapsed to the compressed count, end_reason is NULL, parent_session_id is NULL, no continuation session was created.

Documented behavior (sessions.md "Auto-Lineage on Compression") says the original should be closed with end_reason='compression' and a new continuation session should carry parent_session_id pointing back.

Root cause

Both code paths build a temporary AIAgent for the compression run:

  • _handle_compress_command at gateway/run.py:9445 (tmp_agent = AIAgent(...))
  • Session Hygiene at gateway/run.py:6218 (_hyg_agent = AIAgent(...))

Neither passes session_db=. That makes tmp_agent._session_db = None, and _compress_context()'s session-rotate block is guarded by if self._session_db: (run_agent.py:9048), so it silently no-ops. tmp_agent.session_id never rotates.

The downstream safeguard added in 1544638 / cd2e180:

new_session_id = tmp_agent.session_id
if new_session_id != session_entry.session_id:
    session_entry.session_id = new_session_id
    self.session_store._save()
self.session_store.rewrite_transcript(new_session_id, compressed)

assumes the rotate already happened. With _session_db is None it didn't, so new_session_id == session_entry.session_id and rewrite_transcript overwrites the original.

Fix

Add session_db=self._session_db to both constructors:

 _hyg_agent = AIAgent(
     **_hyg_runtime,
     model=_hyg_model,
     max_iterations=4,
     quiet_mode=True,
     skip_memory=True,
     enabled_toolsets=["memory"],
     session_id=session_entry.session_id,
+    session_db=self._session_db,
 )
 tmp_agent = AIAgent(
     **runtime_kwargs,
     model=model,
     max_iterations=4,
     quiet_mode=True,
     skip_memory=True,
     enabled_toolsets=["memory"],
     session_id=session_entry.session_id,
+    session_db=self._session_db,
 )

Same shape as PR #20021 (ACP adapter) and PR #4802 (API server adapter), which fixed identical omissions in their respective tmp-agent constructors.

Tests

New: tests/gateway/test_compress_preserves_session_db.py — two static-source assertions that both constructor call sites carry session_db=self._session_db. Avoids the SQLite + full AIAgent wiring a true integration test would need, which would be heavier than the bug. The reporter has independently validated end-to-end behavior in production (Telegram /compress on a 112-message session — original preserved, new session linked).

python -m pytest -o addopts= tests/gateway/test_compress_preserves_session_db.py -q
2 passed

Out of scope

  • The ACP / API server fixes referenced above. Already shipped.
  • Refactoring _compress_context() to no longer require session_db. The if self._session_db: guard exists for non-gateway callers (one-shot CLI, etc.) and removing it would change behavior beyond this fix.

Closes NousResearch#21301.

Both `_handle_compress_command` (manual `/compress`) and the Gateway
Session Hygiene auto-compress path build a temporary `AIAgent` to run
context compression. Both omitted `session_db=self._session_db`, so the
tmp agent's `_session_db` was None and `_compress_context()`'s
session-rotate block (`if self._session_db:`) silently no-op'd.

Downstream `rewrite_transcript(session_entry.session_id, compressed)`
then overwrote the original session's transcript with the compressed
list, destroying the searchable history that commits 1544638 and
cd2e180 were specifically introduced to protect.

Same bug class as PR NousResearch#20021 (ACP adapter) and PR NousResearch#4802 (API server
adapter), both of which fixed identical missing-`session_db` omissions
in their respective tmp-agent constructors.

Add `session_db=self._session_db` to both constructors. With this, the
session-rotate block runs, the original session is closed with
`end_reason='compression'`, and the new continuation session gets a
fresh session_id with `parent_session_id` linking back.

Regression test asserts both constructor call sites carry the kwarg via
static source inspection — avoids the SQLite + AIAgent wiring needed
for a full integration test, which would be heavier than the bug.
@alt-glitch alt-glitch added type/bug Something isn't working P1 High — major feature broken, no workaround comp/gateway Gateway runner, session dispatch, delivery labels May 7, 2026
@teknium1

Copy link
Copy Markdown
Contributor

Merged via #49925 — your authorship is preserved as a co-author trailer on the merge. This fix incorporates the hygiene/compress transcript-preservation guard from your PR. Thanks for the contribution! #49925

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery P1 High — major feature broken, no workaround type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug] /compress and gateway hygiene compression destroy original transcript — tmp_agent missing session_db kwarg

3 participants