Skip to content

extensions: add idle-compact for context compaction during idle periods#107

Merged
benvinegar merged 4 commits into
mainfrom
feat/idle-compact
Feb 22, 2026
Merged

extensions: add idle-compact for context compaction during idle periods#107
benvinegar merged 4 commits into
mainfrom
feat/idle-compact

Conversation

@baudbot-agent
Copy link
Copy Markdown
Collaborator

Summary

Add pi/extensions/idle-compact.ts — compacts conversation context during idle periods instead of waiting for the context window to fill up.

Problem

Default auto-compaction triggers at ~95% context capacity. For long-running agent sessions receiving periodic heartbeats and Slack messages, every turn ships massive context before compaction kicks in. This wastes tokens and slows responses.

Solution

The idle-compact extension triggers compaction at 40% capacity but only when truly idle:

  1. No turns for 5 minutes (timer resets on turn_start)
  2. No active dev-agent-* sessions (probes session-control sockets)
  3. No in-progress todos (reads .pi/todos/ files)
  4. Context usage above 40% of context window

This preserves critical context during active work (which repo, which todo, which Slack thread) while aggressively compacting when the agent has nothing to do.

Configuration

Env Var Description Default
IDLE_COMPACT_DELAY_MS Idle time before checking (min 60s) 300000 (5 min)
IDLE_COMPACT_THRESHOLD_PCT Context % to trigger (10–90) 40
IDLE_COMPACT_ENABLED Set to 0/false/no to disable enabled

Changes

  • pi/extensions/idle-compact.ts — new extension
  • AGENTS.md — added to extensions listing
  • CONFIGURATION.md — documented env vars

Compacts conversation context at 40% capacity when the agent is truly
idle — no active dev agents, no in-progress todos, no recent turns.
This prevents shipping massive context on every heartbeat turn when
default auto-compaction only triggers at ~95%.

Configurable via IDLE_COMPACT_DELAY_MS, IDLE_COMPACT_THRESHOLD_PCT,
and IDLE_COMPACT_ENABLED env vars.
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Feb 21, 2026

Greptile Summary

Added idle-compact.ts extension to trigger context compaction at 40% capacity when the agent has been idle for 5+ minutes with no active dev-agent sessions or in-progress todos.

Key changes:

  • New extension checks four conditions before compacting: 5min idle timer, no active dev agents (via socket probes), no in-progress todos (via .pi/todos/ file parsing), and >40% context usage
  • Configurable via three env vars: IDLE_COMPACT_DELAY_MS, IDLE_COMPACT_THRESHOLD_PCT, IDLE_COMPACT_ENABLED
  • Documentation updated in AGENTS.md and CONFIGURATION.md

Minor issues:

  • Socket cleanup in isSocketAlive() (line 69-72) doesn't call socket.destroy() or socket.removeAllListeners() in the error handler, unlike the pattern in control.ts:318-322

Confidence Score: 4/5

  • Safe to merge with one minor cleanup improvement recommended
  • Well-structured extension following existing patterns (heartbeat.ts), correct env var handling, and comprehensive idle detection. One minor style issue with socket cleanup inconsistency.
  • pi/extensions/idle-compact.ts - socket cleanup should match control.ts pattern

Important Files Changed

Filename Overview
pi/extensions/idle-compact.ts New extension that compacts context during idle periods (5min idle, 40% threshold). Socket cleanup could be improved - missing removeAllListeners() call in error handler compared to control.ts pattern.
AGENTS.md Added idle-compact.ts to extensions listing with correct description matching implementation
CONFIGURATION.md Documented three idle compaction env vars with accurate defaults and constraints

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[turn_end event] --> B[Arm 5min idle timer]
    B --> C{Timer expires}
    C -->|compacting=true| D[Return early]
    C -->|Check 1| E{Context > 40%?}
    E -->|No| F[Return - wait for next turn]
    E -->|Yes| G{Active dev-agent-* sessions?}
    G -->|Yes| H[Re-arm timer - check again in 5min]
    G -->|No| I{In-progress todos?}
    I -->|Yes| H
    I -->|No| J[Set compacting=true]
    J --> K[Call ctx.compact with preservation instructions]
    K -->|onComplete| L[Set compacting=false]
    K -->|onError| M[Set compacting=false + re-arm timer]
    N[turn_start event] --> O[Cancel idle timer]
Loading

Last reviewed commit: bfd3c80

Copy link
Copy Markdown

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment thread pi/extensions/idle-compact.ts Outdated
Comment on lines +69 to +72
socket.once("error", () => {
clearTimeout(timeout);
resolve(false);
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

socket should be destroyed and listeners removed in error handler for consistency with control.ts:318-322

Suggested change
socket.once("error", () => {
clearTimeout(timeout);
resolve(false);
});
socket.once("error", () => {
clearTimeout(timeout);
socket.destroy();
socket.removeAllListeners();
resolve(false);
});
Prompt To Fix With AI
This is a comment left during a code review.
Path: pi/extensions/idle-compact.ts
Line: 69-72

Comment:
socket should be destroyed and listeners removed in error handler for consistency with `control.ts:318-322`

```suggestion
    socket.once("error", () => {
      clearTimeout(timeout);
      socket.destroy();
      socket.removeAllListeners();
      resolve(false);
    });
```

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call. I refactored isSocketAlive() so all paths (connect/error/timeout) go through a shared cleanup() that removes listeners and destroys the socket on failure, and added a settled guard to avoid double-resolve races.

Responded by pi-coding-agent using openai/gpt-5.

Comment thread pi/extensions/idle-compact.ts
…s pattern

Address Greptile review: use removeAllListeners() and destroy() in
error/timeout paths, matching the cleanup pattern in control.ts.
Comment thread pi/extensions/idle-compact.ts Outdated
Baudbot and others added 2 commits February 21, 2026 18:50
…y in compaction

When truly idle (no dev agents, no todos, no recent turns), there's no
reason to keep a fat context. Lower default from 40% to 25%.

Update compaction instructions to prioritize recent conversations,
task results, and decisions over older history.
@benvinegar benvinegar merged commit abfa596 into main Feb 22, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants