Skip to content

feat: add idle compaction trigger (idleCompactMinutes)#102

Open
drdotdot wants to merge 1 commit into
Martian-Engineering:mainfrom
drdotdot:feat/idle-compaction
Open

feat: add idle compaction trigger (idleCompactMinutes)#102
drdotdot wants to merge 1 commit into
Martian-Engineering:mainfrom
drdotdot:feat/idle-compaction

Conversation

@drdotdot

Copy link
Copy Markdown

Summary

Adds time-based compaction that triggers when a session has been idle beyond a configurable threshold (idleCompactMinutes). This addresses stale context in sessions that go through periods of inactivity — overnight, between work sessions, or during long-running background jobs.

Motivation

Currently, LCM only compacts when context exceeds the contextThreshold (turn-based trigger). Sessions that accumulate significant context but never quite hit the threshold — or sessions that go idle for hours/days — can resume with stale, unorganized raw context. This is especially common in agentic workflows with periodic cron/watchdog messages.

Idle compaction ensures returning users get lean, organized context instead of a wall of raw messages from hours ago.

Enables practical use of large context windows (1M tokens). With models like Gemini offering 1M-token context at no pricing premium, the turn-based threshold trigger alone isn't sufficient — sessions can accumulate hundreds of thousands of tokens of raw conversation over hours without ever hitting the 75% threshold. Idle compaction provides the missing time-based dimension: after periods of inactivity, context is proactively organized into the summary DAG regardless of size, keeping large-window sessions navigable and performant over long lifespans.

How it works

  1. Config: idleCompactMinutes (env: LCM_IDLE_COMPACT_MINUTES, default: 0 = disabled)
  2. Detection: getLastActivityTimestamp() queries the most recent user or assistant message. Heartbeats (never ingested) don't reset the timer. SystemEvents and sub-agent completions do.
  3. Leaf pass in assemble(): When idle threshold is exceeded, runs a single compactLeaf() with force: true before assembling context. Protected by a 15-second timeout to bound first-message latency.
  4. Full cascade in afterTurn(): Flags the session so afterTurn() forces a full compaction sweep regardless of context threshold, ensuring the leaf pass doesn't leave the DAG in a partial state.

Changes

File Change
src/db/config.ts Added idleCompactMinutes to LcmConfig type and resolveLcmConfig()
src/store/conversation-store.ts Added getLastActivityTimestamp() method
src/compaction.ts Added evaluateIdleTrigger() method
src/engine.ts Idle leaf pass in assemble(), forced cascade in afterTurn(), session tracking map
openclaw.plugin.json Added config schema + UI hints
docs/configuration.md Full documentation section

Configuration

{
  "plugins": {
    "entries": {
      "lossless-claw": {
        "config": {
          "idleCompactMinutes": 180
        }
      }
    }
  }
}

Or via environment: LCM_IDLE_COMPACT_MINUTES=180

Idle timer policy

  • User/assistant messages → reset timer ✅
  • Heartbeats → do NOT reset (never ingested) ✅
  • SystemEvents (cron, watchdog) → reset timer (genuine new information) ✅
  • Sub-agent completions → reset timer ✅

Testing

Tested in production OpenClaw deployment with idleCompactMinutes: 180 across multiple concurrent sessions (main, autoresearch, data collection). Gateway restart successful, config persisted, no errors in logs.

Breaking changes

None. Default is 0 (disabled). Existing behavior unchanged unless explicitly enabled.

Add time-based compaction that triggers when a session has been idle
beyond a configurable threshold. This addresses stale context in sessions
that go through periods of inactivity (overnight, between work sessions).

When enabled (idleCompactMinutes > 0), the first assemble() call after
the idle threshold runs a lightweight leaf pass (15s timeout), followed
by a forced full compaction cascade in afterTurn().

Changes:
- Config: idleCompactMinutes option (env: LCM_IDLE_COMPACT_MINUTES, default: 0)
- ConversationStore: getLastActivityTimestamp() filtering user/assistant roles
- CompactionEngine: evaluateIdleTrigger() method
- Engine: idle leaf pass in assemble() with 15s timeout + forced cascade in afterTurn()
- Plugin schema + UI hints for new config key
- Documentation with usage guidance and idle timer policy
@100yenadmin 100yenadmin added enhancement New feature or request priority:P2 Important bug, compatibility, performance, or reliability issue stale-check Stale issue/PR being checked with the original reporter labels May 30, 2026
@100yenadmin

Copy link
Copy Markdown
Collaborator

@drdotdot triage pass update: I marked this priority:P2 enhancement/stale-check. Idle compaction is related to the background compaction queue, but the branch is dirty and unlinked. Can you confirm whether this is still desired and whether it should be linked to #746 or another issue?

@100yenadmin

Copy link
Copy Markdown
Collaborator

Maintainer review: needs rebase before deeper review.

Summary
@drdotdot, this PR is still potentially useful, but the current head bcaae42cc3623fa899f05ccde13161806fae71cf is CONFLICTING / DIRTY against main, so it cannot be reviewed for merge-readiness yet.

Next step
Please rebase or replace this branch against current main, then refresh CI. After it is clean, we can do the actual bug/priority review and decide whether it should stay in the P1/P2 lane.

Evidence checked
  • PR title: feat: add idle compaction trigger (idleCompactMinutes)
  • Live state: open, mergeable=CONFLICTING, mergeStateStatus=DIRTY.
  • Current labels: enhancement, priority:P2, stale-check
  • No existing maintainer-mode rebase marker was present before this comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request priority:P2 Important bug, compatibility, performance, or reliability issue stale-check Stale issue/PR being checked with the original reporter

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants