c408601937
Cluster: agent/{curator,curator_backup,background_review,review_engine,
review_idle_queue,insights,learning_graph,learning_graph_render,
learning_mutations,learn_prompt,verification_evidence,verification_stop,
verify_hooks,side_question,title_generator,turn_summary,
manual_compression_feedback,trajectory,moa_trace,trace_upload,verify/*}.
13662 -> 10693 LOC (-2969, -21.7%), behavior-neutral.
- Dead code: 27 private helpers with zero references removed
(_auto_title_session, _resolve_review_model, _parse_make_targets,
_filter_verifiable_paths, _find_subsequence, _is_under_root/_temp_dir,
_merge_runs, learning_graph_render bucket/period/node helpers,
_memories_dir/_memory_local_index/_node_detail, _cron_jobs_file,
_retention_cutoff, _scope_for_args, _clean_token, _count_diff_lines,
_ordered_verbs, _hermes_meta, _iter_skill_files).
- Unified helpers: _read_config_section (curator + curator_backup),
_write_file/_write_json (4 curator report writers), _msg_text
(background_review <- side_question), _report_failure/_notify_title
(title_generator instant/auto paths), _is_under (verification_evidence),
_scoped SQL pair builder + _query (insights), _optional_lock
(background_review), verify.recipes table-driven detection.
- if/elif routing -> dict dispatch: side_question role labels,
curator_backup summary bits, learning_graph_render buckets, insights
section rendering, verify recipe pickers.
- Redundant defensive layers, single-use wrappers and verbose narrative
comments collapsed; every non-obvious WHY/invariant kept in compact form.
Verification: parity.py (all REMOVED symbols zero-ref), import smoke for
every module + cli/run_agent/gateway.run/hermes_cli.main/
agent.conversation_loop/tui_gateway.server, old-vs-new fuzz parity on all
shared pure functions, SQL trace parity for insights and
verification_evidence, cluster tests 1354 passed / 0 failed (46 files).
100 lines
4.3 KiB
Python
100 lines
4.3 KiB
Python
"""User-facing summaries for manual compression commands."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any, Sequence
|
|
|
|
from agent.redact import redact_sensitive_text
|
|
|
|
|
|
def describe_compression_lock_skip(lock_signal: Any) -> str:
|
|
"""User-facing text for a manual /compress skipped by the compression lock.
|
|
|
|
``lock_signal`` is ``agent._compression_skipped_due_to_lock`` (or the TUI's
|
|
``CompressionLockHeld.holder``): a holder string when another compressor
|
|
CONFIRMED holds the lock, else ``True``/``None``. A failed acquire is NOT
|
|
proof another compression is running (``try_acquire_compression_lock``
|
|
swallows ``sqlite3.Error``), so the two cases are worded differently.
|
|
"""
|
|
if isinstance(lock_signal, str) and lock_signal.strip():
|
|
return (
|
|
f"⏳ Compression already in progress for this session "
|
|
f"(holder: {lock_signal}). Please wait for it to finish."
|
|
)
|
|
return (
|
|
"⏳ Compression skipped: could not acquire this session's "
|
|
"compression lock. Another compression may still be running, or "
|
|
"the lock check failed — try again shortly."
|
|
)
|
|
|
|
|
|
def _state_flag(state: Any, name: str) -> bool:
|
|
return state is not None and getattr(state, name, False) is True
|
|
|
|
|
|
def summarize_manual_compression(
|
|
before_messages: Sequence[dict[str, Any]],
|
|
after_messages: Sequence[dict[str, Any]],
|
|
before_tokens: int,
|
|
after_tokens: int,
|
|
*,
|
|
compression_state: Any = None,
|
|
) -> dict[str, Any]:
|
|
"""Return consistent user-facing feedback for manual compression."""
|
|
before_count = len(before_messages)
|
|
after_count = len(after_messages)
|
|
noop = list(after_messages) == list(before_messages)
|
|
aborted = _state_flag(compression_state, "_last_compress_aborted")
|
|
refused_would_grow = _state_flag(compression_state, "_last_compress_refused_would_grow")
|
|
fallback_used = _state_flag(compression_state, "_last_summary_fallback_used")
|
|
failure_reason = getattr(compression_state, "_last_summary_error", None) if compression_state is not None else None
|
|
if not isinstance(failure_reason, str) or not failure_reason.strip():
|
|
failure_reason = None
|
|
|
|
note = None
|
|
if refused_would_grow:
|
|
headline = f"Compression refused (summary would grow the conversation): {before_count} messages preserved"
|
|
note = "The generated summary was larger than what it would replace; no messages were removed."
|
|
elif aborted:
|
|
headline = f"Compression aborted: {before_count} messages preserved"
|
|
note = "Summary generation failed; no messages were removed."
|
|
elif fallback_used:
|
|
headline = f"Compressed with fallback: {before_count} → {after_count} messages"
|
|
dropped_count = getattr(compression_state, "_last_summary_dropped_count", None)
|
|
if not isinstance(dropped_count, int) or isinstance(dropped_count, bool):
|
|
dropped_count = max(before_count - after_count, 0)
|
|
note = (
|
|
"Summary generation failed; Hermes used limited fallback context "
|
|
f"and removed {dropped_count} message(s)."
|
|
)
|
|
elif noop:
|
|
headline = f"No changes from compression: {before_count} messages"
|
|
else:
|
|
headline = f"Compressed: {before_count} → {after_count} messages"
|
|
if after_count < before_count and after_tokens > before_tokens:
|
|
note = (
|
|
"Note: fewer messages can still raise this estimate when "
|
|
"compression rewrites the transcript into denser summaries."
|
|
)
|
|
|
|
if (noop and after_tokens == before_tokens) or refused_would_grow:
|
|
token_line = f"Approx request size: ~{before_tokens:,} tokens (unchanged)"
|
|
else:
|
|
token_line = f"Approx request size: ~{before_tokens:,} → ~{after_tokens:,} tokens"
|
|
|
|
if failure_reason and (aborted or fallback_used):
|
|
# Crosses a user-facing UI boundary: never let a disabled global redaction
|
|
# preference expose credentials embedded in provider exception text.
|
|
safe_reason = redact_sensitive_text(failure_reason.strip(), force=True)
|
|
note = f"{note} Reason: {safe_reason}"
|
|
|
|
return {
|
|
"noop": noop,
|
|
"aborted": aborted,
|
|
"refused_would_grow": refused_would_grow,
|
|
"fallback_used": fallback_used,
|
|
"headline": headline,
|
|
"token_line": token_line,
|
|
"note": note,
|
|
}
|