fix(agent): preserve memory-provider context during compression - #64342
fix(agent): preserve memory-provider context during compression#64342GottZ wants to merge 12 commits into
Conversation
The MemoryProvider.on_pre_compress() hook returns text that providers want preserved in the compression summary, but run_agent.py discarded the return value. Additionally, compress() and _generate_summary() had no mechanism to accept this context. - Capture on_pre_compress() return value in run_agent.py - Add memory_context parameter to compress() and _generate_summary() - Inject memory provider insights into summarization prompts Fixes all MemoryProvider plugins that return context from on_pre_compress() (currently silently broken for every plugin).
There was a problem hiding this comment.
Pull request overview
This PR fixes the long-standing gap where MemoryManager.on_pre_compress() provider-returned text was computed but not reliably preserved through Hermes-managed context compression. It threads provider context into the compression pipeline (agent → context engine → summarizer), while hardening egress redaction/framing and improving context-engine compatibility and lock/refresher cleanup behavior.
Changes:
- Capture and sanitize
on_pre_compress()return text, then forward it through the compression orchestrator without droppingfocus_topic/force. - Inject bounded, strictly redacted provider context into both initial and iterative summary prompts (and preserve it across auxiliary→main retry paths) using an escaped JSON string framing.
- Replace the prior broad
TypeErrorretry behavior with signature-based kwarg filtering to avoid double-invoking stateful engines, and strengthen compression lock lease cleanup across failure modes.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
agent/conversation_compression.py |
Captures provider context, filters engine kwargs via signature inspection, and hardens lock/refresher release across error paths. |
agent/context_engine.py |
Adds sanitize_memory_context() and documents new optional compress() params (force, memory_context). |
agent/context_compressor.py |
Injects sanitized provider context into summarization prompts (initial + iterative) and preserves it across retry fallbacks. |
agent/redact.py |
Adds opt-in strict URL credential redaction for non-navigation egress boundaries. |
tests/run_agent/test_pre_compress_memory_context.py |
New end-to-end behavior contracts for agent→engine provider-context forwarding, sanitization/bounds, and TypeError propagation. |
tests/run_agent/test_413_compression.py |
Updates a compression test stub to match the expanded engine call signature. |
tests/agent/test_pre_compress_memory_context.py |
New prompt-level behavior contracts for provider-context injection, framing, bounding, and retry survival. |
tests/agent/test_context_compressor_summary_continuity.py |
Updates summary continuity test stub to accept the new optional kwarg. |
tests/agent/test_compression_concurrent_fork.py |
Adds/updates tests asserting lock/refresher release on signature/refresher/no-op prompt and engine error failure modes. |
tests/agent/test_redact.py |
Adds regression tests for the new opt-in strict URL credential redaction behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Thanks for consolidating the provider-context handoff work. The premise remains valid on current The PR threads that value through the compression dispatch and summary retry paths, sanitizes it before egress, and replaces the broad Automated hermes-sweeper review. |
# Conflicts: # agent/context_compressor.py
# Conflicts: # agent/conversation_compression.py
|
Merged via PR #67938 — all 9 of your commits were cherry-picked onto current main with authorship preserved in git log (rebase-merge, merge commit 766c617). Thanks for the thorough consolidation: the sanitization boundary, signature-based kwarg filtering, and lock-scope hardening all landed intact, along with your full behavior-contract test suites. One tiny fix-up during salvage: a conflict-resolution slip on our side briefly dropped the Also credited: @Tranquil-Flow for the foundational capture commit carried in this PR. |
Summary
Fixes #7192 by carrying the string returned from
MemoryManager.on_pre_compress()into Hermes-managed context compression instead of discarding it.focus_topicorforceTypeErrors after one call and releases compression locks even when capability inspection failsLineage and related work
This consolidates the useful parts and review findings from #7195, #7424, #11236, #22576, #29598, and #43567, plus the broader hardening work in Tranquil-Flow#2.
The original #7195 implementation is preserved as the first commit with @Tranquil-Flow's authorship. Follow-up commits port that behavior onto current
main, replace source-text assertions with executed behavior contracts, and incorporate the compatibility, retry, lock-lifecycle, redaction, and prompt-framing findings from the related reviews.Compatibility and scope
ContextEngine.compress()now documents optionalforceandmemory_contextarguments. The host inspects plugin signatures before calling them, so existing strict-signature engines continue to receive only the arguments they support. This replaces the former broadexcept TypeErrorretry, which could execute a stateful engine twice when theTypeErrorcame from inside the implementation.Codex app-server-native compaction remains intentionally outside this handoff. Its hidden thread is compacted by the app server and Hermes has no truthful summary-prompt injection point for provider-returned text. Existing Codex compaction behavior is unchanged and covered by its regression suite.
No provider-specific core code, new persistence file, configuration key, or prompt-cache mutation is introduced.
Verification
upstream/mainat46e87b14fe013a6bfcf3bcbb1c969e694fba4f70a05265d51