@oh-my-pi/pi-tui 17.4.2 → 18.0.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 +67 -0
- package/README.md +1 -1
- package/dist/types/autocomplete.d.ts +17 -6
- package/dist/types/components/editor.d.ts +42 -5
- package/dist/types/components/image.d.ts +2 -5
- package/dist/types/components/markdown.d.ts +18 -24
- package/dist/types/components/select-list.d.ts +9 -0
- package/dist/types/components/text.d.ts +0 -1
- package/dist/types/keybindings.d.ts +5 -0
- package/dist/types/terminal-capabilities.d.ts +10 -3
- package/dist/types/terminal.d.ts +42 -2
- package/dist/types/tui.d.ts +63 -218
- package/dist/types/utils.d.ts +3 -2
- package/package.json +4 -4
- package/src/autocomplete.ts +147 -61
- package/src/components/editor.ts +407 -157
- package/src/components/image.ts +4 -6
- package/src/components/loader.ts +1 -9
- package/src/components/markdown.ts +133 -417
- package/src/components/select-list.ts +67 -15
- package/src/components/text.ts +8 -18
- package/src/fuzzy.ts +63 -6
- package/src/keybindings.ts +5 -0
- package/src/stdin-buffer.ts +130 -20
- package/src/terminal-capabilities.ts +20 -3
- package/src/terminal.ts +147 -22
- package/src/tui.ts +628 -3510
- package/src/utils.ts +12 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,73 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [18.0.1] - 2026-08-23
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Collapsed individual skill commands into a `/skill:` namespace entry to declutter suggestions
|
|
10
|
+
- Added `TUI.renderNow()` for terminal-safe synchronous priority frames that retain resize debounce, output-backlog, and image deferral safeguards.
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Improved slash command autocompletion to chain suggestions after selecting a namespace
|
|
15
|
+
- Replaced the native-scrollback inference API (`NativeScrollback*` interfaces and the scrollback rebuild/resize settings hooks) with explicit `TerminalFramePlan` history batches.
|
|
16
|
+
- Post-resize repaints now recover the reflowed viewport anchor with a cursor-position report (DSR) instead of trusting stale grid coordinates, so a settled resize no longer duplicates the editor/status rows on screen.
|
|
17
|
+
- History appends that overflow the screen erase the old live viewport first, so a scroll can only push committed rows and blanks into scrollback, never an unfinished frame.
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- Fixed the resize live-region erase wiping visible history rows when the terminal height grows: cursor-relative addressing tracks the reflowed viewport top on grow, while the bottom-preserving bound still guards height shrinks.
|
|
22
|
+
- Fixed consecutive prompt submissions being skipped by persistent history, allowing the latest project metadata to replace the previous entry without duplicating editor navigation history.
|
|
23
|
+
- Fixed the history drain stalling on idle screens: accepting a batch now pumps the next frame, so a large resumed transcript retires to terminal history instead of pinning the live viewport in its emergency aggregate.
|
|
24
|
+
- Fixed fuzzy matching so a qualifying whole-word hit is not hidden by an earlier mid-word occurrence ([#8465](https://github.com/can1357/oh-my-pi/pull/8465) by [@Mustaqeem66](https://github.com/Mustaqeem66)).
|
|
25
|
+
- Fixed stray characters appearing in the terminal viewport during title updates
|
|
26
|
+
- Fixed editor input lag when autocomplete providers are slow by keeping only the latest pending lookup.
|
|
27
|
+
- Fixed pasting an image in kitty occasionally spraying base64 text into the composer alongside the image attachment: a kitty OSC 5522 clipboard packet torn by the incomplete-escape flush is now discarded up to its terminator instead of being replayed as keystrokes.
|
|
28
|
+
- Fixed Kitty OSC 66 headings activating before the host explicitly enables text sizing.
|
|
29
|
+
- Markdown streaming renderer now scans only the mutable tail (not the full document) for reference-link definitions and CR on every frame, eliminating the O(n²) `RegExp.test` cost that accounted for ~26% CPU during active streaming ([#9048](https://github.com/can1357/oh-my-pi/issues/9048)).
|
|
30
|
+
|
|
31
|
+
## [18.0.0] - 2026-08-22
|
|
32
|
+
|
|
33
|
+
### Breaking Changes
|
|
34
|
+
|
|
35
|
+
- Changed native macOS spelling and completion functions to return Promises.
|
|
36
|
+
- Updated `EditorTextAssistProvider.tryAutocorrect` signature to receive editor state instead of raw text.
|
|
37
|
+
- Updated `Editor.decorateText` signature to provide line and column context instead of raw text.
|
|
38
|
+
|
|
39
|
+
### Added
|
|
40
|
+
|
|
41
|
+
- Added `EditorTextAssistProvider` with spelling suggestion support (`ctrl+.`), word replacement choices, and async autocorrection handling.
|
|
42
|
+
- Added `Terminal.pendingOutputBytes` and an output-backpressure render gate to drop stale frames on slow terminals.
|
|
43
|
+
- Added `deferInput` startup option and `enableInput()` across `Terminal`, `TUI`, and `TUIStartOptions` to improve startup responsiveness.
|
|
44
|
+
- Added icon support and customizable theming to autocomplete and select lists.
|
|
45
|
+
- Added `MarkdownTheme.createHighlightStream` for incremental syntax highlighting of completed lines in streaming Markdown code blocks.
|
|
46
|
+
- Added `maxDescriptionRows` option to `SelectList` layouts to truncate wrapped descriptions with an ellipsis.
|
|
47
|
+
- Added `commandUsage` ranking callback support to `CombinedAutocompleteProvider` to prioritize frequently used slash commands.
|
|
48
|
+
- Added `Editor.viewportRowsProvider` to constrain autocomplete dropdowns within the available terminal height.
|
|
49
|
+
- Added `Editor.setTheme()` to dynamically change themes without recreating the editor or losing draft content.
|
|
50
|
+
|
|
51
|
+
### Changed
|
|
52
|
+
|
|
53
|
+
- Adjusted word completion to skip appending a trailing space when the following character is punctuation.
|
|
54
|
+
- Increased default autocomplete dropdown height from 5 to 10 items.
|
|
55
|
+
|
|
56
|
+
### Fixed
|
|
57
|
+
|
|
58
|
+
- Fixed TUI freezing during large repaints on slow or occluded terminals by moving stdout writes to an off-thread writer.
|
|
59
|
+
|
|
60
|
+
## [17.4.4] - 2026-08-22
|
|
61
|
+
|
|
62
|
+
### Added
|
|
63
|
+
|
|
64
|
+
- Added `setResizeScrollback()` / `ResizeScrollbackMode` (`PI_TUI_RESIZE_SCROLLBACK` env initializer) controlling what a settled in-place width resize does to native scrollback, which the host rewraps naively at the old width: `append` replays the transcript at the settled width below the old-wrap history, `rebuild` clears pane history first (ED3) so it holds exactly one current-width copy, and `preserve` repaints the viewport only with zero history growth. The raw engine defaults to `preserve`; the coding agent's `tui.resizeScrollback` setting (default `append`) governs interactive sessions.
|
|
65
|
+
|
|
66
|
+
### Fixed
|
|
67
|
+
|
|
68
|
+
- `visibleWidth` now measures APC sequences (Kitty graphics commands, cursor markers) as zero cells instead of counting their payload as printable text, matching the native width engine.
|
|
69
|
+
- Kitty Unicode-placeholder rows with long styled prefixes (e.g. bordered thumbnail cards) are recognized as image lines again, keeping them on the verbatim render path instead of SGR coalescing/truncation.
|
|
70
|
+
- Fixed multiplexer width-epoch resolution failing for every real component tree, which forced the conservative full-transcript replay (and one duplicated transcript copy in pane history) on every settled width resize: leading children without a width-epoch revision are no longer validated by width-dependent row counts (reflow is not mutation — identity plus the revision, when reported, is the stability proof), and `Markdown` now reports a width-independent mutation revision so it can sit above an epoch source ([#8193](https://github.com/can1357/oh-my-pi/issues/8193), [#7026](https://github.com/can1357/oh-my-pi/issues/7026)).
|
|
71
|
+
|
|
5
72
|
## [17.4.2] - 2026-08-21
|
|
6
73
|
|
|
7
74
|
### Added
|
package/README.md
CHANGED
|
@@ -539,7 +539,7 @@ interface Terminal {
|
|
|
539
539
|
**Built-in implementations:**
|
|
540
540
|
|
|
541
541
|
- `ProcessTerminal` - Uses `process.stdin/stdout`
|
|
542
|
-
- `VirtualTerminal` - For testing (uses
|
|
542
|
+
- `VirtualTerminal` - For testing (uses kitty-vt-wasm)
|
|
543
543
|
|
|
544
544
|
## Utilities
|
|
545
545
|
|
|
@@ -10,6 +10,8 @@ export interface AutocompleteItem {
|
|
|
10
10
|
value: string;
|
|
11
11
|
label: string;
|
|
12
12
|
description?: string;
|
|
13
|
+
/** Optional type-indicator glyph rendered in an aligned column before the label */
|
|
14
|
+
icon?: string;
|
|
13
15
|
/** Dim hint text shown inline after cursor when this item is selected */
|
|
14
16
|
hint?: string;
|
|
15
17
|
}
|
|
@@ -18,6 +20,8 @@ export interface SlashCommand {
|
|
|
18
20
|
name: string;
|
|
19
21
|
aliases?: string[];
|
|
20
22
|
description?: string;
|
|
23
|
+
/** Optional type-indicator glyph shown before the command name in autocomplete */
|
|
24
|
+
icon?: string;
|
|
21
25
|
argumentHint?: string;
|
|
22
26
|
/** Whether the command consumes argument text after the command name. False means the full input stays normal prompt text once args are present. */
|
|
23
27
|
allowArgs?: boolean;
|
|
@@ -28,8 +32,8 @@ export interface SlashCommand {
|
|
|
28
32
|
getInlineHint?(argumentText: string): string | null;
|
|
29
33
|
}
|
|
30
34
|
export interface AutocompleteProvider {
|
|
31
|
-
/** Get autocomplete suggestions for current text/cursor position */
|
|
32
|
-
getSuggestions(lines: string[], cursorLine: number, cursorCol: number): Promise<{
|
|
35
|
+
/** Get autocomplete suggestions for current text/cursor position. Expensive providers SHOULD stop when `signal` aborts. */
|
|
36
|
+
getSuggestions(lines: string[], cursorLine: number, cursorCol: number, signal?: AbortSignal): Promise<{
|
|
33
37
|
items: AutocompleteItem[];
|
|
34
38
|
prefix: string;
|
|
35
39
|
} | null>;
|
|
@@ -64,8 +68,9 @@ export interface AutocompleteProvider {
|
|
|
64
68
|
* Force file-path completion (called on Tab). Returns matched items plus the
|
|
65
69
|
* full prefix, or null when no path token sits before the cursor. Present on
|
|
66
70
|
* file-aware providers; absent on slash-only ones.
|
|
71
|
+
* Expensive providers SHOULD stop when `signal` aborts.
|
|
67
72
|
*/
|
|
68
|
-
getForceFileSuggestions?(lines: string[], cursorLine: number, cursorCol: number): Promise<{
|
|
73
|
+
getForceFileSuggestions?(lines: string[], cursorLine: number, cursorCol: number, signal?: AbortSignal): Promise<{
|
|
69
74
|
items: AutocompleteItem[];
|
|
70
75
|
prefix: string;
|
|
71
76
|
} | null>;
|
|
@@ -73,7 +78,13 @@ export interface AutocompleteProvider {
|
|
|
73
78
|
shouldTriggerFileCompletion?(lines: string[], cursorLine: number, cursorCol: number): boolean;
|
|
74
79
|
}
|
|
75
80
|
type CommandEntry = SlashCommand | AutocompleteItem;
|
|
81
|
+
/** Optional behaviors for {@link CombinedAutocompleteProvider}. */
|
|
82
|
+
export interface CombinedAutocompleteOptions {
|
|
83
|
+
/** Usage count per command name; higher counts rank earlier among equal text-match scores. */
|
|
84
|
+
commandUsage?: (name: string) => number;
|
|
85
|
+
}
|
|
76
86
|
export declare function scoreCommandTextMatch(lowerPrefix: string, lowerTarget: string): number;
|
|
87
|
+
export declare const SKILL_NAMESPACE = "skill:";
|
|
77
88
|
/**
|
|
78
89
|
* Whether a mid-prompt slash token (`prose … /tok`) is skill-shaped enough to
|
|
79
90
|
* surface `name` in the skill popup. Deliberately stricter than submitted
|
|
@@ -90,8 +101,8 @@ export declare function scoreCommandTextMatch(lowerPrefix: string, lowerTarget:
|
|
|
90
101
|
export declare function midPromptSkillTokenMatches(lowerToken: string, name: string, description?: string): boolean;
|
|
91
102
|
export declare class CombinedAutocompleteProvider implements AutocompleteProvider {
|
|
92
103
|
#private;
|
|
93
|
-
constructor(commands?: CommandEntry[], basePath?: string);
|
|
94
|
-
getSuggestions(lines: string[], cursorLine: number, cursorCol: number): Promise<{
|
|
104
|
+
constructor(commands?: CommandEntry[], basePath?: string, options?: CombinedAutocompleteOptions);
|
|
105
|
+
getSuggestions(lines: string[], cursorLine: number, cursorCol: number, signal?: AbortSignal): Promise<{
|
|
95
106
|
items: AutocompleteItem[];
|
|
96
107
|
prefix: string;
|
|
97
108
|
} | null>;
|
|
@@ -101,7 +112,7 @@ export declare class CombinedAutocompleteProvider implements AutocompleteProvide
|
|
|
101
112
|
cursorCol: number;
|
|
102
113
|
};
|
|
103
114
|
invalidateDirCache(dir?: string): void;
|
|
104
|
-
getForceFileSuggestions(lines: string[], cursorLine: number, cursorCol: number): Promise<{
|
|
115
|
+
getForceFileSuggestions(lines: string[], cursorLine: number, cursorCol: number, signal?: AbortSignal): Promise<{
|
|
105
116
|
items: AutocompleteItem[];
|
|
106
117
|
prefix: string;
|
|
107
118
|
} | null>;
|
|
@@ -23,6 +23,38 @@ interface HistoryStorage {
|
|
|
23
23
|
add(prompt: string, cwd?: string): Promise<void>;
|
|
24
24
|
getRecent(limit: number): HistoryEntry[];
|
|
25
25
|
}
|
|
26
|
+
/** A synchronous replacement immediately before the editor cursor. */
|
|
27
|
+
export interface EditorInlineReplacement {
|
|
28
|
+
/** UTF-16 code units to remove immediately before the cursor. */
|
|
29
|
+
replaceLen: number;
|
|
30
|
+
/** Literal text inserted where the removed suffix started. */
|
|
31
|
+
insert: string;
|
|
32
|
+
}
|
|
33
|
+
/** Replacement candidates and the current-line span they replace. */
|
|
34
|
+
export interface EditorWordReplacements {
|
|
35
|
+
line: number;
|
|
36
|
+
startCol: number;
|
|
37
|
+
endCol: number;
|
|
38
|
+
items: readonly string[];
|
|
39
|
+
}
|
|
40
|
+
/** Source location for one visual text segment passed to `decorateText`. */
|
|
41
|
+
export interface EditorTextDecorationContext {
|
|
42
|
+
line: number;
|
|
43
|
+
startCol: number;
|
|
44
|
+
endCol: number;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Optional prose assistance kept separate from command/file autocomplete.
|
|
48
|
+
* Hosts independently decide whether word completion and autocorrection are enabled.
|
|
49
|
+
*/
|
|
50
|
+
export interface EditorTextAssistProvider {
|
|
51
|
+
/** Return ghost-text suffix for the partial word at the cursor, or `null`. */
|
|
52
|
+
getWordCompletion?(lines: string[], cursorLine: number, cursorCol: number): string | null;
|
|
53
|
+
/** Return a correction after one single-character insertion, or `null`. */
|
|
54
|
+
tryAutocorrect?(lines: string[], cursorLine: number, cursorCol: number): EditorInlineReplacement | null | Promise<EditorInlineReplacement | null>;
|
|
55
|
+
/** Return replacement candidates for the misspelled word at the cursor. */
|
|
56
|
+
getWordReplacements?(lines: string[], cursorLine: number, cursorCol: number): EditorWordReplacements | null | Promise<EditorWordReplacements | null>;
|
|
57
|
+
}
|
|
26
58
|
export declare class Editor implements Component, Focusable {
|
|
27
59
|
#private;
|
|
28
60
|
/** Focusable interface - set by TUI when focus changes */
|
|
@@ -34,9 +66,13 @@ export declare class Editor implements Component, Focusable {
|
|
|
34
66
|
/** Optional hook that decorates displayed user text after source-text layout.
|
|
35
67
|
* Width-changing output is allowed on lines without the cursor; it is truncated
|
|
36
68
|
* to the content width rather than reflowed. Cursor glyphs and inline hints are excluded. */
|
|
37
|
-
decorateText: ((text: string) => string) | undefined;
|
|
69
|
+
decorateText: ((text: string, context: EditorTextDecorationContext) => string) | undefined;
|
|
38
70
|
borderColor: (str: string) => string;
|
|
39
71
|
onAutocompleteUpdate?: () => void;
|
|
72
|
+
/** Called after an async text-assist result mutates the document outside an input event, so hosts can schedule a repaint. */
|
|
73
|
+
onTextAssistApplied?: () => void;
|
|
74
|
+
/** Terminal height source for clamping the autocomplete dropdown. Hosts wire this to their Terminal's rows. */
|
|
75
|
+
viewportRowsProvider?: () => number;
|
|
40
76
|
/** Optional pattern matching atomic placeholder tokens (e.g. `[Image #1, 800x600]` or
|
|
41
77
|
* `[Paste #2, +30 lines]`) that the editor treats as indivisible: a backspace or forward-delete
|
|
42
78
|
* landing on any character of a token removes the whole token instead of corrupting it into
|
|
@@ -56,7 +92,10 @@ export declare class Editor implements Component, Focusable {
|
|
|
56
92
|
onAutocompleteCancel?: () => void;
|
|
57
93
|
disableSubmit: boolean;
|
|
58
94
|
constructor(theme: EditorTheme);
|
|
95
|
+
setTheme(theme: EditorTheme): void;
|
|
59
96
|
setAutocompleteProvider(provider: AutocompleteProvider): void;
|
|
97
|
+
/** Install prose assistance without changing command/file autocomplete. */
|
|
98
|
+
setTextAssistProvider(provider: EditorTextAssistProvider | undefined): void;
|
|
60
99
|
/**
|
|
61
100
|
* Set custom content for the top border (e.g., status line).
|
|
62
101
|
* Pass undefined to use the default plain border.
|
|
@@ -75,9 +114,7 @@ export declare class Editor implements Component, Focusable {
|
|
|
75
114
|
* Use this when the top border derives from state that mutates far faster
|
|
76
115
|
* than the render cadence (session events, streaming, subagent updates).
|
|
77
116
|
* The TUI already throttles renders, so a provider is invoked exactly once
|
|
78
|
-
* per frame and does no work between paints.
|
|
79
|
-
* distinguish concurrent status mutations from pure width reflow.
|
|
80
|
-
*/
|
|
117
|
+
* per frame and does no work between paints. */
|
|
81
118
|
setTopBorderProvider(provider: ((availableWidth: number) => EditorTopBorder | undefined) | undefined): void;
|
|
82
119
|
/**
|
|
83
120
|
* Show or hide the editor border chrome.
|
|
@@ -106,6 +143,7 @@ export declare class Editor implements Component, Focusable {
|
|
|
106
143
|
setPaddingX(paddingX: number): void;
|
|
107
144
|
getAutocompleteMaxVisible(): number;
|
|
108
145
|
setAutocompleteMaxVisible(maxVisible: number): void;
|
|
146
|
+
/** Loads persistent prompts for navigation and enables future persistence. */
|
|
109
147
|
setHistoryStorage(storage: HistoryStorage): void;
|
|
110
148
|
/**
|
|
111
149
|
* Add a prompt to history for up/down arrow navigation.
|
|
@@ -116,7 +154,6 @@ export declare class Editor implements Component, Focusable {
|
|
|
116
154
|
render(width: number): readonly string[];
|
|
117
155
|
handleInput(data: string): void;
|
|
118
156
|
getText(): string;
|
|
119
|
-
getNativeScrollbackWidthEpochRevision(): number;
|
|
120
157
|
/** Whether the buffer text equals `value`, without `getText()`'s full join —
|
|
121
158
|
* O(1) for the hot per-keystroke probes against short single-line values. */
|
|
122
159
|
textEquals(value: string): boolean;
|
|
@@ -121,11 +121,8 @@ export declare class ImageBudget {
|
|
|
121
121
|
* Restart every placement epoch after a destructive history clear (`CSI 3 J`
|
|
122
122
|
* full paint). The clear destroys all placement cells — scrollback rows are
|
|
123
123
|
* gone and the replay rewrites the viewport — so no archive remains to
|
|
124
|
-
* protect. Reverting to epoch 1 lets the replay
|
|
125
|
-
*
|
|
126
|
-
* and the highest epoch it reached so the caller can delete all of its
|
|
127
|
-
* registry entries explicitly (`d=i` keeps the transmitted data) — an image
|
|
128
|
-
* absent from the replay never re-places, so even its epoch-1 entry must go.
|
|
124
|
+
* protect. Reverting to epoch 1 lets the replay recreate every visible
|
|
125
|
+
* placement after the terminal-wide cleanup.
|
|
129
126
|
*/
|
|
130
127
|
resetPlacementEpochs(): ReadonlyArray<{
|
|
131
128
|
imageId: number;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { SymbolTheme } from "../symbols.js";
|
|
2
|
-
import type { Component
|
|
2
|
+
import type { Component } from "../tui.js";
|
|
3
3
|
/** @internal exported for tests — must stay index-identical to the old regex scan. */
|
|
4
4
|
export declare function mathStartIndex(src: string): number | undefined;
|
|
5
5
|
/** @internal exported for tests — must stay index-identical to the old regex scan. */
|
|
@@ -26,6 +26,14 @@ export interface DefaultTextStyle {
|
|
|
26
26
|
/** Underline text */
|
|
27
27
|
underline?: boolean;
|
|
28
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* Stateful incremental code highlighter carrying parser state across pushes.
|
|
31
|
+
* Produced per streaming fence by {@link MarkdownTheme.createHighlightStream}.
|
|
32
|
+
*/
|
|
33
|
+
export interface HighlightStreamSession {
|
|
34
|
+
/** Highlight the next chunk and advance parser state. */
|
|
35
|
+
push(chunk: string): string;
|
|
36
|
+
}
|
|
29
37
|
/**
|
|
30
38
|
* Theme functions for markdown elements.
|
|
31
39
|
* Each function takes text and returns styled text with ANSI codes.
|
|
@@ -46,6 +54,14 @@ export interface MarkdownTheme {
|
|
|
46
54
|
strikethrough: (text: string) => string;
|
|
47
55
|
underline: (text: string) => string;
|
|
48
56
|
highlightCode?: (code: string, lang?: string) => string[];
|
|
57
|
+
/**
|
|
58
|
+
* Create a stateful incremental highlighter for one streaming code fence.
|
|
59
|
+
* `push` receives newline-terminated complete lines (only the final push
|
|
60
|
+
* may omit the trailing newline) and must return highlighted ANSI text for
|
|
61
|
+
* exactly the pushed chunk, byte-identical to highlighting the concatenated
|
|
62
|
+
* text through `highlightCode`. Return null when `lang` is unsupported.
|
|
63
|
+
*/
|
|
64
|
+
createHighlightStream?: (lang?: string) => HighlightStreamSession | null;
|
|
49
65
|
/**
|
|
50
66
|
* Resolve a mermaid ASCII rendering by fenced block source text.
|
|
51
67
|
* Return null to fall back to fenced code rendering.
|
|
@@ -53,7 +69,7 @@ export interface MarkdownTheme {
|
|
|
53
69
|
resolveMermaidAscii?: (source: string, maxWidth?: number) => string | null;
|
|
54
70
|
symbols: SymbolTheme;
|
|
55
71
|
}
|
|
56
|
-
export declare class Markdown implements Component
|
|
72
|
+
export declare class Markdown implements Component {
|
|
57
73
|
#private;
|
|
58
74
|
setIgnoreTight(ignore: boolean): this;
|
|
59
75
|
constructor(text: string, paddingX: number, paddingY: number, theme: MarkdownTheme, defaultTextStyle?: DefaultTextStyle, codeBlockIndent?: number);
|
|
@@ -61,28 +77,6 @@ export declare class Markdown implements Component, NativeScrollbackCommittedRow
|
|
|
61
77
|
invalidate(): void;
|
|
62
78
|
get transientRenderCache(): boolean;
|
|
63
79
|
set transientRenderCache(value: boolean);
|
|
64
|
-
/**
|
|
65
|
-
* Rows at the top of the most recent render() (top padding + rendered
|
|
66
|
-
* frozen-token prefix) whose bytes are settled: byte-stable at this
|
|
67
|
-
* width/theme for as long as the text keeps growing append-only. Hosts
|
|
68
|
-
* feed this to transcript commit gating (see the coding agent's
|
|
69
|
-
* `FinalizableBlock.getTranscriptBlockSettledRows`). 0 outside streaming
|
|
70
|
-
* (`transientRenderCache`) mode, after a text rewind (re-earned on the new
|
|
71
|
-
* lineage), and on cache-served non-streaming renders.
|
|
72
|
-
*/
|
|
73
|
-
getLastRenderSettledRows(): number;
|
|
74
|
-
captureNativeScrollbackWidthEpoch(): unknown;
|
|
75
|
-
resolveNativeScrollbackWidthEpoch(boundary: unknown): number | undefined;
|
|
76
|
-
getNativeScrollbackWidthEpochRows(): number | undefined;
|
|
77
|
-
isNativeScrollbackWidthEpochAppendOnly(boundary: unknown): boolean;
|
|
78
|
-
/**
|
|
79
|
-
* Freeze every table whose first physical row is already part of the native
|
|
80
|
-
* scrollback prefix. The recorded widths came from the exact frame that was
|
|
81
|
-
* just emitted, so the next streamed delta cannot retroactively widen it.
|
|
82
|
-
*/
|
|
83
|
-
setNativeScrollbackCommittedRows(rows: number): void;
|
|
84
|
-
/** A destructive replay removes the immutable tape this layout was guarding. */
|
|
85
|
-
prepareNativeScrollbackReplay(): void;
|
|
86
80
|
render(width: number): readonly string[];
|
|
87
81
|
}
|
|
88
82
|
/**
|
|
@@ -5,6 +5,8 @@ export interface SelectItem {
|
|
|
5
5
|
value: string;
|
|
6
6
|
label: string;
|
|
7
7
|
description?: string;
|
|
8
|
+
/** Optional type-indicator glyph rendered in an aligned column before the label */
|
|
9
|
+
icon?: string;
|
|
8
10
|
/** Dim hint text shown inline after cursor when this item is selected */
|
|
9
11
|
hint?: string;
|
|
10
12
|
}
|
|
@@ -15,6 +17,8 @@ export interface SelectListTheme {
|
|
|
15
17
|
scrollInfo: (text: string) => string;
|
|
16
18
|
noMatch: (text: string) => string;
|
|
17
19
|
symbols: SymbolTheme;
|
|
20
|
+
/** Style for the type-icon column on unselected rows. Defaults to plain text. */
|
|
21
|
+
icon?: (text: string) => string;
|
|
18
22
|
/** Hover band applied to the full row under the mouse pointer. */
|
|
19
23
|
hovered?: (text: string) => string;
|
|
20
24
|
}
|
|
@@ -39,6 +43,11 @@ export interface SelectListLayoutOptions {
|
|
|
39
43
|
* wrap unevenly.
|
|
40
44
|
*/
|
|
41
45
|
wrapDescription?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Cap wrapped descriptions at this many visual rows; the last kept row is
|
|
48
|
+
* ellipsized. Only meaningful with `wrapDescription`.
|
|
49
|
+
*/
|
|
50
|
+
maxDescriptionRows?: number;
|
|
42
51
|
}
|
|
43
52
|
export declare class SelectList implements Component, MouseRoutable {
|
|
44
53
|
#private;
|
|
@@ -14,7 +14,6 @@ export declare class Text implements Component {
|
|
|
14
14
|
constructor(text?: string, paddingX?: number, paddingY?: number, customBgFn?: (text: string) => string);
|
|
15
15
|
getText(): string;
|
|
16
16
|
setText(text: string): boolean;
|
|
17
|
-
getNativeScrollbackWidthEpochRevision(): number;
|
|
18
17
|
setCustomBgFn(customBgFn?: (text: string) => string): void;
|
|
19
18
|
/**
|
|
20
19
|
* Supply a foreground styler applied to the text at render time (e.g. a
|
|
@@ -25,6 +25,7 @@ export interface Keybindings {
|
|
|
25
25
|
"tui.editor.yank": true;
|
|
26
26
|
"tui.editor.yankPop": true;
|
|
27
27
|
"tui.editor.undo": true;
|
|
28
|
+
"tui.editor.spellingSuggestions": true;
|
|
28
29
|
"tui.input.newLine": true;
|
|
29
30
|
"tui.input.submit": true;
|
|
30
31
|
"tui.input.tab": true;
|
|
@@ -129,6 +130,10 @@ export declare const TUI_KEYBINDINGS: {
|
|
|
129
130
|
readonly defaultKeys: ["ctrl+-", "ctrl+_"];
|
|
130
131
|
readonly description: "Undo";
|
|
131
132
|
};
|
|
133
|
+
readonly "tui.editor.spellingSuggestions": {
|
|
134
|
+
readonly defaultKeys: "ctrl+.";
|
|
135
|
+
readonly description: "Show spelling replacements";
|
|
136
|
+
};
|
|
132
137
|
readonly "tui.input.newLine": {
|
|
133
138
|
readonly defaultKeys: ["shift+enter", "ctrl+j"];
|
|
134
139
|
readonly description: "Insert newline";
|
|
@@ -21,7 +21,7 @@ export declare class TerminalInfo {
|
|
|
21
21
|
readonly deccara: boolean;
|
|
22
22
|
readonly supportsScreenToScrollback: boolean;
|
|
23
23
|
/** Renders the Kitty OSC 66 text-sizing protocol (scaled spans). Kitty only. */
|
|
24
|
-
readonly
|
|
24
|
+
readonly supportsTextSizing: boolean;
|
|
25
25
|
/**
|
|
26
26
|
* Hangul Compatibility Jamo (U+3131..=U+318E) cell width. Ghostty follows
|
|
27
27
|
* UAX#11 (2 cells); Warp paints 1; "platform" keeps the OS default
|
|
@@ -30,7 +30,7 @@ export declare class TerminalInfo {
|
|
|
30
30
|
readonly hangulJamoWidth: HangulCompatibilityJamoWidth;
|
|
31
31
|
constructor(id: TerminalId, imageProtocol: ImageProtocol | null, trueColor: boolean, hyperlinks: boolean, notifyProtocol?: NotifyProtocol, deccara?: boolean, supportsScreenToScrollback?: boolean,
|
|
32
32
|
/** Renders the Kitty OSC 66 text-sizing protocol (scaled spans). Kitty only. */
|
|
33
|
-
|
|
33
|
+
supportsTextSizing?: boolean,
|
|
34
34
|
/**
|
|
35
35
|
* Hangul Compatibility Jamo (U+3131..=U+318E) cell width. Ghostty follows
|
|
36
36
|
* UAX#11 (2 cells); Warp paints 1; "platform" keeps the OS default
|
|
@@ -167,6 +167,7 @@ export interface RuntimeTerminal extends TerminalInfo {
|
|
|
167
167
|
hyperlinks: boolean;
|
|
168
168
|
deccara: boolean;
|
|
169
169
|
supportsScreenToScrollback: boolean;
|
|
170
|
+
/** Whether OSC 66 text sizing is currently enabled. */
|
|
170
171
|
textSizing: boolean;
|
|
171
172
|
}
|
|
172
173
|
export declare const TERMINAL: RuntimeTerminal;
|
|
@@ -184,7 +185,7 @@ export declare function setTerminalDeccara(enabled: boolean): void;
|
|
|
184
185
|
export declare function setTerminalScreenToScrollback(enabled: boolean): void;
|
|
185
186
|
/**
|
|
186
187
|
* Enable/disable OSC 66 text-sizing at runtime. The coding-agent calls this from
|
|
187
|
-
* the `tui.textSizing` setting (gated on the terminal's static `
|
|
188
|
+
* the `tui.textSizing` setting (gated on the terminal's static `supportsTextSizing`
|
|
188
189
|
* capability); tests flip it directly to exercise the scaled-heading path.
|
|
189
190
|
*/
|
|
190
191
|
export declare function setTerminalTextSizing(enabled: boolean): void;
|
|
@@ -282,6 +283,12 @@ export declare function encodeKittyPlacementLine(options: {
|
|
|
282
283
|
* this is the only way to actually purge a placed image.
|
|
283
284
|
*/
|
|
284
285
|
export declare function encodeKittyDeleteImage(imageId: number): string;
|
|
286
|
+
/**
|
|
287
|
+
* Delete every Kitty image and placement in the terminal. Used only by an
|
|
288
|
+
* explicit destructive display reset: text erases leave untracked placements
|
|
289
|
+
* painted, so per-image bookkeeping cannot guarantee a clean viewport.
|
|
290
|
+
*/
|
|
291
|
+
export declare function encodeKittyDeleteAllImages(): string;
|
|
285
292
|
/**
|
|
286
293
|
* Delete a single placement of an image (`d=i`, lowercase): removes its cells
|
|
287
294
|
* and registry entry but keeps the transmitted data, so a later `a=p` under a
|
package/dist/types/terminal.d.ts
CHANGED
|
@@ -51,6 +51,16 @@ export declare class OutputBacklogGuard {
|
|
|
51
51
|
}
|
|
52
52
|
/** Record alternate-screen state (called by the TUI on `?1049h`/`?1049l` writes). */
|
|
53
53
|
export declare function setAltScreenActive(active: boolean): void;
|
|
54
|
+
/**
|
|
55
|
+
* Route an out-of-band escape sequence (e.g. an OSC title update) through the
|
|
56
|
+
* active terminal's output path. While a TUI owns stdout, frame paints go
|
|
57
|
+
* through the off-thread write pump and can split across multiple write(2)
|
|
58
|
+
* calls; a direct main-thread `process.stdout.write` can land between two of
|
|
59
|
+
* them — mid escape sequence — and the host terminal then prints the payload
|
|
60
|
+
* as literal text at the cursor position. Returns false when no terminal has
|
|
61
|
+
* started, in which case the caller owns stdout and may write directly.
|
|
62
|
+
*/
|
|
63
|
+
export declare function writeThroughActiveTerminal(data: string): boolean;
|
|
54
64
|
/**
|
|
55
65
|
* Emergency terminal restore - call this from signal/crash handlers
|
|
56
66
|
* Resets terminal state without requiring access to the ProcessTerminal instance
|
|
@@ -58,10 +68,30 @@ export declare function setAltScreenActive(active: boolean): void;
|
|
|
58
68
|
export declare function emergencyTerminalRestore(): void;
|
|
59
69
|
/** Terminal-reported appearance (dark/light mode). */
|
|
60
70
|
export type TerminalAppearance = "dark" | "light";
|
|
71
|
+
/** Options for {@link Terminal.start}. */
|
|
72
|
+
export interface TerminalStartOptions {
|
|
73
|
+
/**
|
|
74
|
+
* Paint-only start: skip raw mode, stdin ownership, and every probe that
|
|
75
|
+
* elicits a response on stdin. The host tty keeps cooked-mode line editing
|
|
76
|
+
* (kernel echo lands at the hardware cursor), and typed bytes stay queued
|
|
77
|
+
* in the kernel until {@link Terminal.enableInput} takes ownership and
|
|
78
|
+
* replays them through `onInput`. Used for the startup prepaint so typing
|
|
79
|
+
* echoes even while module loading blocks the event loop.
|
|
80
|
+
*/
|
|
81
|
+
deferInput?: boolean;
|
|
82
|
+
}
|
|
61
83
|
/** Identity of an accepted explicit terminal appearance refresh request. */
|
|
62
84
|
export type TerminalAppearanceRequestToken = number;
|
|
63
85
|
export interface Terminal {
|
|
64
|
-
start(onInput: (data: string) => void, onResize: () => void, onDisconnect?: () => void): void;
|
|
86
|
+
start(onInput: (data: string) => void, onResize: () => void, onDisconnect?: () => void, options?: TerminalStartOptions): void;
|
|
87
|
+
/**
|
|
88
|
+
* Take ownership of stdin after a `deferInput` start: enable raw mode,
|
|
89
|
+
* attach input handlers, and run the capability probes start() skipped.
|
|
90
|
+
* Bytes the user typed in cooked mode meanwhile are replayed through
|
|
91
|
+
* `onInput`. No-op when input was never deferred. Optional so custom
|
|
92
|
+
* Terminals built against older pi-tui versions keep working.
|
|
93
|
+
*/
|
|
94
|
+
enableInput?(): void;
|
|
65
95
|
stop(): void;
|
|
66
96
|
/**
|
|
67
97
|
* Drain stdin before exiting to prevent Kitty key release events from
|
|
@@ -73,6 +103,14 @@ export interface Terminal {
|
|
|
73
103
|
write(data: string): void;
|
|
74
104
|
get columns(): number;
|
|
75
105
|
get rows(): number;
|
|
106
|
+
/**
|
|
107
|
+
* Output bytes accepted but not yet delivered to the terminal, when the
|
|
108
|
+
* implementation can report it. The renderer skips composing new frames
|
|
109
|
+
* while this backlog is deep, so a slow terminal receives only fresh
|
|
110
|
+
* frames instead of a queue of stale ones. Optional so custom Terminals
|
|
111
|
+
* built against older pi-tui versions keep working.
|
|
112
|
+
*/
|
|
113
|
+
readonly pendingOutputBytes?: number;
|
|
76
114
|
get kittyProtocolActive(): boolean;
|
|
77
115
|
get kittyEnableSequence(): string | null;
|
|
78
116
|
readonly keyboardEnhancementEnterSequence?: string | null;
|
|
@@ -158,11 +196,13 @@ export declare class ProcessTerminal implements Terminal {
|
|
|
158
196
|
*/
|
|
159
197
|
refreshAppearance(requestToken?: TerminalAppearanceRequestToken): TerminalAppearanceRequestToken | void;
|
|
160
198
|
onPrivateModeReport(callback: (mode: number, supported: boolean, confirmed?: boolean) => void): void;
|
|
161
|
-
start(onInput: (data: string) => void, onResize: () => void, onDisconnect?: () => void): void;
|
|
199
|
+
start(onInput: (data: string) => void, onResize: () => void, onDisconnect?: () => void, options?: TerminalStartOptions): void;
|
|
200
|
+
enableInput(): void;
|
|
162
201
|
drainInput(maxMs?: number, idleMs?: number): Promise<void>;
|
|
163
202
|
stop(): void;
|
|
164
203
|
write(data: string): void;
|
|
165
204
|
get columns(): number;
|
|
205
|
+
get pendingOutputBytes(): number;
|
|
166
206
|
get rows(): number;
|
|
167
207
|
moveBy(lines: number): void;
|
|
168
208
|
hideCursor(force?: boolean): void;
|