@oh-my-pi/pi-tui 18.1.22 → 18.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -0
- package/THIRD-PARTY-NOTICES.txt +54 -25
- package/dist/types/autocomplete.d.ts +2 -1
- package/dist/types/components/editor.d.ts +16 -0
- package/dist/types/components/image.d.ts +49 -7
- package/dist/types/terminal-capabilities.d.ts +24 -0
- package/dist/types/terminal-multiplexer.d.ts +17 -1
- package/dist/types/terminal.d.ts +17 -2
- package/package.json +3 -3
- package/src/autocomplete.ts +48 -19
- package/src/components/editor.ts +95 -54
- package/src/components/image.ts +244 -45
- package/src/terminal-capabilities.ts +104 -38
- package/src/terminal-multiplexer.ts +31 -10
- package/src/terminal.ts +29 -12
- package/src/tui.ts +404 -136
|
@@ -10,15 +10,36 @@ export function isInsideHerdr(env: NodeJS.ProcessEnv = Bun.env): boolean {
|
|
|
10
10
|
return false;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
/**
|
|
14
|
-
export
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
13
|
+
/** Terminal multiplexers omp recognizes as owning the screen grid. */
|
|
14
|
+
export type TerminalMultiplexer = "herdr" | "tmux" | "screen" | "zellij" | "cmux" | "wmux";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Classify which terminal multiplexer owns the current screen grid, or `null`
|
|
18
|
+
* for a direct terminal. Single source of truth for both the render-path gate
|
|
19
|
+
* (`isInsideTerminalMultiplexer`) and the debug snapshot label.
|
|
20
|
+
*
|
|
21
|
+
* TMUX/STY/ZELLIJ, Herdr, and the CMUX/WMUX workspace/surface/remote-transport
|
|
22
|
+
* markers are authoritative session signals. TERM can also survive when those
|
|
23
|
+
* are stripped (`sudo` without -E, `su`, env-sanitizing launchers/ssh). Do not
|
|
24
|
+
* use CMUX_SOCKET_PATH / WMUX_CLI / WMUX_PIPE here: they are CLI socket/path
|
|
25
|
+
* overrides and can be set outside a CMUX/WMUX terminal. wmux is a Windows
|
|
26
|
+
* multiplexer (Electron + xterm.js) modeled on cmux/herdr that repaints its
|
|
27
|
+
* pane in place and exports WMUX=1 plus a native WMUX_SURFACE_ID.
|
|
28
|
+
*/
|
|
29
|
+
export function classifyTerminalMultiplexer(env: NodeJS.ProcessEnv = Bun.env): TerminalMultiplexer | null {
|
|
30
|
+
if (isInsideHerdr(env)) return "herdr";
|
|
31
|
+
if (env.TMUX) return "tmux";
|
|
32
|
+
if (env.STY) return "screen";
|
|
33
|
+
if (env.ZELLIJ) return "zellij";
|
|
34
|
+
if (env.CMUX_WORKSPACE_ID || env.CMUX_SURFACE_ID || env.CMUX_REMOTE_TRANSPORT) return "cmux";
|
|
35
|
+
if (env.WMUX === "1" || env.WMUX_SURFACE_ID) return "wmux";
|
|
22
36
|
const term = env.TERM?.toLowerCase() ?? "";
|
|
23
|
-
|
|
37
|
+
if (term.startsWith("tmux")) return "tmux";
|
|
38
|
+
if (term.startsWith("screen")) return "screen";
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** True when a terminal multiplexer owns the current screen grid. */
|
|
43
|
+
export function isInsideTerminalMultiplexer(env: NodeJS.ProcessEnv = Bun.env): boolean {
|
|
44
|
+
return classifyTerminalMultiplexer(env) !== null;
|
|
24
45
|
}
|
package/src/terminal.ts
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
import { dlopen, FFIType, ptr } from "bun:ffi";
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
3
|
import { TtyWriter } from "@oh-my-pi/pi-natives";
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
isWsl,
|
|
9
|
-
logger,
|
|
10
|
-
postmortem,
|
|
11
|
-
restoreTerminalStderr,
|
|
12
|
-
suppressTerminalStderr,
|
|
13
|
-
} from "@oh-my-pi/pi-utils";
|
|
4
|
+
import { $env, isBunTestRuntime, isTerminalHeadless, isWsl } from "@oh-my-pi/pi-utils/env";
|
|
5
|
+
import * as logger from "@oh-my-pi/pi-utils/logger";
|
|
6
|
+
import * as postmortem from "@oh-my-pi/pi-utils/postmortem";
|
|
7
|
+
import { restoreTerminalStderr, suppressTerminalStderr } from "@oh-my-pi/pi-utils/stderr-guard";
|
|
14
8
|
import { setKittyProtocolActive } from "./keys";
|
|
15
9
|
import { StdinBuffer } from "./stdin-buffer";
|
|
16
10
|
import {
|
|
@@ -520,6 +514,20 @@ export interface Terminal {
|
|
|
520
514
|
*/
|
|
521
515
|
readonly pendingOutputBytes?: number;
|
|
522
516
|
|
|
517
|
+
/**
|
|
518
|
+
* Whether a pseudoconsole host owns the grid this terminal writes to, so
|
|
519
|
+
* neither the cursor nor the painted rows survive a resize under the
|
|
520
|
+
* application's own model. Measured on Windows conhost: resizing the
|
|
521
|
+
* pseudoconsole makes it re-emit its whole viewport from `CSI H` with
|
|
522
|
+
* absolute addressing while the application writes nothing, and it re-homes
|
|
523
|
+
* the cursor, so a DSR reply after a resize reports column 1 instead of the
|
|
524
|
+
* column the application parked. The renderer's resize anchor recovery needs
|
|
525
|
+
* both properties, so it takes the rebuild path instead when this is set.
|
|
526
|
+
* Optional so custom Terminals built against older pi-tui versions keep
|
|
527
|
+
* working; absent means the terminal itself owns the grid.
|
|
528
|
+
*/
|
|
529
|
+
readonly hostOwnsGridOnResize?: boolean;
|
|
530
|
+
|
|
523
531
|
// Whether Kitty keyboard protocol is active
|
|
524
532
|
get kittyProtocolActive(): boolean;
|
|
525
533
|
|
|
@@ -662,8 +670,9 @@ function isPrivateModeSupported(status: string): boolean {
|
|
|
662
670
|
export interface ProcessTerminalOptions {
|
|
663
671
|
/**
|
|
664
672
|
* Force ConPTY-hosted behavior on or off. Defaults to live detection via
|
|
665
|
-
* {@link isConPTYHosted}. Tests set this so the kitty-flag
|
|
666
|
-
*
|
|
673
|
+
* {@link isConPTYHosted}. Tests set this so the kitty-flag, write-chunking
|
|
674
|
+
* and resize-routing ({@link Terminal.hostOwnsGridOnResize}) paths stay
|
|
675
|
+
* hermetic regardless of the ambient WSL env (`WSL_DISTRO_NAME` /
|
|
667
676
|
* `WSL_INTEROP`) — the suite must behave identically on WSL and on CI.
|
|
668
677
|
*/
|
|
669
678
|
conpty?: boolean;
|
|
@@ -1995,6 +2004,14 @@ export class ProcessTerminal implements Terminal {
|
|
|
1995
2004
|
return process.stdout.writableLength ?? 0;
|
|
1996
2005
|
}
|
|
1997
2006
|
|
|
2007
|
+
get hostOwnsGridOnResize(): boolean {
|
|
2008
|
+
// #conpty, not a fresh isConPTYHosted() call: the construction override
|
|
2009
|
+
// must gate every ConPTY-dependent path uniformly, or an injected
|
|
2010
|
+
// `conpty` value models one host for writes and kitty flags and the
|
|
2011
|
+
// opposite host for resize routing.
|
|
2012
|
+
return this.#conpty;
|
|
2013
|
+
}
|
|
2014
|
+
|
|
1998
2015
|
/**
|
|
1999
2016
|
* Reconcile the stdout backlog after a write or a poll. The watchdog runs an
|
|
2000
2017
|
* episode from the moment the backlog crosses the arm cap until it drains to
|