@code-yeongyu/senpi-tui 2026.11.3-1 → 2026.11.3-3
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/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/program-status.d.ts +20 -0
- package/dist/program-status.js +45 -0
- package/dist/terminal.d.ts +4 -0
- package/dist/terminal.js +15 -2
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -34,6 +34,7 @@ export { parseTerminalColorSchemeReport, type RgbColor, type TerminalColorScheme
|
|
|
34
34
|
export declare function calculateImageRows(imageDimensions: ImageDimensions, targetWidthCells: number, cellDimensions?: CellDimensions): number;
|
|
35
35
|
export { allocateImageId, buildKittyPlaceholderRow, type CellDimensions, deleteAllKittyImages, deleteKittyImage, detectCapabilities, encodeITerm2, encodeKitty, getCapabilities, getCellDimensions, getGifDimensions, getImageDimensions, getJpegDimensions, getPngDimensions, getTerminalColorMode, getWebpDimensions, hyperlink, type ImageDimensions, type ImageProtocol, type ImageRenderOptions, imageFallback, KITTY_PLACEHOLDER_MAX, outerKittyGraphicsMode, renderImage, resetCapabilitiesCache, setCapabilities, setCapabilityOverrides, setCellDimensions, type TerminalCapabilities, type TmuxPassthroughState, wrapTmuxPassthrough, } from "./terminal-image.ts";
|
|
36
36
|
export { sanitizeTerminalLabel, shortenImagePath } from "./terminal-text.ts";
|
|
37
|
+
export { encodeProgramStatus, type ProgramStatus, type ProgramStatusKind, type ProgramStatusState, } from "./program-status.ts";
|
|
37
38
|
export { type Component, CompositeRevision, Container, CURSOR_MARKER, claimFrameRow, compositeTuiLine, currentRenderRevision, dispatchMouseEvent, type Focusable, type FrameLineBytesTotals, frameLineBytesTotals, frameMode, frameScrollbackRows, isFocusable, isViewportTUI, joinLineArrays, mainScreenHistoryLines, nextRenderRevision, type OverlayAnchor, type OverlayBounds, type OverlayHandle, type OverlayMargin, type OverlayOptions, type OverlayUnfocusOptions, renderAtFrameRow, resetMainScreenHistoryLines, type SizeValue, TUI, type TuiInputListener, type TuiInputListenerResult, type TuiMode, type TuiMouseButton, type TuiMouseDispatchResult, type TuiMouseEvent, type TuiMouseEventResult, type TuiMouseEventType, type TuiStopOptions, type ViewportTUI, } from "./tui.ts";
|
|
38
39
|
export { TuiAltScreen, type TuiAltScreenOptions } from "./tui-alt-screen.ts";
|
|
39
40
|
export { TuiMainScreen, type TuiMainScreenRenderState } from "./tui-main-screen.ts";
|
package/dist/index.js
CHANGED
|
@@ -49,6 +49,7 @@ export function calculateImageRows(imageDimensions, targetWidthCells, cellDimens
|
|
|
49
49
|
}
|
|
50
50
|
export { allocateImageId, buildKittyPlaceholderRow, deleteAllKittyImages, deleteKittyImage, detectCapabilities, encodeITerm2, encodeKitty, getCapabilities, getCellDimensions, getGifDimensions, getImageDimensions, getJpegDimensions, getPngDimensions, getTerminalColorMode, getWebpDimensions, hyperlink, imageFallback, KITTY_PLACEHOLDER_MAX, outerKittyGraphicsMode, renderImage, resetCapabilitiesCache, setCapabilities, setCapabilityOverrides, setCellDimensions, wrapTmuxPassthrough, } from "./terminal-image.js";
|
|
51
51
|
export { sanitizeTerminalLabel, shortenImagePath } from "./terminal-text.js";
|
|
52
|
+
export { encodeProgramStatus, } from "./program-status.js";
|
|
52
53
|
export { CompositeRevision, Container, CURSOR_MARKER, claimFrameRow, compositeTuiLine, currentRenderRevision, dispatchMouseEvent, frameLineBytesTotals, frameMode, frameScrollbackRows, isFocusable, isViewportTUI, joinLineArrays, mainScreenHistoryLines, nextRenderRevision, renderAtFrameRow, resetMainScreenHistoryLines, TUI, } from "./tui.js";
|
|
53
54
|
export { TuiAltScreen } from "./tui-alt-screen.js";
|
|
54
55
|
export { TuiMainScreen } from "./tui-main-screen.js";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OSC 7501 Program Status Protocol (rev 0.4): a program tells its terminal whether it is idle, working,
|
|
3
|
+
* blocked on the user, done or failed. https://control-codes.page/proposals/osc-7501/
|
|
4
|
+
*/
|
|
5
|
+
export type ProgramStatusState = "idle" | "working" | "blocked" | "done" | "error";
|
|
6
|
+
export type ProgramStatusKind = "permission" | "question" | "auth";
|
|
7
|
+
export interface ProgramStatus {
|
|
8
|
+
state: ProgramStatusState;
|
|
9
|
+
/** How the user must act; only sent with `blocked`. */
|
|
10
|
+
kind?: ProgramStatusKind;
|
|
11
|
+
/** One line on what the program is doing or waiting for. */
|
|
12
|
+
message?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Build the OSC 7501 report for `status`, or the `state=clear` report that removes every record when it is
|
|
16
|
+
* undefined. `app` is repeated in every report because each one replaces its record; an app name outside the
|
|
17
|
+
* protocol's charset or length is left out rather than sent for the terminal to discard.
|
|
18
|
+
*/
|
|
19
|
+
export declare function encodeProgramStatus(status: ProgramStatus | undefined, app?: string): string;
|
|
20
|
+
//# sourceMappingURL=program-status.d.ts.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OSC 7501 Program Status Protocol (rev 0.4): a program tells its terminal whether it is idle, working,
|
|
3
|
+
* blocked on the user, done or failed. https://control-codes.page/proposals/osc-7501/
|
|
4
|
+
*/
|
|
5
|
+
const MAX_MESSAGE_BYTES = 2048;
|
|
6
|
+
const APP_PATTERN = /^[A-Za-z0-9_.+-]{1,32}$/;
|
|
7
|
+
// C0, DEL and C1 controls: a decoded msg holding any of them makes the terminal drop the whole report.
|
|
8
|
+
const CONTROL_PATTERN = /[\u0000-\u001f\u007f-\u009f]+/g;
|
|
9
|
+
// Bidi overrides/isolates and invisible formatting, which a terminal may show outside the grid.
|
|
10
|
+
const INVISIBLE_FORMATTING_PATTERN = /[\u00ad\u061c\u180e\u200b\u200e\u200f\u202a-\u202e\u2060-\u2064\u2066-\u2069\ufeff]/g;
|
|
11
|
+
function sanitizeMessage(message) {
|
|
12
|
+
return message.replace(INVISIBLE_FORMATTING_PATTERN, "").replace(CONTROL_PATTERN, " ").replace(/\s+/g, " ").trim();
|
|
13
|
+
}
|
|
14
|
+
function truncateUtf8(text, maxBytes) {
|
|
15
|
+
if (Buffer.byteLength(text, "utf8") <= maxBytes)
|
|
16
|
+
return text;
|
|
17
|
+
let bytes = 0;
|
|
18
|
+
let result = "";
|
|
19
|
+
for (const char of text) {
|
|
20
|
+
bytes += Buffer.byteLength(char, "utf8");
|
|
21
|
+
if (bytes > maxBytes)
|
|
22
|
+
break;
|
|
23
|
+
result += char;
|
|
24
|
+
}
|
|
25
|
+
return result;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Build the OSC 7501 report for `status`, or the `state=clear` report that removes every record when it is
|
|
29
|
+
* undefined. `app` is repeated in every report because each one replaces its record; an app name outside the
|
|
30
|
+
* protocol's charset or length is left out rather than sent for the terminal to discard.
|
|
31
|
+
*/
|
|
32
|
+
export function encodeProgramStatus(status, app) {
|
|
33
|
+
if (status === undefined)
|
|
34
|
+
return "\x1b]7501;state=clear\x1b\\";
|
|
35
|
+
const pairs = [`state=${status.state}`];
|
|
36
|
+
if (status.state === "blocked" && status.kind !== undefined)
|
|
37
|
+
pairs.push(`kind=${status.kind}`);
|
|
38
|
+
if (app !== undefined && APP_PATTERN.test(app))
|
|
39
|
+
pairs.push(`app=${app}`);
|
|
40
|
+
const message = status.message === undefined ? "" : truncateUtf8(sanitizeMessage(status.message), MAX_MESSAGE_BYTES);
|
|
41
|
+
if (message.length > 0)
|
|
42
|
+
pairs.push(`msg=${Buffer.from(message, "utf8").toString("base64")}`);
|
|
43
|
+
return `\x1b]7501;${pairs.join(":")}\x1b\\`;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=program-status.js.map
|
package/dist/terminal.d.ts
CHANGED
|
@@ -22,6 +22,10 @@ export declare function isAppleTerminalSession(): boolean;
|
|
|
22
22
|
*/
|
|
23
23
|
export declare function refreshTerminalDimensions(): void;
|
|
24
24
|
export declare function normalizeNativeShiftEnterInput(data: string, shouldDetectNativeShiftEnter: boolean, isShiftPressed: boolean): string;
|
|
25
|
+
/**
|
|
26
|
+
* Terminal.app can deliver Shift+Return as ESC CR, which legacy key parsing reads as Alt+Enter.
|
|
27
|
+
* The pressed native Shift keeps it apart from an Option-as-Meta Return, which stays Alt+Enter.
|
|
28
|
+
*/
|
|
25
29
|
export declare function normalizeAppleTerminalInput(data: string, isAppleTerminal: boolean, isShiftPressed: boolean): string;
|
|
26
30
|
export declare function isWarpWslSession(env?: NodeJS.ProcessEnv, platform?: NodeJS.Platform, socketExists?: (socketPath: string) => boolean): boolean;
|
|
27
31
|
export declare function normalizeWarpWslShiftEnterInput(data: string, env?: NodeJS.ProcessEnv, platform?: NodeJS.Platform, socketExists?: (socketPath: string) => boolean): string;
|
package/dist/terminal.js
CHANGED
|
@@ -12,6 +12,7 @@ const TERMINAL_PROGRESS_KEEPALIVE_MS = 1000;
|
|
|
12
12
|
const TERMINAL_PROGRESS_ACTIVE_SEQUENCE = "\x1b]9;4;3\x07";
|
|
13
13
|
const TERMINAL_PROGRESS_CLEAR_SEQUENCE = "\x1b]9;4;0\x07";
|
|
14
14
|
const NATIVE_SHIFT_ENTER_SEQUENCE = "\x1b[13;2u";
|
|
15
|
+
const APPLE_TERMINAL_ESCAPED_RETURN_SEQUENCE = "\x1b\r";
|
|
15
16
|
const DESIRED_KITTY_KEYBOARD_PROTOCOL_FLAGS = 7;
|
|
16
17
|
const DEAD_TERMINAL_ERROR_CODES = new Set(["EIO", "EPIPE", "ENOTCONN"]);
|
|
17
18
|
// Bun's macOS tty shim can report synchronous ioctl EIO as raw positive errno 5 without a string code.
|
|
@@ -75,7 +76,14 @@ export function normalizeNativeShiftEnterInput(data, shouldDetectNativeShiftEnte
|
|
|
75
76
|
return NATIVE_SHIFT_ENTER_SEQUENCE;
|
|
76
77
|
return data;
|
|
77
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* Terminal.app can deliver Shift+Return as ESC CR, which legacy key parsing reads as Alt+Enter.
|
|
81
|
+
* The pressed native Shift keeps it apart from an Option-as-Meta Return, which stays Alt+Enter.
|
|
82
|
+
*/
|
|
78
83
|
export function normalizeAppleTerminalInput(data, isAppleTerminal, isShiftPressed) {
|
|
84
|
+
if (isAppleTerminal && data === APPLE_TERMINAL_ESCAPED_RETURN_SEQUENCE && isShiftPressed) {
|
|
85
|
+
return NATIVE_SHIFT_ENTER_SEQUENCE;
|
|
86
|
+
}
|
|
79
87
|
return normalizeNativeShiftEnterInput(data, isAppleTerminal, isShiftPressed);
|
|
80
88
|
}
|
|
81
89
|
export function isWarpWslSession(env = process.env, platform = process.platform, socketExists = (socketPath) => {
|
|
@@ -571,8 +579,13 @@ export class ProcessTerminal {
|
|
|
571
579
|
forwardInputSequence(sequence) {
|
|
572
580
|
if (!this.inputHandler)
|
|
573
581
|
return;
|
|
574
|
-
const
|
|
575
|
-
const
|
|
582
|
+
const isReturn = sequence === "\r" || sequence === APPLE_TERMINAL_ESCAPED_RETURN_SEQUENCE;
|
|
583
|
+
const isAppleTerminal = isReturn && isAppleTerminalSession();
|
|
584
|
+
const shouldDetectNativeShiftEnter = isAppleTerminal || (sequence === "\r" && process.platform === "win32");
|
|
585
|
+
const isShiftPressed = shouldDetectNativeShiftEnter && isNativeModifierPressed("shift");
|
|
586
|
+
const input = isAppleTerminal
|
|
587
|
+
? normalizeAppleTerminalInput(sequence, true, isShiftPressed)
|
|
588
|
+
: normalizeNativeShiftEnterInput(sequence, shouldDetectNativeShiftEnter, isShiftPressed);
|
|
576
589
|
this.inputHandler(input);
|
|
577
590
|
}
|
|
578
591
|
enableModifyOtherKeys() {
|
package/package.json
CHANGED