-
Notifications
You must be signed in to change notification settings - Fork 21
🤖 refactor: move compaction logic to backend #670
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
b186d47 to
7d2df23
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codex Review
Here are some automated review suggestions for this pull request.
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
7d2df23 to
2b2b2fc
Compare
|
@codex review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codex Review
Here are some automated review suggestions for this pull request.
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
@codex review |
1eda7a1 to
4560627
Compare
|
|
||
| // Wait for first stream to complete | ||
| const collector1 = createEventCollector(env.sentEvents, workspaceId); | ||
| await collector1.waitForEvent("stream-end", 30000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was flaking on Thomas' PRs too, so I've bumped the timeout
ibetitsmike
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm but I'd add some testing
## Stack 1. #685 1. #683 1. #670 1. #650 ⬅ This PR (base) ## Problem Compact continue messages were handled by a frontend hook that watched workspace states and manually sent continue messages after compaction. This was complex, had potential race conditions, and poor separation of concerns. Relates to #651. ## Solution Use the existing message queue system: - Backend queues continue message when compaction starts - Queue auto-sends when stream ends (existing behavior) - Clear queue on error paths **Benefits:** Simpler (-134 lines), more reliable, better UX (continue message visible in queue). _Generated with `mux`_
Move history compaction handling from WorkspaceStore to agentSession to centralize server-side operations. Backend changes: - Added handleCompactionCompletion() to detect and handle compaction stream-end events - Added handleCompactionAbort() to handle Ctrl+A (accept early with [truncated]) and Ctrl+C (cancel) flows - Added performCompaction() to atomically replace chat history with summary message - Added processedCompactionRequestIds Set to dedupe repeated compaction events - Implemented abandonPartial flag flow from IPC through to StreamAbortEvent - Extract truncated message content from history instead of partialService - Wrap compaction handlers in try-catch to ensure stream events always forwarded - Made performCompaction return Result type for proper error handling Frontend changes: - Removed compaction handlers from WorkspaceStore - Simplified cancelCompaction() to just call interruptStream with abandonPartial flag - Fixed Ctrl+A keybind to pass abandonPartial: false for early accept Shared changes: - Updated StreamAbortEvent to include abandonPartial flag - historyService.clearHistory() now returns deleted sequence numbers - Created calculateCumulativeUsage() utility to extract and sum usage from messages - aiService respects abandonPartial flag - skips committing when true
Move compaction handling from agentSession to dedicated CompactionHandler class. Changes: - Created src/node/services/compactionHandler.ts with CompactionHandler class - Extracted handleAbort, handleCompletion, and performCompaction methods - Updated agentSession.ts to delegate to CompactionHandler - Moved frontend compaction handler to browser utils - Reduced agentSession.ts from 764 to 589 lines Benefits: - Better separation of concerns - Easier to test compaction logic independently - Cleaner session orchestration code _Generated with `mux`_
e72e057 to
f93f212
Compare
## Stack 1. #685 1. #683 ⬅ This PR 1. #670 1. #650 (base) ## Summary Adds automatic context compaction that triggers at 70% usage, with progressive countdown warnings starting at 60%. <img width="905" height="155" alt="image" src="https://github.com/user-attachments/assets/b0db20c5-c377-44bb-891c-f8ddadd561c8" /> <img width="891" height="194" alt="image" src="https://github.com/user-attachments/assets/6385cfd2-5e3c-45ec-afce-935dae56ad1a" /> Relates to #651. ## Key Changes **Auto-Compaction:** - Triggers automatically when current context usage reaches 70% of model's context window - Queues user's message to send after compaction completes - Includes image parts in continue messages **Progressive Warnings:** - Shows countdown at 60-69% usage: "Context left until Auto-Compact: X% remaining" - Shows urgent message at 70%+: "⚠️ Approaching context limit. Next message will trigger auto-compaction." **Implementation:** - New `shouldAutoCompact()` utility centralizes threshold logic with configurable constants - Returns `{ shouldShowWarning, usagePercentage, thresholdPercentage }` - Uses **last usage entry** (current context size) to match UI token meter display - Excludes historical usage from threshold check to prevent infinite compaction loops - `ContinueMessage` type now includes optional `imageParts` ## Technical Details **Usage Calculation:** The auto-compaction check uses the most recent usage entry from `usageHistory` to calculate the current context size. This matches the percentage displayed in the UI token meter and correctly handles post-compaction scenarios: - **Before compaction**: Last entry represents full context → triggers at 70% correctly - **After compaction**: Last entry excludes historical usage → resets to actual context size - **Historical usage preserved**: Remains in usage history for cost tracking, but not used for threshold calculations This prevents the infinite loop where post-compaction workspaces would continuously re-compact because historical usage tokens were being included in the threshold check. ## Future Work Future PRs will add user settings to configure auto-compaction (enable/disable, custom threshold). _Generated with `mux`_
## Stack 1. #685 ⬅ This PR 1. #683 1. #670 1. #650 (base) Relates to #651. Adds per-workspace settings for auto-compaction (any percentage between 50 and 90): <img width="305" height="130" alt="image" src="https://github.com/user-attachments/assets/039e19d9-d95c-4249-8274-6a34116ee062" /> <img width="295" height="163" alt="image" src="https://github.com/user-attachments/assets/6095b100-732e-4c2c-bc39-3e66298245e4" /> **New Features:** - Toggle to enable/disable auto-compaction - Configurable threshold percentage (50-90%, default 70%) - Settings persist to localStorage and sync across tabs - UI integrated into right sidebar below existing settings **Implementation:** - Extracted threshold constants to `ui.ts` for DRY - Created reusable `useClampedNumberInput` hook for numeric input validation - Updated `shouldAutoCompact` to accept settings parameters - Follows existing patterns (uses `HelpIndicator` for tooltips) Settings are forked with workspace and cleaned up on workspace deletion. _Generated with `mux`_
Generated with
muxStack
Summary
Moves history compaction handling from WorkspaceStore (frontend) to agentSession (backend) to centralize server-side operations and fix race conditions.
Relates to #651.
Changes
Backend (agentSession.ts)
handleCompactionCompletion()- detects compaction stream-end, extracts summary from event.parts, performs history replacementhandleCompactionAbort()- handles Ctrl+A (accept early with[truncated]) and Ctrl+C (cancel) flowsperformCompaction()- atomically replaces chat history with summary message including cumulative usageabandonPartialflag flow from IPC through to StreamAbortEventFrontend (WorkspaceStore.ts)
handleCompactionCompletion()andhandleCompactionAbort()methodsperformCompaction()methodprocessedCompactionRequestIdsSetcancelCompaction()- just callsinterruptStreamwithabandonPartial: trueabandonPartial: falsefor early acceptShared
StreamAbortEventto includeabandonPartial?: booleanhistoryService.clearHistory()now returns deleted sequence numberscalculateCumulativeUsage()utility indisplayUsage.tsto extract and sum usage from messagesTesting
/compactcompletes successfully[truncated]