fix(tui): responsive /compress with live progress + CLI-parity feedback (#17661)

* fix(tui): offload manual compaction RPC

Route TUI session compression through the existing long-handler pool so slow compaction does not block other gateway RPCs.

* fix(tui): show compaction progress immediately

Print a local status line before the compress RPC starts so slow manual compaction does not look like a no-op.

* feat(tui): rich /compress feedback parity with CLI

Show pre-compaction message count and rough token estimate immediately, emit a status update so the bottom bar reflects ongoing compaction, and report a multi-line summary (headline + token delta + optional note) using the shared summarize_manual_compression helper.

* fix(tui): show live compaction estimate in transcript

Mirror compression progress status into the transcript so users see the backend message count and token estimate while /compress is still running.

* fix(tui): single live compaction line with spinner glyph

Drop the redundant local "compressing context..." placeholder and prefix the live backend status line with a braille spinner glyph so /compress reads as a single in-progress row.

* fix(tui): address review nits on /compress feedback

Reuse the precomputed token estimate inside _compress_session_history so the gateway does not redo the O(n) work while holding history_lock, keep the status bar pinned during long manual compactions instead of auto-restoring after 4s, and drop the redundant noop bullet that doubled with the system role glyph.

* fix(tui): release history_lock during compaction LLM call

Move the snapshot/commit pattern into _compress_session_history so the lock is held only across the in-memory bookkeeping, not during agent._compress_context. Also emit a final neutral status update from session.compress so the pinned compressing indicator clears even on errors.

* fix(tui): rebuild prompt cleanly + sync session_key after compress

Pass system_message=None so AIAgent._compress_context rebuilds the system prompt without nesting the cached identity block. Reuse the handler's pre-snapshotted history inside _compress_session_history to avoid a second O(n) copy under the lock. After compaction, when AIAgent._compress_context rotates session_id, sync the gateway session_key, migrate approval notify + yolo state, restart the slash worker, and clear the stale pending title. Mirrors HermesCLI._manual_compress.

* Avoid /compress lock re-entry in slash side effects.

Stop pre-locking history before _compress_session_history in slash command mirroring, keep session-key sync parity with manual compression, and add a regression test that asserts /compress is invoked without holding history_lock.
This commit is contained in:
brooklyn! 2026-04-29 18:01:18 -07:00 committed by GitHub
parent 98f5be13fa
commit fc7f55f490
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 309 additions and 29 deletions

View file

@ -282,6 +282,11 @@ export function createGatewayEventHandler(ctx: GatewayEventHandlerContext): (ev:
setStatus(p.text)
if (p.kind === 'compressing') {
sys(p.text)
return
}
if (!p.kind || p.kind === 'status') {
return
}

View file

@ -154,6 +154,22 @@ export const sessionCommands: SlashCommand[] = [
patchUiState(state => ({ ...state, usage: { ...state.usage, ...r.usage } }))
}
if (r.summary?.headline) {
const prefix = r.summary.noop ? '' : '✓ '
ctx.transcript.sys(`${prefix}${r.summary.headline}`)
if (r.summary.token_line) {
ctx.transcript.sys(` ${r.summary.token_line}`)
}
if (r.summary.note) {
ctx.transcript.sys(` ${r.summary.note}`)
}
return
}
if ((r.removed ?? 0) <= 0) {
return ctx.transcript.sys('nothing to compress')
}
@ -163,6 +179,7 @@ export const sessionCommands: SlashCommand[] = [
)
})
)
.catch(ctx.guardedErr)
}
},