Skip to content

fix(web-ui): keep an admitted /compact out of the composer - #3588

Open
Raing5Days wants to merge 2 commits into
GCWing:mainfrom
Raing5Days:raing5days/fix-compact-composer-residue-20261028
Open

Raing5Days wants to merge 2 commits into
GCWing:mainfrom
Raing5Days:raing5days/fix-compact-composer-residue-20261028

Conversation

@Raing5Days

Copy link
Copy Markdown
Contributor

Problem

Submitting /compact put /compact back into the composer at the moment the compaction finished.

submitCompactFromInput clears the composer and then awaits the desktop compact_session command, which does not settle when the request is admitted: ConversationCoordinator::compact_session_manually awaits the terminal state of the maintenance turn. The failure path restored the submitted text, so the refill landed minutes later - including when the compaction had already been applied and only its terminal bookkeeping failed. /usage, /init and /reload use the same failure-restore pattern but return immediately, which is why only /compact shows the symptom.

Fix

  • Clear the composer through the submission contract - value, pending large pastes, machine queue, history cursor - before sending the command. A machine-queue entry left behind lets the queuedInput sync effect write the text back into the now-empty composer.
  • Restore /compact only when the host never admitted it. An early rejection (session busy, context not loaded, agent unavailable) creates no maintenance turn, so the text is still a retryable draft. Once a manual_compaction turn appeared after the submission, the outcome already lives in the transcript and the composer stays cleared.
  • Failure feedback is unchanged: a notification plus the turn's own terminal state in the transcript.

Verification

  • vitest run for the composer-ownership contract, the draft-recovery rules and the image-intake contract: 3 files / 22 tests pass.
  • tsc --noEmit on src/web-ui passes; ESLint reports no problems for the touched files.
  • Not reproduced against a running desktop build - a manual compaction needs a configured model and a session with history. The root cause is derived from the command's await semantics plus the /usage control case reported in the issue.

Notes

The desktop entry point stays blocking (its promise settles when the compaction ends). Making the Web UI observe the outcome through the turn events instead would be a separate change: it needs a non-blocking command path and a Product Operation Registry row.

The desktop /compact entry point only settles after the compaction reaches a terminal state, so restoring the command text from the failure path put '/compact' back into the composer long after it was submitted - including when the compaction had already been applied and only its terminal bookkeeping failed.

Treat the submitted command as committed: clear the composer through the submission contract (value, pending large pastes, machine queue, history cursor) and report a failure notification without refilling the composer. The outcome stays visible through the transcript turn and the compression card.
An early rejection (session busy, context not loaded, agent unavailable) never starts a maintenance turn, so handing /compact back for a retry is still correct. Once the host admitted the compaction its terminal outcome already lives in the transcript - and may have applied before its bookkeeping failed - so refilling the composer there resurrects the command minutes later.

Gate the restore on a maintenance turn that appeared after the submission.
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.

1 participant