extensions: add idle-compact for context compaction during idle periods#107
Merged
Conversation
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 SummaryAdded Key changes:
Minor issues:
Confidence Score: 4/5
Important Files Changed
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]
Last reviewed commit: bfd3c80 |
Comment on lines
+69
to
+72
| socket.once("error", () => { | ||
| clearTimeout(timeout); | ||
| resolve(false); | ||
| }); |
There was a problem hiding this comment.
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.
Member
There was a problem hiding this comment.
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.
…s pattern Address Greptile review: use removeAllListeners() and destroy() in error/timeout paths, matching the cleanup pattern in control.ts.
…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.
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.
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:
turn_start)dev-agent-*sessions (probes session-control sockets).pi/todos/files)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
IDLE_COMPACT_DELAY_MS300000(5 min)IDLE_COMPACT_THRESHOLD_PCT40IDLE_COMPACT_ENABLED0/false/noto disableChanges
pi/extensions/idle-compact.ts— new extensionAGENTS.md— added to extensions listingCONFIGURATION.md— documented env vars