mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-05 23:37:25 +00:00
fix(tui): stop writing OSC 133 prompt markers in regular mode (#11565)
In regular TUI mode, user and assistant messages wrote OSC 133 (`A`/`B`/`C`) shell-integration markers straight to the terminal. Terminals that display OSC 7501 program status (Rex, iTerm2 3.7.5+) read `133;A` as a new shell prompt and drop the current status. As a result, the `working` indicator disappeared right after a run started and only `done` showed up at the end. Fullscreen mode was not affected because it already strips these markers before writing. ## Change - `TuiMainScreen.doRender()` (`packages/tui/src/tui-main-screen.ts`) now strips OSC 133 markers from the start of each rendered line before compositing and writing. It uses the same pattern as fullscreen (`OSC133_ZONE_PREFIX`). - The message components still produce the markers. Fullscreen uses them internally for prompt navigation and already strips them before writing, so its behavior is unchanged. - In regular mode, the terminal's own jump-to-prompt shortcuts no longer stop at pi messages (added in #1805). ## Testing - New test in `packages/tui/test/tui-render.test.ts`: no `ESC]133;` reaches the terminal across a full render and a differential render, with both BEL and ST terminators. It fails without the change and passes with it. - These pass: - `packages/tui` `npm test` - `test/user-message.test.ts` and `test/assistant-message.test.ts` in coding-agent - `npm run check` - I ran `pi -ne --tui-mode regular` with `PI_PROGRAM_STATUS=1` and a streaming test provider, capturing all terminal output with `script`. - Before: `7501 working`, then repeated `133;A`/`133;B`/`133;C`, then `7501 done`. - After: only `7501 idle` → `working` → `done`, and no OSC 133. Fixes #11519 Requested by @davidbrai Co-authored-by: triagent <triagent@localhost>
This commit is contained in:
parent
ba7bdb9afc
commit
19ce8059c3
4 changed files with 25 additions and 1 deletions
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
### Fixed
|
||||
|
||||
- Fixed regular-mode `TUI` writing OSC 133 prompt markers from rendered lines to the terminal. Terminals treat `133;A` as a new shell prompt and drop the OSC 7501 program status, so the working indicator disappeared during runs. Fullscreen still uses the markers for prompt navigation and already stripped them ([#11519](https://github.com/earendil-works/pi/issues/11519))
|
||||
- Fixed fullscreen double-click selection splitting paths and tokens at `~`, `.`, `\`, and `+`. Word characters now match iTerm2's defaults ([#10980](https://github.com/earendil-works/pi/issues/10980))
|
||||
- Fixed `fuzzyMatch()` ranking a query scattered over an earlier part of the text above a contiguous match later in it. It now also scores each contiguous occurrence of the query and keeps the best alignment ([#11220](https://github.com/earendil-works/pi/issues/11220), [#11296](https://github.com/earendil-works/pi/pull/11296))
|
||||
- Fixed `ProcessTerminal.setTitle()` writing control characters from the title, which could end the title sequence and send the rest to the terminal as escape sequences
|
||||
|
|
|
|||
|
|
@ -5,6 +5,9 @@ import { deleteKittyImage, isImageLine } from "./terminal-image.ts";
|
|||
import { type TUI, TuiBase, type TuiStopOptions } from "./tui.ts";
|
||||
import { visibleWidth } from "./utils.ts";
|
||||
|
||||
/** OSC 133 prompt markers at the start of a rendered line. Fullscreen uses them for prompt navigation. */
|
||||
const OSC133_ZONE_PREFIX = /^(?:\x1b\]133;[ABC](?:\x07|\x1b\\))+/;
|
||||
|
||||
const KITTY_SEQUENCE_PREFIX = "\x1b_G";
|
||||
const MAX_RENDER_WRITE_CHARS = 1024 * 1024;
|
||||
|
||||
|
|
@ -262,7 +265,8 @@ export class TuiMainScreen extends TuiBase implements TUI {
|
|||
|
||||
// Render all components to get new lines
|
||||
// Resolve fake cursors before compositing so overlays and line slicing see plain SGR codes
|
||||
let newLines = this.resolveFakeCursors(this.render(width));
|
||||
// Drop OSC 133 markers: the terminal reads 133;A as a new shell prompt, which ends program status (OSC 7501)
|
||||
let newLines = this.resolveFakeCursors(this.render(width).map((line) => line.replace(OSC133_ZONE_PREFIX, "")));
|
||||
|
||||
// Composite overlays into the rendered lines (before differential compare)
|
||||
if (this.hasOverlayEntries) {
|
||||
|
|
|
|||
|
|
@ -209,6 +209,24 @@ describe("TUI bounded render output", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("TUI OSC 133 markers", () => {
|
||||
it("does not write OSC 133 prompt markers to the terminal", () => {
|
||||
// Terminals read 133;A as a new shell prompt and drop the OSC 7501 program status.
|
||||
const terminal = new BoundedWriteTerminal();
|
||||
const tui = new TuiMainScreen(terminal);
|
||||
const component = new TestComponent();
|
||||
tui.addChild(component);
|
||||
component.lines = ["\x1b]133;A\x07prompt", "\x1b]133;B\x07\x1b]133;C\x07output"];
|
||||
tui.renderNow();
|
||||
component.lines = [...component.lines, "\x1b]133;A\x1b\\reply", "\x1b]133;B\x1b\\\x1b]133;C\x1b\\done"];
|
||||
tui.renderNow();
|
||||
|
||||
const output = terminal.writes.join("");
|
||||
assert.ok(!output.includes("\x1b]133;"), "regular mode must not emit OSC 133 markers");
|
||||
for (const text of ["prompt", "output", "reply", "done"]) assert.ok(output.includes(text));
|
||||
});
|
||||
});
|
||||
|
||||
/** Set each environment variable to `value`, returning a function that restores the previous state. */
|
||||
function overrideEnv(names: readonly string[], value: string): () => void {
|
||||
const previousValues = names.map((name) => [name, process.env[name]] as const);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue