Skip to content

Conversation

@ethanndickson
Copy link
Member

@ethanndickson ethanndickson commented Nov 20, 2025

Stack

  1. 🤖 feat: add auto-compaction configuration UI #685 ⬅ This PR
  2. 🤖 feat: add auto-compaction with progressive warnings #683
  3. 🤖 refactor: move compaction logic to backend #670
  4. 🤖 refactor: use message queue for compact continue messages #650 (base)

Relates to #651.

Adds per-workspace settings for auto-compaction (any percentage between 50 and 90):

image image

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

github-merge-queue bot pushed a commit that referenced this pull request Nov 21, 2025
## 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`_
github-merge-queue bot pushed a commit that referenced this pull request Nov 21, 2025
_Generated with `mux`_

## Stack
1. #685 
1. #683 
1. #670  ⬅ This PR
1. #650 (base)


## 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)
- Added `handleCompactionCompletion()` - detects compaction stream-end,
extracts summary from event.parts, performs history replacement
- Added `handleCompactionAbort()` - handles Ctrl+A (accept early with
`[truncated]`) and Ctrl+C (cancel) flows
- Added `performCompaction()` - atomically replaces chat history with
summary message including cumulative usage
- Implemented `abandonPartial` flag flow from IPC through to
StreamAbortEvent
- Extracts truncated message content from history instead of
partialService

### Frontend (WorkspaceStore.ts)
- Removed `handleCompactionCompletion()` and `handleCompactionAbort()`
methods
- Removed `performCompaction()` method
- Removed `processedCompactionRequestIds` Set
- Simplified `cancelCompaction()` - just calls `interruptStream` with
`abandonPartial: true`
- Fixed Ctrl+A keybind to pass `abandonPartial: false` for early accept

### Shared
- Updated `StreamAbortEvent` to include `abandonPartial?: boolean`
- `historyService.clearHistory()` now returns deleted sequence numbers
- Created `calculateCumulativeUsage()` utility in `displayUsage.ts` to
extract and sum usage from messages

## Testing
- [x] Manual: `/compact` completes successfully
- [x] Manual: Ctrl+A during compaction accepts early with `[truncated]`
- [x] Manual: Ctrl+C during compaction cancels and enters edit mode
- [x] Verify cumulative usage preserved across multiple compactions
@ethanndickson ethanndickson force-pushed the frontend-auto-compaction-queue branch from 2438689 to 087e85f Compare November 21, 2025 01:56
@ethanndickson ethanndickson reopened this Nov 21, 2025
@ethanndickson ethanndickson force-pushed the auto-compaction-config branch 2 times, most recently from 7faf26f to d9e9139 Compare November 21, 2025 09:10
@ethanndickson
Copy link
Member Author

@codex review

@chatgpt-codex-connector
Copy link

Codex Review: Didn't find any major issues. Breezy!

ℹ️ 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".

- Countdown warning (60-69%): Small grey text, right-aligned
- Urgent warning (70%+): Keep prominent blue box styling
- Makes countdown unobtrusive while keeping urgent warning visible

_Generated with `mux`_
@ethanndickson ethanndickson force-pushed the frontend-auto-compaction-queue branch from e2149ae to 444c3ba Compare November 24, 2025 01:57
Adds !isCompacting check to shouldAutoCompact calculation to prevent
queueing a second compaction request when user sends a message while
the first compaction is still running.

Without this check, messages sent during compaction would trigger
another compaction, resulting in back-to-back compactions and
delayed user messages.

_Generated with `mux`_
@ethanndickson ethanndickson linked an issue Nov 24, 2025 that may be closed by this pull request
Adds 23 unit tests covering:
- Basic functionality (safe defaults, threshold detection)
- Usage calculation (last entry vs cumulative, historical usage handling)
- 1M context mode (model support, fallback behavior)
- Edge cases (zero tokens, custom thresholds, boundary conditions)
- Percentage calculation accuracy

All tests verify the infinite loop fix - that historical usage from
compaction is correctly excluded from threshold calculations.

Tests run: 23 pass, 0 fail, 62 expect() calls

_Generated with `mux`_
- Add configurable auto-compaction threshold (50-90%) per workspace
- Extract threshold constants to ui.ts (DRY)
- Create reusable useClampedNumberInput hook for numeric inputs
- Add settings to right sidebar with checkbox and percentage input
- Wire settings through to shouldAutoCompact check
- Use existing HelpIndicator pattern for tooltips
- Rename shouldAutoCompact to checkAutoCompaction in tests
- Add enabled parameter to all test function calls
- Remove enabled field assertions (no longer in return type)
- Fix function parameter ordering for custom threshold tests
- All 23 tests passing
@ethanndickson ethanndickson force-pushed the frontend-auto-compaction-queue branch 2 times, most recently from a4f8272 to b184dcf Compare November 25, 2025 00:46
@ethanndickson
Copy link
Member Author

@codex review

chatgpt-codex-connector[bot]

This comment was marked as resolved.

@ethanndickson
Copy link
Member Author

@codex review

@chatgpt-codex-connector
Copy link

Codex Review: Didn't find any major issues. Nice work!

ℹ️ 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".

github-merge-queue bot pushed a commit that referenced this pull request Nov 25, 2025
## 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`_
Base automatically changed from frontend-auto-compaction-queue to main November 25, 2025 03:38
@ethanndickson ethanndickson added this pull request to the merge queue Nov 25, 2025
Merged via the queue into main with commit 714677a Nov 25, 2025
13 checks passed
@ethanndickson ethanndickson deleted the auto-compaction-config branch November 25, 2025 04:03
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.

Automatic context compaction

1 participant