Add continuous compaction with contextual hand summaries#948
Open
pbranchu wants to merge 8 commits intoRightNow-AI:mainfrom
Open
Add continuous compaction with contextual hand summaries#948pbranchu wants to merge 8 commits intoRightNow-AI:mainfrom
pbranchu wants to merge 8 commits intoRightNow-AI:mainfrom
Conversation
Add periodic compaction that triggers every N exchanges and queries configured hands (e.g. calendar, mail) for contextual summaries that get stored in shared memory for long-term recall. - CompactionTomlConfig + CompactionContextSource types in openfang-types - needs_continuous_compaction() helper + continuous_interval field in compactor - Exchange counter + spawned continuous compaction task in kernel post-loop - Queries context_sources hands with timeout, stores results in memory Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a user returns after >15 minutes (configurable session_gap_secs), the bridge triggers compaction + context source queries BEFORE dispatching the first message. This gives the agent situational awareness on the first response. The lookback for context sources is bounded by max_lookback_secs (default 24h) — so a 3-day absence queries only the last 24 hours, not 3 days of events/emails. The context preamble is prepended to the user's message as [Session context] so the agent sees it naturally. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Exchange counter was only wired in the streaming send path. Add the same counter + compaction trigger to send_message_inner so API and agent_send calls also trigger continuous compaction. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The continuous compaction in the non-streaming send_message_inner path only ran standard compaction without querying context sources (calendar-hand, mail-hand). Now both streaming and non-streaming paths have identical compaction behavior: compact + query hands + store context in memory. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Previously calendar-hand and mail-hand were queried sequentially, adding 14.5s to the first response after a session gap. Now both run concurrently via tokio::spawn, reducing latency to the slower of the two (~11s). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The compaction summarizer now receives the current timestamp and is
instructed to:
- Drop past events that are no longer actionable (completed meetings,
delivered orders, resolved questions)
- Keep future events and pending tasks
- Use absolute dates/times, never relative
- Focus on what's still relevant
This prevents stale event data ("hike today" from yesterday's session)
from persisting across compaction cycles.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ies, proper time window - Context summaries now appended to the live session as a synthetic user message after compaction, so the agent sees them on the next turn without needing to call memory_recall (previously they were only written to memory) - Context source queries now run in parallel (tokio::spawn per source) instead of sequentially — matches session gap detection behaviour - Time window is now bounded on both ends: from_ts (last compaction time) to to_ts (now), tracked per-agent in last_compaction_at DashMap; first compaction uses max_lookback_secs as the lower bound - Extracted query_context_sources_parallel() and inject_context_into_session() as module-level helpers, eliminating duplication between streaming and non-streaming paths - Fix clippy: use .is_multiple_of() for modulo-zero checks, redundant closure in tool_runner LazyLock Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Use StreamableHttpClientTransportConfig::with_uri().custom_headers() builder instead of struct expression syntax, which broke when rmcp marked the struct #[non_exhaustive] in 1.3.0. Also removes the now-unused Arc import. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #896
Summary
Addresses the core problem in #896: conversation history grows unboundedly, old topics bleed into new sessions, and the agent has no situational awareness of what happened between exchanges.
What this adds
Continuous compaction — every N exchanges (configurable, default 5), when the session exceeds
keep_recentmessages:memory_recallSession gap detection — when a user returns after a configurable gap (default 15 min), the bridge triggers compaction + context refresh before dispatching the first message. The context preamble is prepended so the agent is situationally aware on the first response.
Key design points
[[compaction.context_sources]]are queried — no unexpected calls to arbitrary handsfrom_ts(last compaction) →to_ts(now), tracked per-agent;max_lookback_secscaps how far back a gap query reachestokio::spawn, latency is the slowest source not the sum[Context refresh — timestamp]user message appended after compaction, in thekeep_recentwindowquery_context_sources_parallel()andinject_context_into_session()helpersConfiguration
Also fixes
StreamableHttpClientTransportConfigstruct expression broken by rmcp 1.3.0 marking it#[non_exhaustive]— switched to thewith_uri().custom_headers()builder APIis_multiple_of()and redundant closure inLazyLockTest plan
cargo clippy -- -D warningspassescargo testpassescontinuous_interval = 5: after 5 exchanges, compaction triggers and context appears in sessionfrom {ts} to {ts}time window in querymax_lookback_secscaps gap query (3-day absence doesn't dump 3 days of events)context_sourceslist: compaction runs normally, no hand queries🤖 Generated with Claude Code