diff --git a/ui-tui/src/__tests__/createGatewayEventHandler.test.ts b/ui-tui/src/__tests__/createGatewayEventHandler.test.ts index c17aa565306..c09bd4ee966 100644 --- a/ui-tui/src/__tests__/createGatewayEventHandler.test.ts +++ b/ui-tui/src/__tests__/createGatewayEventHandler.test.ts @@ -81,6 +81,9 @@ describe('createGatewayEventHandler', () => { expect(finalText).toBeDefined() expect(trail).toMatchObject({ kind: 'trail', role: 'system', todos, todoIncomplete: true }) + // Todo archive must sit ABOVE the final assistant text so the panel + // doesn't visibly jump across the final answer at end-of-turn. + expect(appended.indexOf(trail!)).toBeLessThan(appended.indexOf(finalText!)) expect(getTurnState().todos).toEqual([]) }) diff --git a/ui-tui/src/app/createGatewayEventHandler.ts b/ui-tui/src/app/createGatewayEventHandler.ts index c314fc100b6..b0ef2daf251 100644 --- a/ui-tui/src/app/createGatewayEventHandler.ts +++ b/ui-tui/src/app/createGatewayEventHandler.ts @@ -537,9 +537,14 @@ export function createGatewayEventHandler(ctx: GatewayEventHandlerContext): (ev: const { finalMessages, finalText, wasInterrupted } = turnController.recordMessageComplete(ev.payload ?? {}) if (!wasInterrupted) { + // Archive the todo list FIRST so it sits above the final assistant + // text in the transcript — same position it held during streaming. + // Otherwise the panel would visibly jump from "above live answer" to + // "below final answer" at message.complete. + archiveTodosAtTurnEnd().forEach(appendMessage) + const msgs: Msg[] = finalMessages.length ? finalMessages : [{ role: 'assistant', text: finalText }] msgs.forEach(appendMessage) - archiveTodosAtTurnEnd().forEach(appendMessage) if (bellOnComplete && stdout?.isTTY) { stdout.write('\x07') diff --git a/ui-tui/src/components/appLayout.tsx b/ui-tui/src/components/appLayout.tsx index 0c13640765c..50a99e2325d 100644 --- a/ui-tui/src/components/appLayout.tsx +++ b/ui-tui/src/components/appLayout.tsx @@ -59,6 +59,8 @@ const TranscriptPane = memo(function TranscriptPane({ {transcript.virtualHistory.bottomSpacer > 0 ? : null} + + - -