NousResearch/hermes-agent

Route compression warning to TUI via status emit

Cluster 36908 · agent. Data as of

Nothing open on GitHub. Fix merged in #50302 on 21 Jun 2026. Check it covers your case.

The short answer

0open issues
0open PRs
3items grouped
Known?
Yes. 3 related items grouped here, 1 issue already closed.
Fix event
A fix was merged to main in PR #50302. Check it covers your case. No release data is tracked.
Tracker
The maintainers' tracker marks this unresolved. That is separate from the fix event.
Still open
Nothing open on GitHub.

These issues and PRs address a bug where the compression count warning (indicating accuracy degradation) is silently lost and never displayed in the TUI. The fix routes this warning through the _emit_status mechanism so it reaches the user interface.

Open issues0

No open issues.

Open PRs0

No open pull requests.

Fixes on record

Merged to main. A stamp counts the issues a fix is linked to.

  • #50302 fix(agent): route repeated-compression warning through _emit_status (#36908)

    merged to main

    files: agent/conversation_compression.py, tests/agent/test_compression_count_warning_36908.py

    Show the diff
    • agent/conversation_compression.py
      @@ -719,14 +719,20 @@ def _release_lock() -> None:
           except Exception as _me_err:
               logger.debug("memory manager on_session_switch (compression): %s", _me_err)
       
      -    # Warn on repeated compressions (quality degrades with each pass)
      +    # Warn on repeated compressions (quality degrades with each pass).
      +    # Route through _emit_status (like the other compression warnings above)
      +    # so the warning reaches the TUI / Telegram / Discord via status_callback,
      +    # not just CLI stdout. _emit_status still _vprints for the CLI, and
      +    # storing it on _compression_warning lets replay_compression_warning
      +    # re-deliver it once a late-bound gateway status_callback is wired (#36908).
           _cc = agent.context_compressor.compression_count
           if _cc >= 2:
      -        agent._vprint(
      +        _cc_msg = (
                   f"{agent.log_prefix}⚠️  Session compressed {_cc} times — "
      -            f"accuracy may degrade. Consider /new to start fresh.",
      -            force=True,
      +            f"accuracy may degrade. Consider /new to start fresh."
               )
      +        agent._compression_warning = _cc_msg
      +        agent._emit_status(_cc_msg)
       
           # Emit session:compress event so hooks (e.g. MemPalace sync) can ingest
           # the completed old session before its details are lost. In in-place mode
    • tests/agent/test_compression_count_warning_36908.py
      @@ -0,0 +1,87 @@
      +"""Regression for #36908: the repeated-compression warning must reach the
      +TUI / gateway, not just CLI stdout.
      +
      +When a session is compressed >= 2 times, ``compress_context`` warns that
      +accuracy may degrade. That warning used to go through ``_vprint`` (stdout
      +only), so the Ink TUI / Telegram / Discord never saw it — unlike the two
      +other compression warnings in the same module, which route through
      +``_emit_status`` (and store ``_compression_warning`` for late-bound
      +gateway replay). This pins the warning onto the gateway-aware channel.
      +"""
      +
      +from __future__ import annotations
      +
      +import os
      +from pathlib import Path
      +from unittest.mock import MagicMock, patch
      +
      +from hermes_state import SessionDB
      +
      +
      +def _build_agent_with_db(db: SessionDB, session_id: str, compression_count: int):
      +    with patch.dict(os.environ, {"OPENROUTER_API_KEY": "[redacted:secret-assignment]"}):
      +        from run_agent import AIAgent
      +
      +        agent = AIAgent(
      +            api_key="[redacted:secret-assignment]",
      +            base_url="https://openrouter.ai/api/v1",
      +            model="test/model",
      +            quiet_mode=True,
      +            session_db=db,
      +            session_id=session_id,
      +            skip_context_files=True,
      +            skip_memory=True,
      +        )
      +
      +    compressor = MagicMock()
      +    compressor.compress.return_value = [
      +        {"role": "user", "content": "[CONTEXT COMPACTION] summary"},
      +        {"role": "user", "content": "tail"},
      +    ]
      +    compressor.compression_count = compression_count
      +    compressor.last_prompt_tokens = 0
      +    compressor.last_completion_tokens = 0
      +    compressor._last_summary_error = None
      +    compressor._last_compress_aborted = False
      +    compressor._last_aux_model_failure_model = None
      +    compressor._last_aux_model_failure_error = None
      +    agent.context_compressor = compressor
      +    return agent
      +
      +
      +def test_repeated_compression_warning_routed_through_emit_status(tmp_path: Path) -> None:
      +    db = SessionDB(db_path=tmp_path / "state.db")
      +    sid = "PARENT_36908"
      +    db.create_session(sid, source="cli")
      +
      +    # compression_count == 2 → the "compressed N times" warning should fire.
      +    agent = _build_agent_with_db(db, sid, compression_count=2)
      +
      +    emitted: list[str] = []
      +    agent._emit_status = lambda message: emitted.append(message)
      +
      +    messages = [{"role": "user", "content": f"m{i}"} for i in range(20)]
      +    agent._compress_context(messages, "sys", approx_tokens=[redacted:secret-assignment]
      +
      +    # The warning reached the gateway-aware channel...
      +    assert any("compressed 2 times" in m.lower() for m in emitted), (
      +        f"repeated-compression warning not emitted via _emit_status: {emitted}"
      +    )
      +    # ...and was stored for late-bound gateway status_callback replay.
      +    assert "compressed 2 times" in (getattr(agent, "_compression_warning", "") or "").lower()
      +
      +
      +def test_no_warning_below_threshold(tmp_path: Path) -> None:
      +    db = SessionDB(db_path=tmp_path / "state.db")
      +    sid = "PARENT_36908_ONCE"
      +    db.create_session(sid, source="cli")
      +
      +    # compression_count == 1 → no repeated-compression warning.
      +    agent = _build_agent_with_db(db, sid, compression_count=1)
      +    emitted: list[str] = []
      +    agent._emit_status = lambda message: emitted.append(message)
      +
      +    messages = [{"role": "user", "content": f"m{i}"} for i in range(20)]
      +    agent._compress_context(messages, "sys", approx_tokens=[redacted:secret-assignment]
      +
      +    assert not any("compressed" in m.lower() and "times" in m.lower() for m in emitted)

1 PR closed without merging

From the close comments: merged via another change 1

  • #36922 fix(agent): route compression count warning through _emit_status for TUI delivery · merged via another change → #50302
Closed issues · 1
  • Closed#36908TUI: compression count warning (accuracy degrade) is silently swallowed
How this cluster was grouped
  • Link evidence (structural links throughout): every member is connected by structural evidence: shared changed files, or a closing/superseded reference.
  • Pairwise link density 0.67: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. 1.00 means every pair is linked.

Pick up a Lab task

Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.

Open the Lab

At a glance

Subsystem
agent
Merged PRs
#50302
Closed issues
1
Attempts
1 PR closed without merging
Fix link checked
21 Jun 2026

For your agent

The same facts, typed.