From 7f288a49fc062fc6be802774186bb1166420b6c8 Mon Sep 17 00:00:00 2001 From: chengyongru <61816729+chengyongru@users.noreply.github.com> Date: Mon, 24 Aug 2026 14:32:48 +0800 Subject: [PATCH] fix(tui): preserve shell after Ctrl+C (#5502) --- tui/src/app.test.ts | 6 ++++-- tui/src/app.ts | 5 ++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/tui/src/app.test.ts b/tui/src/app.test.ts index fa6f52834..8f055ca23 100644 --- a/tui/src/app.test.ts +++ b/tui/src/app.test.ts @@ -2379,7 +2379,7 @@ describe("NanobotTui layout", () => { expect(exited).toEqual(["chat"]) }) - test("exits immediately when Ctrl+C is pressed on an idle empty composer", async () => { + test("exits after Ctrl+C input dispatch completes on an idle empty composer", async () => { setup = await createRenderer({ width: 72, height: 20, screenMode: "alternate-screen" }) let closed = false const transport = client() @@ -2393,7 +2393,9 @@ describe("NanobotTui layout", () => { setup.mockInput.pressCtrlC() - expect(closed).toBe(true) + expect(closed).toBe(false) + expect(setup.renderer.isDestroyed).toBe(false) + await waitUntil(() => closed) expect(setup.renderer.isDestroyed).toBe(true) }) diff --git a/tui/src/app.ts b/tui/src/app.ts index a2a1d32e3..dcb530a69 100644 --- a/tui/src/app.ts +++ b/tui/src/app.ts @@ -1653,7 +1653,10 @@ export class NanobotTui { this.clearComposer() this.status.content = this.readyStatus() } else { - this.quit() + // Finish dispatching the raw ETX before destroy() restores terminal input. + // Releasing the terminal from inside this callback can leak the same Ctrl+C + // to the parent shell on Windows terminals. + setTimeout(() => this.quit(), 0) } return }