mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-23 10:42:00 +00:00
fix(tui): /compress shows a before/after summary (#46686)
The TUI /compress slash side-effect compressed the session, synced the key, and emitted session.info — but returned an empty string, so the user saw no 'Compressed: N → M messages / ~X → ~Y tokens' feedback. The CLI (_manual_compress) and gateway (slash_commands) paths both already call summarize_manual_compression; the TUI slash path was the lone gap. Snapshot history + rough token estimate before and after compaction and return the formatted summarize_manual_compression() feedback, mirroring the session.compress RPC handler. The estimate uses the same estimate_request_tokens_rough(system_prompt, tools) inputs as the RPC path, re-reading the system prompt after compaction (it may be rebuilt). Co-authored-by: liuhao1024 <sunsky.lau@gmail.com>
This commit is contained in:
parent
9e4fe32d36
commit
d0de4601d2
2 changed files with 53 additions and 4 deletions
|
|
@ -4968,7 +4968,8 @@ def test_mirror_slash_side_effects_allowed_when_idle(monkeypatch):
|
|||
def test_mirror_slash_compress_does_not_prelock_history(monkeypatch):
|
||||
"""Regression guard: /compress side effect must not hold history_lock
|
||||
when calling _compress_session_history (the helper snapshots under
|
||||
the same non-reentrant lock internally)."""
|
||||
the same non-reentrant lock internally). It also returns a before/after
|
||||
summary string (#46686)."""
|
||||
import types
|
||||
|
||||
seen = {"compress": False, "sync": False}
|
||||
|
|
@ -4977,7 +4978,9 @@ def test_mirror_slash_compress_does_not_prelock_history(monkeypatch):
|
|||
def _fake_compress(session, focus_topic=None, **_kw):
|
||||
seen["compress"] = True
|
||||
assert not session["history_lock"].locked()
|
||||
return (0, {"total": 0})
|
||||
# Simulate a real compaction shrinking the transcript.
|
||||
session["history"] = [{"role": "user", "content": "summary"}]
|
||||
return (1, {"total": 0})
|
||||
|
||||
def _fake_sync(_sid, _session):
|
||||
seen["sync"] = True
|
||||
|
|
@ -4988,14 +4991,20 @@ def test_mirror_slash_compress_does_not_prelock_history(monkeypatch):
|
|||
monkeypatch.setattr(server, "_emit", lambda *args: emitted.append(args))
|
||||
|
||||
session = _session(running=False)
|
||||
session["agent"] = types.SimpleNamespace(model="x")
|
||||
session["history"] = [
|
||||
{"role": "user", "content": f"m{i}"} for i in range(6)
|
||||
]
|
||||
session["agent"] = types.SimpleNamespace(model="x", _cached_system_prompt="", tools=None)
|
||||
|
||||
warning = server._mirror_slash_side_effects("sid", session, "/compress")
|
||||
|
||||
assert warning == ""
|
||||
# Now returns a before/after summary (was "" before #46686).
|
||||
assert seen["compress"]
|
||||
assert seen["sync"]
|
||||
assert ("session.info", "sid", {"model": "x"}) in emitted
|
||||
assert "Compressed:" in warning
|
||||
assert "6 → 1 messages" in warning
|
||||
assert "tokens" in warning
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -9806,9 +9806,49 @@ def _mirror_slash_side_effects(sid: str, session: dict, command: str) -> str:
|
|||
agent.ephemeral_system_prompt = new_prompt or None
|
||||
agent._cached_system_prompt = None
|
||||
elif name == "compress" and agent:
|
||||
# Mirror the session.compress RPC: build a before/after summary so
|
||||
# the user gets feedback (#46686). The slash path previously just
|
||||
# compressed + emitted session.info and returned "", so the TUI
|
||||
# showed no "compressed N → M messages / ~X → ~Y tokens" stats
|
||||
# while CLI and gateway both did.
|
||||
from agent.manual_compression_feedback import summarize_manual_compression
|
||||
from agent.model_metadata import estimate_request_tokens_rough
|
||||
|
||||
with session["history_lock"]:
|
||||
_before_messages = list(session.get("history", []))
|
||||
_before_count = len(_before_messages)
|
||||
_sys_prompt = getattr(agent, "_cached_system_prompt", "") or ""
|
||||
_tools = getattr(agent, "tools", None) or None
|
||||
_before_tokens = (
|
||||
estimate_request_tokens_rough(
|
||||
_before_messages, system_prompt=_sys_prompt, tools=_tools
|
||||
)
|
||||
if _before_count
|
||||
else 0
|
||||
)
|
||||
|
||||
_compress_session_history(session, arg)
|
||||
_sync_session_key_after_compress(sid, session)
|
||||
|
||||
with session["history_lock"]:
|
||||
_after_messages = list(session.get("history", []))
|
||||
_sys_prompt_after = getattr(agent, "_cached_system_prompt", "") or _sys_prompt
|
||||
_tools_after = getattr(agent, "tools", None) or _tools
|
||||
_after_tokens = (
|
||||
estimate_request_tokens_rough(
|
||||
_after_messages, system_prompt=_sys_prompt_after, tools=_tools_after
|
||||
)
|
||||
if _after_messages
|
||||
else 0
|
||||
)
|
||||
_emit("session.info", sid, _session_info(agent, session))
|
||||
_fb = summarize_manual_compression(
|
||||
_before_messages, _after_messages, _before_tokens, _after_tokens
|
||||
)
|
||||
_lines = [_fb["headline"], _fb["token_line"]]
|
||||
if _fb.get("note"):
|
||||
_lines.append(_fb["note"])
|
||||
return "\n".join(_lines)
|
||||
elif name == "fast" and agent:
|
||||
mode = arg.lower()
|
||||
if mode in {"fast", "on"}:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue