fix(tui): keep terminal progress alive

closes #3610
This commit is contained in:
Mario Zechner
2026-04-23 23:39:06 +02:00
parent 19f2478599
commit 76bc605ad1
2 changed files with 28 additions and 2 deletions

View File

@@ -2,6 +2,10 @@
## [Unreleased]
### Fixed
- Kept OSC 9;4 terminal progress alive with periodic updates so Ghostty does not clear the indicator during long-running agent work ([#3610](https://github.com/badlogic/pi-mono/issues/3610))
## [0.69.0] - 2026-04-22
### Added

View File

@@ -6,6 +6,10 @@ import { StdinBuffer } from "./stdin-buffer.js";
const cjsRequire = createRequire(import.meta.url);
const TERMINAL_PROGRESS_KEEPALIVE_MS = 1000;
const TERMINAL_PROGRESS_ACTIVE_SEQUENCE = "\x1b]9;4;3\x07";
const TERMINAL_PROGRESS_CLEAR_SEQUENCE = "\x1b]9;4;0;\x07";
/**
* Minimal terminal interface for TUI
*/
@@ -64,6 +68,7 @@ export class ProcessTerminal implements Terminal {
private _modifyOtherKeysActive = false;
private stdinBuffer?: StdinBuffer;
private stdinDataHandler?: (data: string) => void;
private progressInterval?: ReturnType<typeof setInterval>;
private writeLogPath = (() => {
const env = process.env.PI_TUI_WRITE_LOG || "";
if (!env) return "";
@@ -264,6 +269,10 @@ export class ProcessTerminal implements Terminal {
}
stop(): void {
if (this.clearProgressInterval()) {
process.stdout.write(TERMINAL_PROGRESS_CLEAR_SEQUENCE);
}
// Disable bracketed paste mode
process.stdout.write("\x1b[?2004l");
@@ -364,10 +373,23 @@ export class ProcessTerminal implements Terminal {
setProgress(active: boolean): void {
if (active) {
// OSC 9;4;3 - indeterminate progress
process.stdout.write("\x1b]9;4;3\x07");
process.stdout.write(TERMINAL_PROGRESS_ACTIVE_SEQUENCE);
if (!this.progressInterval) {
this.progressInterval = setInterval(() => {
process.stdout.write(TERMINAL_PROGRESS_ACTIVE_SEQUENCE);
}, TERMINAL_PROGRESS_KEEPALIVE_MS);
}
} else {
this.clearProgressInterval();
// OSC 9;4;0 - clear progress
process.stdout.write("\x1b]9;4;0;\x07");
process.stdout.write(TERMINAL_PROGRESS_CLEAR_SEQUENCE);
}
}
private clearProgressInterval(): boolean {
if (!this.progressInterval) return false;
clearInterval(this.progressInterval);
this.progressInterval = undefined;
return true;
}
}