@oh-my-pi/pi-tui 18.7.0 → 18.8.0
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 +21 -52
- package/dist/types/apps/debug/log-viewer.d.ts +4 -0
- package/dist/types/apps/debug/raw-sse-buffer.d.ts +2 -0
- package/dist/types/chat/fence-figure.d.ts +42 -0
- package/dist/types/chat/svg-figure.d.ts +1 -1
- package/dist/types/chat/tool-execution.d.ts +2 -0
- package/dist/types/components/editor.d.ts +8 -3
- package/dist/types/components/markdown.d.ts +11 -6
- package/dist/types/fuzzy.d.ts +17 -3
- package/dist/types/native/backend.d.ts +2 -1
- package/dist/types/native/blobs.d.ts +4 -2
- package/dist/types/native/encode.d.ts +3 -4
- package/dist/types/overlays/agent-transcript-viewer.d.ts +8 -1
- package/dist/types/overlays/history-search.d.ts +10 -0
- package/dist/types/overlays/model-browser.d.ts +6 -0
- package/dist/types/prompt/custom-editor.d.ts +7 -4
- package/dist/types/prompt/interactive-context-helpers.d.ts +2 -1
- package/dist/types/tools/renderer.d.ts +22 -0
- package/dist/types/tools/streaming-output.d.ts +11 -1
- package/dist/types/tools/write.d.ts +8 -1
- package/package.json +9 -9
- package/src/apps/debug/log-viewer.ts +188 -72
- package/src/apps/debug/raw-sse-buffer.ts +8 -0
- package/src/apps/debug/raw-sse.ts +39 -5
- package/src/apps/git/diff-pane.ts +26 -5
- package/src/autocomplete.ts +59 -33
- package/src/chat/assistant-message.ts +30 -18
- package/src/chat/fence-figure.ts +80 -0
- package/src/chat/svg-figure.ts +2 -4
- package/src/chat/tool-execution.ts +53 -4
- package/src/components/editor.ts +16 -3
- package/src/components/markdown.ts +80 -307
- package/src/fuzzy.ts +59 -14
- package/src/native/backend.ts +170 -15
- package/src/native/blobs.ts +4 -2
- package/src/native/encode.ts +58 -31
- package/src/overlays/agent-hub-projection.ts +70 -2
- package/src/overlays/agent-hub.ts +3 -2
- package/src/overlays/agent-transcript-viewer.ts +64 -13
- package/src/overlays/agents-hub.ts +14 -7
- package/src/overlays/copy-selector.ts +30 -8
- package/src/overlays/extensions/state-manager.ts +52 -12
- package/src/overlays/history-search.ts +100 -7
- package/src/overlays/jobs-panel.ts +30 -2
- package/src/overlays/model-browser.ts +107 -21
- package/src/overlays/model-hub.ts +34 -7
- package/src/overlays/oauth-selector.ts +41 -26
- package/src/overlays/plan-review-overlay.ts +142 -64
- package/src/overlays/rewind-selector.ts +86 -17
- package/src/overlays/session-selector.ts +24 -4
- package/src/overlays/settings-selector.ts +21 -6
- package/src/overlays/tree-selector.ts +20 -4
- package/src/overlays/usage-dashboard.ts +12 -15
- package/src/prompt/attachment-chips.ts +2 -1
- package/src/prompt/composer-attachments.ts +6 -4
- package/src/prompt/custom-editor.ts +48 -19
- package/src/prompt/interactive-context-helpers.ts +27 -18
- package/src/prompt/macos-spelling.ts +7 -0
- package/src/prompt/magic-keywords.ts +11 -2
- package/src/prompt/word-completion.ts +38 -5
- package/src/setup/scenes/splash.ts +109 -45
- package/src/status-line/component.ts +220 -64
- package/src/status-line/segments.ts +5 -2
- package/src/terminal.ts +3 -2
- package/src/tools/ast-edit.ts +59 -35
- package/src/tools/ast-grep.ts +35 -16
- package/src/tools/default-renderer.ts +35 -19
- package/src/tools/eval-format/index.ts +28 -2
- package/src/tools/eval-format/javascript.ts +7 -5
- package/src/tools/eval.ts +164 -78
- package/src/tools/grep.ts +81 -48
- package/src/tools/lsp.ts +81 -59
- package/src/tools/mcp.ts +98 -68
- package/src/tools/renderer.ts +27 -0
- package/src/tools/streaming-output.ts +120 -48
- package/src/tools/task.ts +111 -54
- package/src/tools/todo.ts +115 -29
- package/src/tools/wait.ts +34 -24
- package/src/tools/write.ts +77 -39
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [18.8.0] - 2026-10-07
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- SVG and Mermaid files now render as images or diagrams beneath their file cards, with SVG previews updating while the file streams and Mermaid previews appearing when the file is complete.
|
|
10
|
+
- Native tool cards can open expanded regardless of the transcript’s expansion state; the todo checklist uses this behavior.
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- TSP composer placeholders now appear as the composer title in italicized curly quotes, with “What are we cooking?” used when no title is provided.
|
|
15
|
+
- TSP image transfers are more efficient across reconnects and multiple surfaces: images are sent once per connection, existing terminal blobs are detected before upload, and images in the Tern blob cache can be reused without crossing the terminal pty.
|
|
16
|
+
- Improved performance and responsiveness across the TUI, including large TSP messages and Markdown documents, streaming output, tool-result cards, debug logs, raw SSE and Git diff views, path and model searches, session and settings lists, plan review, agent transcripts, status updates, assistant links, Kitty images, and large prompt or evaluation content.
|
|
17
|
+
- Large debug logs and plan-review histories now retain bounded history to keep the interface responsive, while preserving the newest log entries.
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- Fixed slow Markdown processing for certain LaTeX environments and incomplete delimiters.
|
|
22
|
+
- Fixed excessive slowdown when formatting long semicolon-free JavaScript evaluations.
|
|
23
|
+
- Fixed prompt-editor lag in large drafts containing magic keywords.
|
|
24
|
+
|
|
5
25
|
## [18.7.0] - 2026-10-06
|
|
6
26
|
|
|
7
27
|
### Added
|
|
@@ -2972,55 +2992,4 @@ Initial release under @oh-my-pi scope. See previous releases at [badlogic/pi-mon
|
|
|
2972
2992
|
|
|
2973
2993
|
- **Experimental:** Overlay compositing for `ctx.ui.custom()` with `{ overlay: true }` option ([#558](https://github.com/badlogic/pi-mono/pull/558) by [@nicobailon](https://github.com/nicobailon))
|
|
2974
2994
|
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
### Added
|
|
2978
|
-
|
|
2979
|
-
- `EditorComponent` interface for custom editor implementations
|
|
2980
|
-
- `StdinBuffer` class to split batched stdin into individual sequences (adapted from [OpenTUI](https://github.com/anomalyco/opentui), MIT license)
|
|
2981
|
-
|
|
2982
|
-
### Fixed
|
|
2983
|
-
|
|
2984
|
-
- Key presses no longer dropped when batched with other events over SSH ([#538](https://github.com/badlogic/pi-mono/pull/538))
|
|
2985
|
-
|
|
2986
|
-
## [0.37.8] - 2026-01-07
|
|
2987
|
-
|
|
2988
|
-
### Added
|
|
2989
|
-
|
|
2990
|
-
- `Component.wantsKeyRelease` property to opt-in to key release events (default false)
|
|
2991
|
-
|
|
2992
|
-
### Fixed
|
|
2993
|
-
|
|
2994
|
-
- TUI now filters out key release events by default, preventing double-processing of keys in editors and other components
|
|
2995
|
-
|
|
2996
|
-
## [0.37.7] - 2026-01-07
|
|
2997
|
-
|
|
2998
|
-
### Fixed
|
|
2999
|
-
|
|
3000
|
-
- `matchesKey()` now correctly matches Kitty protocol sequences for unmodified letter keys (needed for key release events)
|
|
3001
|
-
|
|
3002
|
-
## [0.37.6] - 2026-01-06
|
|
3003
|
-
|
|
3004
|
-
### Added
|
|
3005
|
-
|
|
3006
|
-
- Kitty keyboard protocol flag 2 support for key release events. New exports: `isKeyRelease(data)`, `isKeyRepeat(data)`, `KeyEventType` type. Terminals supporting Kitty protocol (Kitty, Ghostty, WezTerm) now send proper key-up events.
|
|
3007
|
-
|
|
3008
|
-
## [0.37.0] - 2026-01-05
|
|
3009
|
-
|
|
3010
|
-
### Fixed
|
|
3011
|
-
|
|
3012
|
-
- Crash when pasting text with trailing whitespace exceeding terminal width through Markdown rendering ([#457](https://github.com/badlogic/pi-mono/pull/457) by [@robinwander](https://github.com/robinwander))
|
|
3013
|
-
|
|
3014
|
-
## [0.34.1] - 2026-01-04
|
|
3015
|
-
|
|
3016
|
-
### Added
|
|
3017
|
-
|
|
3018
|
-
- Symbol key support in keybinding system: `SymbolKey` type with 32 symbol keys, `Key` constants (e.g., `Key.backtick`, `Key.comma`), updated `matchesKey()` and `parseKey()` to handle symbol input ([#450](https://github.com/badlogic/pi-mono/pull/450) by [@kaofelix](https://github.com/kaofelix))
|
|
3019
|
-
|
|
3020
|
-
## [0.34.0] - 2026-01-04
|
|
3021
|
-
|
|
3022
|
-
### Added
|
|
3023
|
-
|
|
3024
|
-
- `Editor.getExpandedText()` method that returns text with paste markers expanded to their actual content ([#444](https://github.com/badlogic/pi-mono/pull/444) by [@aliou](https://github.com/aliou))
|
|
3025
|
-
|
|
3026
|
-
Older entries are archived in [packages/tui/CHANGELOG.md@58141d4e5fa8](https://github.com/can1357/oh-my-pi/blob/58141d4e5fa892166024e2168866c45e0baacde3/packages/tui/CHANGELOG.md).
|
|
2995
|
+
Older entries are archived in [packages/tui/CHANGELOG.md@fa14205f838f](https://github.com/can1357/oh-my-pi/blob/fa14205f838f282fcea048c64fca74026789a492/packages/tui/CHANGELOG.md).
|
|
@@ -15,6 +15,8 @@ type DebugLogViewerModelOptions = {
|
|
|
15
15
|
processPid?: number;
|
|
16
16
|
hasOlderLogs?: () => boolean;
|
|
17
17
|
loadOlderLogs?: (limitDays?: number) => Promise<string>;
|
|
18
|
+
/** Most entries kept; older history beyond it is not loaded. Defaults to {@link MAX_LOG_ENTRIES}. */
|
|
19
|
+
maxLogEntries?: number;
|
|
18
20
|
};
|
|
19
21
|
type ViewerRow = {
|
|
20
22
|
kind: "warning";
|
|
@@ -33,6 +35,8 @@ export declare class DebugLogViewerModel {
|
|
|
33
35
|
#private;
|
|
34
36
|
constructor(logText: string, options?: DebugLogViewerModelOptions);
|
|
35
37
|
get logCount(): number;
|
|
38
|
+
/** True once the entry cap is reached, so older history no longer loads. */
|
|
39
|
+
get historyLimitReached(): boolean;
|
|
36
40
|
get visibleLogCount(): number;
|
|
37
41
|
get rows(): readonly ViewerRow[];
|
|
38
42
|
get cursorRowIndex(): number | undefined;
|
|
@@ -41,6 +41,8 @@ export declare function rawSseRecordLines(record: RawSseDebugRecord): string[];
|
|
|
41
41
|
/** Bounded, observable capture of raw provider responses and SSE frames. */
|
|
42
42
|
export declare class RawSseDebugBuffer {
|
|
43
43
|
#private;
|
|
44
|
+
/** Bumped on every change to the captured window (append, eviction, clear); equal revisions mean equal snapshots. */
|
|
45
|
+
get revision(): number;
|
|
44
46
|
subscribe(listener: () => void): () => void;
|
|
45
47
|
recordResponse(response: ProviderResponseMetadata, model?: Model): void;
|
|
46
48
|
recordEvent(event: RawSseEvent, model?: Model): void;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A tool call's {@link ToolFigure} drawn under its card, the way assistant
|
|
3
|
+
* Markdown draws that fence: ```svg as an inline image ({@link SvgFigure}),
|
|
4
|
+
* redrawn as the body streams; ```mermaid as ASCII art once the body is
|
|
5
|
+
* final. The card already shows the source, so unlike the assistant's fence
|
|
6
|
+
* it never falls back to code: {@link FenceFigure.draws} turns down fences
|
|
7
|
+
* this terminal shows as code, and an svg that does not rasterize stays blank.
|
|
8
|
+
*/
|
|
9
|
+
import type { ImageBudget } from "../components/image.js";
|
|
10
|
+
import type { ToolFigure } from "../tools/renderer.js";
|
|
11
|
+
import type { Component } from "../tui.js";
|
|
12
|
+
/** Fence languages a {@link FenceFigure} draws. */
|
|
13
|
+
export type FenceFigureLang = "svg" | "mermaid";
|
|
14
|
+
export interface FenceFigureOptions {
|
|
15
|
+
/** Shared inline-image budget for an svg's rasters. */
|
|
16
|
+
budget?: ImageBudget;
|
|
17
|
+
/** The figure's rows changed outside a render: a raster landed. */
|
|
18
|
+
onChange: () => void;
|
|
19
|
+
}
|
|
20
|
+
export declare class FenceFigure implements Component {
|
|
21
|
+
#private;
|
|
22
|
+
/**
|
|
23
|
+
* Whether this terminal draws `figure` now: an svg where inline images show
|
|
24
|
+
* (`showImages` and a graphics protocol), a closed mermaid fence when
|
|
25
|
+
* diagram rendering is on and the source renders.
|
|
26
|
+
*/
|
|
27
|
+
static draws(figure: ToolFigure, options: {
|
|
28
|
+
showImages: boolean;
|
|
29
|
+
}): figure is ToolFigure & {
|
|
30
|
+
readonly lang: FenceFigureLang;
|
|
31
|
+
};
|
|
32
|
+
readonly lang: FenceFigureLang;
|
|
33
|
+
constructor(lang: FenceFigureLang, options: FenceFigureOptions);
|
|
34
|
+
/** Feed the fence as it stands; its `lang` is this figure's. */
|
|
35
|
+
update(figure: ToolFigure): void;
|
|
36
|
+
/** Whether a closed svg's raster is still on its way. */
|
|
37
|
+
get pending(): boolean;
|
|
38
|
+
/** The drawing; no rows while an svg draws, or when it does not. */
|
|
39
|
+
render(width: number): readonly string[];
|
|
40
|
+
invalidate(): void;
|
|
41
|
+
dispose(): void;
|
|
42
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ImageBudget } from "../components/image.js";
|
|
2
|
-
import type
|
|
2
|
+
import { type Markdown } from "../components/markdown.js";
|
|
3
3
|
import type { Component } from "../tui.js";
|
|
4
4
|
/** The active theme's color per figure token, for resolving a figure with `prepareSvg`. */
|
|
5
5
|
export declare function svgFigurePalette(): Record<string, string>;
|
|
@@ -90,6 +90,8 @@ export declare class ToolExecutionComponent extends Container {
|
|
|
90
90
|
* component-scoped so the TUI reuses every other root subtree (issue #4377).
|
|
91
91
|
*/
|
|
92
92
|
tickSpinner(frame: number): void;
|
|
93
|
+
/** Whether the result's figure still waits for its raster; the transcript holds retirement meanwhile. */
|
|
94
|
+
isTranscriptBlockPending(): boolean;
|
|
93
95
|
/**
|
|
94
96
|
* Whether this block is ready to retire as immutable history. Partial
|
|
95
97
|
* results, including detached background tasks, remain active and mutable
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type AutocompleteProvider } from "../autocomplete.js";
|
|
2
|
-
import type { TspEditorDecoration, TspTone } from "@oh-my-pi/pi-wire";
|
|
2
|
+
import type { TspEditorDecoration, TspText, TspTone } from "@oh-my-pi/pi-wire";
|
|
3
3
|
import { type DescribeContext, type NativeChild, type NativeNode, type NativeTextEdit, type NativeUiEvent } from "../native/node.js";
|
|
4
4
|
import type { SymbolTheme } from "../symbols.js";
|
|
5
5
|
import { type Component, type Focusable } from "../tui.js";
|
|
@@ -106,8 +106,11 @@ export declare class Editor implements Component, Focusable {
|
|
|
106
106
|
* dialog's text field; only the prompt composer claims `omp.editor`).
|
|
107
107
|
*/
|
|
108
108
|
describeLayout: ((input: NativeNode, cx: DescribeContext) => NativeEditorLayout) | undefined;
|
|
109
|
-
/**
|
|
110
|
-
|
|
109
|
+
/**
|
|
110
|
+
* TSP placeholder for the empty buffer; natively it replaces the rotating ANSI {@link placeholder} hints.
|
|
111
|
+
* Return a stable value (the same spans array) while it is unchanged: the editor node is reused by identity.
|
|
112
|
+
*/
|
|
113
|
+
describePlaceholder: (() => TspText) | undefined;
|
|
111
114
|
/** Called with the selected text when Visual mode yanks, so hosts can reach the system
|
|
112
115
|
* clipboard — `packages/tui` deliberately has no clipboard dependency of its own. */
|
|
113
116
|
onYank?: (text: string) => void;
|
|
@@ -250,6 +253,8 @@ export declare class Editor implements Component, Focusable {
|
|
|
250
253
|
get atoms(): ReadonlyMap<string, string>;
|
|
251
254
|
/** Monotonic buffer-content revision for render caches. Cursor-only movement does not advance it. */
|
|
252
255
|
get textRevision(): number;
|
|
256
|
+
/** Monotonic atom-table revision for render caches: advances whenever {@link atoms} is mutated or replaced. */
|
|
257
|
+
get atomsRevision(): number;
|
|
253
258
|
/** Whether the buffer text equals `value`, without `getText()`'s full join —
|
|
254
259
|
* O(1) for the hot per-keystroke probes against short single-line values. */
|
|
255
260
|
textEquals(value: string): boolean;
|
|
@@ -4,16 +4,21 @@ import type { SymbolTheme } from "../symbols.js";
|
|
|
4
4
|
import type { Component } from "../tui.js";
|
|
5
5
|
/** @internal exported for tests — the grown-line block-kind gate. */
|
|
6
6
|
export declare function fastLineStartHazard(grownLine: string): boolean;
|
|
7
|
-
/** @internal exported for tests — the windowed lexer's first-probe window size. */
|
|
8
|
-
export declare const LEX_WINDOW_BYTES: number;
|
|
9
7
|
/**
|
|
10
8
|
* Lex a whole document with the renderer's rules (math, custom rules,
|
|
11
|
-
* strikethrough)
|
|
12
|
-
*
|
|
13
|
-
* that split a document along its blocks (table charts) lex through this so
|
|
14
|
-
* they see the blocks Markdown renders.
|
|
9
|
+
* strikethrough). Callers that split a document along its blocks (table
|
|
10
|
+
* charts) lex through this so they see the blocks Markdown renders.
|
|
15
11
|
*/
|
|
16
12
|
export declare function lexDocument(text: string): TokensList;
|
|
13
|
+
/**
|
|
14
|
+
* `source` as a fenced code block in `lang`: the fence is one backtick longer
|
|
15
|
+
* than any backtick run in the source (at least three), so the block always
|
|
16
|
+
* closes where intended. `open` leaves it unclosed, the source verbatim, for
|
|
17
|
+
* a body that is still arriving.
|
|
18
|
+
*/
|
|
19
|
+
export declare function fencedCode(lang: string, source: string, options?: {
|
|
20
|
+
open?: boolean;
|
|
21
|
+
}): string;
|
|
17
22
|
/** A hyperlink as the renderer sees it: inline `[text](href)`, `<autolink>`, bare GFM URL, or reference link. */
|
|
18
23
|
export interface MarkdownLink {
|
|
19
24
|
/** Flattened visible label with whitespace collapsed to one row; falls back to `href` when empty. */
|
package/dist/types/fuzzy.d.ts
CHANGED
|
@@ -16,6 +16,20 @@ export interface FuzzyFilterResult<T> {
|
|
|
16
16
|
score: number;
|
|
17
17
|
}
|
|
18
18
|
export declare function fuzzyMatch(query: string, text: string): FuzzyMatch;
|
|
19
|
+
/**
|
|
20
|
+
* A query normalized and tokenized once for matching against many texts.
|
|
21
|
+
*
|
|
22
|
+
* `fuzzyMatch(query, text)` re-normalizes `query` (and rebuilds its
|
|
23
|
+
* alphanumeric-swap variants) on every call; filters that test one query
|
|
24
|
+
* against every row should build one `FuzzyQuery` per keystroke instead.
|
|
25
|
+
* `query.match(text)` returns exactly what `fuzzyMatch(query, text)` returns.
|
|
26
|
+
*/
|
|
27
|
+
export declare class FuzzyQuery {
|
|
28
|
+
#private;
|
|
29
|
+
constructor(query: string);
|
|
30
|
+
/** Same result as `fuzzyMatch(query, text)`; `text` may be a prepared {@link FuzzyText}. */
|
|
31
|
+
match(text: string | FuzzyText): FuzzyMatch;
|
|
32
|
+
}
|
|
19
33
|
/**
|
|
20
34
|
* A text prepared once for repeated fuzzy matching.
|
|
21
35
|
*
|
|
@@ -30,13 +44,13 @@ export declare class FuzzyText {
|
|
|
30
44
|
#private;
|
|
31
45
|
constructor(text: string);
|
|
32
46
|
/** Match `query` (space-separated tokens; all must match) against the prepared text. */
|
|
33
|
-
match(query: string): FuzzyMatch;
|
|
47
|
+
match(query: string | FuzzyQuery): FuzzyMatch;
|
|
34
48
|
}
|
|
35
49
|
/**
|
|
36
50
|
* Items prepared once for repeated {@link fuzzyRank}-equivalent ranking.
|
|
37
51
|
*
|
|
38
|
-
* `fuzzyRank` resolves each candidate's search index through the module
|
|
39
|
-
* which
|
|
52
|
+
* `fuzzyRank` resolves each candidate's search index through the bounded module
|
|
53
|
+
* cache, which holds at most {@link INDEX_CACHE_MAX} entries; larger candidate
|
|
40
54
|
* lists (the full model catalog) rebuild the overflow on every query. Hold one
|
|
41
55
|
* corpus per stable candidate list and call {@link rank} per keystroke instead.
|
|
42
56
|
*/
|
|
@@ -49,7 +49,8 @@ export interface NativeBackendOptions {
|
|
|
49
49
|
* The reply a v1 terminal is assumed to give before its real `hello` arrives
|
|
50
50
|
* (the `TERM_PROGRAM=tern` optimistic start): the whole vocabulary, the
|
|
51
51
|
* default APC limit and credits, the terminal's width, the appearance omp
|
|
52
|
-
* already detected, and
|
|
52
|
+
* already detected, full motion, and `blobs`, so a resumed session's images
|
|
53
|
+
* are asked about rather than resent before the reply comes.
|
|
53
54
|
*/
|
|
54
55
|
export declare function assumedTspHello(terminal: Terminal): TspHello;
|
|
55
56
|
export declare class NativeBackend {
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
* Content-addressed binary blobs (images) for `image` nodes.
|
|
3
3
|
*
|
|
4
4
|
* `describe()` registers the bytes and puts the returned id in `image.p.blob`;
|
|
5
|
-
* the native backend
|
|
6
|
-
*
|
|
5
|
+
* the native backend delivers each referenced blob once per terminal
|
|
6
|
+
* connection (asking the terminal first which it holds, or through its blob
|
|
7
|
+
* cache), else uploads it with verb `b` before the frame that first
|
|
8
|
+
* references it.
|
|
7
9
|
*/
|
|
8
10
|
import type { TspProps } from "@oh-my-pi/pi-wire";
|
|
9
11
|
import type { NativeNode } from "./node.js";
|
|
@@ -15,11 +15,10 @@ export type TspIncoming = {
|
|
|
15
15
|
};
|
|
16
16
|
/** Message parameters (`k=v`, ASCII, never containing `;`). */
|
|
17
17
|
export type TspParams = Readonly<Record<string, string | number>>;
|
|
18
|
-
/** Split `body` into pieces of at most `limit` UTF-8 bytes, never inside a code point. */
|
|
19
|
-
export declare function splitUtf8(body: string, limit: number): string[];
|
|
20
18
|
/**
|
|
21
|
-
* Encode one logical message, chunked when `body` exceeds `limit` UTF-8 bytes
|
|
22
|
-
*
|
|
19
|
+
* Encode one logical message, chunked when `body` exceeds `limit` UTF-8 bytes:
|
|
20
|
+
* the first chunk carries `params`, every chunk `c=<id>` and all but the last
|
|
21
|
+
* `m=1`. Returns the complete byte string to write (all chunks, in order).
|
|
23
22
|
*/
|
|
24
23
|
export declare function encodeTspMessage(verb: TspVerb, body: string, params?: TspParams, limit?: number): string;
|
|
25
24
|
/** Encode a JSON message body. */
|
|
@@ -31,7 +31,14 @@ export type AgentTranscriptEntry = SessionMessageEntryLike | {
|
|
|
31
31
|
};
|
|
32
32
|
/** Local filesystem and session parsing capabilities supplied by the host. */
|
|
33
33
|
export interface AgentTranscriptSource {
|
|
34
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Sync primitives drive the first paint and the incremental tail. When the
|
|
36
|
+
* host also supplies `promises.readFile` (e.g. passes `node:fs` itself), full
|
|
37
|
+
* reloads after rotation/rewrite read the file off the UI thread.
|
|
38
|
+
*/
|
|
39
|
+
fs: Pick<typeof fs, "openSync" | "closeSync" | "readSync" | "readFileSync" | "statSync"> & {
|
|
40
|
+
promises?: Pick<typeof fs.promises, "readFile">;
|
|
41
|
+
};
|
|
35
42
|
parseEntries(text: string): AgentTranscriptEntry[];
|
|
36
43
|
}
|
|
37
44
|
export interface AgentTranscriptViewerDeps {
|
|
@@ -15,6 +15,13 @@ import type { DescribeContext, NativeNode, NativeUiEvent } from "../native/node.
|
|
|
15
15
|
export declare class HistorySearchComponent extends OverlayPanel {
|
|
16
16
|
#private;
|
|
17
17
|
constructor(historyStorage: HistorySource, onSelect: (prompt: string) => void, onCancel: () => void);
|
|
18
|
+
/**
|
|
19
|
+
* Repaint hook for debounced result updates. Once set, query edits search
|
|
20
|
+
* storage after a {@link SEARCH_DEBOUNCE_MS} quiet period instead of on
|
|
21
|
+
* every key; without it every edit searches synchronously.
|
|
22
|
+
*/
|
|
23
|
+
setOnRequestRender(callback: () => void): void;
|
|
24
|
+
dispose(): void;
|
|
18
25
|
handleInput(keyData: string): void;
|
|
19
26
|
/**
|
|
20
27
|
* With the `picker` kind: a `size:"md"` sheet of past prompts (first line
|
|
@@ -29,6 +36,9 @@ export declare class HistorySearchComponent extends OverlayPanel {
|
|
|
29
36
|
* Picker: a row click highlights, a second click or `Insert` inserts it
|
|
30
37
|
* (Enter), `Close` cancels (Esc), `Clear search` empties the query.
|
|
31
38
|
* List: picking a result does what highlighting it and pressing Enter does.
|
|
39
|
+
* A row picked while a debounced search is pending belongs to the previous
|
|
40
|
+
* query: results are refreshed first and the pick only lands if that entry
|
|
41
|
+
* is still among them.
|
|
32
42
|
*/
|
|
33
43
|
handleNativeEvent(event: NativeUiEvent): void;
|
|
34
44
|
}
|
|
@@ -262,6 +262,12 @@ export declare class ModelBrowser implements Component {
|
|
|
262
262
|
setQuery(query: string): void;
|
|
263
263
|
getSelected(): ModelBrowserItem | undefined;
|
|
264
264
|
get visibleCount(): number;
|
|
265
|
+
/**
|
|
266
|
+
* Base items matching the live query, best first, without the separator
|
|
267
|
+
* row; undefined while the query is blank. Reuses the ranking the list
|
|
268
|
+
* already ran, so hosts can derive match counts without ranking again.
|
|
269
|
+
*/
|
|
270
|
+
get queryMatches(): readonly ModelBrowserItem[] | undefined;
|
|
265
271
|
/** Move selection to `selector`; false when it is not in the current view. */
|
|
266
272
|
selectSelector(selector: string): boolean;
|
|
267
273
|
/** True when `item`'s context window is smaller than the live session token count (grayed row; hosts compact before switching). */
|
|
@@ -7,7 +7,7 @@ import type { AppKeybinding } from "../app-keybindings.js";
|
|
|
7
7
|
import type { DescribeContext, NativeNode, NativeUiEvent } from "../native/node.js";
|
|
8
8
|
import type { ComposerFactsSource } from "../status-line/types.js";
|
|
9
9
|
import { type MacOSSpellingFeatures } from "./macos-spelling.js";
|
|
10
|
-
import type { TspEditorDecoration } from "@oh-my-pi/pi-wire";
|
|
10
|
+
import type { TspEditorDecoration, TspText } from "@oh-my-pi/pi-wire";
|
|
11
11
|
import { type WordCompletionMethod } from "./word-completion.js";
|
|
12
12
|
/** Live composer state the TSP layout shows; the interactive host wires {@link CustomEditor.composerState}. */
|
|
13
13
|
export interface ComposerNativeState {
|
|
@@ -26,6 +26,8 @@ export interface ComposerNativeState {
|
|
|
26
26
|
readonly running: boolean;
|
|
27
27
|
/** The viewed subagent's lineage, outermost first and the viewed agent last; undefined on the main session. */
|
|
28
28
|
readonly viewing?: readonly string[];
|
|
29
|
+
/** The session's title, quoted in italics as the TSP placeholder; undefined until it has one. */
|
|
30
|
+
readonly title?: string;
|
|
29
31
|
}
|
|
30
32
|
/** Independently switchable prose-assistance features of the composer. */
|
|
31
33
|
export interface SpellingFeatures extends MacOSSpellingFeatures {
|
|
@@ -191,7 +193,8 @@ export declare class CustomEditor extends Editor {
|
|
|
191
193
|
static readonly SHIMMER_PERIOD_MS = 1800;
|
|
192
194
|
/** Decorate magic keywords, attachments, and the queue-composer header/list markers.
|
|
193
195
|
* Queue shorthand reserves its first logical line as a dim `Queueing` label; sequential
|
|
194
|
-
* item markers use the accent color so separate follow-ups remain visible while composing.
|
|
196
|
+
* item markers use the accent color so separate follow-ups remain visible while composing.
|
|
197
|
+
* Called once per layout segment, so whole-buffer inputs are computed once per text revision. */
|
|
195
198
|
decorateText: (text: string, context: EditorTextDecorationContext) => string;
|
|
196
199
|
/**
|
|
197
200
|
* TSP decorations: magic keywords shimmer (terminal-clocked) in the accent
|
|
@@ -219,8 +222,8 @@ export declare class CustomEditor extends Editor {
|
|
|
219
222
|
setShimmerRepaintHandler(handler: (() => void) | undefined): void;
|
|
220
223
|
/** Editing is available during bootstrap; atomic sends wait until submission is wired and enabled. */
|
|
221
224
|
protected get nativeSendable(): boolean;
|
|
222
|
-
/** Viewing a subagent, the draft goes to it: the placeholder names it. */
|
|
223
|
-
describePlaceholder: () =>
|
|
225
|
+
/** Viewing a subagent, the draft goes to it: the placeholder names it; else the session's title, quoted in italics. */
|
|
226
|
+
describePlaceholder: () => TspText;
|
|
224
227
|
/** A shell-mode draft highlights as its language. */
|
|
225
228
|
describeLanguage: () => string | undefined;
|
|
226
229
|
/** Host-owned live state for the TSP composer (shell mode, effort chip, send/stop). */
|
|
@@ -25,7 +25,8 @@ export interface AssistantMessageHost {
|
|
|
25
25
|
requestRender(): void;
|
|
26
26
|
readonly imageBudget: ImageBudget;
|
|
27
27
|
};
|
|
28
|
-
|
|
28
|
+
/** Resolve already-extracted Markdown link destinations to local targets. */
|
|
29
|
+
resolveAssistantMessageLinkHrefs(hrefs: readonly string[]): Promise<ReadonlyMap<string, string>>;
|
|
29
30
|
}
|
|
30
31
|
/**
|
|
31
32
|
* Resolve and cache the current session's model-authored prose links. Existing
|
|
@@ -39,6 +39,18 @@ export interface ToolRenderResult<TDetails = unknown> {
|
|
|
39
39
|
details?: TDetails;
|
|
40
40
|
isError?: boolean;
|
|
41
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* A fence a tool call draws under its card, as assistant Markdown draws that
|
|
44
|
+
* fence. Any fence language may be named (`svg`, `mermaid`, `obj`); the
|
|
45
|
+
* transcript draws only those it draws as figures in assistant text.
|
|
46
|
+
*/
|
|
47
|
+
export interface ToolFigure {
|
|
48
|
+
readonly lang: string;
|
|
49
|
+
/** The body so far. */
|
|
50
|
+
readonly source: string;
|
|
51
|
+
/** No more of the body arrives. */
|
|
52
|
+
readonly closed: boolean;
|
|
53
|
+
}
|
|
42
54
|
/**
|
|
43
55
|
* Per-renderer opt-in for a full viewport replay when the first result
|
|
44
56
|
* replaces a painted pending-call render. A predicate receives the painted
|
|
@@ -103,6 +115,8 @@ export interface NativeToolView {
|
|
|
103
115
|
readonly preview?: TspPreview | {
|
|
104
116
|
readonly tail: number;
|
|
105
117
|
} | "none";
|
|
118
|
+
/** Starts expanded whatever the transcript's expand state (the todo checklist); the user can still fold it. */
|
|
119
|
+
readonly open?: boolean;
|
|
106
120
|
/** Render frameless (`frame:"inline"`): a head line plus a disclosed body. */
|
|
107
121
|
readonly inline?: boolean;
|
|
108
122
|
/** Head actions offered on hover (`copy`, `retry`). */
|
|
@@ -125,6 +139,14 @@ export interface ToolRenderer<TArgs = unknown, TDetails = unknown> {
|
|
|
125
139
|
/** Semantic result view for TSP terminals; merged with the call view when {@link mergeCallAndResult}. */
|
|
126
140
|
describeResult?(result: ToolRenderResult<TDetails>, options: RenderResultContextOptions, args?: TArgs): NativeToolView | undefined;
|
|
127
141
|
mergeCallAndResult?: boolean;
|
|
142
|
+
/**
|
|
143
|
+
* The fence a call draws under its card (a `.svg` being written, as its
|
|
144
|
+
* image): growing while the args stream, closed once they are final; none
|
|
145
|
+
* after an error. `result` is undefined until the call has one. Rendered
|
|
146
|
+
* TUI only, and only fences the terminal draws as figures; native views put
|
|
147
|
+
* their drawing in their describe hooks.
|
|
148
|
+
*/
|
|
149
|
+
figure?(args: TArgs, result: ToolRenderResult<TDetails> | undefined, options: RenderResultOptions): ToolFigure | undefined;
|
|
128
150
|
/** Describes current activity without coupling a renderer to terminal layout. */
|
|
129
151
|
activitySummary?(args: TArgs, context: ToolActivityContext): ToolActivitySummary;
|
|
130
152
|
/** Render without background box, inline in the response flow */
|
|
@@ -236,7 +236,8 @@ export declare class OutputSink {
|
|
|
236
236
|
constructor(options?: OutputSinkOptions);
|
|
237
237
|
/**
|
|
238
238
|
* Push a chunk of output. The buffer management and onChunk callback run
|
|
239
|
-
* synchronously
|
|
239
|
+
* synchronously; onChunk fires after the chunk is stored, so {@link preview}
|
|
240
|
+
* already includes it. File sink writes are deferred and serialized internally.
|
|
240
241
|
*
|
|
241
242
|
* `inline` substitutes a bounded representation for the in-memory buffer and
|
|
242
243
|
* live preview while the complete chunk is mirrored to the artifact.
|
|
@@ -260,6 +261,15 @@ export declare class OutputSink {
|
|
|
260
261
|
* branch in `dump()` against stale totals.
|
|
261
262
|
*/
|
|
262
263
|
replace(text: string): void;
|
|
264
|
+
/**
|
|
265
|
+
* Current inline view without finalizing: the body {@link dump} would
|
|
266
|
+
* return right now (head + elision marker + rolling tail), minus any notice
|
|
267
|
+
* and minus the newline `dump()` appends after output that ends in a bare
|
|
268
|
+
* carriage return. Each call trims the rolling tail to its budget (a copy
|
|
269
|
+
* of the tail window once it overflowed), so call it from a throttled
|
|
270
|
+
* onChunk (`chunkThrottleMs`), not once per raw chunk.
|
|
271
|
+
*/
|
|
272
|
+
preview(): string;
|
|
263
273
|
dump(notice?: string): Promise<OutputSummary>;
|
|
264
274
|
/**
|
|
265
275
|
* Release the artifact spill descriptor on an exit path that skips
|
|
@@ -6,7 +6,7 @@ import { type ProcWriteDetails } from "./proc-render.js";
|
|
|
6
6
|
import { type CfgWriteDetails } from "./cfg-render.js";
|
|
7
7
|
import type { FileDiagnosticsResult } from "./lsp.js";
|
|
8
8
|
import type { OutputMeta } from "./output-meta.js";
|
|
9
|
-
import type { NativeToolView, RenderResultOptions, ToolActivityContext, ToolActivitySummary } from "./renderer.js";
|
|
9
|
+
import type { NativeToolView, RenderResultOptions, ToolActivityContext, ToolActivitySummary, ToolFigure } from "./renderer.js";
|
|
10
10
|
import { type XdevRenderDispatch, type XdevMountedRenderer } from "./xdev.js";
|
|
11
11
|
/** Details returned by the write tool for transcript rendering. */
|
|
12
12
|
export interface WriteToolDetails {
|
|
@@ -37,6 +37,12 @@ interface WriteResult {
|
|
|
37
37
|
details?: WriteToolDetails;
|
|
38
38
|
isError?: boolean;
|
|
39
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* The fence a file write draws as while its content streams and after: its
|
|
42
|
+
* extension names a figure language and it has content, closed once the args
|
|
43
|
+
* are final. None for URL-card writes, or after an error.
|
|
44
|
+
*/
|
|
45
|
+
declare function writeFigure(args: WriteRenderArgs | undefined, result: WriteResult | undefined, options: RenderResultOptions): ToolFigure | undefined;
|
|
40
46
|
declare const writeStreamingPreviewStateKey: unique symbol;
|
|
41
47
|
/**
|
|
42
48
|
* Per-component state for incrementally rendering a streamed write.
|
|
@@ -84,6 +90,7 @@ export declare const writeToolRenderer: {
|
|
|
84
90
|
describeResult(result: WriteResult, options: RenderResultOptions & {
|
|
85
91
|
renderContext?: WriteRenderContext;
|
|
86
92
|
}, args?: WriteRenderArgs): NativeToolView | undefined;
|
|
93
|
+
figure: typeof writeFigure;
|
|
87
94
|
mergeCallAndResult: true;
|
|
88
95
|
forceFirstResultViewportRepaint: (args: unknown, options: RenderResultOptions) => boolean;
|
|
89
96
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/pi-tui",
|
|
4
|
-
"version": "18.
|
|
4
|
+
"version": "18.8.0",
|
|
5
5
|
"description": "Terminal User Interface library with differential rendering for efficient text-based applications",
|
|
6
6
|
"homepage": "https://omp.sh",
|
|
7
7
|
"author": {
|
|
@@ -41,14 +41,14 @@
|
|
|
41
41
|
"gen:glyphs": "bun scripts/gen-glyphs.ts"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@oh-my-pi/omptype": "18.
|
|
45
|
-
"@oh-my-pi/pi-agent-core": "18.
|
|
46
|
-
"@oh-my-pi/pi-ai": "18.
|
|
47
|
-
"@oh-my-pi/pi-catalog": "18.
|
|
48
|
-
"@oh-my-pi/pi-natives": "18.
|
|
49
|
-
"@oh-my-pi/pi-utils": "18.
|
|
50
|
-
"@oh-my-pi/pi-wire": "18.
|
|
51
|
-
"@oh-my-pi/snapcompact": "18.
|
|
44
|
+
"@oh-my-pi/omptype": "18.8.0",
|
|
45
|
+
"@oh-my-pi/pi-agent-core": "18.8.0",
|
|
46
|
+
"@oh-my-pi/pi-ai": "18.8.0",
|
|
47
|
+
"@oh-my-pi/pi-catalog": "18.8.0",
|
|
48
|
+
"@oh-my-pi/pi-natives": "18.8.0",
|
|
49
|
+
"@oh-my-pi/pi-utils": "18.8.0",
|
|
50
|
+
"@oh-my-pi/pi-wire": "18.8.0",
|
|
51
|
+
"@oh-my-pi/snapcompact": "18.8.0"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"kitty-vt-wasm": "^0.2.0"
|