fix(tui): ignore late thinking deltas after completion (#31055)

* fix(tui): ignore late thinking deltas after completion

Prevent stale reasoning events from repainting the TUI status after a turn has already completed and the UI is idle.

* test(tui): restore timers after thinking delta assertion

Keep fake timer cleanup in a finally block so assertion failures cannot leak timer mode into later tests.
This commit is contained in:
brooklyn!
2026-05-23 13:31:06 -05:00
committed by GitHub
parent e6ca730a22
commit 874c2b1fe6
2 changed files with 44 additions and 8 deletions

View File

@@ -1,6 +1,6 @@
import { STARTUP_IMAGE, STARTUP_QUERY } from '../config/env.js'
import { STREAM_BATCH_MS } from '../config/timing.js'
import { SETUP_REQUIRED_TITLE, buildSetupRequiredSections } from '../content/setup.js'
import { buildSetupRequiredSections, SETUP_REQUIRED_TITLE } from '../content/setup.js'
import type {
CommandsCatalogResponse,
ConfigFullResponse,
@@ -313,6 +313,10 @@ export function createGatewayEventHandler(ctx: GatewayEventHandlerContext): (ev:
}
case 'thinking.delta': {
if (!getUiState().busy) {
return
}
const text = ev.payload?.text
if (text !== undefined) {
@@ -340,6 +344,7 @@ export function createGatewayEventHandler(ctx: GatewayEventHandlerContext): (ev:
if (p.kind === 'goal') {
sys(p.text)
const brief = p.text.startsWith('✓')
? '✓ goal complete'
: p.text.startsWith('↻')
@@ -347,8 +352,10 @@ export function createGatewayEventHandler(ctx: GatewayEventHandlerContext): (ev:
: p.text.startsWith('⏸')
? '⏸ goal paused'
: 'ready'
setStatus(brief)
restoreStatusAfter(6000)
return
}
@@ -356,6 +363,7 @@ export function createGatewayEventHandler(ctx: GatewayEventHandlerContext): (ev:
if (p.kind === 'compressing') {
sys(p.text)
return
}
@@ -528,6 +536,7 @@ export function createGatewayEventHandler(ctx: GatewayEventHandlerContext): (ev:
case 'tool.complete': {
const inlineDiffText =
ev.payload.inline_diff && getUiState().inlineDiffs ? stripAnsi(String(ev.payload.inline_diff)).trim() : ''
const resultText = ev.payload.result_text ? stripAnsi(String(ev.payload.result_text)) : undefined
if (inlineDiffText) {
@@ -589,7 +598,6 @@ export function createGatewayEventHandler(ctx: GatewayEventHandlerContext): (ev:
sys(`[bg ${ev.payload.task_id}] ${ev.payload.text}`)
return
case 'review.summary': {
// Self-improvement background review emitted a persistent summary
// of what it saved to memory/skills. Surface it as a system line
@@ -597,6 +605,7 @@ export function createGatewayEventHandler(ctx: GatewayEventHandlerContext): (ev:
// flash. Python-side already formats it as "💾 Self-improvement
// review: …".
const text = String(ev.payload?.text ?? '').trim()
if (text) {
sys(text)
}