fix(onboarding): exit cleanly after web ui hatch

This commit is contained in:
Peter Steinberger
2026-02-13 03:20:25 +01:00
parent 65be9ccf63
commit cd50b5ded2
3 changed files with 55 additions and 7 deletions

View File

@@ -2,6 +2,12 @@
Docs: https://docs.openclaw.ai
## 2026.2.13 (Unreleased)
### Fixes
- Onboarding/CLI: restore terminal state without resuming paused `stdin`, so onboarding exits cleanly after choosing Web UI and the installer returns instead of appearing stuck.
## 2026.2.12
### Changes

View File

@@ -0,0 +1,49 @@
import { afterEach, describe, expect, it, vi } from "vitest";
const clearActiveProgressLine = vi.hoisted(() => vi.fn());
vi.mock("./progress-line.js", () => ({
clearActiveProgressLine,
}));
import { restoreTerminalState } from "./restore.js";
describe("restoreTerminalState", () => {
const originalStdinIsTTY = process.stdin.isTTY;
const originalStdoutIsTTY = process.stdout.isTTY;
const originalSetRawMode = (process.stdin as { setRawMode?: (mode: boolean) => void }).setRawMode;
const originalResume = (process.stdin as { resume?: () => void }).resume;
const originalIsPaused = (process.stdin as { isPaused?: () => boolean }).isPaused;
afterEach(() => {
vi.restoreAllMocks();
Object.defineProperty(process.stdin, "isTTY", {
value: originalStdinIsTTY,
configurable: true,
});
Object.defineProperty(process.stdout, "isTTY", {
value: originalStdoutIsTTY,
configurable: true,
});
(process.stdin as { setRawMode?: (mode: boolean) => void }).setRawMode = originalSetRawMode;
(process.stdin as { resume?: () => void }).resume = originalResume;
(process.stdin as { isPaused?: () => boolean }).isPaused = originalIsPaused;
});
it("does not resume paused stdin while restoring raw mode", () => {
const setRawMode = vi.fn();
const resume = vi.fn();
const isPaused = vi.fn(() => true);
Object.defineProperty(process.stdin, "isTTY", { value: true, configurable: true });
Object.defineProperty(process.stdout, "isTTY", { value: false, configurable: true });
(process.stdin as { setRawMode?: (mode: boolean) => void }).setRawMode = setRawMode;
(process.stdin as { resume?: () => void }).resume = resume;
(process.stdin as { isPaused?: () => boolean }).isPaused = isPaused;
restoreTerminalState("test");
expect(setRawMode).toHaveBeenCalledWith(false);
expect(resume).not.toHaveBeenCalled();
});
});

View File

@@ -26,13 +26,6 @@ export function restoreTerminalState(reason?: string): void {
} catch (err) {
reportRestoreFailure("raw mode", err, reason);
}
if (typeof stdin.isPaused === "function" && stdin.isPaused()) {
try {
stdin.resume();
} catch (err) {
reportRestoreFailure("stdin resume", err, reason);
}
}
}
if (process.stdout.isTTY) {